theme: vue-prohighlight: a11y-dark
#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
:定义扮演什么角色、它应该如何表现、以什么方式回答等的说明,比其他类型的消息优先级更高。最好不要让最终用户自由访问定义或注入一些输入。通常,它位于对话的开头。
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
和 code>Chains</code>。</p><h2>一些注解</h2><ul>@AiService:定义一个集成大模型的服务,标注在接口上,无需实现方法。<blockquote
参数说明:
- wiringMode:类注入类型,有两种方式,AUTOMATIC「自定注入」 和 EXPLICIT「手动指定名称」。chatModel:指定使用大模型,如果wiringMode =EXPLICIT,则chatModel指定模型的Bean名称。streamingChatModel:指定支持流式响应的大模型,设置规则与wiringMode设置有关系。chatMemory:指定上下文记忆Bean,设置规则与wiringMode设置有关系。chatMemoryProvider:指定上下文记忆Provider,设置规则与wiringMode设置有关系。contentRetriever:xxx 目前还不知道用途 后续补上retrievalAugmentor:目前还不知道用途 后续补上tools:指定需要调用的函数集合,支持函数调用。
{{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
自定审核功能封装,方便调用模型,对输入/输出内容进行内容过滤审核,防止一些违规、反动言论、辱骂等信息出现。代码示例如下;
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. 依赖包
<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配置
server: port: 8801spring: application: name: chat-servicelangchain4j: 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
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
package org.ivy.aiservice.func;import dev.langchain4j.agent.tool.Tool;import org.springframework.stereotype.Component;@Componentpublic 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
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")@RestControllerpublic 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以及连接多个服务都没有进行代码示例。先对整个有个感觉,后面会不断进行更新文章对每一部分都进行详细的分析和实战。