Skip to content
xiaoyang 的头像xiaoyang发布于 2025-01-144,864 字阅读约 16 分钟浏览加载中

聊天和语言模型 ​

此页面描述了低级别的 LLM API。有关高级 LLM API,请参阅 AI 服务。

所有支持的 LLM 可以在 此处找到。目前,LLM 提供两种 API 类型:

  • LanguageModel。其 API 非常简单,接受一个 String 作为输入并返回一个 String 作为输出。 这种 API 现在逐渐被聊天 API(第二种 API 类型)取代。
  • ChatLanguageModel。此类型接受多个 ChatMessage 作为输入,并返回单个 AiMessage 作为输出。 ChatMessage 通常包含文本,但某些 LLM 还支持其他模态(如图像、音频等)。 此类聊天模型的示例包括 OpenAI 的 gpt-4o-mini 和 Google 的 gemini-1.5-pro。

LangChain4j 不再扩展对 LanguageModel 的支持,因此所有新功能都将使用 ChatLanguageModel API。

ChatLanguageModel 是 LangChain4j 中与 LLM 交互的低级 API,提供了最强的功能和灵活性。 此外还有一个高级 API(AI 服务),将在我们介绍基础知识后再讨论。

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

  • EmbeddingModel - 将文本转换为 Embedding。
  • ImageModel - 生成和编辑 Image。
  • ModerationModel - 检查文本是否包含有害内容。
  • ScoringModel - 针对查询为多段文本评分(或排名),以确定每段文本与查询的相关性。 这对 RAG 很有用。 这些内容会在后续讨论。

现在,我们来深入了解 ChatLanguageModel API。

java
public interface ChatLanguageModel {

    String generate(String userMessage);
    
    ...
}

如上所示,这里有一个简单的 generate 方法,接受一个 String 作为输入并返回一个 String 作为输出,类似于 LanguageModel。 这是一个方便的方法,让您无需将 String 包装成 UserMessage 就能快速体验。

以下是实际的聊天 API:

java
    ...
    
    Response<AiMessage> generate(ChatMessage... messages);

    Response<AiMessage> generate(List<ChatMessage> messages);
        
    ...

这些版本的 generate 方法接受一个或多个 ChatMessage 作为输入。 ChatMessage 是表示聊天消息的基本接口。

ChatMessage 的类型 ​

目前有四种类型的聊天消息,每种对应消息的来源:

  • UserMessage:来自用户的消息。用户可以是应用程序的终端用户(人类)或应用程序本身。 根据 LLM 支持的模态,UserMessage 可以仅包含文本(String),也可以包含其他模态。
  • AiMessage:由 AI 生成的消息,通常是对 UserMessage 的响应。 如您所见,generate 方法返回的是一个包含 AiMessage 的 Response。 AiMessage 可以包含文本响应(String)或工具执行请求(ToolExecutionRequest)。稍后会介绍工具。
  • ToolExecutionResultMessage:ToolExecutionRequest 的结果,稍后会详细讨论。
  • SystemMessage:系统消息。 通常由开发者定义消息内容,用于描述 LLM 在对话中的角色、行为方式、回答风格等。 LLM 训练时会对 SystemMessage 赋予比其他消息更高的权重,因此应谨慎操作,最好不要让终端用户自由定义或插入 SystemMessage 的内容。 通常此类消息位于对话的开头。

了解了 ChatMessage 的所有类型后,我们来看如何在对话中组合它们。

在最简单的场景中,可以在 generate 方法中提供一个 UserMessage 实例作为输入。 这与第一版接受 String 的 generate 方法类似,但现在返回的不是 String,而是 Response<AiMessage>。 Response 是对内容(payload)的封装,您会经常在 *Model 类的返回类型中看到它。 除了内容(在此为 AiMessage)之外,Response 还包含关于生成的元信息。 首先,它包括 TokenUsage,用于统计输入(传递给 generate 方法的所有 ChatMessage)的 token 数量、输出(AiMessage)的 token 数量,以及总计(输入 + 输出)的 token 数量。 您需要此信息来计算调用 LLM 的费用。 此外,Response 还包含 FinishReason,这是一个枚举,表示生成终止的原因。 通常会是 FinishReason.STOP,表示 LLM 自行决定停止生成。

