背景
测试了下SpringAI,文档繁琐,一团乱麻,搞了好久终于搞定了,因此本次文档分享一下如何快速接入。
目标
接入openai-兼容的LLM,且官方没有提供原始实现的,如:qianfan,等
版本:
- springboot: 3.5.9
- springai: 1.1.2
示例
本次以qianfan为例子,自行在idea创建一个java项目,包管理使用gradle(如果是maven自行把gradle转换成maven就行,用llm转很快)
1. 配置文件gradle
- 要引入spring-boot-starter-webflux,用于返回流式内容
- 引入openai包,spring-ai-starter-model-openai
gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.9'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'ai-learn'
version = '0.0.1-SNAPSHOT'
description = 'springai-test'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
repositories {
mavenCentral()
}
ext {
set('springAiVersion', "1.1.2")
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-webflux'
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
dependencyManagement {
imports {
mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}"
}
}
tasks.named('test') {
useJUnitPlatform()
}
2. yml配置
参考如下
yml
server:
port: 8080
spring:
ai:
openai:
# 模型的基础地址
base-url: https://qianfan.baidubce.com/v2
api-key: 你的api-key
chat:
options:
# 模型名
model: ernie-4.5-turbo-32k
completions-path: /chat/completions
注意:
- 模型基础地址,观察对应模型的说明文档,一般都会给出openai兼容的地址,如千帆OpenAI SDK兼容介绍。
- 一些其他坑人情况,如:completions-path,这个具体配置成什么,可以参考说明文档,如:千帆AI应用开发者中心-API参考:模型:文本生成,其中写道:请求地址拼接出来应该是:
https://qianfan.baidubce.com/v2/chat/completions
我们观察springai官方文档说的是:
spring.ai.openai.chat.completions-path(附加到基础 URL 的路径)
默认值:/v1/chat/completions
和我们api中看到的/v2/chat/completions不一致,因此,这里要修改配置completions-path为/chat/completions,大功告成。
3. 新增测试Controller
可以测试三种情况,阻塞,转json,流式
java
package ailearn.springaitest;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder
.defaultSystem("你是一个友好的 AI 助手,请用中文简洁地回答问题。")
.build();
}
// 1. 最简单的文本对话
@GetMapping("/chat")
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
// 2. 结构化输出 (Structured Output) - 返回 Java Bean
// Spring AI 会自动提示 LLM 输出 JSON 并解析
@GetMapping("/actor")
public ActorInfo getActorInfo(@RequestParam String name) {
return chatClient.prompt()
.user(u -> u
.text("请生成一个关于演员 '{actor}' 的简介")
.param("actor", name))
.call()
.entity(ActorInfo.class); // 自动映射到 Record
}
// 3. 流式响应 (Streaming)
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.stream()
.content()
// 【关键】打印每一个 Token,观察控制台
.doOnNext(token -> System.out.println("收到 Token: " + token))
.doOnComplete(() -> System.out.println("流结束"));
}
// 用于结构化输出的 Record
record ActorInfo(String name, String famousMovie, int age) {}
}
4. 测试
在前端页面分别调用即可,注意流式测试时,输入内容可以是:"帮我生成1个500字的故事",可以观察是否是真流式
附录
其他参数可以自行查看SpringAI官方文档:SpringAI