今天来聊聊Spring Boot 如何集成LangChain4j,怎么搭配使用。这俩技术结合起来,能在咱们的Java程序里轻松集成大语言模型(LLMs)。这篇文章可以帮助大家快速上手,学会用LangChain4j的聊天API,还会通过几个实用的示例,让你对它们的组合有更深入的理解。

一、LangChain4j框架是什么?

LangChain4j是个超实用的开源库,专门用来在Java应用里集成大语言模型。它的灵感来源于Python界超火的LangChain框架,能让开发过程更丝滑,API用起来也更顺手。要是你想深入了解LangChain4j的各种特性和理论知识,可以去它的官方Github页面瞅瞅。下面详细讲讲LangChain4j里一些重要的API。

(一)聊天和语言模型接口

语言模型接口是LangChain4j的核心部分,通过它可以和大语言模型愉快“对话”,发送各种指令,接收模型给出的回答,还能解析这些回复。LangChain4j提供了好几种不同的接口,用来对接不同类型的大语言模型,具体如下:

  • ChatLanguageModel:这个接口对应的大语言模型有聊天功能,像ChatGPT-3.5就是这类。使用它的方法时,给它传入一条或多条聊天消息,它就能返回模型生成的AI回复消息。比如常见的GPT-4就属于这一类。
  • StreamingChatLanguageModel:同样是有聊天功能的模型接口,但它厉害的地方在于可以按“令牌”(token,简单理解就是文本的基本处理单元)逐个返回回复,这样我们就能在模型处理输入的同时,实时收到回复内容。典型的例子就是GPT-4 Stream。
  • EmbeddingModel:这类模型能把文本转化成一种叫“嵌入向量”(Embedding)的东西。这个嵌入向量在语义搜索、文本聚类和分类这些任务里可太有用了。像Ada Embedding模型就具备这个能力。
  • ImageModel:从名字就能猜到,它可以根据文本描述,利用深度学习技术生成或者编辑图片。DALL-E就是这类很有名的模型。
  • ModerationModel:负责检查文本内容,判断其中有没有有害信息,然后进行分类和过滤。Moderation模型就是干这个的。
  • ScoringModel:能按照各种标准给文本打分,比如情感倾向、语法对错、相关性高低等等。像经过SST-2数据集微调后的DistilBERT模型,就可以用来做文本评分。

(二)聊天消息类型

在LangChain4j里,聊天消息主要有下面这几种类型:

  • SystemMessage:它用来给大语言模型“定规矩”,告诉模型在这次对话里它扮演什么角色,应该怎么表现,用什么风格回答问题等等。
  • UserMessage:就是用户发的消息啦,一般包含用户用文本或者图片提出的各种问题。
  • AiMessage:这是大语言模型收到用户消息后给出的回复。回复内容可能是一段普通文本,也有可能是一个工具执行请求(ToolExecutionRequest),这个工具执行请求通常是用来调用API获取实时数据的,比如汇率、天气数据之类的。
  • ToolExecutionResultMessage:表示工具执行请求的最终结果。

(三)聊天记忆

聊天记忆(ChatMemory)用来记录聊天对话的历史内容。在任何一场对话里,为了让模型“心里有数”,我们都得把之前的聊天记录喂给它,同时还要保证这些消息的总量在模型能处理的上下文窗口范围内。ChatMemory就像是一个装聊天消息的“大箱子”,除了存储消息,它还具备消息淘汰策略和持久化存储这些实用功能。

不过要注意哦,LangChain4j目前只能保存“当前记忆”,没办法自动保存完整的对话历史,要是想留存全部历史记录,就得手动处理啦。ChatMemory接口主要有下面这两种实现方式:

  • MessageWindowChatMemory:它就像一个滑动的小窗口,只会保留最近的N条消息,那些太“老”的消息,一旦超出窗口范围就会被“挤出去”。
  • TokenWindowChatMemory:同样是滑动窗口的形式,但它是按照“令牌”数量来保留内容的,只会留存最近的N个令牌。这里有个特别的地方,它不会保存不完整的消息,哪怕一条消息里只需要去掉几个令牌,这条消息也会被整个从记忆里删掉。

二、Spring Boot配置步骤

