一、项目初始化
首先,先搭建一个简单的springboot 项目,我们通过spring Initializr 初始化一个springboot 项目,jdk版本设置17,springboot 版本3.4.4,引入依赖如下:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
定义一个AiController,
java
@RestController
@RequestMapping("/ai")
public class AiController {
@GetMapping("/chat")
public String chat() {
return "Hello World";
}
}
启动,访问http://127.0.0.1:8080/ai/chat
页面输出:
项目初始化结束。
二、引入langchain4j依赖
因为使用的是阿里的百炼平台,这边直接引入百炼的依赖,其他大模型类似。
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
<version>1.0.0-beta2</version>
</dependency>
三、langchain4j基本测试
1、文本输出
直接开始测试调用,选择deepseek-r1模型
java
@Test
void test_deepseek_chat() {
QwenChatModel chatModel = QwenChatModel.builder()
.apiKey(System.getenv("ALI_AI_KEY"))
.modelName("deepseek-r1")
.build();
System.out.println(chatModel.chat("你是谁?"));
}
返回
2、文本流式输出
java
@Test
void test_deepseek_stream_chat() throws InterruptedException {
QwenStreamingChatModel chatModel = QwenStreamingChatModel.builder()
.apiKey(System.getenv("ALI_AI_KEY"))
.modelName("deepseek-r1")
.build();
CountDownLatch countDownLatch = new CountDownLatch(1);
chatModel.chat("你是谁?", new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String s) {
System.out.println(s);
}
@Override
public void onCompleteResponse(ChatResponse chatResponse) {
System.out.println("完成。。。");
countDownLatch.countDown();
}
@Override
public void onError(Throwable throwable) {
System.out.println("出错了。。。");
}
});
countDownLatch.await();
}
返回
可以看到数据是流式输出的。
3、图片生成
使用万相大模型
java
@Test
void test_image_generate(){
WanxImageModel imageModel = WanxImageModel.builder()
.apiKey(System.getenv("ALI_AI_KEY"))
.modelName("wanx2.1-t2i-turbo")
.build();
Response<Image> generate = imageModel.generate("给我生成一张猫的图片");
System.out.println(generate.content().url());
}
输出如下:
生成的图片
还不错。。。
4、图片理解
java
@Test
void test_image_recognize(){
QwenChatModel chatModel = QwenChatModel.builder()
.apiKey(System.getenv("ALI_AI_KEY"))
.modelName("qwen2.5-vl-32b-instruct")
.build();
UserMessage userMessage = UserMessage.from(
TextContent.from("这个照片上面描述了什么?"),
ImageContent.from("https://dashscope-result-wlcb-acdr-1.oss-cn-wulanchabu-acdr-1.aliyuncs.com/1d/76/20250325/b0fe3396/c09ada40-37f1-4748-9d32-82a373c79534151007983.png?Expires=1742978890&OSSAccessKeyId=LTAI5tKPD3TMqf2Lna1fASuh&Signature=gOV4MUh2glEKgk2PNXJZBOEENDI%3D")
);
ChatResponse chatResponse = chatModel.chat(userMessage);
System.out.println(chatResponse.aiMessage().toString());
}
输出如下:
5、AI Services
langchain4j还有很多其他的组件,比如对话流记忆,RAG,function call(Tools)等等(这些我就不单独测试了),这些都能自由使用和组合,但在业务中使用,就会写很多类似的模板方法,langchain4j提供了更高层级的封装,就是AI Services。
需要先引入langchain4j的依赖
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-spring-boot-starter</artifactId>
<version>${langchain4j.version}</version>
</dependency>
使用如下:
定义一个AI Services接口
java
interface Assistant {
String chat(String userMessage);
}
定义Tools
java
static class Tools {
@Tool("获取用户所在的班级")
public String getUserClass(
@P("用户姓名") String userName) {
System.out.println("用户姓名是:"+userName);
return "三班";
}
}
组合AI Services
java
@Test
void test_ai_service(){
ChatLanguageModel model = QwenChatModel.builder()
.apiKey(System.getenv("ALI_AI_KEY"))
.modelName("qwen2.5-7b-instruct-1m")
.build();
Assistant assistant = AiServices.builder(Assistant.class)
.chatLanguageModel(model)
// 对话记忆
.chatMemory(new MessageWindowChatMemory.Builder()
.id("test")
.maxMessages(10)
.chatMemoryStore(new InMemoryChatMemoryStore())
.build())
// function call
.tools(new Tools())
.build();
String message = assistant.chat("你好,我叫张三,今年20岁。");
System.out.println(message);
message = assistant.chat("我是谁,我是几班的?");
System.out.println(message);
}
返回如下:
基本测试使用就这些,后面就直接配合springboot 使用。
四、springboot中使用
定义一个配置类,配置对话流历史的存储方式
java
@Configuration
public class AssistantConfig {
@Bean
public ChatMemoryProvider chatMemoryProvider(ChatMemoryStore chatMemoryStore){
return id -> new MessageWindowChatMemory.Builder()
.id(id)
.chatMemoryStore(chatMemoryStore)
.maxMessages(10)
.build();
}
@Bean
public ChatMemoryStore chatMemoryStore(){
return new InMemoryChatMemoryStore();
}
}
定义Tools,使用@Component依赖注入到spring容器中
java
@Component
public class TestTools {
@Tool("获取用户所在的班级")
public String getUserClass(
@P("用户姓名") String userName) {
System.out.println("用户姓名是:"+userName);
return "三班";
}
@Tool("获取今天的天气")
public String getWeather(
@P("地址") String address) {
System.out.println("当前地址是:"+address);
return "天气晴朗!";
}
}
定义ai services,配置相应的使用参数
java
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "qwenChatModel",
streamingChatModel = "qwenStreamingChatModel", chatMemoryProvider = "chatMemoryProvider",
tools = "testTools")
public interface AiAssistant {
String chat(@MemoryId String id, @UserMessage String message);
Flux<String> chatStream(@MemoryId String id, @UserMessage String message);
}
配置属性中配置qwen的配置
properties
langchain4j.community.dashscope.chat-model.api-key=${ALI_AI_KEY}
langchain4j.community.dashscope.chat-model.model-name=qwen2.5-7b-instruct-1m
langchain4j.community.dashscope.streaming-chat-model.api-key=${ALI_AI_KEY}
langchain4j.community.dashscope.streaming-chat-model.model-name=qwen2.5-7b-instruct-1m
Flux输出还需要引入langchain4j依赖
xml
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
<version>${langchain4j.version}</version>
</dependency>
定义web接口
java
@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
public class AiController {
private final AiAssistant aiAssistant;
@GetMapping("/chat")
public String chat(@RequestParam(value = "message", defaultValue = "Hello") String message,
@RequestParam(value = "userId", defaultValue = "111") String userId) {
return aiAssistant.chat(userId,message);
}
@GetMapping(value = "/chat-stream",produces = MediaType.TEXT_PLAIN_VALUE+";charset=utf-8")
public Flux<String> chatStream(@RequestParam(value = "message", defaultValue = "Hello") String message,
@RequestParam(value = "userId", defaultValue = "111") String userId) {
return aiAssistant.chatStream(userId,message);
}
}
页面上直接调用
历史对话&tools使用
换另一个用户,发现对话流式是新的
流式输出
over。。。