创建一个新的SpringBoot工程,勾选Web、MySQL驱动、Ollama:
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>3.4.4version>
<relativePath/>
parent>
<groupId>com.shisangroupId>
<artifactId>chat-robotartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>chat-robotname>
<description>chat-robotdescription>
<url/>
<licenses>
<license/>
licenses>
<developers>
<developer/>
developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
scm>
<properties>
<java.version>17java.version>
<spring-ai.version>1.0.0-M6spring-ai.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-ollama-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.mysqlgroupId>
<artifactId>mysql-connector-jartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-bomartifactId>
<version>${spring-ai.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
SpringAI完全适配了SpringBoot的自动装配功能,而且给不同的大模型提供了不同的starter比如:
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-anthropic-spring-boot-starterartifactId>
dependency>
dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-azure-openai-spring-boot-starterartifactId>
dependency>
实际上 DeepSeek 使用的是 OpenAI 接口协议,因此使用 OpenAI 的 starter。
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-openai-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-huggingface-spring-boot-starterartifactId>
dependency>
org.springframework.ai
spring-ai-ollama-spring-boot-starter
<dependency>
<groupId>org.springframework.aigroupId>
<artifactId>spring-ai-openai-spring-boot-starterartifactId>
dependency>
spring:
application:
name: chart-robot
ai:
ollama:
base-url: http://localhost:11434 # ollama服务地址, 这就是默认值
chat:
model: deepseek-r1:14b # 模型名称
options:
temperature: 0.8 # 模型温度,影响模型生成结果的随机性,越小越稳定
这ChatClient
提供用于与 AI 模型通信的 Fluent API。 它支持同步和流式编程模型。
Fluent API 具有构建 Prompt 的组成部分的方法,这些部分作为输入传递给 AI 模型。 这Prompt
包含指导 AI 模型的输出和行为的说明文本。从 API 的角度来看,提示由一组消息组成。
AI 模型处理两种主要类型的消息:用户消息(来自用户的直接输入)和系统消息(由系统生成以指导对话)。
这些消息通常包含占位符,这些占位符在运行时根据用户输入进行替换,以自定义 AI 模型对用户输入的响应。
还有一些可以指定的 Prompt 选项,例如要使用的 AI 模型的名称以及控制生成输出的随机性或创造性的温度设置。
这ChatClient
是使用ChatClient.Builder
对象。 您可以获取自动配置的ChatClient.Builder
实例,或者以编程方式创建一个。
@Bean
public ChatClient chatClient(OllamaChatModel model) {
return ChatClient.builder(model) // 创建ChatClient工厂
.build(); // 构建ChatClient实例
}
@RestController
class MyController {
private final ChatClient chatClient;
public MyController(ChatClient.Builder chatClientBuilder) {
this.chatClient = chatClientBuilder.build();
}
@GetMapping("/ai")
String generation(String userInput) {
return this.chatClient.prompt()
.user(userInput)
.call()
.content();
}
}
在这个简单的示例中,用户输入设置用户消息的内容。 这call()
method 向 AI 模型发送请求,并且content()
方法将 AI 模型的响应作为String
.
这stream()
method 允许你获得异步响应,如下所示:
Flux<String> output = chatClient.prompt()
.user("Tell me a joke")
.stream()
.content();
SpringAI基于AOP机制实现与大模型对话过程的增强、拦截、修改等功能,所有的增强通知都需要实现Advisor接口;Spring提供了一些Advisor的默认实现,来实现一些基本的增强功能
SimpleLoggerAdvisor
:日志记录的Advisor;MessageChatMemoryAdvisor
:会话记忆的Advisor;QuestionAnswerAdvisor
:实现RAG的Advisor;@Bean
public ChatClient chatClient(OllamaChatModel model) {
return ChatClient
.builder(model)
.defaultAdvisors(new SimpleLoggerAdvisor()) // 添加默认的Advisor,记录日志
.build(); // 构建ChatClient实例
}
logging:
level:
org.springframework.ai.chat.client.advisor: debug # AI对话的日志级别
com.heima.ai: debug # 本项目的日志级别
将 advisor 添加到链中的顺序至关重要,因为它决定了它们的执行顺序。每个 advisor 都以某种方式修改 prompt 或 context,并且一个 advisor 所做的更改将传递给链中的下一个 advisor。
ChatMemory
表示聊天对话历史记录的存储。它提供了向对话添加消息、从对话中检索消息以及清除对话历史记录的方法。
目前有两种实现:InMemoryChatMemory
和CassandraChatMemory
,它们为聊天对话历史记录提供存储,内存和time-to-live
相应。
@Bean
public ChatMemory chatMemory() {
return new InMemoryChatMemory();
}
@Bean
public ChatClient chatClient(AlibabaOpenAiChatModel model, ChatMemory chatMemory) {
return ChatClient
.builder(model)
.defaultSystem("你是一个热心、可爱的智能助手,你的名字叫小团团,请以小团团的身份和语气回答问题。")
.defaultAdvisors(
new SimpleLoggerAdvisor(),
new MessageChatMemoryAdvisor(chatMemory)
)
.build();
}
重点是会话id
/**
* 发起流式对话请求
* @param prompt 用户输入
* @param chatId 会话ID(用于上下文记忆)
* @return 响应流
*/
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> chat(@RequestParam String prompt,
@RequestParam String chatId) {
return chatClient.prompt()
.user(prompt)
.advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId))
.stream()
.content();
}
这边可以自己根据具体场景实现,主要有两个接口
1.查询某个用户的会话历史
2.查询某个会话的对话