想要在Spring Boot项目里用LangChain4j,第一步得把相关的依赖包加进项目里。这些依赖包在Maven仓库就能找到。要是你想用LangChain4j对接OpenAI的大语言模型,那就得添加langchain4j-open-ai这个依赖。

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

要是你用的是Spring Boot项目,还有个更方便的办法,就是引入启动器项目。这样一来,Spring Boot的自动配置功能就能在后台默默帮你创建好需要的Bean,直接就能用啦。比如引入下面这个langchain4j-open-ai-spring-boot-starter依赖:

<dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId> <version>0.31.0</version> </dependency> 

引入之后,Spring Boot会根据application.properties文件里配置的属性,自动创建ChatLanguageModelStreamingChatLanguageModel这两个Bean。配置的时候可以像下面这样写:

langchain4j.open-ai.chat-model.api-key=${OPENAI_API_KEY} langchain4j.open-ai.streaming-chat-model.api-key=${OPENAI_API_KEY} 

要是你想知道还有哪些可以自动配置的Bean,以及它们相关的属性,去AutoConfig.java文件里就能找到答案。Github页面上也有各种可用的启动器,大家可以按需选择。

三、初始化聊天模型

虽说Spring Boot会根据引入的依赖,提供一个默认配置好的聊天模型实现,一般情况下也够用了。但要是你想自己定制一些参数,也可以通过定义必要的属性来覆盖自动配置。比如说,想定制OpenAiChatModel这个Bean,可以在配置文件里加上下面这些属性:

langchain4j.open-ai.chat-model.api-key=${OPENAI_API_KEY} langchain4j.open-ai.chat-model.model-name=gpt-3.5-turbo langchain4j.open-ai.chat-model.temperature=0.7 langchain4j.open-ai.chat-model.log-requests = true langchain4j.open-ai.chat-model.log-responses = true 

要是你更喜欢通过代码来创建Bean,不想用配置文件,也没问题。可以用ChatModel.builder()方法来手动创建,示例代码如下:

import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import dev.langchain4j.model.openai.OpenAiChatModel; // 配置类,用于定义Spring容器中的Bean @Configuration public class LlmConfig { // 定义一个名为openAiChatModel的Bean,类型为OpenAiChatModel @Bean OpenAiChatModel openAiChatModel() { return OpenAiChatModel.builder() .apiKey(...) .modelName(...) .temperature(...) .logRequests(...) .logResponses(...) .build(); } } 

这里的...需要替换成你自己的OpenAI API密钥、模型名称等具体参数。

四、首次调用大语言模型

等需要的语言模型Bean准备好之后,就可以调用它的generate()方法,给大语言模型发送指令,然后接收模型返回的回复啦。看下面这段代码:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import dev.langchain4j.model.chat.ChatLanguageModel; // 配置类,用于定义Spring容器中的Bean @Configuration public class MainAppConfig { // 自动注入ChatLanguageModel实例 @Autowired ChatLanguageModel model; // 定义一个名为mainApplicationRunner的Bean,实现CommandLineRunner接口 @Bean(name = "mainApplicationRunner") CommandLineRunner applicationRunner() { return args -> { // 调用模型的generate方法,发送"Hello, how are you"指令,并获取回复 String responseText = model.generate("Hello, how are you"); // 打印模型的回复 System.out.println(responseText); }; } } 

运行这段代码,输出结果大概是这样:

Hello! I'm just a computer program, so I don't have feelings, but I'm here to help you with anything you need. How can I assist you today? 

要是在模型配置或者属性文件里开启了请求和响应日志记录功能,还能在应用日志里查看发送的指令和收到的回复。日志内容类似下面这样:

2024-06-02T01:29:20.040+05:30 DEBUG 17668 --- [ restartedMain] d.a.openai4j.RequestLoggingInterceptor : Request: - method: POST - url: https://api.openai.com/v1/chat/completions - headers: [Authorization: Bearer sk-pr...W9], [User-Agent: langchain4j-openai] - body: { "model": "gpt-3.5-turbo", "messages": [ { "role": "user", "content": "Hello, how are you" } ], "temperature": 0.7 } 2024-06-02T01:29:21.815+05:30 DEBUG 17668 --- [ restartedMain] d.a.openai4j.ResponseLoggingInterceptor : Response: - status code: 200 - headers: [...HIDDEN...] - body: { "id": "chatcmpl-9VPAn21JksWMomyYKZiXHf31maA4I", "object": "chat.completion", "created": 1717271961, "model": "gpt-3.5-turbo-0125", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "Hello! I'm just a computer program, so I don't have feelings, but I'm here to help you with anything you need. How can I assist you today?" }, "logprobs": null, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 12, "completion_tokens": 35, "total_tokens": 47 }, "system_fingerprint": null } 

