This commit is contained in:
2026-04-30 16:08:39 +08:00
parent f95aa18724
commit 1503b26959
41 changed files with 4503 additions and 0 deletions

View File

@@ -0,0 +1,129 @@
package com.learn.config;
import com.learn.tool.CalculatorTool;
import com.learn.tool.SearchTool;
import com.learn.tool.WeatherTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.openai.OpenAiEmbeddingModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
/**
* Week 10 核心配置 —— Agent 能力装配
*
* 新增(对比 Week 9
* 1. EmbeddingModel手动创建用 Ollama 本地) → RAG
* 2. VectorStoreSimpleVectorStore内存 → RAG
* 3. ChatMemory 持久化RedisChatMemoryRepository → 记忆不丢失
* 4. ChatClient 注册 Tools + QuestionAnswerAdvisor → Agent
*/
@Configuration
public class AIConfig {
private static final Logger log = LoggerFactory.getLogger(AIConfig.class);
// ==================== Embedding用于 RAG ====================
/**
* EmbeddingModel —— 把文本转成向量。
*
* 这里手动创建 OpenAiEmbeddingModel指向 Ollama 本地服务,
* 因为 Chat 用的是 DeepSeek不支持 Embedding两者 base-url 不同。
*
* 前置条件ollama pull nomic-embed-text
*/
@Bean
@Lazy
public EmbeddingModel embeddingModel(
@Value("${spring.ai.openai.embedding.base-url:http://localhost:11434}") String baseUrl,
@Value("${spring.ai.openai.embedding.api-key:ollama}") String apiKey) {
var api = OpenAiApi.builder()
.baseUrl(baseUrl.endsWith("/v1") ? baseUrl : baseUrl + "/v1")
.apiKey(apiKey)
.build();
log.info("EmbeddingModel created with base-url: {}", baseUrl);
return new OpenAiEmbeddingModel(api);
}
// ==================== VectorStore用于 RAG ====================
/**
* SimpleVectorStore —— 纯内存向量存储,免外部服务。
* 生产环境可替换为 RedisVectorStore / PgVectorStore 等。
*/
@Bean
@Lazy
public VectorStore vectorStore(EmbeddingModel embeddingModel) {
return SimpleVectorStore.builder(embeddingModel).build();
}
// ==================== ChatMemory持久化 ====================
/**
* ChatMemory —— 对话记忆Redis 持久化Day 5
*
* 架构: MessageWindowChatMemory (滑动窗口, 最多 30 条)
* ↓ 存储
* ChatMemoryRepository → RedisChatMemoryRepository (自定义实现)
*
* 切换方案:把注入的 ChatMemoryRepository 换成 InMemoryChatMemoryRepository
* 就回到 Week 9 的内存模式,其他代码完全不用改。
*/
@Bean
public ChatMemory chatMemory(ChatMemoryRepository repository) {
return MessageWindowChatMemory.builder()
.chatMemoryRepository(repository)
.maxMessages(30)
.build();
}
// ==================== ChatClientAgent 入口) ====================
/**
* ChatClient —— Week 10 增强版:
* - 复用 Week 9 的 defaultSystem + MessageChatMemoryAdvisor
* - 新增 defaultTools注册所有 @Tool 方法
* - 新增 QuestionAnswerAdvisorRAG 检索增强
*
* 注意Tool 对象通过 Spring 注入(用 @Component 标注),
* .defaultTools() 接收所有带 @Tool 注解的 Bean。
*/
@Bean
public ChatClient chatClient(
ChatModel chatModel,
ChatMemory chatMemory,
@Lazy VectorStore vectorStore,
WeatherTool weatherTool,
CalculatorTool calculatorTool,
SearchTool searchTool) {
return ChatClient.builder(chatModel)
.defaultSystem("""
你是一个 AI Agent 助手,名字叫"小智 Agent"
你可以调用工具来获取信息或执行计算。
当用户询问天气、计算数学、或搜索信息时,请使用对应的工具。
回答时请用中文,基于工具返回的结果来组织自然流畅的回复。
""")
.defaultTools(weatherTool, calculatorTool, searchTool)
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(),
new QuestionAnswerAdvisor(vectorStore)
)
.build();
}
}