欢迎访问我的GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
LangChain4j实战全系列链接
本篇概览
- 《前文》[https://xinchen.blog.csdn.net/article/details/155223658\]对API做了梳理,如下图,今天通过编码实战来熟悉这些API

- 由于spring-boot是工程中的常用框架,因此本次实战把spring-boot与LangChain4j集成在一起,增加项目的扩展性和实用性
- 上图中涉及的API,有一部分不会进入实战,它们是:
- LanguageMode:官方都不推荐使用了,那么我们也没必要体验了
- ToolExecutionResultMessage:和Tool有关的略为复杂,后面会有单独的一篇来实践,所以本次跳过
- CustomMessage:只有ollama支持,所以本次跳过
- ImageContent:涉及到文件处理和模型选择,会有单独一篇来讲解
- AudioContent、VideoContent、PdfContent:这些都和ImageContent类似,因此就略过了
- 现在开始编码吧
源码下载(觉得作者啰嗦的,直接在这里下载)
- 如果您只想快速浏览完整源码,可以在GitHub下载代码直接运行,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):
| 名称 | 链接 | 备注 |
|---|---|---|
| 项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
| git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
- 这个git项目中有多个文件夹,本篇的源码在langchain4j-tutorials文件夹下,如下图红色箭头所示:

开发:创建子工程
- 《准备工作》(https://xinchen.blog.csdn.net/article/details/155104992)一文中创建好了整个实战系列的父工程langchain4j-totorials,所以今天的实战就在此父工程下创建子工程即可,名为demo-with-spring-boot
- 父工程下新增文件夹demo-with-spring-boot,里面增加pom.xml文件,内容如下,可见主要是spring-boot和langchain4j部分的依赖:
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>langchain4j-totorials</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>demo-with-spring-boot</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- JUnit Jupiter Engine -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<!-- Mockito Core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!-- Mockito JUnit Jupiter -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<!-- LangChain4j Core -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
</dependency>
<!-- LangChain4j OpenAI支持(用于通义千问的OpenAI兼容接口) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai</artifactId>
</dependency>
<!-- 官方 langchain4j(包含 AiServices 等服务类) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
</dependency>
<!-- 日志依赖由Spring Boot Starter自动管理,无需单独声明 -->
</dependencies>
<build>
<plugins>
<!-- Spring Boot Maven Plugin -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.3.5</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
开发:配置文件
- 新建目录langchain4j-totorials/demo-with-spring-boot/src/main/resources,在里面新增文件application.properties,内容如下,重点是和模型有关的参数,请把your-api-key改成你自己的大模型API Key
properties
# Spring Boot 应用配置
server.port=8080
server.servlet.context-path=/
# LangChain4j 使用OpenAI兼容模式配置通义千问模型
# 注意:请将your-api-key替换为您实际的通义千问API密钥
langchain4j.open-ai.chat-model.api-key=your-api-key
# 通义千问模型名称
langchain4j.open-ai.chat-model.model-name=qwen3-max
# 阿里云百炼OpenAI兼容接口地址
langchain4j.open-ai.chat-model.base-url=https://dashscope.aliyuncs.com/compatible-mode/v1
# 日志配置
logging.level.root=INFO
logging.level.com.bolingcavalry=DEBUG
logging.pattern.console=%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
# 应用名称
spring.application.name=demo-with-spring-boot
编码:启动类
- 首先有springboot的application类,平平无奇
java
package com.bolingcavalry;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot应用程序的主类
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
编码:高级LLM API的功能定义
- 本篇要体验高级LLM API,如下图红框所示

- 需要通过接口来定义这个高级LLM API能做什么,这里打算提供三种能力:
- 最简单的对话,传入字符串返回字符串,方法名为simpleChat
- 使用模板,就是定义好模板,然后用外部变量来替代模板中的占位符,方法名为temlateChat
- 设置系统消息,就是设定大模型的身份角色等,方法名为temlateChatWithSysMsg
- 上述三种能力都集中在名为Assistant的接口中,如下所示,可见这些能力由一些注解来辅助实现
java
package com.bolingcavalry.service;
import dev.langchain4j.service.*;
public interface Assistant {
/**
* 最简单的对话,只返回助手的回答,不包含任何额外信息
*
* @param userMessage 用户消息
* @return 助手生成的回答
*/
String simpleChat(String userMessage);
/**
* 使用模板进行对话,返回助手的回答
*
* @param name 模板中的变量
* @return 助手生成的回答
*/
@UserMessage("简单介绍一下{{name}}")
String temlateChat(@V("name") String name);
@SystemMessage("你的回答不会超过一百汉字")
@UserMessage("简单介绍一下{{name}}")
String temlateChatWithSysMsg(@V("name") String name);
}
- 高级LLM API的好处就是我们只要做好上述定义,具体实现交给LangChain4j来负责,也就是截图中的AiServices.create
编码:配置类
- 接下来是配置类,这样就可以通过配置文件来创建模型服务类的实例了
java
package com.bolingcavalry.config;
import dev.langchain4j.model.openai.OpenAiChatModel;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import dev.langchain4j.service.AiServices;
import com.bolingcavalry.service.Assistant;
/**
* LangChain4j配置类
*/
@Configuration
public class LangChain4jConfig {
@Value("${langchain4j.open-ai.chat-model.api-key}")
private String apiKey;
@Value("${langchain4j.open-ai.chat-model.model-name:qwen-turbo}")
private String modelName;
@Value("${langchain4j.open-ai.chat-model.base-url}")
private String baseUrl;
/**
* 创建并配置OpenAiChatModel实例(使用通义千问的OpenAI兼容接口)
* @return OpenAiChatModel实例
*/
@Bean
public OpenAiChatModel openAiChatModel() {
return OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(modelName)
.baseUrl(baseUrl)
.build();
}
@Bean
public Assistant assistant(OpenAiChatModel chatModel) {
return AiServices.create(Assistant.class, chatModel);
}
}
- 上述代码中的assistant方法值得注意,这里创建了高级LLM API实例bean,就是下图红框中那个,可以看到只要把Assistant.class作为入参,LangChain4j就能创建具有对应能力的bean

- 也就是说应用会通过LangChain4jConfig类创建两个实例:openAiChatModel负责低级LLM API,assistant负责高级LLM API
编码:服务类
- 前面如果依赖注入创建了openAiChatModel和assistant,接下来就创建服务类QwenService,作用是使用openAiChatModel和assistant完成业务功能
- 完整的代码如下,稍后会详细说明里面的重点
java
package com.bolingcavalry.service;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.openai.OpenAiChatModel;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import dev.langchain4j.data.message.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 通义千问服务类,用于与通义千问模型进行交互
*/
@Service
public class QwenService {
private static final Logger logger = LoggerFactory.getLogger(QwenService.class);
// 注入OpenAiChatModel,用于与通义千问进行交互
private final OpenAiChatModel openAiChatModel;
/**
* 构造函数,通过依赖注入获取OpenAiChatModel实例
*
* @param openAiChatModel OpenAiChatModel实例
*/
@Autowired
public QwenService(OpenAiChatModel openAiChatModel) {
this.openAiChatModel = openAiChatModel;
}
/**
* 调用通义千问模型进行对话
*
* @param message 用户消息
* @return AI回复
*/
public String chat(String message) {
return openAiChatModel.chat(message);
}
/**
* 获取AI模型的响应(用于接口调用)
*
* @param prompt 用户提示词
* @return AI生成的回答
*/
public String getResponse(String prompt) {
return openAiChatModel.chat(prompt);
}
@Autowired
private Assistant assistant;
/**
* 调用AiService进行最简单的对话
*
* @param prompt 用户提示词
* @return 助手生成的回答
*/
public String aiServiceSimpleChat(String prompt) {
return assistant.simpleChat(prompt) + "[from aiservice simpleChat]";
}
/**
* 调用AiService进行模板对话
*
* @param name 模板中的变量
* @return 助手生成的回答
*/
public String aiServiceTemplateChat(String name) {
return assistant.temlateChat(name) + "[from aiservice templateChat]";
}
/**
* 调用AiService进行模板对话,包含系统消息
*
* @param name 模板中的变量
* @return 助手生成的回答
*/
public String aiServiceTemplateChatWithSysMsg(String name) {
return assistant.temlateChatWithSysMsg(name) + "[from aiservice templateChatWithSysMsg]";
}
/**
* 模拟多轮对话
*
* @param prompt 模板中的变量
* @return 助手生成的回答
*/
public String simulateMultiRoundChat(String prompt) {
List<ChatMessage> history = List.of(
SystemMessage.from("你是历史学者,回答问题是简洁风格"),
UserMessage.from("介绍曹操是谁"),
AiMessage.from("曹操(155-220年),东汉末年杰出政治家、军事家、文学家,魏国奠基者。他统一北方,推行屯田,唯才是举,善用兵法,亦为建安文学代表人物,著有《观沧海》等诗作。"),
UserMessage.from(prompt));
AiMessage reply = openAiChatModel.chat(history).aiMessage();
return reply.text() + "[from simulateMultiRoundChat]";
}
public String useChatRequest(String prompt) {
List<ChatMessage> messages = List.of(
SystemMessage.from("你是Java程序员,回答问题是简洁风格"),
UserMessage.from(prompt));
ChatRequest request = ChatRequest.builder()
.messages(messages)
.temperature(0.7)
.maxOutputTokens(100)
.build();
return openAiChatModel.chat(request).aiMessage().text() + "[from useChatRequest]";
}
}
- 上述代码有下面七处要注意的重点:
- openAiChatModel和assistant都被依赖注入进来,可以直接使用
- getResponse方法,其实就是最简单的一问一答
- aiServiceSimpleChat方法,演示了AiService的基本用法,assistant是LangChain4j根据我们定义的Assistant接口创建的实例,内部实现会调用openAiChatModel
- aiServiceTemplateChat方法,演示了AiService的模板用法,会拿着入参去填充模板中的占位符,以此作为传入大模型的提示词
- aiServiceTemplateChatWithSysMsg方法,演示了AiService的系统提示词能力,该能力通过SystemMessage注解就实现了
- simulateMultiRoundChat方法,这里演示了如何手动实现多轮对话,举个例子,你问AI:他的主要对手有哪些?,这时候AI一定不知道你说的那个他是谁,但如果之前你和AI聊过曹操的话题,并且把之前的聊天记录在本次对话时都带上,那么AI就知道你说的那个他是曹操,所以simulateMultiRoundChat方法就模拟了第二次对话时带上第一次对话信息的场景
- useChatRequest方法,演示了如何使用ChatRequest作为入参
- 以上就是服务类的全部代码,可以看到其实非常简单,只需调用模型对象或者AiService对象的方法,看来LangChain4j确实在帮我们简化LLM应用开发
- 好了,现在服务类已备好,接下来再开发一个controller类接收http请求,这样就能通过http接口调用来使用服务类提供的能力了
编码:controller类
- controller类也很简单:定义好path,然后在响应方法中调用前面服务类的方法即可
java
/*
* @Author: 程序员欣宸 zq2599@gmail.com
* @Date: 2025-11-28 09:41:52
* @LastEditors: 程序员欣宸 zq2599@gmail.com
* @LastEditTime: 2025-11-28 11:37:52
* @FilePath: /langchain4j-totorials/demo-with-spring-boot/src/main/java/com/bolingcavalry/controller/QwenController.java
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
package com.bolingcavalry.controller;
import com.bolingcavalry.service.QwenService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 通义千问控制器,处理与大模型交互的HTTP请求
*/
@RestController
@RequestMapping("/api/qwen")
public class QwenController {
private final QwenService qwenService;
/**
* 构造函数,通过依赖注入获取QwenService实例
*
* @param qwenService QwenService实例
*/
@Autowired
public QwenController(QwenService qwenService) {
this.qwenService = qwenService;
}
/**
* 提示词请求实体类
*/
@Data
static class PromptRequest {
private String prompt;
}
/**
* 响应实体类
*/
@Data
static class Response {
private String result;
public Response(String result) {
this.result = result;
}
}
/**
* 检查请求体是否有效
*
* @param request 包含提示词的请求体
* @return 如果有效则返回null,否则返回包含错误信息的ResponseEntity
*/
private ResponseEntity<Response> check(PromptRequest request) {
if (request == null || request.getPrompt() == null || request.getPrompt().trim().isEmpty()) {
return ResponseEntity.badRequest().body(new Response("提示词不能为空"));
}
return null;
}
/**
* 处理POST请求,接收提示词并返回模型响应
*
* @param request 包含提示词的请求体
* @return 包含模型响应的ResponseEntity
*/
@PostMapping("/chat")
public ResponseEntity<Response> chat(@RequestBody PromptRequest request) {
// 检查请求体是否有效
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.getResponse(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
@PostMapping("/aiservicesimplechat")
public ResponseEntity<Response> aiServiceSimpleChat(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.aiServiceSimpleChat(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
@PostMapping("/aiservicetemplatechat")
public ResponseEntity<Response> aiServiceTemplateChat(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.aiServiceTemplateChat(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
@PostMapping("/aiservicetemplatechatwithsysmsg")
public ResponseEntity<Response> aiServiceTemplateChatWithSysMsg(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.aiServiceTemplateChatWithSysMsg(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
@PostMapping("/simulatemultiroundchat")
public ResponseEntity<Response> simulateMultiRoundChat(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.simulateMultiRoundChat(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
@PostMapping("/usechatrequest")
public ResponseEntity<Response> useChatRequest(@RequestBody PromptRequest request) {
ResponseEntity<Response> checkRlt = check(request);
if (checkRlt != null) {
return checkRlt;
}
try {
// 调用QwenService获取模型响应
String response = qwenService.useChatRequest(request.getPrompt());
return ResponseEntity.ok(new Response(response));
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body(new Response("请求处理失败: " + e.getMessage()));
}
}
}
- 至此,代码已写完,我们运行起来
体验:启动服务
- 这是个spring-boot应用,因此我用了下面的mvn命令来启动
bash
# 进入本篇创建的demo-with-spring-boot子工程内
cd langchain4j-totorials/demo-with-spring-boot
# 这是启动spring-boot应用的命令
mvn spring-boot:run
- 启动成功的输出效果如下

体验:准备http工具
- 接下来要做的就是发http请求了,由于个人喜好的关系,大家的http工具各不相同,我这里使用的是vscode的REST Client插件,主要是为了好管理历史请求数据
- 装好REST Client插件后,再创建个XXX.http的脚本文件,就能在vscode上发送请求了,我的test-api.http内容如下
bash
# 测试 Qwen API 接口
### GET 请求测试
GET http://localhost:8080/api/qwen
Accept: application/json
### POST 请求测试 (如果接口支持POST)
POST http://localhost:8080/api/qwen/chat
Content-Type: application/json
Accept: application/json
{
"prompt": "你好,请介绍一下自己,包括详细的版本信息以及当前的年月日时分秒"
}
### POST 请求测试 (如果接口支持POST)
POST http://localhost:8080/api/qwen/aiservicesimplechat
Content-Type: application/json
Accept: application/json
{
"prompt": "他打败过哪些对手?"
}
### 测试带参数的 GET 请求
GET http://localhost:8080/api/qwen?query=你好世界
Accept: application/json
### POST 请求测试 (如果接口支持POST)
POST http://localhost:8080/api/qwen/aiservicetemplatechat
Content-Type: application/json
Accept: application/json
{
"prompt": "三国演义"
}
### POST 使用系统消息的模板对话
POST http://localhost:8080/api/qwen/aiservicetemplatechatwithsysmsg
Content-Type: application/json
Accept: application/json
{
"prompt": "三国演义"
}
### POST 模拟多轮对话
POST http://localhost:8080/api/qwen/simulatemultiroundchat
Content-Type: application/json
Accept: application/json
{
"prompt": "他打败过哪些对手?"
}
### POST 使用 ChatRequest 作为入参
POST http://localhost:8080/api/qwen/usechatrequest
Content-Type: application/json
Accept: application/json
{
"prompt": "Java最新版本有哪些特性?"
}
- 如下图所示,只要在vscode打开上述文件,再用鼠标点击下图黄框位置,就能发送请求

- 收到http响应后,会自动弹出新的TAB页展示响应详情,如下图

体验:低级LLM API,最简单的问答
-
先体验一下最简单的问答,对应下图红框的知识点

-
请求信息
bash
POST http://localhost:8080/api/qwen/chat
Content-Type: application/json
Accept: application/json
{
"prompt": "简单介绍曹操是谁?"
}
- 没问题,收到来自大模型的回答
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 00:51:08 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年著名的政治家、军事家、文学家和诗人,沛国谯县(今安徽亳州)人。他是三国时期曹魏政权的奠基者,虽未称帝,但其子曹丕建立魏国后追尊他为魏武帝。\n\n在东汉末年天下大乱、群雄割据的背景下,曹操以"挟天子以令诸侯"的策略,迎汉献帝至许都,掌握朝廷实权。他统一了中国北方,击败袁绍、吕布、袁术等割据势力,并推行屯田制、唯才是举等政策,恢复社会秩序与经济生产。\n\n曹操也是一位杰出的文学家,是"建安文学"的代表人物之一,其诗作如《观沧海》《短歌行》等气势雄浑,情感深沉,对后世影响深远。\n\n历史上对曹操的评价复杂多元:传统史书(如《三国志》《后汉书》)多肯定其才能与功绩;而小说《三国演义》则将其塑造成"奸雄"形象,强调其权谋与多疑。现代史学界普遍认为他是乱世中的杰出人物,兼具雄才大略与复杂性格。"
}
- 上面的问题问了曹操的情况,如果我们打算像平时对话一样接着聊曹操,大模型会不会和我们继续聊呢?咋们再请求一次试试,如下所示,继续问他有哪些主要对手?
bash
POST http://localhost:8080/api/qwen/chat
Content-Type: application/json
Accept: application/json
{
"prompt": "他有哪些主要对手?"
}
- 得到回复如下,可见大模型完全不知道所谓的他是谁,也就是说回答问题是完全不知道前面的对话信息
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 07:23:35 GMT
Connection: close
{
"result": "您的问题中没有明确指出"他"具体指代哪位人物。为了提供准确的回答,请您补充说明所指的人物姓名或相关背景(例如:历史人物、政治人物、企业家、运动员等)。这样我才能更好地为您解答。"
}
- 有两种方法解决这个问题:
- 自己动手,把前面的聊天记录也发给大模型,让它知道之前发生了什么,稍后我们就会体验到
- 借助LangChain4J的记忆功能,这个后面会有单独的一篇来学习
体验:低级LLM API,自己动手实现多轮问答
- 这里会体验QwenService的simulateMultiRoundChat方法,在聊天时把前面问答的内容也带上,以此来实现多轮问答的效果
- 下面是聊天内容,可见这里没有提到他是谁,而在QwenService的simulateMultiRoundChat方法中,实际上已经给出了前面的聊天内容,即关于曹操的问答
bash
### POST 模拟多轮对话
POST http://localhost:8080/api/qwen/simulatemultiroundchat
Content-Type: application/json
Accept: application/json
{
"prompt": "他有哪些主要对手?"
}
- 响应如下,可见只要带上了之前的问答信息,大模型就能理解你说的他是谁
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 07:45:20 GMT
Connection: close
{
"result": "曹操主要对手包括: \n1. **袁绍**------北方强敌,官渡之战被曹操击败。 \n2. **刘备**------汉室宗亲,后建蜀汉,长期与曹魏对峙。 \n3. **孙权**------据江东,联刘抗曹,赤壁之战大败曹操。 \n4. **马超、韩遂**------关中割据势力,被曹操平定。 \n5. **吕布**------勇将,曾占徐州,后被曹操擒杀。[from simulateMultiRoundChat]"
}
体验:高级LLM API,最简单的问答
- 接下来要连续体验AiService的能力,如下图红框,看看LangChain4j帮我们把开发简化到什么程度

- 先体验最简单的问答,就是Assistant接口的simpleChat方法,如下图黄框

- 接下来发送http请求:
bash
### POST 请求测试 (如果接口支持POST)
POST http://localhost:8080/api/qwen/aiservicesimplechat
Content-Type: application/json
Accept: application/json
{
"prompt": "简单介绍曹操是谁?"
}
- 这是收到的响应
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 03:41:48 GMT
Connection: close
{
"result": "曹操(155年-220年),字孟德,东汉末年著名的政治家、军事家、文学家和诗人,沛国谯县(今安徽亳州)人。他是三国时期曹魏政权的奠基者。\n\n在东汉末年天下大乱、群雄割据的背景下,曹操通过征战逐步统一了中国北方,挟天子以令诸侯,迎汉献帝至许昌,掌握朝廷实权。他推行屯田制、唯才是举等政策,恢复经济、稳定社会,为后来曹魏的建立打下基础。\n\n曹操也是一位杰出的文学家,擅长诗歌,其作品如《观沧海》《短歌行》等气势雄浑,开创建安文学之风,与儿子曹丕、曹植并称"三曹"。\n\n虽然传统戏曲和小说(如《三国演义》)常将他描绘为"奸雄",但历史上曹操兼具雄才大略与复杂性格,是中国历史上极具影响力的人物之一。他去世后,其子曹丕称帝,追尊他为魏武帝。[from aiservice simpleChat]"
}
- 可见使用了AiService后,不用显式调用大模型服务,只需要设计一个接口也能实现同样效果
体验:高级LLM API,使用模板
- 使用模板来格式化对话内容,请求如下,请求参数会被放入模板中,生成一个新的内容再发给大模型
bash
### POST 请求测试 (如果接口支持POST)
POST http://localhost:8080/api/qwen/aiservicetemplatechat
Content-Type: application/json
Accept: application/json
{
"prompt": "三国演义"
}
- 响应如下
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 08:54:10 GMT
Connection: close
{
"result": "《三国演义》全名《三国志通俗演义》,是中国古代四大名著之一,由元末明初小说家罗贯中根据陈寿的正史《三国志》以及民间传说、戏曲等资料创作而成。它是一部历史演义小说,以东汉末年到西晋初年约百年间的历史为背景,描写了魏、蜀、吴三个政治集团之间的政治斗争和军事冲突。\n\n小说以"桃园三结义"开篇,讲述了刘备、关羽、张飞结为兄弟,共图大业的故事;随后围绕曹操、刘备、孙权三大势力展开,重点刻画了诸如诸葛亮、周瑜、吕布、赵云、司马懿等众多性格鲜明的历史人物。书中融合了真实历史与艺术虚构,情节跌宕起伏,语言生动,充满谋略、忠义、智谋与悲壮色彩。\n\n《三国演义》不仅具有很高的文学价值,也深刻影响了中国人的价值观和文化心理,其中"忠义仁勇""运筹帷幄""天下大势,分久必合,合久必分"等思想广为流传。著名情节如"草船借箭""赤壁之战""空城计""三顾茅庐"等,至今仍被广泛传颂和改编。[from aiservice templateChat]"
}
体验:高级LLM API,设置系统消息
- 再来体验设置系统消息的AiService,用注解SystemMessage来实现

- 请求如下
bash
### POST 使用系统消息的模板对话
POST http://localhost:8080/api/qwen/aiservicetemplatechatwithsysmsg
Content-Type: application/json
Accept: application/json
{
"prompt": "三国演义"
}
- 响应如下,与前面的/api/qwen/aiservicetemplatechat相比,同样的问题,这次的回答更加简洁,可见系统消息已经生效
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 09:06:50 GMT
Connection: close
{
"result": "《三国演义》是罗贯中所著历史小说,描写了东汉末年魏、蜀、吴三国争霸的故事,以忠义智谋为核心,塑造了诸葛亮、关羽、曹操等经典人物形象。[from aiservice templateChatWithSysMsg]"
}
体验:低级LLM API,用ChatRequest作为入参
- 最后是ChatRequest作为入参的体验,与ChatMesage相比,可以在ChatRequest中加入各种设置,这里设置了系统消息
bash
### POST 使用 ChatRequest 作为入参
POST http://localhost:8080/api/qwen/usechatrequest
Content-Type: application/json
Accept: application/json
{
"prompt": "Java最新版本有哪些特性?"
}
- 响应如下
bash
HTTP/1.1 200 OK
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 02 Dec 2025 09:11:21 GMT
Connection: close
{
"result": "截至 Java 21(2023年9月发布,当前最新 LTS 版本),主要新特性包括:\n\n1. **虚拟线程(Virtual Threads)**(JEP 446) \n 轻量级线程,简化高并发编程,替代传统平台线程。\n\n2. **模式匹配 for switch**(JEP 441) \n 支持在 `switch` 中使用类型、null 和守卫[from useChatRequest]"
}
- 至此,聊天API的实战体验就全部完成了,相信您已经熟悉了基本使用方法,接下来还会继续探索LangChain4j的更多能力,把咱们得大模型应用构造得更加强大