五、发送系统消息和用户消息

学会了基本的调用之后,咱们还可以创建不同类型的消息对象,然后用generate()方法发送给大语言模型。下面这个例子里,会创建系统消息和用户消息,把这些指令发给模型,再把收到的回复打印到控制台。

import dev.langchain4j.model.chat.ChatLanguageModel; import dev.langchain4j.model.chat.Response; import dev.langchain4j.model.chat.SystemMessage; import dev.langchain4j.model.chat.UserMessage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; // 配置类,用于定义Spring容器中的Bean @Configuration public class MessageSendingConfig { // 自动注入ChatLanguageModel实例 @Autowired ChatLanguageModel chatLanguageModel; // 定义一个名为messageSendingRunner的Bean,实现CommandLineRunner接口 @Bean(name = "messageSendingRunner") CommandLineRunner messageSendingRunner() { return args -> { // 创建系统消息,告诉模型它的角色和回复要求 SystemMessage systemMessage = SystemMessage.from(""" You are a helpful AI assistant that helps people find information. Your name is Alexa Start with telling your name and quick summary of answer you are going to provide in a sentence. Next, you should reply to the user's request. Finish with thanking the user for asking question in the end. """); // 创建用户消息,这里用占位符表示实际要查询的内容 String userMessageTxt = """ Tell me about {{place}}. Write the answer briefly in form of a list. """; // 替换占位符,生成具体的用户消息 UserMessage userMessage = UserMessage.from(userMessageTxt.replace("{{place}}", "USA")); // 调用模型的generate方法,发送系统消息和用户消息,并获取回复 Response<AiMessage> response = chatLanguageModel.generate(systemMessage, userMessage); // 打印模型的回复内容 System.out.println(response.content()); }; } } 

运行上面这段代码,得到的输出可能是这样:

AiMessage { text = "Hello, I'm Alexa, and I'll provide you with a brief list about the USA. Here are some key points about the United States of America: 1. The USA is a federal republic composed of 50 states. 2. It is located in North America and is the third-largest country in the world by total area. 3. The capital city is Washington, D.C. 4. The official language is English. 5. The currency used is the United States Dollar (USD). Thank you for asking about the USA!" toolExecutionRequests = null } 

要是开启了日志记录,同样能查看这次请求和响应的详细信息:

2024-06-02T01:39:41.007+05:30 DEBUG 252 --- [ restartedMain] d.a.openai4j.RequestLoggingInterceptor : Request: //... - body: { "model": "gpt-3.5-turbo", "messages": [ { "role": "system", "content": "You are a helpful AI ...n" }, { "role": "user", "content": "Tell me about USA.nWrite the answer briefly in form of a list.n" } ], "temperature": 0.7 } 2024-06-02T01:39:43.491+05:30 DEBUG 252 --- [ restartedMain] d.a.openai4j.ResponseLoggingInterceptor : Response: - status code: 200 - headers: [...] - body: { //... "choices": [ { "index": 0, "message": { "role": "assistant", "content": "Hello, I'm Alexa, and I'll provide you with a brief list about the USA..." }, "logprobs": null, "finish_reason": "stop" } ], //... } 

六、总结

这篇文章带大家入门了LangChain4j和Spring Boot的结合使用。从LangChain4j的基础概念,像各种API接口、消息类型、聊天记忆,到Spring Boot的配置、聊天模型的初始化,再到和大语言模型的交互示例,都详细讲了一遍。还学会了利用Spring Boot的自动配置功能创建Bean,以及通过日志记录查看和大语言模型的交互过程。希望大家在实际开发中能灵活运用这些知识,打造出更有趣、更实用的AI应用!要是在学习过程中有啥问题,欢迎一起交流讨论呀!