注意:本篇文章建立在官方文档的理解上,文章会围绕官方文档去书写,博主会根据对框架的理解去动态修改文章内容,由于该框架的官方文档写的并不是很详细,市面上也没有特别详细的教程,所以博主也不能很全面的理解整个框架,但是对于入门来说,已经足够了,如果有看不懂的地方建议把全部文章都阅读一遍后再回顾会有不同的理解。
LangChain4j 支持的 API 和消息类型(Chat and Language Models)
官网Chat and Language Models介绍
LangChain4j 的核心 API 类型
当前,LangChain4j 支持的 LLMs API 主要分为两种:
LanguageModel
s.- 早期的简单 API,只接受
String
输入并返回String
输出。此 API 已过时,未来将主要支持新的聊天 API(即ChatLanguageModel
)。
- 早期的简单 API,只接受
ChatLanguageModel
s- 目前推荐使用的主要 API,支持更复杂的输入和输出。
- 接受单个或多个
ChatMessage
s 作为输入,并返回AiMessage
作为输出。ChatMessage
通常包含文本,但某些 LLMs 还支持文本和Image
s 的混合。此类聊天模型的示例包括 OpenAI 的gpt-4o-mini
和 Google 的gemini-1.5-pro
。
未来 LangChain4j 不再扩展
LanguageModel
支持,因此推荐在所有新功能中使用ChatLanguageModel
。
特定功能模型类型
除了这两类核心 API,LangChain4j 还支持几种特定功能的模型类型,这些模型并非标准的聊天和语言 API,但用于特定应用场景中:
EmbeddingModel
:用于将文本转换为向量(Embedding
),便于语义搜索和聚类。ImageModel
:用于生成和编辑图像。ModerationModel
:用于检测文本是否包含有害内容,确保内容安全。ScoringModel
:用于根据查询对文本段落进行相关性评分,适用于 RAG(检索增强生成)任务。
ChatLanguageModel
的API
简化版 generate
方法
public interface ChatLanguageModel {String generate(String userMessage);...
}
如上所示,generate
方法接收一个 String
类型的输入,并返回一个 String
类型的输出,这与 LanguageModel
类似。这是一个简化的便捷方法,方便你快速进行测试,而无需将字符串封装在 UserMessage
中。
实际的聊天 API
...Response<AiMessage> generate(ChatMessage... messages);Response<AiMessage> generate(List<ChatMessage> messages);...
这两个版本的 generate
方法接受一个或多个 ChatMessage
作为输入。ChatMessage
是一个基础接口,代表一条聊天消息。
ChatMessage
的类型
ChatLanguageModel
的 generate
方法接受一个或多个 ChatMessage
作为输入。ChatMessage
是聊天消息的基本结构,目前有四种类型:
UserMessage
:- 表示用户的消息。用户可以是应用程序的最终用户 (人类) 或应用程序本身。根据 LLM,
UserMessage
可以只包含文本 (String
) 或文本和/或图像 (Image
)。
- 表示用户的消息。用户可以是应用程序的最终用户 (人类) 或应用程序本身。根据 LLM,
AiMessage
:- 由 AI 生成的响应消息,通常是为了响应
UserMessage
。generate
方法返回一个AiMessage
(包装在Response
对象中),可以包含文本响应或请求执行特定工具的命令(ToolExecutionRequest
)。
- 由 AI 生成的响应消息,通常是为了响应
ToolExecutionResultMessage
:- 表示
ToolExecutionRequest
的执行结果,将在后续内容中详细介绍。
- 表示
SystemMessage
:- 由系统生成的消息。通常用于定义对话的上下文和规则。开发人员可以在此提供 AI 应该扮演的角色、回答的方式和对话的基调等说明。
- LLMs 通常更关注
SystemMessage
,因此要谨慎编写此消息内容,避免最终用户任意定义或修改。
简单场景示例:
public static void main(String[] args) {// 创建一个OpenAiChatModel实例,这是ChatLanguageModel的子类实现。// LangChain4j支持多种LLM模型,每种模型类型都有相应的实现类,这里使用的是OpenAiChatModel。ChatLanguageModel model = OpenAiChatModel.builder().apiKey("demo") // 设置OpenAI API密钥。这里使用“demo”作为演示密钥,适用于临时测试,且仅限于gpt-4o-mini模型.modelName("gpt-4o-mini") // 指定要调用的模型名称(例如,gpt-4o-mini)。.build(); // 构建模型实例。// 创建一个 UserMessage 实例,表示来自用户的消息。UserMessage message = UserMessage.from("说 'Hello World'");// 将 UserMessage 作为输入并获取响应。返回的结果是一个 Response 对象,封装了 AiMessage。Response<AiMessage> response = model.generate(message);// 打印出模型响应内容的文本部分。调用 response.content().text() 获取响应的具体文本。System.out.println(response.content().text());
}
多个 ChatMessage
s
LLMs 本质上是无状态的,也就是说,它们不会自动记住对话的历史。为了实现多轮对话,必须手动管理对话的状态,将历史对话内容一起传入,确保 LLM 可以基于上下文理解当前请求。
假设我们要实现一个简单的聊天机器人,用户和 AI 之间的多轮对话如下:
- 用户:你好,我叫 XX
- AI:你好,XX,我能帮你什么吗?
- 用户:我叫什么名字?
- AI:XX
在此例中,如果不提供对话上下文,AI 可能会错误回答用户的问题,因为它 “忘记” 了之前的对话。这时,需要通过多个 ChatMessage
实现上下文的保留,让 AI 能正确识别用户的名字。
代码示例:
public static void main(String[] args) {// 创建一个OpenAiChatModel实例,这是ChatLanguageModel的子类实现。// LangChain4j支持多种LLM模型,每种模型类型都有相应的实现类,这里使用的是OpenAiChatModel。ChatLanguageModel model = OpenAiChatModel.builder().apiKey("demo") // 设置OpenAI API密钥。这里使用“demo”作为演示密钥,适用于临时测试,且仅限于gpt-4o-mini模型.modelName("gpt-4o-mini") // 指定要调用的模型名称(例如,gpt-4o-mini)。.build(); // 构建模型实例。// 开始多轮对话UserMessage firstUserMessage = UserMessage.from("你好,我叫 浩博");AiMessage firstAiMessage = model.generate(firstUserMessage).content();System.out.println(firstAiMessage.text()); // 输出 AI 回复// 第二轮对话UserMessage secondUserMessage = UserMessage.from("我叫什么名字?");// 传入第一轮用户消息、AI 回复和第二轮用户消息,以维持对话上下文AiMessage secondAiMessage = model.generate(firstUserMessage, firstAiMessage, secondUserMessage).content();System.out.println(secondAiMessage.text()); // 输出 AI 回应
}
通过在 generate
方法中传入多条 ChatMessage
,我们让模型保持对话上下文,使其理解当前轮对话的意义。
多模态(Multimodality)
UserMessage
不仅可以包含文本,还可以包含其他类型的内容。UserMessage
包含一个 List<Content>
类型的 contents
。Content
是一个接口,具有以下几种实现:
TextContent
ImageContent
AudioContent
VideoContent
PdfFileContent
你可以查看比较表,了解哪些 LLM 提供商支持哪些模态。
以下是一个同时发送文本和图片给 LLM 的示例:
UserMessage userMessage = UserMessage.from(TextContent.from("Describe the following image"),ImageContent.from("https://example.com/cat.jpg")
);
Response<AiMessage> response = model.generate(userMessage);
文本内容(Text Content)
TextContent
是最简单的 Content
类型,表示纯文本,并包装一个单独的 String
。UserMessage.from(TextContent.from("Hello!"))
等价于 UserMessage.from("Hello!")
。
可以在 UserMessage
中提供一个或多个 TextContent
:
UserMessage userMessage = UserMessage.from(TextContent.from("Hello!"),TextContent.from("How are you?")
);
图片内容(Image Content)
根据 LLM 提供商的不同,ImageContent
可以通过远程图片的 URL 来创建(如上例所示),也可以通过 Base64 编码的二进制数据来创建:
byte[] imageBytes = readBytes("/home/me/cat.jpg");
String base64Data = Base64.getEncoder().encodeToString(imageBytes);
ImageContent imageContent = ImageContent.from(base64Data, "image/jpg");
UserMessage userMessage = UserMessage.from(imageContent);
还可以指定 DetailLevel
枚举(包括 LOW
、HIGH
、AUTO
选项)来控制模型如何处理图像。更多细节请参见文档。
音频内容(Audio Content)
AudioContent
与 ImageContent
类似,但表示的是音频内容。
视频内容(Video Content)
VideoContent
与 ImageContent
类似,但表示的是视频内容。
PDF 文件内容(PDF File Content)
PdfFileContent
与 ImageContent
类似,但表示的是 PDF 文件的二进制内容。
Kotlin 扩展
ChatLanguageModel
的 Kotlin 扩展提供了用于与语言模型进行聊天交互的异步方法,充分利用了 Kotlin 的协程功能。chatAsync
方法支持对 ChatRequest
或 ChatRequest.Builder
的配置进行非阻塞处理,并返回包含模型回复的 ChatResponse
。类似地,generateAsync
用于异步生成聊天消息的回复。
这些扩展简化了聊天请求的构建和会话的高效处理,非常适合在 Kotlin 应用中使用。需要注意的是,这些方法被标记为实验性功能,未来可能会有所变化。