1 新建Springboot项目
1.1 引入依赖
<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>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.4.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>org.example</groupId><artifactId>langchain4jSpringbootpro</artifactId><version>1.0-SNAPSHOT</version><packaging>jar</packaging><name>langchain4jSpringbootpro</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><langchain4j.version>1.0.0-beta1</langchain4j.version></properties><dependencies><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-dashscope-spring-boot-starter</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-test</artifactId><scope>test</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-community-bom</artifactId><version>${langchain4j.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement></project>
2 配置项
查看加载的依赖中的langchain4j-community-dashscope-spring-boot-starter的Autoconfig文件。
可以看到使用时需要的配置条件,需要配置apikey。
在源文件中可以查看配置模型:
新建配置application.properties
server.port=8080langchain4j.community.dashscope.chat-model.api-key = 你的apikey
langchain4j.community.dashscope.chat-model.model-name = qwen-plus
2.3 代码实现
package org.example.controller;import dev.langchain4j.community.model.dashscope.QwenChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/ai")
public class AiController {@AutowiredQwenChatModel qwenChatModel;@RequestMapping("/chat")public String test(@RequestParam(defaultValue = "你是谁") String message){String chat = qwenChatModel.chat(message);return chat;}}
2.4 访问结果
启动后,访问链接http://localhost:8080/ai/chat。
2 接入DeepSeek
接入DeepSeek只需要修改配置文件即可,如下:
langchain4j.community.dashscope.chat-model.api-key = 你的key
langchain4j.community.dashscope.chat-model.model-name = deepseek-r1
启动后,访问链接http://localhost:8080/ai/chat。
3 接入Ollama
安装Ollama,下载想要的大模型。
引用依赖:
<dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-ollama-spring-boot-starter</artifactId><version>${langchain4j.version}</version></dependency>
加入配置文件:
langchain4j.ollama.chat-model.base-url = http://localhost:11434
langchain4j.ollama.chat-model.model-name = deepseek-r1:1.5b
代码如下:
package org.example.controller;import dev.langchain4j.community.model.dashscope.QwenChatModel;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/ai")
public class AiController {@AutowiredChatLanguageModel chatLanguageModel;@RequestMapping("/ollamachat")public String ollamachatfuc(@RequestParam(defaultValue = "你是谁") String message){String ollamachat = chatLanguageModel.chat(message);return ollamachat;}}
结果如下:
4 流式输出
之前的依赖不变,但是因为langchain4j不是spring家族,所以我们在wen应用中需要引入webflux。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
通过Flux进行流式响应
@RequestMapping(value = "/streamchat",produces = "text/stream;charset=UTF-8")public Flux<String> streamchatfuc(@RequestParam(defaultValue="你是谁") String message){Flux<String> flux = Flux.create(fluxSink -> {streamingChatModel.chat(message, new StreamingChatResponseHandler() {@Overridepublic void onPartialResponse(String partialResponse) {fluxSink.next(partialResponse);}@Overridepublic void onCompleteResponse(ChatResponse completeResponse) {fluxSink.complete();}@Overridepublic void onError(Throwable error) {fluxSink.error(error);}});});return flux;}
加入配置文件:
langchain4j.community.dashscope.streaming-chat-model.api-key = sk-4d1748fba8994a2e94cb0fbaf3d34f23
langchain4j.community.dashscope.chat-model.model-name = deepseek-r1
启动后访问链接:http://localhost:8080/ai/streamchat,会发现答复是按照流式输出的。
5 记忆对话
5.1 ChatMemory
大模型并不会把我们每次的对话存在服务端,所以他记不住我们说的话,如下代码:
@Testpublic void test_bad(){ChatLanguageModel model = OpenAiChatModel.builder().apiKey("demo").modelName("gpt-4o-mini").build();System.out.println(model.chat("你好,我是徐庶老师"));System.out.println("----");System.out.println(model.chat("我叫什么"));}
运行结果如下:
所以每次对话都需要将之前的对话记录,都发给大模型,这样才能知道我们之前说了什么:
@Testpublic void test03(){ChatLanguageModel model = OpenAiChatModel.builder().apiKey("demo").modelName("gpt-4o-mini").build();UserMessage userMessage1 = UserMessage.userMessage("你好,我是徐庶");ChatResponse response1 = model.chat(userMessage1);AiMessage aiMessage1 = response1.aiMessage();//大模型的第一次响应System.out.println(aiMessage1.text());System.out.println("----");// 下面一行代码是重点ChatResponse response2 = model.chat(userMessage1,aiMessage1, UserMessage.userMessage("我叫什么?"));AiMessage aiMessage2 = response2.aiMessage();// 大模型的第二次响应System.out.println(aiMessage2.text());System.out.println(model.chat("你好,我是徐庶老师"));System.out.println("----");System.out.println(model.chat("我叫什么"));}
返回结果如下:
但是如果要我们每次把之前的记录自己去维护,未免太麻烦,所以提供了ChatMemory但是他这个ChatMemory没有SpringAi好用、易用、十分麻烦!所以说谁在跟我说Langchain4i比SpringAi好我跟谁急!
package org.example.config;import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.service.TokenStream;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class Aiconfig {public interface Assistant{String chat(String message);// 流式响应TokenStream stream(String message);}@Beanpublic Assistant assistant(ChatLanguageModel qwenchatModel, StreamingChatLanguageModel qwenstreamingchatModel) {//设置最大记录对话数ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);Assistant assistant = AiServices.builder(Assistant.class).chatLanguageModel(qwenchatModel).streamingChatLanguageModel(qwenstreamingchatModel).chatMemory(chatMemory).build();return assistant;}
}
原理:
- 通过AiService创建的代理对象(Aiservices.builder(XushuChatModel.class))调用chat方法(XushuChatModel.chat)
- 代理对象会去ChatMemory中获取之前的对话记录(获取记忆)
- 将获取到的对话记录合并到当前对话中(此时大模型根据之前的聊天记录肯定就拥有了“记忆”)
- 将当前的对话内容存入ChatMemory(保存记忆)
代码如下:
package org.example.controller;import dev.langchain4j.service.TokenStream;
import jakarta.servlet.http.HttpServletResponse;
import org.example.config.Aiconfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;import java.time.LocalDate;@RestController
@RequestMapping("/ai_other")
public class OtherAiController {@AutowiredAiconfig.Assistant assistant;//告诉模型我叫诸葛懿@RequestMapping(value = "/memory_chat")public String memorychat(@RequestParam(defaultValue = "我叫诸葛懿") String message) {return assistant.chat(message);}//流式响应@RequestMapping(value = "/memory_stream_chat",produces ="text/stream;charset=UTF-8")public Flux<String> memoryStreamChat(@RequestParam(defaultValue="我是谁") String message, HttpServletResponse response) {TokenStream stream = assistant.stream(message);return Flux.create(sink -> {stream.onPartialResponse(s -> sink.next(s)).onCompleteResponse(c -> sink.complete()).onError(sink::error).start();});}
}
先访问http://localhost:8080/ai_other/memory_chat告诉模型你的名字,后访问http://localhost:8080/ai_other/memory_stream_chat看结果,结果如下:
5.2 记忆分离
现在我们再来想另一种情况:如果不同的用户或者不同的对话肯定不能用同一个记忆,要不然对话肯定会混淆此时就需要进行区分:
可以通过memoryld进行区分
5.3 持久对话