Skip to content

项目工程全景(代码级地图)

面试中回答"项目规模多大""代码结构是什么""数据库怎么设计的"时的参考。 所有数据来自源码实际统计,非估算。


一、仓库统计

维度数值
后端 Java 源文件143 个(~18,200 行)
前端 Vue/TS 源文件35 个(~6,900 行)
核心 RAG 组件29 个文件
数据库表14 张(7 核心业务 + 7 离线评测)
动态配置参数39 个(sys_ai_config,6 组:rag/llm/cache/safety/功能开关/agent)
Prompt 模板8 个
MCP 工具5 个 / 6 端点(双路径)
Docker 服务5 个(Redis + MinIO + etcd + Milvus standalone + Milvus attu)

二、后端包结构(com.simon.DocMind)

agent/ — Agent 核心(21 文件)

文件行数职责
DocMindAgent.java1510ReAct 主编排器:SSE 流式、语义缓存、紧急短路、范畴路由、路径决策、6 阶段推理循环
MetaIntentDetector.javaPhase 5: Tier-0 纯正则范畴判定(6 条规则,零 LLM)
ScopeDecision.javaPhase 5: 范畴判定结果 record(6 种 Scope + confidence + fastPath)
PathDecision.javaPhase 5: 路径决策结果 record(SELECTED_DOC / DECOMPOSED / RULE_PLANNER + reason)
AgentToolContext.javaThreadLocal 侧通道:工具执行结果汇总,synchronizedList + finally 清理
SelectedDocumentScopeDecider.java用户选定文档时绕过搜索,直接读 chunk 均匀采样
SelfReflection.java254四维评分(事实一致/完整/来源/表达)+ 条件重写 + 切题度检查(Phase 5)

agent/supervisor/ (7 文件)

文件行数职责
SupervisorAgent.java586编排核心:3 路策略(迭代 ReAct / Plan-and-Execute / 子问题拆解)
IterationDecider.java终止决策:置信度阈值 + 轮次上限 + 停滞检测 → CONTINUE/SWITCH/TERMINATE
ObservationEvaluator.java质量评估 + 5 种降级动作推荐(空召回→Web, 低分→HyDE, 冲突→Analysis)
PlanGenerator.javaLLM 生成结构化 JSON 执行计划
PlanExecutor.java按 dependsOn 拓扑排序 + 同层 CompletableFuture 并行
ExecutionPlan.java计划数据载体(record)+ fallback 工厂方法
SupervisorResult.java编排输出(record)

agent/worker/ (7 文件)

文件行数职责
Worker.java统一接口(execute + name)
RetrievalWorker.java封装 Vector + BM25 + RRF + Rerank + MMR + ParentChunk
WebWorker.java封装 Tavily 搜索
MemoryWorker.java封装 Redis 长期记忆读取
AnalysisWorker.javaLLM 多文档对比分析
WorkerRequest.javaWorker 入参(record)
WorkerResult.javaWorker 出参 + 工厂方法(record)

agent/state/ (2 文件)

文件职责
AgentState.java推理状态机:Evidence 累积、置信度轨迹、策略记录、查询分类
Evidence.java标准证据结构(record)

service/rag/ — RAG 检索管线(29 文件)

