1. 准备工作
1.1. 构建项目,添加pom文件
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.0</version>
<relativePath/>
</parent>
<groupId>cn.cjc</groupId>
<artifactId>springboot-ai</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/dev.langchain4j/langchain4j -->
<!-- LangChain4j 核心库 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j</artifactId>
<version>1.9.1</version>
</dependency>
<!-- AiService依赖 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>1.0.1-beta6</version>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-core</artifactId>
<version>1.9.1</version>
</dependency>
<!-- LangChain4j OpenAI支持(可用于通义千问的OpenAI兼容接口) -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
<version>1.9.1-beta17</version>
</dependency>
<!-- 导入响应式编程依赖包-->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>1.9.1-beta17</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
</project>
1.2. 配置文件
yaml
spring:
application:
name: springboot-ai
main:
allow-bean-definition-overriding: true
langchain4j:
open-ai:
chat-model:
api-key: ******
model-name: qwen-plus
base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
1.3. 提示词请求类
java
@Data
public class PromptRequest {
private String prompt;
private int userId;
}
2. 高级LLM API的功能定义
-
以下三种能力都集中在名为Assistant的接口中,这些能力由一些注解来辅助实现
-
高级LLM API的好处就是只要做好接口定义,具体实现交给LangChain4j来负责,也就是AiServices.create
java
public interface Assistant {
/**
* 最简单的对话,只返回助手的回答,不包含任何额外信息
* @param userMessage 用户消息
* @return 助手生成的回答
*/
String simpleChat(String userMessage);
/**
* 使用模板进行对话,返回助手的回答
* @param name 模板中的变量
* @return 助手生成的回答
*/
@UserMessage("简单介绍一下{{name}}")
String templateChat(@V("name") String name);
/**
* 设置系统消息,就是设定大模型的身份角色,返回助手的回答
* @param name 模板中的变量
* @return 助手生成的回答
*/
@SystemMessage("你的回答不会超过一百汉字")
@UserMessage("简单介绍一下{{name}}")
String templateChatWithSysMsg(@V("name") String name);
}
3. 配置类
- 应用会通过LangChain4jConfig类创建两个实例:openAiChatModel负责低级LLM API,assistant负责高级LLM API
java
@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兼容接口)
*/
@Bean
public OpenAiChatModel openAiChatModel() {
return OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName(modelName)
.baseUrl(baseUrl)
.build();
}
@Bean
public Assistant assistant(@Qualifier("openAiChatModel") OpenAiChatModel chatModel) {
return AiServices.create(Assistant.class, chatModel);
}
}
4. 服务类
java
package cn.cjc.ai.service.impl;
import cn.cjc.ai.service.HighAssistant;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.SystemMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.chat.request.ChatRequest;
import dev.langchain4j.model.openai.OpenAiChatModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 通义千问服务类,用于与通义千问模型进行交互
*/
@Service
@Slf4j
public class QwenService {
@Autowired
private OpenAiChatModel openAiChatModel;
@Autowired
private Assistant assistant;
/**
* 获取AI模型的响应(用于接口调用)
* @param prompt 用户提示词
* @return AI生成的回答
*/
public String getResponse(String prompt) {
return openAiChatModel.chat(prompt);
}
/**
* 调用AiService进行最简单的对话
* @param prompt 用户提示词
* @return 助手生成的回答
*/
public String simpleChat(String prompt) {
return assistant.simpleChat(prompt) + "[from simpleChat]";
}
/**
* 调用AiService进行模板对话
* @param name 模板中的变量
* @return 助手生成的回答
*/
public String templateChat(String name) {
return assistant.templateChat(name) + "[from templateChat]";
}
/**
* 调用AiService进行模板对话,包含系统消息
* @param name 模板中的变量
* @return 助手生成的回答
*/
public String templateChatWithSysMsg(String name) {
return assistant.templateChatWithSysMsg(name) + "[from 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]";
}
}
5. controller
java
@RestController
@RequestMapping("/api/qwen")
public class QwenController {
@Autowired
private QwenService qwenService;
/**
* 1.仅支持一轮对话
*/
@PostMapping("/chat")
public ResponseEntity<String> chat(@RequestBody PromptRequest request) {
// 检查请求体是否有效
if (request == null || request.getPrompt() == null || request.getPrompt().trim().isEmpty()) {
return ResponseEntity.badRequest().body("提示词不能为空");
}
try {
// 调用QwenService获取模型响应
String response = qwenService.getResponse(request.getPrompt());
return ResponseEntity.ok(response);
} catch (Exception e) {
// 捕获异常并返回错误信息
return ResponseEntity.status(500).body("请求处理失败: " + e.getMessage());
}
}
/**
* 2.使用了AiService,不用显式调用大模型服务,仅支持一轮对话
*/
@PostMapping("/simpleChat")
public ResponseEntity<String> simpleChat(@RequestBody PromptRequest request) {
String response = qwenService.simpleChat(request.getPrompt());
return ResponseEntity.ok(response);
}
/**
* 3.使用了AiService,使用模板
*/
@PostMapping("/templateChat")
public ResponseEntity<String> templateChat(@RequestBody PromptRequest request) {
String response = qwenService.templateChat(request.getPrompt());
return ResponseEntity.ok(response);
}
/**
* 4.使用了AiService,设置系统消息,用注解SystemMessage来实现,相比3回答更简洁
*/
@PostMapping("/templateChatWithSysMsg")
public ResponseEntity<String> templateChatWithSysMsg(@RequestBody PromptRequest request) {
String response = qwenService.templateChatWithSysMsg(request.getPrompt());
return ResponseEntity.ok(response);
}
/**
* 5.手动实现多轮对话
* "prompt": "他有哪些主要对手?"
*/
@PostMapping("/simulatemultiroundchat")
public ResponseEntity<String> simulateMultiRoundChat(@RequestBody PromptRequest request) {
String response = qwenService.simulateMultiRoundChat(request.getPrompt());
return ResponseEntity.ok(response);
}
/**
* 6.用ChatRequest作为入参,与ChatMesage相比,可以在ChatRequest中加入各种设置
*/
@PostMapping("/usechatrequest")
public ResponseEntity<String> useChatRequest(@RequestBody PromptRequest request) {
String response = qwenService.useChatRequest(request.getPrompt());
return ResponseEntity.ok(response);
}
}