项目工程全景(代码级地图)#
面试中回答”项目规模多大""代码结构是什么""数据库怎么设计的”时的参考。 所有数据来自源码实际统计,非估算。
一、仓库统计#
| 维度 | 数值 |
|---|---|
| 后端 Java 源文件 | 153 个(~18,500 行) |
| 前端 React/TS 源文件 | 81 个(~5,600 行) |
| 核心 RAG 组件 | 26 个文件(service/rag/) |
| 数据库表 | 13 张(含 RBAC 4 表 + sys_dept + user_memory) |
| 动态配置参数 | 50+ 个(sys_ai_config,以 AiConfigInitializer.defaultConfigs() 为准) |
| Prompt 模板 | 6 个 |
| MCP 工具 | 6 个 / 6 端点(双路径;executeCode 内部专用,不对外暴露) |
| Docker 服务 | dev 4 个(Redis + etcd + Milvus + OpenSandbox)/ 生产全栈 13 个(+ MySQL + MinIO + 后端 + 前端 + Langfuse v3 栈) |
二、后端包结构(com.jake.DocMind)#
agent/ — Agent 核心(22 文件,含 supervisor/worker/state/emit 子包)#
| 文件 | 行数 | 职责 |
|---|---|---|
DocMindAgent.java | ~135 | 入口薄壳(#31 拆上帝类后):会话装配 + 根 span + 顶层分流,委托下列协作者 |
ScopeRouter.java | — | #31 析出:Tier-0 规则 + Tier-1 合并模式 LLM 的范畴路由 |
ShortCircuitResponder.java | — | #31 析出:紧急词 / META / CHITCHAT / KB_META / OUT_OF_SCOPE 五条短路终态分支 |
SemanticCacheReplayer.java | — | #31 析出:语义缓存命中回放(模拟流式 + 合成 trace + done payload) |
RagPipeline.java | ~600 | #31 析出:知识问答主流水线(QU→路径→记忆→检索→CRAG→Prompt→生成持久化)、路径决策三模式、结构化引用解析(生成即终态) |
MetaIntentDetector.java | — | Phase 5: Tier-0 纯正则范畴判定(6 条规则,零 LLM) |
ScopeDecision.java | — | Phase 5: 范畴判定结果 record(6 种 Scope + confidence + fastPath) |
PathDecision.java | — | 路径决策结果 record(SELECTED_DOC / RULE_PLANNER / AGENTIC + reason) |
AgentToolContext.java | — | ThreadLocal 侧通道:工具执行结果汇总,synchronizedList + finally 清理 |
注:
SelfReflection.java(自反思)已于四刀改造整类删除;文档直读改由service/rag/DocumentDirectReader.java承接(原SelectedDocumentScopeDecider已下线)。
agent/supervisor/ (3 文件)
| 文件 | 行数 | 职责 |
|---|---|---|
AgenticSearchOrchestrator.java | — | 四刀改造核心:真·LLM 工具调用循环(Spring AI ToolCallingManager 手动控环、max_iterations=4、白名单 4 读工具 + executeCode 沙箱计算工具(默认关)硬排 store_memory/kb_meta);模型自驱拆解/多跳/补检索/计算/停;finalize 去重→rerank→MMR→压缩→CRAG;异常/空回退 oneShotRetrieval |
SupervisorAgent.java | ~595 | 一次性检索 oneShotRetrieval:并行 Worker 派发 → RRF→rerank→MMR→压缩 → CRAG,供 RULE_PLANNER 模式 + agentic 兜底 |
SupervisorResult.java | — | 编排输出(record) |
注:自研拆解 / 串行多跳 / CRAG-web 回溯三条分支与
SelfReflection已于四刀改造统一收敛为AgenticSearchOrchestrator;更早的PlanGenerator/PlanExecutor/ExecutionPlan(Plan-and-Execute)已在链路精简中删除。见 04-优化迭代记录 #21/#22。
agent/worker/ (7 文件)
| 文件 | 行数 | 职责 |
|---|---|---|
Worker.java | — | 统一接口(execute + name) |
RetrievalWorker.java | — | 封装 Vector + BM25 + RRF + Rerank + MMR + ParentChunk |
WebWorker.java | — | 封装 Tavily 搜索 |
MemoryWorker.java | — | 封装长期记忆读取(Milvus 向量召回 → MySQL SoR 取全文,Redis cache-aside) |
AnalysisWorker.java | — | LLM 多文档对比分析 |
WorkerRequest.java | — | Worker 入参(record) |
WorkerResult.java | — | Worker 出参 + 工厂方法(record) |
agent/state/ (2 文件)
| 文件 | 职责 |
|---|---|
AgentState.java | 共享执行上下文:Evidence 累积、置信度轨迹、策略记录、查询分类 |
Evidence.java | 标准证据结构(record) |
agent/emit/ (1 文件)
| 文件 | 职责 |
|---|---|
StageEmitter.java | 观测标准化 #25:统一三套埋点(SSE 事件 / Langfuse span / 日志),各检索阶段一次调用同时落 SSE + trace |
service/rag/ — RAG 检索管线(26 文件)#
| 文件 | 行数 | 职责 |
|---|---|---|
QueryUnderstandingService.java | 281 | 合并 5 个旧组件的统一分类器:意图/复杂度/专指度/时效/记忆 |
BM25Retriever.java | 265 | MySQL FULLTEXT 预召回 + Java BM25 评分(K1=1.5, B=0.75)+ 短语覆盖加分 |
PromptAssembler.java | 249 | 2 模式 Prompt 组装(标准/降级)+ 对话历史裁剪(6 条) |
CrossEncoderReranker.java | 233 | DashScope gte-rerank API + 降级关键词覆盖度打分 + 去重截断 |
SemanticCacheService.java | 209 | query embedding cosine 近邻 + KB version 校验 + Redis 存取 |
VectorRetriever.java | 154 | Milvus COSINE 检索(HNSW ef=64)+ 标量过滤 |
MMRDiversifier.java | 127 | MMR 多样性重排(λ=0.7 clamp[0,1],向量 cosine 相似度 I-perf-4,失败降级 bigram Jaccard) |
ParentChunkResolver.java | 128 | 子块→父块展开 + 同父去重 |
SafetyGuard.java | 111 | 紧急词检测 + 置信度阈值 + LLM 答案安全审查 |
RRFFusion.java | 92 | RRF 等权/加权融合(k=60)+ HYBRID 标记 + 50-char 去重 |
HyDEGenerator.java | 70 | 假设文档生成(小模型 200-400ms)+ 失败回退原 query |
RetrievalPlanner.java | 100 | Phase 5: 规则引擎(零 LLM):4 信号 → 工具选择,双源时效性校验 |
RetrievalGrader.java | — | Phase 5: CRAG 三档评分(HIGH/AMBIGUOUS/LOW)+ 灰区仲裁(heuristic/cross_encoder/disabled) |
GradeResult.java | — | Phase 5: 评分结果 record(tier + topScore + avgScore + reason) |
RecommendationGenerator.java | — | 推荐阅读:同 category + tags 共现 → 最多 3 条 |
ParentChunkResolver.java | — | 父块展开:命中子块按 parent_chunk_id 查父块内容,同父去重保最高分(one-shot 在 RetrievalWorker 内、AGENTIC 在 finalize 调用) |
KbVersionService.java | — | KB 版本号管理(缓存失效用) |
SourcePayloadFactory.java | — | 来源 JSON 构建(文档名+章节+页码+分数+id) |
CitationParser.java | — | 四刀改造:纯 Java 解析答案 [n]→结构化引用 + 越界 invalidRefs + 句子级覆盖率(置信度 = clamp(coverage) × rerank-top1) |
DocumentDirectReader.java | — | 文档直读:选中文档时绕过搜索,直接读 chunk 均匀采样 |
ChineseTextTokenizer.java | — | Lucene SmartCN 中文分词包装 |
QueryClassification.java | — | 分类输出 record(10 字段,已删 needDecompose/multiHop) |
QueryUnderstandingResult.java | — | 理解结果 record |
RetrievalPlan.java | — | 检索计划 record |
RetrievedChunk.java | — | 检索 chunk 载体(score + metadata + source 枚举) |
SemanticCacheEntry.java | — | 缓存条目 record |
service/knowledge/ — 文档处理(4 文件)#
| 文件 | 行数 | 职责 |
|---|---|---|
TextChunker.java | 542 | Markdown-Aware 双层切块:5 种 block 识别 + heading 栈 + content_hash |
DocumentExtractor.java | — | 多格式路由:PDF→MinerU+PDFBox / DOCX→POI / PPT+图片→MinerU / URL→MinerU-HTML |
MilvusService.java | — | Milvus CRUD:insertVectors(带外部 ID) / deleteByVectorIds / search / countEntities |
MinerUClient.java | — | MinerU 云端 API 双流程客户端(文件+URL)+ 合并轮询 |
注:原
MinioService.java(MinIO S3 原件存储)已删除——原始文件与头像改为直接落本地磁盘(uploads/),不再使用对象存储。
mcp/ — MCP 工具(6 工具类,双路径;另含 MemoryStore/MemoryRecord/MemoryType 三个记忆支撑类)#
| 文件 | 内部调用 | 外部暴露 | 职责 |
|---|---|---|---|
DocSearchTool.java | Spring AI Function Calling | MCP Server endpoint | 语义向量检索 |
KeywordSearchTool.java | Spring AI Function Calling | MCP Server endpoint | BM25 关键词检索 |
WebSearchTool.java | Spring AI Function Calling | MCP Server endpoint | Tavily 联网搜索 |
MemoryTool.java | Spring AI Function Calling(recall);store 走 stageMemoryWrite() 直调,循环硬排 | MCP Server endpoint | 长期记忆 recall + store(MySQL SoR + Redis 缓存 + Milvus 向量,见 MemoryStore) |
KbMetaTool.java | Agent KB_META 短路路径直接查 DB | MCP Server endpoint | 知识库元信息查询 |
CodeExecTool.java | 仅 agentic 循环白名单(executeCode,OpenSandbox 跑 LLM 现写 Python,sandbox.enabled 动态门控) | 不外暴露(运行任意代码攻击面过大,故意不入 McpToolsConfig) | 精确计算/统计 |
外部暴露 6 端点(doc_search / keyword_search / web_search / recall_memory / store_memory / kb_meta);executeCode 内部专用。同一套 @Tool 注解代码既被内部 ChatClient 调用,也通过 spring-ai-starter-mcp-server-webmvc 对外暴露。工具执行结果通过 AgentToolContext ThreadLocal 写入,Agent 读取后清理。
MCP 安全边界(MVP → 生产):内部调用由 AgentToolContext + 用户会话上下文保证 kbIds 隔离和 userId 注入。外部调用 4 个加固点中①已落地——McpApiKeyAuthFilter 校验 X-API-Key(配置键 docmind.mcp.api-key),/mcp/**、/sse 匿名访问被 401(见 21-权限系统对齐报告);剩余:②kbIds 需校验用户归属(外部持 API-Key 仍可传任意 kbIds);③Memory userId 需从 auth context 注入、禁止外部指定;④Web Search 需接入 rate-limiter 防配额滥用。
config/ — 配置(24 文件)#
| 文件 | 职责 |
|---|---|
AiConfigHolder.java | ConcurrentHashMap 配置 + AtomicReference 热替换 ChatModel + 三层成本分层(smallModelOptions / extractModelOptions per-call 覆盖 model 名) |
AiConfigInitializer.java | 启动时按 key 增量插入 sys_ai_config 默认值 |
LlmConfig.java | Spring AI OpenAI-compatible ChatModel / EmbeddingModel Bean |
MilvusConfig.java | Milvus 连接 + Collection 初始化(COSINE, HNSW) |
RedisConfig.java | RedisTemplate<String, Object> 序列化 |
SecurityConfig.java | Spring Security 过滤链 + JWT + MCP API-Key + CORS + 路径白名单 |
WebSearchConfig.java | Tavily RestTemplate Bean |
McpToolsConfig.java | ToolCallbackProvider 注册 MCP 工具 |
MinerUConfig.java | MinerU 专用 RestTemplate(独立超时策略) |
MinerUProperties.java | @ConfigurationProperties MinerU 配置封装 |
LangfuseOtelConfig.java | 观测标准化: 删手写 OTel SDK,改用 Spring Boot 原生 OTLP tracing autoconfig;仅余 2 Bean(业务 Tracer + businessRootSpanSampler head-based 白名单 Sampler,替代旧 RootNameFilteringSpanProcessor),228→约 90 行 |
LangfuseOtelAuthInitializer.java | 观测标准化: ApplicationListener<ApplicationPreparedEvent>,public/secret 双 key 算 base64 注入 management.otlp.tracing.headers.Authorization(.env-safe,替代已删的 LangfuseProperties) |
ChatModelObservationFilter.java | 给原生 gen_ai 观测补 prompt/completion(截断 10000 字);因 refreshLlmModel() 接上 ObservationRegistry 而由休眠转激活 |
RagExecutorConfig.java | 一次性检索多路 Worker 专用线程池(core=8, max=16, CallerRunsPolicy) |
DocmindWebSearchProperties.java | Web 搜索配置属性 |
WebSocketConfig.java | WebSocket 端点配置 |
WebMvcConfig.java | 静态资源映射 |
MybatisPlusConfig.java | MyBatis Plus 分页插件 |
AppInitConfig.java | 应用启动初始化:建 Collection / flush 落盘 / 同步工具 / 恢复中断任务 / 向量一致性自检 |
KbChunkIndexInitializer.java | 启动时初始化 BM25 Lucene 索引 |
AgenticToolingConfig.java | agentic 循环工具白名单 + ToolCallingManager 手动控环装配 |
SandboxConfig.java | OpenSandbox 代码执行沙箱客户端(按需连接) |
DocmindSandboxProperties.java | @ConfigurationProperties 沙箱配置(domain / enabled) |
LangfuseScoreClient.java | 观测:回写 Langfuse score(置信度/grounded 等业务评分) |
controller/ — REST API(9 文件)#
| 文件 | 端点前缀 | 职责 |
|---|---|---|
DocMindChatController.java | /api/v2/chat | SSE 流式问答 + 会话管理 |
KnowledgeBaseController.java | /api/knowledge | 文档上传/列表/删除/更新/URL 入库 |
KbChunkController.java | /api/chunks | chunk 明细查看 |
McpConsoleController.java | /api/mcp | MCP 工具注册表 + 调用统计 |
AiConfigController.java | /api/ai-config | 49 个动态参数 CRUD |
UserController.java | /api/users | 用户注册/登录/JWT 刷新/RBAC |
StatsController.java | /api/stats | 统计面板数据 |
DocMindStatsController.java | /api/v2/stats | 增强统计 |
SpeechWebSocketServer.java | /ws/speech | 语音输入 WebSocket |
support/ — 工具类(4 文件)#
| 文件 | 职责 |
|---|---|
TracedOp.java | Phase 6: OTel span 样板代码消除工具(run/exec 方法封装 span 生命周期) |
ConfidenceBands.java | #31 析出:置信度分档(HIGH/MEDIUM/LOW)阈值映射 |
KbAccessGuard.java | 对话层 kbIds 归属校验(用户只能检索自己可见的知识库) |
KbIdsParser.java | kbIds JSON ↔ List 解析工具 |
entity/ — 数据模型(20 文件)#
实体 + DTO + VO,对应 13 张数据库表(含 RBAC 4 表 + sys_dept + user_memory)。
mapper/ — MyBatis Plus#
每个实体一个 Mapper 接口。XML 配置在 src/main/resources/mapper/。
security/ — 安全(3 文件)#
| 文件 | 职责 |
|---|---|
JwtAuthenticationFilter.java | 拦截请求,解析 JWT,设置 SecurityContext |
McpApiKeyAuthFilter.java | 校验 MCP 端点 X-API-Key(/mcp/**、/sse 匿名 401) |
UserDetailsServiceImpl.java | 从 sys_user 表加载用户信息 |
三、前端结构(DocMind-frontend/src/)#
2026-06 前端从 Vue 3 + Element Plus 彻底重构为 React 18 + TS + Vite + TailwindCSS + shadcn/ui(Radix) + TanStack Query + Zustand + React Router v7 + ECharts。旧 Vue 实现保留在
DocMind-frontend-backup/。后端 REST + SSE 契约不变。采用 feature-sliced 结构(页面按features/<domain>/切分,各自 default-export 页面组件)。
features/ — 业务域页面(8 域)#
| 目录 | 职责 |
|---|---|
chat/ | 聊天主界面:ChatPage + useChat hook(原生 EventSource,40ms token 缓冲刷新)+ ThinkingTimeline / SourcePanel / MessageBubble / MarkdownMessage / RetrievalProcessDialog / ConversationSidebar / KbScopeSelector / MessageInput + rehypeCitations(可点击 [n]) |
knowledge/ | 知识库管理:上传双模(文件/URL)+ 进度 + chunk 查看 |
mcp/ | MCP 控制台:工具注册表 + 调用统计图表 |
adminConfig/ | AI 动态配置分组编辑面板 |
dashboard/ | ECharts 数据面板 |
auth/ | Login / Register / ForgotPassword(AuthShell 品牌分栏,react-hook-form + zod) |
users/ | 用户管理(admin) |
profile/ | 个人资料 |
api/ — 类型化 HTTP 封装(6 TS 文件)#
aiConfig.ts / chat.ts / knowledge.ts / mcp.ts / stats.ts / user.ts
lib/ — 基础设施#
http.ts— Axios 实例 + 拦截器(注入 Bearer、code===200解包、401→登录)sse.ts—openChatStream()EventSource 封装(token 走 URL query,类型化 handler)token.ts— token 读写utils.ts— 通用工具(cn 等)
stores/ — Zustand 状态#
authStore.ts— token + userInfo + isAdminuiStore.ts— 侧边栏等 UI 状态
其他#
types/— 后端契约类型(单一事实来源,含 13 个 SSE 事件载荷)components/ui/(shadcn 风 Radix 原语)+components/shared/(StatCard / ConfidenceBadge / EChart…)layout/MainLayout(Sidebar + Topbar)+router/(createBrowserRouter+RequireAuth/RequireAdmin守卫)
四、数据库表设计(13 张表)#
kb_chunk — 文档切片表(核心表,8 个设计决策)#
| 字段 | 类型 | 设计决策 |
|---|---|---|
content | TEXT | 切片文本,FULLTEXT INDEX (ngram) 支持 BM25 |
content_hash | VARCHAR(64) | SHA-256 hex,增量索引核心——按 (kb_id, content_hash) diff |
vector_id | VARCHAR(100) | 与 Milvus 1:1 映射(VarChar PK),精准删除依赖此字段 |
metadata | JSON | {chapter, contentType, pageNumber, docVersion, effectiveDate} |
tags | VARCHAR(512) | JSON 数组,从 heading 栈自动提取,支持 LIKE 过滤 |
doc_version | VARCHAR(32) | 文档版本号 |
parent_chunk_id | BIGINT | 外键→父块 ID,Parent Document Retrieval 的基础 |
source_file_name | VARCHAR(255) | 原始文件名 |
索引:idx_kb_id + idx_kb_id_content_hash(增量索引)+ idx_parent_chunk_id + FULLTEXT ft_kb_chunk_content_ngram
kb_knowledge_base — 知识库文档表#
| 字段 | 设计决策 |
|---|---|
version | BIGINT,chunk 任何变更后自增,语义缓存通过此字段判断失效 |
status | uploading → processing → ready / error,异步处理状态机 |
file_type | pdf/docx/md/txt/ppt/pptx/jpg/png/url,MinerU 扩展后新增多种 |
file_url | 本地磁盘路径(uploads/)或原始 URL(url 类型)——不再用对象存储 |
qa_message — 对话消息表(4 类 JSON 结构化存储)#
| JSON 字段 | 存储内容 |
|---|---|
sources | 来源引用:文档名 + 章节 + 页码 + 相关性分数 |
agent_trace | ReAct 推理链:每步的 thought → action → observation |
mcp_calls | MCP 工具调用记录:工具名 + 入参 + 出参 + 耗时 |
reflection_log | (遗留列,自反思整类删除后保留兼容、不再写入;引用改由结构化 citations 随 done 下发) |
额外字段:confidence_score (FLOAT) + confidence_band (VARCHAR) 直接存储置信度。
qa_conversation — 对话会话表#
kb_ids (JSON) 存储关联知识库 ID 列表,message_count 计数,last_active 排序。
sys_ai_config — 动态配置表(详见下节)#
sys_user — 用户表#
role (admin/user) RBAC,password BCrypt 加密,preference (JSON) 用户偏好。
mcp_tool_registry — MCP 工具注册表#
call_count + avg_latency_ms 统计,mode (embedded/remote)。
user_memory — 长期记忆 SoR(系统事实来源)#
按 (user_id, memory_id) 唯一;软删 invalidated_at(审计)、superseded_by 审计链、access_count/last_accessed 支撑 recency×frequency 淘汰;无 TTL(记忆不能随空闲蒸发)。Redis 仅作读缓存、Milvus docmind_memory 仅作向量索引。详见 长期记忆三层存储。
sys_dept / sys_role / sys_permission / sys_role_permission / sys_user_role — RBAC#
部门 + 角色 + 权限 + 两张关联表,支撑 admin/user 角色与细粒度权限。
五、动态配置参数全景(sys_ai_config)#
RAG 组(19 个)#
| Key | 默认值 | 说明 |
|---|---|---|
rag.vector_top_k | 10 | 基础向量召回 Top-K |
rag.bm25_top_k | 10 | 基础 BM25 召回 Top-K |
rag.rerank_top_n | 5 | 基础重排 Top-N |
rag.chunk_size | 512 | 切片大小 |
rag.chunk_overlap | 64 | 切片重叠 |
rag.rrf_top_n | 30 | RRF 融合后候选数 |
rag.rerank_top_k | 6 | 重排最终保留数 |
rag.rrf_k_constant | 60 | RRF 平滑常数 |
retrieval.main.vector_top_k | 50 | 主查询向量候选池 |
retrieval.main.bm25_top_k | 50 | 主查询 BM25 候选池 |
retrieval.rerank.top_k | 8 | 精排输出条数 |
retrieval.early_stop.vector_threshold | 0.55 | 向量低质量阈值 |
retrieval.early_stop.bm25_threshold | 5.0 | BM25 低质量阈值 |
retrieval.early_stop.require_both_low | true | 双路低分才早停 |
retrieval.early_stop.rerank_threshold | 0.30 | 精排 fallback 阈值 |
generation.high_confidence_threshold | 0.85 | 高置信度阈值 |
generation.medium_confidence_threshold | 0.60 | 中等置信度阈值 |
agentic.enabled | true | agentic 检索循环总开关(灰度) |
agentic.max_iterations | 4 | agentic 循环迭代上限 |
citation.confidence_uses_coverage | true | 置信度是否用引用覆盖率 × rerank-top1 |
LLM 组(7 个)#
| Key | 默认值 | 说明 |
|---|---|---|
llm.model | qwen-plus | 主回答模型 |
llm.small_model | qwen-turbo | 轻决策模型(Query 改写 / 工具选择 / 范畴路由) |
llm.temperature | 0.7 | 通用温度 |
llm.chat_temperature | 0.7 | 对话温度 |
llm.streaming_temperature | 0.7 | 流式温度 |
llm.timeout_seconds | 60 | 请求超时 |
llm.max_tokens | 2048 | 最大输出 Token |
Memory 组(1 个)#
| Key | 默认值 | 说明 |
|---|---|---|
memory.extract_model | qwen-flash | 跨会话记忆提取专用模型。「LLM 即 Gate」下每轮都触发提取,用最廉价模型承接高频成本 |
Cache 组(5 个)#
| Key | 默认值 | 说明 |
|---|---|---|
cache.enable | true | 缓存总开关 |
cache.ttl_seconds | 3600 | 缓存 TTL(秒) |
cache.ttl_hours | 1 | 缓存 TTL(小时) |
cache.freq_threshold | 2 | 频次阈值(2 次即缓存) |
cache.semantic.distance_threshold | 0.92 | 语义缓存近邻阈值 |
cache.semantic.ttl_hours | 24 | 语义缓存兜底 TTL |
Safety 组(4 个)#
| Key | 默认值 | 说明 |
|---|---|---|
safety.enable_guard | true | 安全过滤开关 |
safety.max_retries | 2 | 最大自纠错轮数 |
safety.confidence_threshold | 0.6 | 兜底触发阈值 |
safety.fallback_msg | 抱歉… | 兜底话术 |
功能开关(3 个)#
| Key | 默认值 | 说明 |
|---|---|---|
mmr.enabled | true | MMR 多样性开关 |
mmr.lambda | 0.7 | MMR λ 参数 |
hyde.enabled | true | HyDE 开关 |
Agent 组(1 个)#
| Key | 默认值 | 说明 |
|---|---|---|
agent.observation.low_score_threshold | 0.4 | 低分触发 HyDE 阈值 |
六、Prompt 模板清单#
| 文件 | 用途 | 注入变量 |
|---|---|---|
knowledge_qa.txt | 标准 QA 回答生成 | {{question}} {{context}} {{history}} {{memoryContext}} {{userProfile}} |
knowledge_qa_low_confidence.txt | 低置信度降级回答 | 同上(显式声明证据不足) |
query_understanding.txt | 意图/复杂度/专指度/范畴一次分类 | {{query}} {{history}} |
hyde_generation.txt | HyDE 假设文档生成 | {{query}},输出约 200 字假设回答 |
memory_extract.txt | 长期记忆抽取 | {{query}} {{answer}} |
safety_check.txt | LLM 答案安全审查 | {{query}} {{context}} {{answer}} |
注:
knowledge_qa_decomposed.txt/query_decompose.txt/hop_answer_extract.txt已随拆解·多跳链路于四刀改造删除(当前 6 个模板)。
PromptAssembler 提供 3 种组装模式:
assemble()— 标准 QA,带 context + history + memoryassembleLowConfidence()— 低置信度(CRAG LOW 但有证据):仍注入 KB/Web chunk 据实作答并[n]引用(#28 主通路,不丢弃证据)assembleFallback()— 真·无证据兜底(compressed空,0 chunk):声明”知识库与联网检索均未返回相关内容” + 防陈旧幻觉护栏(严禁断言实体”不存在/未发布”,#28 P1-A) (assembleDecomposed()已随拆解链路删除)
七、部署架构#
两套 compose:docker-compose.dev.yml 只起基础设施(本地 npm run dev + mvn spring-boot:run 开发用);docker-compose.yml 是生产/演示全栈,一条 docker compose up -d --build 起全部 13 个服务。Milvus 用本地盘(COMMON_STORAGETYPE=local),MinIO 仅作 Langfuse v3 的 S3 后端,不再做应用对象存储。MySQL 已纳入全栈 compose(dev 版仍需独立运行)。
docker-compose.dev.yml(仅基础设施,4 服务)
┌──────────────────────────────────────────────┐
│ Redis 7 :6379 语义缓存 + 记忆读缓存 │
│ etcd :2379 Milvus 元数据存储 │
│ Milvus 2.4 :19530 向量数据库(本地盘) │
│ OpenSandbox :8090 代码执行沙箱控制面 │
└──────────────────────────────────────────────┘
(MySQL 8 :3306 需独立运行,dev 不纳入 compose)
docker-compose.yml(生产全栈,13 服务,一键起)
┌──────────────────────────────────────────────┐
│ 业务核心:mysql / redis / etcd / milvus │
│ backend(:8080) / frontend(:80) │
│ 代码沙箱:opensandbox(:8090) │
│ 可观测 :Langfuse v3 自托管栈 │
│ langfuse-web(:3000) / langfuse-worker │
│ + ClickHouse + Postgres + MinIO(:9001 控制台)│
│ (MinIO 仅作 Langfuse S3 事件/媒体存储) │
└──────────────────────────────────────────────┘
↑ 外部 API
┌──────────────────────────────────────────────┐
│ DashScope API — LLM (qwen-plus/max) │
│ DashScope API — Embedding (text-emb-v3) │
│ DashScope API — Rerank (gte-rerank) │
│ MinerU API — 文档解析(可选) │
│ Tavily API — 联网搜索(可选) │
│ Langfuse — LLM 可观测(自托管/可选) │
└──────────────────────────────────────────────┘plaintext八、面试 Q&A#
Q: 项目代码规模多大?
A: 后端 153 个 Java 文件(~18,500 行),核心 RAG 组件 26 个文件(
service/rag/)。前端 81 个 React/TypeScript 文件(~5,600 行,2026-06 从 Vue 3 彻底重构为 React 18 + shadcn/ui)。13 张数据库表,50+ 动态配置参数,6 个 Prompt 模板。全栈独立开发,经历 6 个 Phase + 对标主流四刀改造、评测驱动迭代。
Q: 最复杂的文件是哪个?
A: 核心编排原来是
DocMindAgent.java(曾 ~1349 行的上帝类),#31 已按职责拆开:入口DocMindAgent收缩到 ~135 行薄壳(会话装配 + 根 span + 顶层分流),析出ScopeRouter(范畴路由)、ShortCircuitResponder(紧急/闲聊/越界等短路)、SemanticCacheReplayer(缓存回放)、以及最复杂的RagPipeline(~600 行,知识问答主流水线:QU→路径决策三模式 SELECTED_DOC / RULE_PLANNER / AGENTIC→记忆→检索→CRAG→Prompt→流式生成 + 结构化引用,生成即终态、自反思已删)。检索核心仍拆两块:AGENTIC 走AgenticSearchOrchestrator(真·LLM 工具调用循环),其余走SupervisorAgent.oneShotRetrieval(四刀改造后从 ~1683 行瘦身到 ~595 行)。
Q: 数据库设计有什么亮点?
A: 三个设计值得讲:第一是
kb_chunk.content_hash(SHA-256),支撑增量索引——100 页 PDF 改 1 字只重新 embedding ~1 次。第二是kb_chunk.parent_chunk_id,支撑 Parent Document Retrieval 双层切块。第三是qa_message的 JSON 字段(sources / agent_trace / mcp_calls),把推理过程结构化存储,前端可回放展示(reflection_log列在自反思移除后保留兼容、不再写入;引用改由结构化 citations 随done下发)。