文件行数职责
QueryUnderstandingService.java498合并 5 个旧组件的统一分类器:意图/复杂度/专指度/时效/记忆 + 确定性后处理
BM25Retriever.java265MySQL FULLTEXT 预召回 + Java BM25 评分(K1=1.5, B=0.75)+ 短语覆盖加分
PromptAssembler.java2493 模式 Prompt 组装(标准/拆解/降级)+ 对话历史裁剪(6 条)
CrossEncoderReranker.java233DashScope gte-rerank API + 降级关键词覆盖度打分 + 去重截断
SemanticCacheService.java209query embedding cosine 近邻 + KB version 校验 + Redis 存取
VectorRetriever.java154Milvus COSINE 检索(HNSW ef=64)+ 标量过滤
MMRDiversifier.java127MMR 多样性重排(λ=0.7, bigram Jaccard 相似度)
ParentChunkResolver.java128子块→父块展开 + 同父去重
SafetyGuard.java111紧急词检测 + 置信度阈值 + LLM 答案安全审查
RRFFusion.java92RRF 等权/加权融合(k=60)+ HYBRID 标记 + 50-char 去重
HyDEGenerator.java70假设文档生成(小模型 200-400ms)+ 失败回退原 query
RetrievalPlanner.java100Phase 5: 规则引擎(零 LLM):4 信号 → 工具选择,双源时效性校验
RetrievalGrader.javaPhase 5: CRAG 三档评分(HIGH/AMBIGUOUS/LOW)+ 灰区仲裁(heuristic/cross_encoder/disabled)
GradeResult.javaPhase 5: 评分结果 record(tier + topScore + avgScore + reason)
RecommendationGenerator.java推荐阅读:同 category + tags 共现 → 最多 3 条
EarlyStopGate.java双关检索质量门:vector/BM25 低分 + rerank 低分
KbVersionService.javaKB 版本号管理(缓存失效用)
SourcePayloadFactory.java来源 JSON 构建(文档名+章节+页码+分数)
SubQueryMerger.java保底分配 + 全局补齐 + 跨子问题去重
ChineseTextTokenizer.javaLucene SmartCN 中文分词包装
QueryClassification.java分类输出 record(9 字段)
QueryUnderstandingResult.java理解结果 record
DecompositionResult.java拆解结果 record
SubQuery.java子问题 record
SubQueryRetrievalResult.java子问题检索结果 record
RetrievalPlan.java检索计划 record
RetrievedChunk.java检索 chunk 载体(score + metadata + source 枚举)
SemanticCacheEntry.java缓存条目 record

service/knowledge/ — 文档处理(5 文件)

文件行数职责
TextChunker.java542Markdown-Aware 双层切块:5 种 block 识别 + heading 栈 + content_hash
DocumentExtractor.java多格式路由:PDF→MinerU+PDFBox / DOCX→POI / PPT+图片→MinerU / URL→MinerU-HTML
MilvusService.javaMilvus CRUD:insertVectors(带外部 ID) / deleteByVectorIds / search
MinerUClient.javaMinerU 云端 API 双流程客户端(文件+URL)+ 合并轮询
MinioService.javaMinIO S3 兼容存储:上传/下载/删除原件

mcp/ — MCP 工具(5 文件,双路径)

文件内部调用外部暴露职责
DocSearchTool.javaSpring AI Function CallingMCP Server endpoint语义向量检索
KeywordSearchTool.javaSpring AI Function CallingMCP Server endpointBM25 关键词检索
WebSearchTool.javaSpring AI Function CallingMCP Server endpointTavily 联网搜索
MemoryTool.javaSpring AI Function CallingMCP Server endpointRedis 长期记忆(recall + store)
KbMetaTool.javaAgent KB_META 短路路径直接查 DBMCP Server endpoint知识库元信息查询

同一套 @Tool 注解代码既被内部 ChatClient 调用,也通过 spring-ai-starter-mcp-server-webmvc 对外暴露。工具执行结果通过 AgentToolContext ThreadLocal 写入,Agent 读取后清理。

MCP 安全边界(MVP → 生产):当前 MCP Server 无独立鉴权层,内部调用由 AgentToolContext + 用户会话上下文保证 kbIds 隔离和 userId 注入。外部调用存在 4 个加固点:①工具端点需接入 JWT/API-Key 校验;②kbIds 需校验用户归属;③Memory userId 需从 auth context 注入,禁止外部指定;④Web Search 需接入 rate-limiter 防配额滥用。


config/ — 配置(21 文件)

