AI 服务
到目前为止,我们介绍的都是 ChatModel、ChatMessage、ChatMemory 等底层组件。
在这一层级工作非常灵活,能给你完全的自由,但也会迫使你编写大量样板代码。
由于由 LLM 驱动的应用通常不只需要单个组件,而是多个组件协同工作
(例如:提示词模板、聊天记忆、LLM、输出解析器、RAG 组件:嵌入模型和存储),
并且往往涉及多次交互,编排它们会变得更加繁琐。
我们希望你专注于业务逻辑,而不是底层实现细节。 因此,LangChain4j 目前有两个高层概念可以帮助做到这一点:AI 服务(AI Services)和链(Chains)。
链(Chains,遗留)
链(Chains)的概念源自 Python 版 LangChain(在引入 LCEL 之前)。
其思路是为每个常见用例(如聊天机器人、RAG 等)提供一个 Chain。
链将多个底层组件组合在一起,并编排它们之间的交互。
它们的主要问题是:一旦你需要自定义某些行为,就会显得过于僵硬。
LangChain4j 目前只实现了两个链(ConversationalChain 和 ConversationalRetrievalChain),
我们暂时不打算再增加更多。
AI 服务
我们提出另一种为 Java 量身定制的方案,称为 AI 服务(AI Services)。 其思路是:将与 LLM 及其他组件交互的复杂性隐藏在一个简单的 API 背后。
这种方式非常类似于 Spring Data JPA 或 Retrofit:你声明式地定义一个带有期望 API 的接口, 然后由 LangChain4j 提供一个实现该接口的对象(代理)。 你可以把 AI 服务看作应用中服务层的一个组件。 它提供 AI 服务,因此得名。
AI 服务处理最常见的操作:
- 为 LLM 格式化输入
- 解析来自 LLM 的输出
它们还支持更高级的功能:
- 聊天记忆
- 工具
- RAG
AI 服务既可以用来构建支持来回交互的有状态聊天机器人, 也可以用来自动化那些每次对 LLM 的调用彼此独立的流程。
让我们先看一个最简单的 AI 服务。之后,我们再探索更复杂的示例。
最简单的 AI 服务
首先,我们定义一个带有单个方法 chat 的接口,该方法接受一个 String 作为输入并返回一个 String。
interface Assistant {
String chat(String userMessage);
}
然后,我们创建底层组件。这些组件将在 AI 服务底层使用。
在本例中,我们只需要 ChatModel:
ChatModel model = OpenAiChatModel.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.modelName(GPT_4_O_MINI)
.build();
最后,我们可以使用 AiServices 类来创建 AI 服务的实例:
Assistant assistant = AiServices.create(Assistant.class, model);
在 Quarkus
和 Spring Boot 应用中,
自动配置会负责创建 Assistant bean。
这意味着你不需要调用 AiServices.create(...),只需在需要的地方注入/自动装配 Assistant 即可。
现在我们可以使用 Assistant:
String answer = assistant.chat("Hello");
System.out.println(answer); // Hello, how can I help you?