没有理想的人不伤心

LangChain4j 框架

2025/09/05
2
0

image.png

1 介绍

LangChain4j 是一个专为 Java 开发者设计的框架,其目的在于简化构建与大型语言模型(LLMs)相关的应用程序。它为开发者提供了一系列工具和抽象概念,借助这些,开发者能够迅速打造出由 LLM 驱动的复杂应用,像聊天机器人、智能助手以及文档分析工具等。

核心功能:

  1. 与多种 LLM 轻松集成:LangChain4j 支持众多主流的 LLM 服务,包括 OpenAI、Hugging Face、Cohere 等。这使得开发者可以根据自身需求灵活选择合适的模型,而无需为每种模型单独编写复杂的集成代码。
  2. 检索增强生成(RAG):该框架提供了强大的文档处理能力,能够对文档进行加载、分割、嵌入和存储操作。通过检索增强生成技术,当需要回答用户问题时,系统可以从文档中检索相关信息,为生成的回答提供更丰富、准确的依据。
  3. 工具调用机制:LangChain4j 允许将外部工具(如计算器、天气 API 等)与 LLM 集成。当 LLM 在处理用户问题时,若判断需要借助外部工具来获取更准确的信息,就可以自动调用这些工具,并将工具返回的结果融入到最终的回答中。
  4. Agent 能力:它支持构建能够自主决策和行动的 Agent。这些 Agent 可以根据用户的需求,在多个工具之间进行协调和调度,以完成复杂的任务。
  5. 内存管理:框架提供了会话内存功能,能够记录和管理对话的历史信息。这使得对话具有连贯性,让用户在与智能助手交互时感觉更加自然和流畅。

工作流程:

  1. 文档预处理:系统会输入的文档进行加载,将其分割成便于处理的小块,然后为这些小块生成嵌入向量,最后将这些向量存储到向量数据库中,以便后续快速检索
  2. 用户问题处理:当用户提出问题后,系统会对问题进行分析,并生成问题的嵌入向量
  3. 检索:系统会根据问题的嵌入向量,在向量数据库中检索出与问题最相关的文档片段。
  4. 工具调用:如果问题需要借助外部工具来解决,LLM 会做出判断并调用相应的工具获取结果。
  5. 回答生成:LLM 会结合检索到的文档片段和工具调用的结果,生成最终的回答并呈现给用户。

2 langchain 基础使用

2.1 Maven 依赖导入

在 pom.xml 中导入指定大模型对应的依赖
如 openAI

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>1.0.0-beta3</version>
</dependency>

所有支持的大模型:https://docs.langchain4j.info/integrations/language-models/

这里我们使用国内的阿里的大模型 DataScope(通义千问)

<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
    <version>${latest version here}</version>
</dependency>

2.2 ChatLanguageModel

2.2.1 介绍

大模型目前有两种 API 的形式:

  • LanguageMode:接受 String 作为输入,并返回 String 输出,非常简单,已经被淘汰
  • ChatLanguageModel:可以接受多个 ChatMessage 作为输入,并返回单个 AiMessage 作为输出,某些大模型也支持多模态

ChatLanguageModel 是 LangChain 中较底层的 API(没什么封装,但是最灵活,随你怎么封装)

AI Services 更为高级

除了 ChatLanguageModel 和 LanguageModel 外,LangChain4j 还支持以下类型的模型:

  • EmbeddingModel - 这种模型可以将文本转换为 Embedding
  • ImageModel - 这种模型可以生成和编辑 Image
  • ModerationModel - 这种模型可以检查文本是否包含有害内容。
  • ScoringModel - 这种模型可以对查询的多个文本片段进行评分(或排名), 本质上确定每个文本片段与查询的相关性,这对 RAG 很有用

2.2.2 ChatLanguageModel 接口

public interface ChatLanguageModel {
	//接受 string 输入,返回 string 输出
	String chat(String userMessage) 

	//接口一个或多个 ChatMessage 作为输入,并以 ChatResponse 作为输出
	ChatResponse chat(ChatMessage... messages);  
	ChatResponse chat(List<ChatMessage> messages);

