Java-LangChain4j-基本使用篇
javaSpring框架下集成langchain4j,通过ollama实现本地部署大模型,远程调用阿里云大模型并使用,讲解会话记忆
Java AI
基本概念
LLM:AI大模型
Langchain4j、SpringAI:这两个框架让我们可以通过java调用大模型相关api
RAG:检索增强生成,检索外部知识源来增强生成模型的能力
MCP:模型上下文协议,打通AI模型与外部工具、数据源的桥梁
too:可以被AI模型调用以补充功能的外部应用程序(文件系统、数据库、搜索引擎、各种API接口等)
AI发展史:
- 符号主义
- 连接主义(基于感知机模型)
- 神经网络(多层次的连接主义)
感知机模型:
- 输入
- 权重
- 偏值(阈值)
- 激活函数
- 输出
大模型部署
本地部署
使用Ollama快速本地部署大模型
步骤:
-
下载安装Ollama
到官网下载即可
安装时会自动添加Ollama的环境变量
-
去Ollama官网找到想要部署的大模型
选择大模型时需要考虑大模型类型、大小(b为十亿)
-
在cmd命令行窗口下载对应的大模型
ollama run qwen3:0.6b ollama run 版本 # 开启大模型对话就是用上面的语句,若没下载,自动下载,下载好了就开启对话 # 关闭大模型对话 /bye当然我们肯定不能在命令行窗口调用大模型,项目中要调用大模型也是通过发送http请求
当我们安装好Ollama以后,Ollama会常驻并占用11434端口
我们在调用大模型时,不需要额外启动什么,直接发http请求即可
如何请求如下
-
通过Http请求大模型
发送Post请求到 http://localhost:11434/api/chat
带上如下Json数据作为请求体
{ "model": "deepseek-r1", "messages": [ { "role": "user", "content": "how many r in the word strawberry?" } ], "think": true, "stream": false }响应结果类似如下
{"model":"deepseek-r1", "created_at":"2025-05-29T09:35:56.836222Z", "message": {"role": "assistant", "content": "The word \"strawberry\" contains **three** instances of the letter 'R' ..." "thinking": "First, the question is: \"how many r in the word strawberry?\" I need to count the number of times the letter 'r' appears in the word \"strawberry\". Let me write down the word:...", "done_reason":"stop", "done":true, "total_duration":47975065417, "load_duration":29758167, "prompt_eval_count":10, "prompt_eval_duration":174191542, "eval_count":2514, "eval_duration":47770692833 } }关于请求参数以及响应数据,后续会讲
他人部署
也就是调用别人部署好的大模型,通过网络访问
这会导致额外费用,且数据不安全,但会更加方便
调用阿里云百炼大模型基本步骤:
-
登入阿里云
-
开通大模型服务平台百炼服务
-
申请百炼平台API-KEY
-
选择模型并使用
-
根据案例通过http请求或者java方式请求大模型
curl -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \ -H "Authorization: Bearer $DASHSCOPE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "qwen-plus", "messages": [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": "你是谁?" } ] }'// 该代码 OpenAI SDK 版本为 2.6.0 import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; import com.openai.models.chat.completions.ChatCompletion; import com.openai.models.chat.completions.ChatCompletionCreateParams; public class Main { public static void main(String[] args) { OpenAIClient client = OpenAIOkHttpClient.builder() .apiKey(System.getenv("DASHSCOPE_API_KEY")) .baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1") .build(); ChatCompletionCreateParams params = ChatCompletionCreateParams.builder() .addUserMessage("你是谁") .model("qwen-plus") .build(); try { ChatCompletion chatCompletion = client.chat().completions().create(params); System.out.println(chatCompletion); } catch (Exception e) { System.err.println("Error occurred: " + e.getMessage()); e.printStackTrace(); } } }
大模型调用
讲解上面提到的请求参数以及响应数据的含义
请求参数
{
"model": "qwen-plus",
"messages": [
{
"role": "system",
"content": "你是大模型助手"
},
{
"role": "user",
"content": "你是谁?"
},
{
"role": "assistent",
"content": ""
}
],
"think": true,
"stream": false,
"enable_search": true
}
| 字段名 | 核心含义 | 具体说明 |
|---|---|---|
| model | 指定 AI 模型 | 这次请求的是名为 “qwen-plus” 的模型,这通常是阿里云开发的通义千问系列大模型的一个版本。 |
| messages | 对话历史与内容 | 这是核心部分,包含了对话中所有角色的发言,模型会根据这些内容生成回复。 |
| - role: “system” | 系统设定 | 给 AI 模型的 “身份指令”,这里设定为 “你是大模型助手”,定义了 AI 的基础角色。 |
| - role: “user” | 用户提问 | 用户发出的问题,内容是 “你是谁?”,这是模型需要回答的核心问题。 |
| - role: “assistent” | AI 回复位 | 这是留给 AI 模型填充回复内容的位置,当前为空(""),等待模型生成答案后填入。 |
| think | 是否开启思维链 | 取值为true,表示希望模型在生成最终回复前,先进行内部的逻辑推理(类似 “思考过程”),通常用于提升复杂问题回答的准确性。 |
| stream | 是否流式输出 | 取值为false,表示模型会一次性返回完整的回答;如果为true,则会像聊天一样逐字 / 逐句地实时输出内容。 |
| enable_search | 是否启用联网搜索 | 取值为true,表示允许模型在回答问题时,通过联网获取最新信息来补充回答(例如回答实时新闻、天气等问题时会用到)。 |
响应数据
{
"response_id": "unique-uuid-123456", // 唯一响应ID,用于日志追踪和请求匹配
"request_id": "request-uuid-654321", // 关联的请求ID,便于联调与问题定位
"model": "gpt-4o-mini-2024-07-18", // 实际调用的模型版本,确保可复现性
"created": 1721234567, // 响应生成时间戳(Unix时间,秒级)
"usage": { // token使用统计,用于成本核算
"prompt_tokens": 120, // 输入提示词消耗的token数
"completion_tokens": 350, // 模型生成内容消耗的token数
"total_tokens": 470 // 总消耗token数
},
"choices": [ // 生成结果列表(支持多候选返回)
{
"index": 0, // 结果序号(多候选时区分)
"message": { // 消息体(对话式场景常用)
"role": "assistant", // 角色标识(assistant表示模型回复)
"content": "这是大模型生成的具体响应内容...", // 核心文本结果
"tool_calls": null // 工具调用信息(未调用时为null)
},
"finish_reason": "stop" // 生成停止原因(stop:正常结束;length:达到token上限)
}
],
"error": null // 错误信息(成功时为null;失败时包含code和message)
}
Java 使用
Java调用大模型的工具库
- LangChain4j
- Spring AI
本文中就使用LangChain4j来实现在Java spring项目中调用大模型
使用OpenAiChatModel
基本步骤:
-
引入LangChain4j依赖
<!-- langchain4j起步依赖--> <!-- OpenAiChatModel--> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId> <version>1.0.1-beta6</version> </dependency> -
构建OpenAiChatModel对象
在非Spring框架中,我们需要手动构建该对象
在Spring框架中,通过引入langchain4j的start依赖,我们可以直接自动注入OpenAiChatModel对象
只需要在配置文件中配置即可
server: port: 8080 langchain4j: open-ai: chat-model: base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: ${API-KEY} # 自己在阿里云上的key model-name: qwen-plus -
调用OpenAiChatModel对象的chat方法与大模型交互
@RestController
public class ChatController {
@Autowired
private OpenAiChatModel model;
@RequestMapping("/chat")
public String chat(String message) {
String result = model.chat(message);
return result;
}
}
使用AiServices
但我们使用时并不直接使用OpenAiChatModel对象,而是使用AiServices
AiServices是基于OpenAiChatModel封装好的,更方便后续的使用
基本步骤:
-
引入依赖
<!-- AiServices相关依赖--> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-spring-boot-starter</artifactId> <version>1.0.1-beta6</version> </dependency> -
声明接口(chat方法)
public interface ConsultantService { //用于聊天的方法 public String chat(String message); } -
使用AiServices为接口创建代理对象
//1.通过配置类创建代理对象 @Configuration public class AiConfig { @Resource private OpenAiChatModel model; @Bean public ConsultantService consultantService() { ConsultantService service = AiServices.builder(ConsultantService.class) .chatModel(model) .build(); return service; } }//2.直接在上面的接口中使用注解 @AiService( wiringMode = AiServiceWiringMode.EXPLICIT, //手动装配 chatModel = "openAiChatModel" //这里一定要小写开头,代表bean实例 ) public interface ConsultantService { //用于聊天的方法 public String chat(String message); } //3.直接自动装配 @AiService public interface ConsultantService { //用于聊天的方法 public String chat(String message); } -
调用
@RestController public class ChatController { @Autowired private ConsultantService consultantService; @RequestMapping("/chat") public String chat(String message) { String result = consultantService.chat(message); return result; } }
打印日志
在yml配置中添加日志配置即可
server:
port: 8080
langchain4j:
open-ai:
chat-model:
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
api-key: ${API-KEY} # 自己在阿里云上的key
model-name: qwen-plus
log-requests: true
log-responses: true
logging:
level:
dev.langchain4j: DEBUG
流式调用
在前面的使用中,都是阻塞式调用
即 “stream”: false
我们也可以指定为流式调用
基本步骤:
-
引入依赖
<!-- 流式调用相关依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>dev.langchain4j</groupId> <artifactId>langchain4j-reactor</artifactId> <version>1.0.1-beta6</version> </dependency> -
配置流式模型对象
langchain4j: open-ai: chat-model: base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: ${API-KEY} # 自己在阿里云上的key model-name: qwen-plus log-requests: true log-responses: true streaming-chat-model: base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: ${API-KEY} # 自己在阿里云上的key model-name: qwen-plus log-requests: true log-responses: true -
切换接口方法的返回值类型(Flux)
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel" //配置流式模型 ) public interface ConsultantService { //改用Flux并指定泛型 public Flux<String> chat(String message); } -
修改Controller中的代码(Flux)
//需要注意修改编码 @RequestMapping(value = "/chat",produces = "text/html;charset=UTF-8") public Flux<String> chat(String message) { Flux<String> result = consultantService.chat(message); return result; }
消息注解
-
@SystemMessage
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel" ) public interface ConsultantService { //直接在这里写系统消息 @SystemMessage("你是slc的编程小助手") public Flux<String> chat(String message); //或者指向另一个文件,这里的路径就是类路径即resources下 @SystemMessage(fromResource = "text/aisystem.txt") public String chat1(String message); } -
@UserMessage
和System注解使用方式类似,但System是系统信息,User是用户发送给大模型的信息
//可用来将用户传递的数据message和默认数据(注解中定义的)拼接在一起 //默认是it,可以通过 @UserMessage("你好啊!{{it}}") public String chat1(String message); @UserMessage("你好啊!{{msg}}") public String chat1(@V("msg")String message);
会话记忆
首先需要明确三个对象:
- 用户
- 后端系统
- 大模型
在使用时,为了实现会话记忆的功能,需要:
- 用户发送请求
- 后端系统将请求中的信息保存在
会话记忆对象中 - 后端将整个
会话记忆对象交给大模型 - 大模型根据
会话记忆对象中所有的信息生成结果 - 后端将结果保存到
会话记忆对象 - 后端将结果返回给前端
通过会话记忆对象,我们将用户请求和大模型响应结果都保存起来,从而实现会话记忆功能
但会话记忆对象则会不断壮大
实现基本会话记忆
使用chatMemory
基本步骤:
-
定义会话记忆对象(chatMemory)
//在配置类中创建bean @Bean public ChatMemory chatMemory(){ MessageWindowChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(20) .build(); return memory; } -
配置会话记忆对象
//在AiServices上指定即可 @AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", //这里的三个值都是固定的 streamingChatModel = "openAiStreamingChatModel", chatMemory = "chatMemory" //配置会话记忆对象,chatMemory就是上面那个方法名 )
会话记忆隔离
上面讲解的基本会话记忆会有问题
如果不隔离,则多个用户会用同一个会话记忆对象
我们通过memoryId来实现会话记忆隔离
简单来说我们要使用ChatMemoryProvider代替前面的ChatMemory
基本步骤:
-
定义会话记忆对象提供者
//会话记忆对象提供者 @Bean public ChatMemoryProvider chatMemoryProvider(){ ChatMemoryProvider provider = new ChatMemoryProvider() { @Override public ChatMemory get(Object memoryId) { MessageWindowChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(20) .id(memoryId) .build(); return memory; } }; return provider; } -
配置会话记忆对象提供者
@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "openAiChatModel", streamingChatModel = "openAiStreamingChatModel", // chatMemory = "chatMemory" chatMemoryProvider = "chatMemoryProvider" //配置会话记忆对象提供者 ) public interface ConsultantService { //传递memoryId @SystemMessage("你是slc的小助手-小席德") public Flux<String> chat(@MemoryId String memoryId,@UserMessage String message); }
会话记忆持久化
ChatMemory底层是List来存储会话内容
每当后端重新启动,会话记忆则会丢失,因此需要实现持久化
这里采用redis
ChatMemory由ChatMemoryProvider创建,我们需要在创建ChatMemory时指定ChatMemoryStore,从而让会话记忆被保存到redis中
简而言之就是要在前面ChatMemoryProvider的基础上添加store
基本步骤:
-
定义chatMemoryStore实现类
//使用Redis实现会话记忆持久化 @Repository public class RedisChatMemoryStore implements ChatMemoryStore { @Autowired private RedisTemplate redisTemplate; @Override public List<ChatMessage> getMessages(Object memoryId) { //获取会话消息 String json = redisTemplate.opsForValue().get(memoryId.toString()); //把Json转换为List<ChatMessage> List<ChatMessage> list = ChatMessageSerializer.messagesFromJson(json); return list; } @Override public void updateMessages(Object memoryId, List<ChatMessage> list) { //更新会话消息 //把List<ChatMessage>转换为Json String json = ChatMessageSerializer.messagesToJson(list); //把Json保存到Redis中 redisTemplate.opsForValue().set(memoryId.toString(),json, Duration.ofDays(1)); } @Override public void deleteMessages(Object o) { //删除会话消息 redisTemplate.delete(o.toString()); } } -
配置chatMemoryStore
//会话记忆对象提供者 @Bean public ChatMemoryProvider chatMemoryProvider(){ ChatMemoryProvider provider = new ChatMemoryProvider() { @Override public ChatMemory get(Object memoryId) { MessageWindowChatMemory memory = MessageWindowChatMemory.builder() .maxMessages(20) .id(memoryId) .chatMemoryStore(redisChatMemoryStore) //加上store,提前自动注入 .build(); return memory; } }; return provider; }
更多推荐



所有评论(0)