文件职责
AiConfigHolder.javaConcurrentHashMap 配置 + AtomicReference 热替换 ChatModel + 双模型 callSmallModel
AiConfigInitializer.java启动时按 key 增量插入 sys_ai_config 默认值
LlmConfig.javaSpring AI OpenAI-compatible ChatModel / EmbeddingModel Bean
MilvusConfig.javaMilvus 连接 + Collection 初始化(COSINE, HNSW)
RedisConfig.javaRedisTemplate<String, Object> 序列化
MinioConfig.javaMinIO S3 客户端 Bean
SecurityConfig.javaSpring Security 过滤链 + JWT + CORS + 路径白名单
WebSearchConfig.javaTavily RestTemplate Bean
McpToolsConfig.javaToolCallbackProvider 注册 MCP 工具
MinerUConfig.javaMinerU 专用 RestTemplate(独立超时策略)
MinerUProperties.java@ConfigurationProperties MinerU 配置封装
LangfuseOtelConfig.javaPhase 6 增强: OTel SDK + BatchSpanProcessor + RootNameFilteringSpanProcessor 白名单过滤
LangfuseProperties.javaLangfuse 连接参数(enabled/baseUrl/publicKey/secretKey)
ChatModelObservationFilter.javaPhase 6: Spring AI Observation → OTel span 桥接(prompt/completion 自动采集,截断 10000 字)
RagExecutorConfig.javaQuery Decomposition 专用线程池(core=8, max=16)
DocmindWebSearchProperties.javaWeb 搜索配置属性
WebSocketConfig.javaWebSocket 端点配置
WebMvcConfig.java静态资源映射
MybatisPlusConfig.javaMyBatis Plus 分页插件
AppInitConfig.java应用启动初始化
KbChunkIndexInitializer.java启动时初始化 BM25 Lucene 索引

controller/ — REST API(9 文件)

文件端点前缀职责
DocMindChatController.java/api/v2/chatSSE 流式问答 + 会话管理
KnowledgeBaseController.java/api/knowledge文档上传/列表/删除/更新/URL 入库
KbChunkController.java/api/chunkschunk 明细查看
McpConsoleController.java/api/mcpMCP 工具注册表 + 调用统计
AiConfigController.java/api/ai-config27 个动态参数 CRUD
UserController.java/api/users用户注册/登录/JWT 刷新/RBAC
StatsController.java/api/stats统计面板数据
DocMindStatsController.java/api/v2/stats增强统计
SpeechWebSocketServer.java/ws/speech语音输入 WebSocket

support/ — 工具类

文件职责
TracedOp.javaPhase 6: OTel span 样板代码消除工具(run/exec 方法封装 span 生命周期)

entity/ — 数据模型(15 文件)

实体 + DTO + VO,对应 14 张数据库表(7 核心业务 + 7 离线评测)。

mapper/ — MyBatis Plus

每个实体一个 Mapper 接口。XML 配置在 src/main/resources/mapper/

security/ — 安全(2 文件)

文件职责
JwtAuthenticationFilter.java拦截请求,解析 JWT,设置 SecurityContext
UserDetailsServiceImpl.java从 sys_user 表加载用户信息

三、前端结构(DocMind-frontend/src/)

views/ — 页面(10 Vue 文件)

文件职责
chat/ChatView.vueSSE 事件状态机 + 流式 Markdown 渲染 + 来源卡片 + Agent trace + 置信度徽章 + Phase 6: 思考时间线(11 步类型)+ 路由/评分三色徽章
knowledge/KnowledgeView.vue文件上传 + URL 入库 + 处理状态轮询 + 文档管理
mcp/McpView.vueMCP 工具注册表 + 调用统计图表
admin/AiConfigView.vue49 参数分组编辑面板
dashboard/DashboardView.vueECharts 统计面板
auth/LoginView.vue登录页
auth/RegisterView.vue注册页
auth/ForgotPasswordView.vue密码重置
user/ProfileView.vue用户信息
user/UserManageView.vue用户管理(admin)

api/ — HTTP 客户端(6 TS 文件)

chat.ts / knowledge.ts / mcp.ts / aiConfig.ts / stats.ts / user.ts

其他

  • stores/user.ts — Pinia 用户状态(JWT token 管理)
  • utils/request.ts — Axios 实例 + JWT 拦截器 + 401 自动跳转
  • router/index.ts — Vue Router + 路由守卫
  • layout/MainLayout.vue — 侧边栏导航布局

