Spring AI Alibaba使用
简单访问
导入依赖
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter</artifactId>
<version>1.0.0-M5.1</version>
</dependency>
如果中央仓库找不到则添加:
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
配置文件
spring:
ai:
dashscope:
api-key: XXXX
chat:
options:
model: qwen-plus
controller
@RestController
@RequestMapping("/ai")
public class ChatController {
@Autowired
@Qualifier("dashscopeChatModel")
private ChatModel chatModel;
@GetMapping("chat/{message}")
public String chat(@PathVariable String message){
return chatModel.call(message);
}
@GetMapping("chat2/{message}")
public String chat2(@PathVariable String message){
ChatClient chatClient = ChatClient.create(chatModel);
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
流式输出
@GetMapping(value = "stream/{message}",produces = "text/stream;charset=UTF-8")
public Flux<String> stream(@PathVariable String message){
return chatModel.stream(message);
}
定制化访问
@GetMapping("/opt/{message}")
public String opt(@PathVariable String message) {
DashScopeChatOptions options = DashScopeChatOptions.builder()
.withTopK(1024)
.withTemperature(0.7)
.withModel("deepseek-r1")
.build();
return chatModel.call(new Prompt(message,options)).getResult().getOutput().getText();
}
角色预设
@RestController
@RequestMapping("ai")
public class AIController {
private final ChatClient client;
public AIController(ChatClient.Builder builder, ChatMemory memory) {
this.client = builder
.defaultSystem("""
你是一个航空公司的客服,请以友好且乐于助人的方式来回复
今天的日期是{current_date}
在提供预定或取消预定之前,必须获取用户姓名和手机号
询问之前检查历史是否已经获取消息
""")
.build();
}
@GetMapping("chat/{message}")
public String chat(@PathVariable String message) {
return client.prompt()
.user(message)
.system(promptSystemSpec ->
promptSystemSpec.param("current_date", LocalDate.now().toString()))//传递参数
.call()
.content();
}
}
结构化输出
简单对象
@GetMapping("entity/{message}")
public production entity(@PathVariable String message){
return ChatClient.builder(chatModel).build()
.prompt()
.user(message)
.call()
.entity(production.class);
}
集合对象
@GetMapping("list/{message}")
public List<production> list(@PathVariable String message){
return ChatClient.builder(chatModel).build()
.prompt()
.user(message)
.call()
.entity(new ParameterizedTypeReference<List<production>>() {});
}
对话记忆
添加配置
//存储位置
@Bean
public ChatMemory chatMemory(){
return new InMemoryChatMemory();//内存
}
controller
@RestController
@RequestMapping("ai")
public class AIController {
private final ChatClient client;
public AIController(ChatClient.Builder builder, ChatMemory memory) {
this.client = builder
.defaultAdvisors(new PromptChatMemoryAdvisor(memory))
.build();
}
@GetMapping("chat/{message}")
public String chat(@PathVariable String message) {
return client.prompt()
.user(message)
.advisors(advisorSpec -> advisorSpec.param(AbstractChatMemoryAdvisor.CHAT_MEMORY_RETRIEVE_SIZE_KEY,10))//控制记忆的数量
.call()
.content();
}
}
使用Ollama
导入依赖
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
<version>1.0.0-M6</version>
</dependency>
添加配置
spring:
ai:
ollama:
base-url: http://localhost:11434
chat:
model: deepseek-r1:14b
controller
@RestController
@RequestMapping("ollama")
public class OllamaController {
@Autowired
@Qualifier("ollamaChatModel")
private ChatModel chatModel;
@GetMapping("chat/{message}")
public String chat(@PathVariable String message) {
return chatModel.call(message);
}
}
生成图片
添加配置
spring:
ai:
dashscope:
api-key: xxxx
image:
options:
model: wanx2.1-t2i-turbo
controller
@Controller
@RequestMapping("image")
public class ImageController {
@Autowired
@Qualifier("dashScopeImageModel")
private ImageModel imageModel;
@GetMapping("{message}")
public String image(@PathVariable("message") String message) {
ImagePrompt ip = new ImagePrompt(message);
ImageResponse response = imageModel.call(ip);
return "redirect:"+response.getResult().getOutput().getUrl();
}
@GetMapping("opt/{message}")
public String option(@PathVariable("message") String message) {
ImageOptions options = ImageOptionsBuilder.builder()
.model("wanx2.1-t2i-turbo")
.width(1024)
.height(1024)
.build();
ImagePrompt ip = new ImagePrompt(message,options);
ImageResponse response = imageModel.call(ip);
return "redirect:"+response.getResult().getOutput().getUrl();
}
}
向量模型
@RestController
@RequestMapping("embedding")
public class EmbeddingController {
@Autowired
@Qualifier("dashscopeEmbeddingModel")
private EmbeddingModel embeddingModel;
@GetMapping("emb1/{message}")
public Object emb1(@PathVariable String message) {
return embeddingModel.embed(message);
}
}
function call
tool
public record Reserve(String name,String phoneNumber){
}
@Bean
@Description("处理预定")
public Function<Reserve,String> reserve(){
return reserve -> {
System.out.println(reserve.name());
System.out.println(reserve.phoneNumber());
return "预定成功";
};
}
controller
@RestController
@RequestMapping("ai")
public class AIController {
private final ChatClient client;
public AIController(ChatClient.Builder builder, ChatMemory memory) {
this.client = builder
.defaultFunctions("reserve")//指定使用的tool的bean名称
.build();
}
@GetMapping("chat/{message}")
public String chat(@PathVariable String message) {
return client.prompt()
.user(message)
.call()
.content();
}
}
RAG
配置向量数据库
@Bean
public VectorStore vectorStore(EmbeddingModel model){
return new SimpleVectorStore(model);
}
初始化数据
@Bean
CommandLineRunner commandLineRunner(VectorStore vectorStore,
@Value("classpath:rag/t1.txt") Resource resource){
return args -> {
vectorStore.write( //写入
new TokenTextSplitter().transform( //转换
new TextReader(resource).read() //读取
)
);
};
}
controller
@Autowired
private VectorStore vectorStore;
@GetMapping("chat/{message}")
public String chat(@PathVariable String message) {
return client.prompt()
.user(message)
.advisors(new QuestionAnswerAdvisor(vectorStore,SearchRequest.builder().query(message).build()))//查询条件
.call()
.content();
}