04、AI Service

前面的内容我们使用的是底层组件,如:ChatLanguageModel、ChatMessage、ChatMemory等等,它们是低级别的API,虽然使用起来灵活,但是需要我们编写大样的样板代码。

然而由LLM驱动的应用不仅仅需要一个组件,而是需要多个组件一起工作(如:提示模板、聊天记忆、RAG、嵌入模型的存储...),它们之间还是相互交互的,这样的话编排他们是非常麻烦的。

通常我们更应该关注的是业务逻辑,对于底层的细节不要太过于关注。在LangChain4j中的两个概念可以帮我们实现:Chains和AiService 

Chains

链这个概念起源于Python和LangChain,它的想法是为每个常见的用例创建一个Chain。链把多个低级组件组合在一起,并编排它们之间的交互。它们有一个缺点就是太过于死板了。

对于LangChain4j只实现了两个链(ConversationalChain和CoversationalRetrievalChain)未来也基本上不会考虑再新增了

AiService

AiService是专为Java量身定制的。其想法是为了隐藏LLM和其他组件交互的复杂性,把它们隐藏在一个简单的API后面。

我们需要做的就是声明式地定义一个接口,LangChain4j提供了实现这个接口的对象(代理)。可以把AiService视作为应用程序中服务层的一个组件。

AiService处理最常见的操作

  • 格式化LLM的输入
  • 解析从LLM得到输出

AiService支持的高级特性:

  • Chat memory
  • Tools
  • RAG

最简单的AiService

先定义一个带chat方法的接口,这个chat方法接收一个String作为输入,并且返回一个String。

public interface Assistant {
    String chat(String userMessage);
}

注意:这里的方法名称是自定义的,不一定非叫chat!!

我们定义好这个接口后,我们要能创建出它的一个实例,我们是与SpringBoot集成的,所以我们可以选择在配置类创建对应的Bean供后续的使用。

我们创建一个config包,并在其下创建配置类:AiServiceConfig

@Configuration
public class AiServiceConfig {

    @Resource
    private ChatLanguageModel chatLanguageModel;

    @Bean
    public Assistant assistant() {
        return AiServices.create(Assistant.class, chatLanguageModel);
    }
}

这里创建Bean的核心就是AiServices.create(Assistant.class, ChatLanguageModel);

AiServices是一个抽象类,其中有多个create方法,上面的这个create方法表示为这个AiService当中传入ChatLanguageModel

在AiServices这个抽象类当中这个create方法实现如下:

public static <T> T create(Class<T> aiService, ChatLanguageModel chatLanguageModel) {
    return builder(aiService)
            .chatLanguageModel(chatLanguageModel)
            .build();
}

// builder方法,返回的是DefaultSAiServices,这个类是AiServices的子类
public static <T> AiServices<T> builder(Class<T> aiService) {
        AiServiceContext context = new AiServiceContext(aiService);
        for (AiServicesFactory factory : loadFactories(AiServicesFactory.class)) {
            return factory.create(context);
        }
        return new DefaultAiServices<>(context);
    }

// chatLanguageModel方法
public AiServices<T> chatLanguageModel(ChatLanguageModel chatLanguageModel) {
        context.chatModel = chatLanguageModel;
        return this;
    }

工作机制

对于create方法我们可以看到,它是把接口类与底层组件一起提供给AiServices,AiServices会创建实现这个接口的代理对象。当前来看使用的是反射机制完成的。这个代理类处理输入与输出的所有转换。在我们定义的接口中chat方法是接收的一个String作为输入,然而ChatLanguageModel它接收的是珍上ChatMessage作为输入,因而在这里AiService会自动把字符串转为UserMessage并调用ChatLanguageModel,chat方法返回的是String,那么ChatLanguageModel返回后也会同样进行转换。

@SystemMessage注解

我们可以在接口方法上加上@SystemMessage,这样子的话可以在聊天中指定它的角色信息

public interface TianWenService {

    @SystemMessage("你是一个无所不知的智能体,你的名字叫玄鉴,“玄鉴”源自《庄子》中“鉴明则尘垢不止”,寓意纯净的洞察力,你要有深度分析用户提问给出有深度的回答")
    String chat(String message);
}

通过这个方式,@SystemMessage注解中提供的内容会转为SystemMessage,并最终与UserMessage一起发送给到LLM。

除了直接指定文本,也可以从资源中加载提示模板,如下所示:

@SystemMessage(fromResource="systemMessage.txt")
String chat(String message);

注意:fromResource相当于调用Class.getResourceAsStream(String),一般会把这个提示模板和txt文档放在resources下

系统消息提供器

系统消息也可以通过系统消息提供器来动态定义,而不是像上面这样直接写死来指定

在AiService接口中的方法上去掉@SystemMessage注解


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值