四、数据库表设计(14 张表)

kb_chunk — 文档切片表(核心表,8 个设计决策)

字段类型设计决策
contentTEXT切片文本,FULLTEXT INDEX (ngram) 支持 BM25
content_hashVARCHAR(64)SHA-256 hex,增量索引核心——按 (kb_id, content_hash) diff
vector_idVARCHAR(100)与 Milvus 1:1 映射(VarChar PK),精准删除依赖此字段
metadataJSON{chapter, contentType, pageNumber, docVersion, effectiveDate}
tagsVARCHAR(512)JSON 数组,从 heading 栈自动提取,支持 LIKE 过滤
doc_versionVARCHAR(32)文档版本号
parent_chunk_idBIGINT外键→父块 ID,Parent Document Retrieval 的基础
source_file_nameVARCHAR(255)原始文件名

索引:idx_kb_id + idx_kb_id_content_hash(增量索引)+ idx_parent_chunk_id + FULLTEXT ft_kb_chunk_content_ngram

kb_knowledge_base — 知识库文档表

字段设计决策
versionBIGINT,chunk 任何变更后自增,语义缓存通过此字段判断失效
statusuploading → processing → ready / error,异步处理状态机
file_typepdf/docx/md/txt/ppt/pptx/jpg/png/url,MinerU 扩展后新增多种
file_urlMinIO 路径或原始 URL(url 类型)

qa_message — 对话消息表(4 类 JSON 结构化存储)

JSON 字段存储内容
sources来源引用:文档名 + 章节 + 页码 + 相关性分数
agent_traceReAct 推理链:每步的 thought → action → observation
mcp_callsMCP 工具调用记录:工具名 + 入参 + 出参 + 耗时
reflection_log自纠错日志:4 维评分 + 通过/不通过 + issues

额外字段: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)。


五、动态配置参数全景(39 个 sys_ai_config)

RAG 组(19 个)

Key默认值说明
rag.vector_top_k10基础向量召回 Top-K
rag.bm25_top_k10基础 BM25 召回 Top-K
rag.rerank_top_n5基础重排 Top-N
rag.chunk_size512切片大小
rag.chunk_overlap64切片重叠
rag.rrf_top_n30RRF 融合后候选数
rag.rerank_top_k6重排最终保留数
rag.rrf_k_constant60RRF 平滑常数
retrieval.main.vector_top_k50主查询向量候选池
retrieval.main.bm25_top_k50主查询 BM25 候选池
retrieval.sub.vector_top_k15子查询向量 Top-K
retrieval.rerank.top_k8精排输出条数
retrieval.early_stop.vector_threshold0.55向量低质量阈值
retrieval.early_stop.bm25_threshold5.0BM25 低质量阈值
retrieval.early_stop.require_both_lowtrue双路低分才早停
retrieval.early_stop.rerank_threshold0.30精排 fallback 阈值
generation.high_confidence_threshold0.85高置信度阈值
generation.medium_confidence_threshold0.60中等置信度阈值
reflection.skip_threshold0.85反思高分短路阈值

LLM 组(6 个)

Key默认值说明
llm.modelqwen-plus主回答模型
llm.temperature0.7通用温度
llm.chat_temperature0.7对话温度
llm.streaming_temperature0.7流式温度
llm.timeout_seconds60请求超时
llm.max_tokens2048最大输出 Token

Cache 组(6 个)

Key默认值说明
cache.enabletrue缓存总开关
cache.ttl_seconds3600缓存 TTL(秒)
cache.ttl_hours1缓存 TTL(小时)
cache.freq_threshold2频次阈值(2 次即缓存)
cache.semantic.distance_threshold0.92语义缓存近邻阈值
cache.semantic.ttl_hours24语义缓存兜底 TTL

Safety 组(4 个)

Key默认值说明
safety.enable_guardtrue安全过滤开关
safety.max_retries2最大自纠错轮数
safety.confidence_threshold0.6兜底触发阈值
safety.fallback_msg抱歉...兜底话术