	//自定义请求作为输入
	ChatResponse chat(ChatRequest chatrequest)
}

2.2.3 ChatMessage 接口的实现

ChatMessage 接口内置五种实现类型:

  1. SystemMessage:这是来自系统的消息。 通常,您作为开发人员应该定义此消息的内容。 通常,您会在这里写入关于 LLM 角色是什么、它应该如何行为、以什么风格回答等指令。LLM 被训练为比其他类型的消息更加关注 SystemMessage, 所以要小心,最好不要让最终用户自由定义或在 SystemMessage 中注入一些输入。 通常,它位于对话的开始。
  2. UserMessage:表示来自用户的消息。根据模型支持的格式(文本、图像、音频、视频等),用户消息可以包含单个文本(字符串)或多个内容(可以是 TextContent、ImageContent、AudioContent、VideoContent 或 PdfFileContent)。用户消息还可以包含用户的名称。请注意,并非所有模型都支持在 UserMessage 中使用名称。
  3. AiMessage:表示来自 AI(语言模型)的响应消息。该消息可以包含文本响应,也可以包含执行一个或多个工具的请求。在工具执行的情况下,此消息的响应应为一个或多个 ToolExecutionResultMessage。
  4. ToolExecutionResultMessage:表示响应 ToolExecutionRequest 的工具执行结果。ToolExecutionRequests 来自之前的 AiMessage.toolExecutionRequests()。
  5. CustomMessage:这是一个可以包含任意属性的自定义消息。这种消息类型只能由 支持它的 ChatLanguageModel 实现使用(目前只有 Ollama)。

2.2.4 示例

下面示例展示了如何与 ChatLanguageModel 进行交互:

UserMessage firstUserMessage = UserMessage.from("Hello,my name is Klaus");
AiMessage firstAiMessage = model.chat(firstUserMessage).aiMessage(); // Hi Klaus,how can I help you?
UserMessage secondUserMessage = UserMessage.from("What is my name?");
AiMessage secondAiMessage = model.chat(firstUserMessage,firstAiMessage,secondUserMessage).aiMessage(); // Klaus

2.3 ChatMemory 记忆

https://docs.langchain4j.info/tutorials/chat-memory

记忆 != 历史

  • 记忆是历史通过某种记忆算法,保留了部分历史信息,而历史是过去的完全态。
  • 这些记忆算法可以以下面方式来修改历史:淘汰一些消息,总结多条消息,总结单独的消息,从消息中删除不重要的细节, 向消息中注入额外信息(例如,用于 RAG)或指令(例如,用于结构化输出)等等

手动维护和管理 ChatMessage 是很麻烦的。 因此,LangChain4j 提供了 ChatMemory 抽象以及多种开箱即用的实现。

ChatMemory 可以作为独立的低级组件使用, 或者作为高级组件(如 AI 服务)的一部分。

ChatMemory 作为 ChatMessage 的容器(由 List 支持),具有以下额外功能:

  • 淘汰策略
  • 持久化
  • 对 SystemMessage 的特殊处理
  • 对工具消息的特殊处理

淘汰一些消息非常必要:

  1. LLM 有上下文窗口限制
  2. 每调用一次 LLM,成本会升高
  3. 减少等待时间

LangChain 提供的两种开箱即用的实现:

  • 较简单的一种,MessageWindowChatMemory,作为滑动窗口运行, 保留最近的N条消息,并淘汰不再适合的旧消息。 然而,由于每条消息可能包含不同数量的令牌, MessageWindowChatMemory主要用于快速原型设计。
  • 更复杂的选项是TokenWindowChatMemory, 它也作为滑动窗口运行,但专注于保留最近的N令牌, 根据需要淘汰旧消息。 消息是不可分割的。如果一条消息不适合,它会被完全淘汰。 TokenWindowChatMemory需要一个Tokenizer来计算每个 ChatMessage中的令牌数。

2.2 API 获取

使用阿里大模型,前往大理云百炼大模型服务平台 获取 API KEY