AI | langchain4j - [底座项目]
依赖管理
<properties>
<spring-boot.version>3.5.14</spring-boot.version>
<langchain4j.version>1.15.1</langchain4j.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 加载bom 后,所有langchain4j引用不需要加版本号 -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-bom</artifactId>
<version>${langchain4j.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
依赖
<!-- 集成openai,如果用其他集成,需要引用 langchain4j-xxx-spring-boot-starter -->
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-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-webflux</artifactId>
</dependency>
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-reactor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
配置
流式输出 + 正常chat + 监听器
需要根据不同场景使用不同模型,比如进行生图任务时可以使用 wan2.7-image 等
@Bean
public StreamingChatModel streaming(){
return OpenAiStreamingChatModel.builder()
.apiKey("sk-xxx")
.modelName("deepseek-v4-flash")
.baseUrl("https://api.deepseek.com")
.sendThinking(false)
.returnThinking(false)
.logRequests(true)
.logResponses(true)
.timeout(Duration.ofSeconds(20))
.build();
}
@Bean
public ChatModel chat(){
return OpenAiChatModel.builder()
.apiKey("sk-xxx")
.modelName("deepseek-v4-flash")
.baseUrl("https://api.deepseek.com")
.sendThinking(false)
.returnThinking(false)
.logRequests(true)
.logResponses(true)
.timeout(Duration.ofSeconds(20))
.build();
}
@Bean
ChatModelListener chatModelListener() {
return new ChatModelListener() {
@Override
public void onRequest(ChatModelRequestContext requestContext) {
log.info("onRequest(): {}", requestContext.chatRequest());
}
@Override
public void onResponse(ChatModelResponseContext responseContext) {
log.info("onResponse(): {}", responseContext.chatResponse());
}
@Override
public void onError(ChatModelErrorContext errorContext) {
log.info("onError(): {}", errorContext.error().getMessage());
}
};
}
可以结合日志获取更多细节
langchain4j.open-ai.chat-model.log-requests = true
langchain4j.open-ai.chat-model.log-responses = true
logging.level.dev.langchain4j = DEBUG
流式输出时需要后端制定前端编码
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
spring.webflux.encoding.charset=UTF-8
AI service
@AiService(wiringMode = EXPLICIT, streamingChatModel = "streaming",chatModel = "chat")
public interface ChatService {
String chat(String prompt);
@SystemMessage("你是一位资深二次元,只回答二次元相关的问题。输出限制:对于其他领域的问题禁止回答,直接返回'不好意思,你的问题不够变态'")
@UserMessage("请回答以下二次元问题:{{question}}")
String chat2(@V("question") String question);
@SystemMessage("你是一位资深二次元,只回答二次元相关的问题。输出限制:对于其他领域的问题禁止回答,直接返回'不好意思,你的问题不够变态'")
@UserMessage("请回答以下二次元问题:{{question}}")
Flux<String> streamChat(@V("question") String question);
}
基础用例
@GetMapping(value = "/lcc/a")
public String assistant(@RequestParam("p") String p){
return chatService.chat(p);
}
@GetMapping(value = "/lcc/a2")
public String assistant2(@RequestParam("p") String p){
return chatService.chat2(p);
}
@GetMapping(value = "/lcc/s", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam("p") String p) {
Sinks.Many<String> sink = Sinks.many().multicast().onBackpressureBuffer();
client.chat(p, new StreamingChatResponseHandler() {
@Override
public void onPartialResponse(String partialResponse) {
sink.tryEmitNext(partialResponse);
}
@Override
public void onCompleteResponse(ChatResponse chatResponse) { sink.tryEmitComplete();}
@Override
public void onError(Throwable throwable) { }
});
return sink.asFlux();
}
@GetMapping(value = "/lcc/ss", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat2(@RequestParam("p") String p) {
return chatService.streamChat(p);
}
浙公网安备 33010602011771号