6.4 KiB
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 知识库检索、多轮对话、结构化数据提取、知识库全生命周期管理。
构建与运行
# 编译
./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 表由 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<String>、Flux<ServerSentEvent>、SseEmitter
ChatMemory 持久化
当前使用 DatabaseChatMemory(PostgreSQL 持久化),FileBasedChatMemory(Kryo 序列化)已注释掉。ProductInfoApp 单独使用 InMemoryChatMemory。
RAG 双模式
- QuestionAnswerAdvisor 模式(生产使用): 预检索优化 +
QuestionAnswerAdvisor - 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表,对已存在的knowledge_document表会自动补加content_hash列。注意knowledge-base.sql脚本为早期版本,缺少此列,实际以DatabaseInitConfig为准
依赖版本注意
Spring AI 相关依赖版本混合:spring-ai-alibaba-starter 1.0.0-M6.1、spring-ai-pgvector-store 1.0.0-M6、spring-ai-tika-document-reader 1.0.0(正式版),可能存在 API 不兼容风险。pom.xml 中注释掉了 spring-ai-starter-vector-store-pgvector 1.0.0-M7(自动整合版本,未启用)。
前端架构
- 技术栈: Vue 3 CDN + ES Module(
importmap引入,无构建工具) - 入口:
src/main/resources/static/index.html→js/app.js - 组件化: 每个功能模块一个 JS 文件(
components/目录),导出 Vue 组件定义对象 - 状态管理:
js/store.js使用 Vue 3reactive,跨组件共享分类、统计、弹窗状态 - API 封装:
js/api.js统一封装所有后端调用,API 基址为空字符串(同源部署) - SSE 流式:
js/utils.js中readSSEStream()统一处理三种 SSE 接口 - 添加新功能: 在
components/下新建 JS 组件文件,在app.js中导入注册即可
API 路由约定
- AI 对话:
/ai/*(AiController) - 文档上传:
/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.0-M6 的 filter 支持有限,分类过滤暂未实现CompressionQueryRewriter: 当前传入空历史列表- MyBatis Plus 3.5.12 的
mybatis-plus-spring-boot3-starter不含PaginationInnerInterceptor,分页通过 SQLLIMIT/OFFSET手动实现