可以通过多种方式创建 UserMessage,具体取决于内容。 最简单的方式是 new UserMessage("Hi") 或 UserMessage.from("Hi")。

多个 ChatMessage ​

为什么需要提供多个 ChatMessage 作为输入,而不是仅仅一个? 原因在于 LLM 本质上是无状态的,不会维护对话状态。 因此,如果想支持多轮对话,就需要自己管理对话的状态。

假设您想构建一个聊天机器人。以下是用户与机器人(AI)的简单多轮对话:

  • 用户:你好,我叫 Klaus
  • AI:你好 Klaus,我能帮你做些什么?
  • 用户:我叫什么名字?
  • AI:Klaus

与 ChatLanguageModel 的交互如下:

java
UserMessage firstUserMessage = UserMessage.from("你好,我叫 Klaus");
AiMessage firstAiMessage = model.generate(firstUserMessage).content(); // 你好 Klaus,我能帮你做些什么?
UserMessage secondUserMessage = UserMessage.from("我叫什么名字?");
AiMessage secondAiMessage = model.generate(firstUserMessage, firstAiMessage, secondUserMessage).content(); // Klaus

如您所见,在第二次调用 generate 方法时,我们不仅提供了 secondUserMessage,还提供了对话中的先前消息。

手动维护和管理这些消息很繁琐,因此引入了 ChatMemory 的概念,我们将在下一节探讨。

多模态 ​

UserMessage 不仅可以包含文本,还可以包含其他类型的内容。 UserMessage 包含一个 List<Content> contents。 Content 是一个接口,具有以下实现:

  • TextContent
  • ImageContent
  • AudioContent
  • VideoContent
  • PdfFileContent

您可以在 此处的比较表中查看 LLM 提供商支持哪些模态。

以下是同时向 LLM 发送文本和图像的示例:

java
UserMessage userMessage = UserMessage.from(
    TextContent.from("描述以下图像"),
    ImageContent.from("https://example.com/cat.jpg")
);
Response<AiMessage> response = model.generate(userMessage);

文本内容 ​

TextContent 是最简单的 Content 实现,表示纯文本并封装单个 String。 UserMessage.from(TextContent.from("你好!")) 等价于 UserMessage.from("你好!")。

可以在 UserMessage 中提供一个或多个 TextContent:

java
UserMessage userMessage = UserMessage.from(
    TextContent.from("你好!"),
    TextContent.from("你好吗?")
);

图像内容 ​

根据 LLM 提供商的不同,可以从 远程 图像的 URL(见上例)或 Base64 编码的二进制数据创建 ImageContent:

java
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)来控制模型如何处理图像。 详见 此处。

音频内容 ​

AudioContent 与 ImageContent 类似,但表示音频内容。

视频内容 ​

VideoContent 与 ImageContent 类似,但表示视频内容。

PDF 文件内容 ​

PdfFileContent 与 ImageContent 类似,但表示 PDF 文件的二进制内容。

Kotlin 扩展 ​

ChatLanguageModel 的 Kotlin 扩展 提供了用于处理与语言模型的聊天交互的异步方法,利用 Kotlin 的 协程 功能。 chatAsync 方法允许对 ChatRequest 或 ChatRequest.Builder 配置进行非阻塞处理,并返回带有模型回复的 ChatResponse。 类似地,generateAsync 用于异步生成来自聊天消息的响应。 这些扩展简化了 Kotlin 应用程序中聊天请求的构建和高效的对话处理。 请注意,这些方法标记为实验性,可能会随着时间演变。

DISCUSSION

评论区

欢迎分享你的思考、补充或问题。

基于 VitePress 搭建