#LangChain4j系列:带你入门LangChain4j框架 文章对LangChain4j框架有个整体的认识,并使用
LowLevel API
接入本地大模型以及OpenAI大模型实现简单的对话功能。本篇文章将介绍如何使用HighLevel API
AiServices 。
LangChain4j 支持的LLMs
:------: | :------: | :------: | :------: | :------: | :------: |
---|---|---|---|---|---|
Provider 「大模型提供商」 | Streaming 「流式调用」 | Tools 「 函数调用 」 | Image Inputs 「图片输入」 | Local 「本地部署」 | Native 「支持原生」 |
Zhipu AI | ✅ | ✅ | |||
Qianfan | ✅ | ✅ | |||
ChatGLM | |||||
Ollama | ✅ | ✅ | ✅ | ||
Hugging Face | |||||
OpenAI | ✅ | ✅ | ✅ | ✅ | |
Azure OpenAI | ✅ | ✅ | ✅ | ||
Amazon Bedrock | |||||
Anthropic | ✅ | ✅ | ✅ | ✅ | |
DashScope | ✅ | ✅ | ✅ | ||
Google Vertex AI Gemini | ✅ | ✅ | ✅ | ||
Google Vertex AI PaLM 2 | ✅ | ||||
Jlama | ✅ | ✅ | ✅ | ||
LocalAI | ✅ | ✅ | ✅ | ||
Mistral AI | ✅ | ✅ | |||
Cloudflare Workers AI |
与Spring AI
框架支持的大模型基本相似。下面我们将详细介绍LangChain4j支持的LLM API
。上一节中我们知道LangChain4j
支持low-level API
和high-level API
两种。
LangChain4j支持的low-level LLM API
Model
类型
LanguageModel
:API 非常简单。接收String
作为输入并返回String
作为输出。 目前废弃!!!!ChatLanguageModel
:取代LanguageModel
,参数:ChatMessage
,返回:AiMessage
。 对于LanguageModel
已不再扩展,可以把这个忘掉了。在实际开发中使用ChatLanguageModel
。EmbeddingModel
:嵌入模型,将文本转换向量。ImageModel
:图片模型,可以生成和编辑图片。ModerationModel
:模型可以检查文本是否包含有害内容。ScoringModel
:可以针对查询对多段文本进行评分(或排名)。
ChatMessage
类型
ChatMessage
有四种类型的聊天消息;
UserMessage
:用户的消息。用户可以是应用程序的最终用户,也可以是应用程序本身。根据 LLM支持UserMessage
的模态。可以只包含文本,也可以包含文本和/或图像。AiMessage
:由 AI 生成的消息,通常用于响应UserMessage
。ToolExecutionResultMessage
:是ToolExecutionRequest
的结果,函数调用时使用,开发人员一般无需关系。SystemMessage
:定义扮演什么角色、它应该如何表现、以什么方式回答等的说明,比其他类型的消息优先级更高。 最好不要让最终用户自由访问定义或注入一些输入。通常,它位于对话的开头。
java
Response<AiMessage> generate(ChatMessage... messages);
Response<AiMessage> generate(List<ChatMessage> messages);
LangChain4j支持的high-level LLM API
low-level API 使用上非常灵活,但是享受了自由的同时也迫使你编写大量的样板代码。
在实现 LLM-powered 应用程序通常不仅需要单个组件,需要多个组件协同工作(例如,提示模板、聊天记忆、LLMs输出解析器、RAG组件:嵌入模型和存储),并且通常涉及多个交互,因此编排它们变得更加繁琐。
为让开发者更专注于业务逻辑,而不是低级实现细节。LangChain4j 中目前有两个高级概念可以帮助解决这个问题:AI Services
和 Chains
。
一些注解
- @AiService:定义一个集成大模型的服务,标注在接口上,无需实现方法。 参数说明:
- wiringMode:类注入类型,有两种方式,AUTOMATIC「自定注入」 和 EXPLICIT「手动指定名称」。
- chatModel:指定使用大模型,如果wiringMode =EXPLICIT,则chatModel指定模型的Bean名称。
- streamingChatModel:指定支持流式响应的大模型,设置规则与wiringMode设置有关系。
- chatMemory:指定上下文记忆Bean,设置规则与wiringMode设置有关系。
- chatMemoryProvider:指定上下文记忆Provider,设置规则与wiringMode设置有关系。
- contentRetriever:xxx 目前还不知道用途 后续补上
- retrievalAugmentor:目前还不知道用途 后续补上
- tools:指定需要调用的函数集合,支持函数调用。
- @Tool:函数定义,可以设置在 @AiService tools的值上。
- @MemoryId:定义上下文记忆Id,支持上下文记忆能力。
- @SystemMessage:定义系统消息,定义模版方式两种:字符串/@SystemMessage(fromResource = "my-prompt-template.txt")
- @UserMessage:定义用户消息,定义模板方式有两种:字符串/@UserMessage(fromResource = "my-prompt-template.txt")
- @V:定义模板中的参数名称,一般与@SystemMessage或者@UserMessage配合使用,如果方法仅有一个参数可以使用模板中使用
{{it}}
,如果有多个参数需要@V定义名称。 - @UserName:@UserName注释的方法参数的值将被注入UserMessage的字段"name"
- @Moderate: 指定方法需要使用审核模型,对输入/输出内容进行检查。
结构化输出
如果要从 LLM接收结构化输出,可以将 AI Service 方法的返回类型更改为 String
其他。 目前支持的类型如下;
- 字符串
String
。 - 基本类型
boolean
/byte
/short
/int
/long
/float
/double
。 - 对象类型
Boolean
/Byte
/Short
/Integer
/Long
/Float
/Double
/BigDecimal
。 - 时间类型
Date
/LocalDate
/LocalTime
/LocalDateTime
。 - 集合类型
List<String>
/Set<String>
。 - 枚举类型
Enum
。 - 自定义 POJO。
- 自定义
Result<T>
。 - 大模型回复消息
AiMessage
。
RAG(检索增强生成)
这个就不在这里详细解释了,会有专栏对 RAG 应用的落地进行详细分析。
Auto-Moderation
自定审核功能封装,方便调用模型,对输入/输出内容进行内容过滤审核,防止一些违规、反动言论、辱骂等信息出现。代码示例如下;
java
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.model.openai.OpenAiModerationModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.Moderate;
import dev.langchain4j.service.ModerationException;
public class ServiceWithAutoModerationExample {
interface Chat {
@Moderate
String chat(String text);
}
public static void main(String[] args) {
OpenAiModerationModel moderationModel = OpenAiModerationModel.withApiKey(ApiKeys.OPENAI_API_KEY);
Chat chat = AiServices.builder(Chat.class)
.chatLanguageModel(OpenAiChatModel.withApiKey(ApiKeys.OPENAI_API_KEY))
// 指定审核模型,在进行大模型生成时,对内容进行审核。
.moderationModel(moderationModel)
.build();
try {
chat.chat("I WILL KILL YOU!!!");
} catch (ModerationException e) {
System.out.println(e.getMessage());
// Text "I WILL KILL YOU!!!" violates content policy
}
}
}
连接多个AI服务
由LLM应用程序驱动的逻辑变得越复杂,将其分解为更小的部分就越重要,这是软件开发中的常见做法。如果想完成复杂的任务就需要组合一些服务共同完成,LangChain4j支持将多个服务连接起来。
使用high-level API实战
1. 依赖包
pom
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
2. yml配置
yml
server:
port: 8801
spring:
application:
name: chat-service
langchain4j:
ollama:
chat-model:
base-url: http://localhost:11434
model-name: mistral:latest # qwen:7b
open-ai:
chat-model:
base-url: xxx
api-key: xx
3. AiService
java
package org.ivy.aiservice.service;
import dev.langchain4j.service.spring.AiService;
import dev.langchain4j.service.spring.AiServiceWiringMode;
/**
* 通过 @AiService 注解声明一个 AI 助手接口,并指定 chatModel 为 openAiChatModel。
*/
@AiService(
wiringMode = AiServiceWiringMode.EXPLICIT, // 指定注入方式
chatModel = "openAiChatModel", // 指定chatModel为OpenAiChatModel
chatMemory = "chatMemory", // 指定上下文记忆
tools = {"calculator"} // 指定自定义的工具
)
public interface Assistant {
String chat(String userMessage);
}
4. Tools
java
package org.ivy.aiservice.func;
import dev.langchain4j.agent.tool.Tool;
import org.springframework.stereotype.Component;
@Component
public class Calculator {
@Tool("Calculates the length of a string")
int stringLength(String s) {
System.out.println("Called stringLength with s='" + s + "'");
return s.length();
}
@Tool("Calculates the sum of two numbers")
int add(int a, int b) {
System.out.println("Called add with a=" + a + ", b=" + b);
return a + b;
}
@Tool("Calculates the square root of a number")
double sqrt(int x) {
System.out.println("Called sqrt with x=" + x);
return Math.sqrt(x);
}
}
5. Controller
java
package org.ivy.aiservice;
import org.ivy.aiservice.service.Assistant;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/hl")
@RestController
public class HighLevelChatController {
private final Assistant assistant;
public HighLevelChatController(Assistant assistant) {
this.assistant = assistant;
}
@GetMapping("/chat")
public String chat(
@RequestParam(value = "prompt",
defaultValue = "What is the square root of the sum of the numbers of letters in the words "hello" and "world"?")
String prompt) {
return assistant.chat(prompt);
}
}
6. 测试结果
借助工具完成复杂的任务处理。
示例代码
Github仓库 参照红框标注的代码即可
总结
先对LLM API 有个简单的认识,对于格式化输出、RAG以及连接多个服务都没有进行代码示例。先对整个有个感觉,后面会不断进行更新文章对每一部分都进行详细的分析和实战。