# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## 项目概述 AI 智能客服系统,基于 Spring AI Alibaba + 通义千问 + PGVector,支持 RAG 知识库检索、多轮对话、结构化数据提取、知识库全生命周期管理。 ## 构建与运行 ```bash # 编译 ./mvnw compile # 运行(端口 9090) ./mvnw spring-boot:run # 运行测试 ./mvnw test # 运行单个测试类 ./mvnw test -Dtest=SupportBotApplicationTests # 运行单个测试方法 ./mvnw test -Dtest=SupportBotApplicationTests#testRag ``` **前提条件**: PostgreSQL 12+ 需运行且安装 PGVector 扩展,数据库 `support_bot` 需存在。`knowledge_category`、`knowledge_document`、`ai_model_config` 等表由 `DatabaseInitConfig` 自动创建,无需手动建表。 **测试说明**: 所有测试均为集成测试(`@SpringBootTest`),需要运行中的 PostgreSQL 和有效的 DashScope API Key。测试类:`SupportBotApplicationTests`(对话/RAG)、`PgVectorVectorStoreConfigTest`(向量存储)、`QueryTransformerTests`(查询重写策略)。无单元测试。 **访问地址**: 前端管理页面 `http://localhost:9090/index.html`,API 文档 `http://localhost:9090/doc.html`(Knife4j) ## 核心架构决策 ### 主启动类排除了 PgVectorStoreAutoConfiguration `SupportBotApplication.java` 中 `@SpringBootApplication(exclude = PgVectorStoreAutoConfiguration.class)`,因为项目在 `PgVectorStoreConfig` 中手动配置 PgVectorStore Bean(标记 `@Primary`),不使用自动配置。另有一个 `InMemoryVectorStoreConfig` 作为开发备选。 ### Spring AI 集成模式 - **ChatClient Builder**: 所有对话通过 `ChatClient.builder(dashscopeChatModel)` 构建 - **Advisor 链**: `MessageChatMemoryAdvisor`(记忆) → `MyLoggerAdvisor`(日志) → `QuestionAnswerAdvisor`(RAG) - **结构化输出**: `ProductInfoApp` 使用 `.entity(ProductInfo.class)` 提取结构化数据 - **SSE 流式**: 三种实现 — Flux\、Flux\、SseEmitter ### ChatMemory 持久化 当前使用 `DatabaseChatMemory`(PostgreSQL 持久化),`FileBasedChatMemory`(Kryo 序列化)已注释掉。`ProductInfoApp` 单独使用 `InMemoryChatMemory`。 ### RAG 双模式 1. **QuestionAnswerAdvisor 模式**(生产使用): 预检索优化 + `QuestionAnswerAdvisor` 2. **RetrievalAugmentationAdvisor 模式**(实验性): `doChatWithRagEnhance()` 中 `queryTransformers` 和 `multiQueryExpander` 未生效 ### 文档处理管道 `DocumentService.uploadDocument()` 统一流程:文档提取 → `MyTokenTextSplitter` 分块 → `MyKeywordEnricher` AI 关键词提取 → `pgVectorVectorStore.add()` 向量化存储。每个分块的 metadata 中注入 `documentId`、`chunkIndex`、`sourceName`、`title` 以关联 `knowledge_document` 表。 ### 预检索查询优化 四种策略在 `rag/preretrieval/` 下,由 `AssistantApp.doChatWithRagStrategy()` 根据 `strategy` 参数动态选择:REWRITE / TRANSLATION / COMPRESSION / MULTI_QUERY。另存在 Bean 配置版本(`QueryTransformerConfig`、`QueryExpanderConfig`),但实际使用自定义 Rewriter 组件。 ## 关键配置 - `application.yml` 含 API Key,已被 `.gitignore` 排除 - 对话模型: `qwen-turbo`,temperature: 0.7;Embedding: `text-embedding-v2`(1536维) - MyBatis Plus 逻辑删除字段: `isDelete`,主键策略: `assign_id`(雪花算法) - **雪花 ID 精度问题**: `KnowledgeDocument.id`、`categoryId` 和 `KnowledgeCategory.id`、`parentId` 已添加 `@JsonSerialize(using = ToStringSerializer.class)`,序列化为字符串避免前端 JS 精度丢失。新增 Long ID 字段时务必加上此注解 - PostgreSQL JSONB 字段使用自定义 `PostgresJsonTypeHandler`(期望 JSON 对象 `'{}'`,非数组 `'[]'`) - 向量维度: 1536,距离类型: COSINE_DISTANCE,索引: HNSW - **分块配置**: `knowledge.chunk.*` 配置项(`ChunkConfig`),默认 chunkSize=200, overlap=100, minChunkSizeChars=10, maxNumChunks=5000, keepSeparator=true - **上传校验**: `ALLOWED_EXTENSIONS` 白名单 + 50MB 大小限制(`spring.servlet.multipart` 配置),前后端双重校验 - **文档去重**: `KnowledgeDocument.contentHash` 字段(SHA-256),上传时自动计算并查重 - **数据库自动初始化**: `DatabaseInitConfig` 在启动时检查并创建 `knowledge_category`/`knowledge_document`/`ai_model_config` 等表,对已存在的 `knowledge_document` 表会自动补加 `content_hash` 列。注意 `knowledge-base.sql` 脚本为早期版本,缺少此列,实际以 `DatabaseInitConfig` 为准 ### 模型配置管理 - **ai_model_config 表**: 存储大模型配置,支持多套配置按 App 类型(CHAT / PRODUCT_EXTRACT / EMBEDDING / RAG_REWRITE)独立管理 - **激活互斥**: 同一 App 类型只能有一个 `is_active=true` 的配置,激活操作由 Service 层 `@Transactional` 保证 - **启动 seed**: 首次启动时自动从 `application.yml` 读取当前配置写入 DB 作为默认数据 - **启动校验**: `ModelConfigLoader` 在应用就绪后比较 DB 活跃配置与 yml 配置,不一致时打印 WARNING 日志 - **API Key 脱敏**: 前端展示时只显示前 4 位 + `****` + 后 4 位 - **运行时切换**: 通过 `ChatModelFactory` 按 DB 活跃配置动态创建/缓存 ChatModel,配置变更时立即生效(无需重启) - **多提供商支持**: DashScope(通义千问)+ OpenAI 兼容提供商(DeepSeek / 豆包 / Kimi / 智谱 / OpenAI),通过 `spring-ai-openai` + 自定义 `baseUrl` 接入 - **缓存刷新**: 配置增删改激活时 Controller 自动调用 `ChatModelFactory.clearCache()` + `AssistantApp.clearCache()` ### 依赖版本 - Spring AI BOM: `1.0.1`,统一管理所有 `org.springframework.ai` 依赖版本 - `spring-ai-alibaba-starter-dashscope`: `1.0.0.4`(新版 starter,替代老版 `spring-ai-alibaba-starter` M6.1) - `spring-ai-openai`: BOM 管理(OpenAI 兼容提供商支持) - `spring-ai-alibaba-starter` (M6.1) 已移除,不再使用 ## 前端架构 - **技术栈**: Vue 3 CDN + ES Module(`importmap` 引入,无构建工具) - **入口**: `src/main/resources/static/index.html` → `js/app.js` - **组件化**: 每个功能模块一个 JS 文件(`components/` 目录),导出 Vue 组件定义对象 - **状态管理**: `js/store.js` 使用 Vue 3 `reactive`,跨组件共享分类、统计、弹窗状态 - **API 封装**: `js/api.js` 统一封装所有后端调用,API 基址为空字符串(同源部署) - **SSE 流式**: `js/utils.js` 中 `readSSEStream()` 统一处理三种 SSE 接口 - **添加新功能**: 在 `components/` 下新建 JS 组件文件,在 `app.js` 中导入注册即可 ## API 路由约定 - AI 对话: `/ai/*`(`AiController`) - 模型配置: `/model-config/*`(`AiModelConfigController`) - 文档上传: `/upload/*`(`DocumentController`) - 文档管理: `/document/*`(`DocumentController`) - 批量操作: `/document/batch/*`(`DocumentController`,用 POST 避免 DELETE+RequestBody 路径冲突) - 分类管理: `/category/*`(`DocumentController`) ## 已知 TODO - `AssistantApp.doChatWithRagEnhance()`: `queryTransformers` 未生效 - `DocumentService.updateDocumentMetadata()`: Spring AI 无直接更新 vector_store metadata 的 API,向量元数据同步留后续 - `DocumentService.searchDocuments()`: Spring AI 1.0.1 的 filter 支持有限,分类过滤暂未实现 - `CompressionQueryRewriter`: 当前传入空历史列表 - MyBatis Plus 3.5.12 的 `mybatis-plus-spring-boot3-starter` 不含 `PaginationInnerInterceptor`,分页通过 SQL `LIMIT/OFFSET` 手动实现 - `ChatModelFactory` 中 DashScope 配置始终返回同一个自动配置 Bean,不支持按 DB 中的不同模型名/温度创建独立实例