功能开关(3 个)

Key默认值说明
mmr.enabledtrueMMR 多样性开关
mmr.lambda0.7MMR λ 参数
hyde.enabledtrueHyDE 开关

Agent 组(1 个)

Key默认值说明
agent.observation.low_score_threshold0.4低分触发 HyDE 阈值

六、Prompt 模板清单

文件用途注入变量
knowledge_qa.txt标准 QA 回答生成
knowledge_qa_decomposed.txt拆解模式回答同上 + + chunk 标注 (子问题 #1, #2)
query_understanding.txtPhase 1a 意图/复杂度/专指度分类
query_decompose.txtPhase 1b 子问题拆解
hyde_generation.txtHyDE 假设文档生成,输出约 200 字假设回答
knowledge_qa_low_confidence.txt低置信度降级回答同 knowledge_qa + 显式声明"检索结果不足"
memory_extract.txt用户记忆提取 → 输出结构化记忆点
safety_check.txtLLM 答案安全审查

PromptAssembler 提供 3 种组装模式:

  • assemble() — 标准 QA,带 context + history + memory
  • assembleDecomposed() — 每条 chunk 标注子问题归属
  • assembleFallback() — 低置信度降级,显式声明"未找到充分依据"

七、部署架构

docker-compose.dev.yml
┌──────────────────────────────────────────────┐
│ Redis 7           :6379    缓存 + 用户记忆   │
│ MinIO             :9000    S3 兼容对象存储    │
│ etcd              :2379    Milvus 元数据存储  │
│ Milvus standalone :19530   向量数据库         │
│ Milvus attu       :8000    向量库管理 UI      │
└──────────────────────────────────────────────┘
         ↑ 连接
┌──────────────────────────────────────────────┐
│ MySQL 8           :3306    业务数据 + BM25    │
│ (需独立运行,非 docker-compose 管理)          │
└──────────────────────────────────────────────┘
         ↑ 连接
┌──────────────────────────────────────────────┐
│ Spring Boot 3.4   :8080    后端 API + MCP    │
│ Vue 3 + Vite      :5173    前端 (proxy→8080) │
└──────────────────────────────────────────────┘
         ↑ 外部 API
┌──────────────────────────────────────────────┐
│ DashScope API     — LLM (qwen-plus/turbo)    │
│ DashScope API     — Embedding (text-emb-v3)  │
│ DashScope API     — Rerank (gte-rerank)      │
│ MinerU API        — 文档解析(可选)          │
│ Tavily API        — 联网搜索(可选)          │
│ Langfuse          — LLM 可观测性(可选)      │
└──────────────────────────────────────────────┘

八、面试 Q&A

Q: 项目代码规模多大?

A: 后端 143 个 Java 文件(~18,200 行),核心 RAG 组件 29 个文件。前端 35 个 Vue/TypeScript 文件(~6,900 行)。14 张数据库表,39 个动态配置参数,8 个 Prompt 模板。全栈独立开发,经历 6 个 Phase、20 次评测驱动迭代。

Q: 最复杂的文件是哪个?

A: DocMindAgent.java(1510 行),是 ReAct 编排器的入口——管理 SSE 流式、语义缓存、紧急短路、范畴路由、路径决策、6 阶段推理循环、Self-Reflection 条件重写。Phase 2 重构时从 1400 行降到 ~900 行,Phase 5/6 加回范畴路由和路径决策后升到 1510 行。核心检索逻辑委托给了 SupervisorAgent(586 行)。

Q: 数据库设计有什么亮点?

A: 三个设计值得讲:第一是 kb_chunk.content_hash(SHA-256),支撑增量索引——100 页 PDF 改 1 字只重新 embedding ~1 次。第二是 kb_chunk.parent_chunk_id,支撑 Parent Document Retrieval 双层切块。第三是 qa_message 的 4 个 JSON 字段(sources / agent_trace / mcp_calls / reflection_log),把推理过程结构化存储,前端可回放展示。