2. LangChain4j 之AI Services

一: AI Services介绍

        LangChain4j提供了很多基础的组件,每次使用都需要你编写大量的样板代码,LangChain4j就提供了一个高级的组件AI Services,它可以简化与大模型(LLM)和其他组件交互的复杂度。让开发者更专注于业务逻辑,而不是底层的实现细节。

        通过AiServices来封装聊天模型API,实现会话记忆,工具调用,搜索增强,内容审查等功能,并提供简单灵活的用户接口 DefaultAiServices是其默认实现类型,通过动态代理的方式实现用户定义的服务接口


二: AI Services功能

  • 处理LLM的输入
  • 解析LLM的输出
  • Chat memory 聊天信息存储器
  • Tools 工具调用
  • RAG 检索增强生成

三: AI Services工作原理

    我们定义一个接口,并将接口的class和LangChain4j的基础组件一起传给AiServices,而AiServices则通过反射创建一个实现此接口的Jdk代理对象。当我们使用这个代理对象去执行方法时,就会去执行代理逻辑,组装UserMessage和SystemMessage对象,然后去调用大模型的接口,返回结果.


四: AI Services实战

注解介绍:

  • @UserMessage: 用户消息
  • @SystemMessage: 系统消息,当@SystemMessage和AiServices.systemMessageProvider(Function) 都配置时, @SystemMessage 优先。
  • @V: 提示模板变量,其值将被注入到通过@UserMessage,@SystemMessage和AiServices.systemMessageProvider定义的提示模版中.
  • @MemoryId: 带有 @MemoryId 注释的方法参数的值将用于查找属于该用户/会话的内存。带有 @MemoryId 注释的参数可以是任何类型,前提是它已正确实现 equals() 和 hashCode() 方法.
  • @Moderate: 和ModerationModel配合使用,对方法的输入进行审核,看是否涉及敏感,不安全的内容.

综合案例

基于AiService实现智能文章小助手

     当我们需要实现智能文章小助手,根据输入的文章标题,得到一篇文章时, 首先需要加上@SystemMessage注解, 告诉大模型让他做什么事情,此时,我们输入文章标题时,大模型才会返回结果给我们. 如果我们需要检测用户输入的文章标题是否包含敏感词,可以使用@Moderate和ModerationModel来支持这个功能, 这个功能没有在智普Ai有找到,所以用了openAi的ModerationModel.

注意事项:

        方法参数大于两个的时候, 每个入参都需要包括@UserMessage,@SystemMessage,@V和

@MemoryId注解中至少一个注解.不然就会报错.

案例代码

public class AiServiceDemo {
    interface Writer {
        @SystemMessage("请扮演一名作家,根据输入的文章题目写一篇{{count}}字以内的作文")
        @Moderate
        String write(@UserMessage String title, @V("count") Integer count);
    }

    public static void main(String[] args) {
        ZhipuAiChatModel zhipuAiModel = ZhipuAiChatModel.builder()
                .apiKey("智普spikey")
                .build();

        OpenAiModerationModel openAiModel = OpenAiModerationModel.builder()
                .apiKey("demo")
                .build();

        Writer writer = AiServices.builder(Writer.class)
                .chatLanguageModel(zhipuAiModel)
                .moderationModel(openAiModel)
                .build();
        //String result = writer.write("我最爱的人",200);
        String result = writer.write("我要杀了你",200);
        System.out.println(result);
    }
}

五: AI Services结构化输出

AI Services支持以下返回类型:

  • String
  • AiMessage
  • boolean/Boolean
  • byte/Byte/short/Short/int/Integer/BigInteger/long/Long/float/Float/double/Double/BigDecimal
  • Date/LocalDate/LocalTime/LocalDateTime
  • List<String>/Set<String>
  • Any Enum
  • Any custom POJO
  • Result<T>

 Enum 和 boolean 作为返回类型

public class AiServiceDemo2 {
    enum Sentiment {
        POSITIVE, NEUTRAL, NEGATIVE
    }
    interface SentimentAnalyzer {

        @UserMessage("Analyze sentiment of {{it}}")
        Sentiment analyzeSentimentOf(String text);
        @UserMessage("Does {{it}} has a positive sentiment?")
        boolean isPositive(String text);
    }
    public static void main(String[] args) {
        ZhipuAiChatModel zhipuAiModel = ZhipuAiChatModel.builder()
                .apiKey("智普apikey")
                .build();
        SentimentAnalyzer sentimentAnalyzer = AiServices.create(SentimentAnalyzer.class, zhipuAiModel);

        Sentiment sentiment = sentimentAnalyzer.analyzeSentimentOf("这是好的吗!");// POSITIVE
        System.out.println(sentiment);

        boolean positive = sentimentAnalyzer.isPositive("It's awful!");
        System.out.println(positive);
    }
}

自定义POJO作为返回类型

@Data
public class Person {
    String firstName;
    String lastName;
    LocalDate birthDate;
    Address address;
}
@Data
public class Address {
    String street;
    Integer streetNumber;
    String city;
}
public class AiServiceDemo {

    interface PersonExtractor {

        @UserMessage("Extract information about a person from {{it}}")
        Person extractPersonFrom(String text);
    }

    public static void main(String[] args) {
        ZhipuAiChatModel zhipuAiModel = ZhipuAiChatModel.builder()
                .apiKey("智普apikey")
                .build();
        PersonExtractor personExtractor = AiServices.create(PersonExtractor.class, zhipuAiModel);

        String text = """
            In 1968, amidst the fading echoes of Independence Day,
            a child named John arrived under the calm evening sky.
            This newborn, bearing the surname Doe, marked the start of a new journey.
            He was welcomed into the world at 345 Whispering Pines Avenue
            a quaint street nestled in the heart of Springfield
            an abode that echoed with the gentle hum of suburban dreams and aspirations.
            """;
        Person person = personExtractor.extractPersonFrom(text);

        System.out.println(person);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值