07 完整架构回顾
学习理念:这是整个章节的最终回顾,用一张全栈架构图串联所有知识点。建议在读完 01-06 后回来做一次"大脑整理"。
海外对标:Databricks Genie(Text2SQL 产品化)、Salesforce X-SQL(企业级 NL2SQL)
本节 AI 替代率:~90% | 人工干预率:~10%
| 角色 | 能力范围 |
|---|---|
| 🤖 AI 擅长 | 生成架构图、技术栈对比、面试问答 |
| 👤 人类需理解 | 12 节点工作流的全链路数据流转、三存储的设计动机 |
📌 原文说明:本章为新增的回顾总结章节,不直接对应原始笔记的某个章节,而是将原始笔记中分散在 2.4、6.3、7.3 等各处的架构图和描述统一编排为完整视图。原始笔记内容已在 01-06 篇中完整保存。
一、全栈架构总图
二、全链路数据流
一条查询的生命周期
用户输入: "统计去年各地区的销售总额"
step 1 [extract_keywords] : "统计" "去年" "各地区" "销售总额" (jieba分词)
↓
step 2 [recall_column 并行] : LLM扩展→"去年 sales amount region"→Qdrant→[order_amount, region_id]
step 2 [recall_metric 并行] : LLM扩展→"GMV sales by region"→Qdrant→[GMV_BY_REGION]
step 2 [recall_value 并行] : LLM扩展→"last year region"→ES→[华东, 华南, 华北, ...]
↓
step 3 [merge_retrieved_info]: 合并字段列表→按表分组→补充主外键→构造TableInfoState
↓
step 4 [filter_table 并行] : LLM→保留fact_order+dim_region相关字段
step 4 [filter_metric 并行] : LLM→保留GMV_BY_REGION
↓
step 5 [add_extra_context] : date=2026-06-29, quarter=Q2, dialect=mysql
↓
step 6 [generate_sql] : LLM生成→ SELECT r.region_name, SUM(f.order_amount) ...
↓
step 7 [validate_sql] : EXPLAIN 验证
↓ (error == None)
step 8 [execute_sql] : 执行→ [{"region_name":"华东","order_amount":150000}, ...]
↓
前端显示: 表格/图表三、技术栈总评估
| 技术 | 用途 | 健康度 | 本项目的角色 | 建议 |
|---|---|---|---|---|
| Python 3.12 | 开发语言 | 🔥 巅峰 | 全项目(async/await 语法) | 保留 |
| FastAPI | Web 框架 | 🔥 巅峰 | API 层(SSE + DI + 生命周期) | 保留 |
| LangGraph | Agent 编排 | 🔥 巅峰 | 12 节点工作流(StateGraph + 条件边) | 保留 |
| Qdrant | 向量数据库 | 🔥 巅峰 | 字段/指标语义检索 | 保留 |
| Elasticsearch | 全文检索 | 🟢 稳定 | 字段取值全文检索 | 保留 |
| SQLAlchemy Async | ORM | 🔥 巅峰 | MySQL 操作(meta + dw 双库) | 保留 |
| HuggingFace TEI | Embedding 服务 | 🟢 稳定 | bge-large-zh-v1.5 模型部署 | 保留 |
| OmegaConf | 配置管理 | ⏳ 成长期 | YAML → dataclass 配置加载 | 关注 Pydantic Settings |
| Loguru | 日志 | 🔥 巅峰 | request_id 全链路日志 | 保留 |
| jieba | 中文分词 | 🟢 稳定 | 关键词抽取 | 保留 |
| Vue3 + Vite | 前端框架 | 🔥 巅峰 | 前端展示 | 保留 |
| Docker Compose | 容器编排 | 🔥 巅峰 | 5 服务统一部署 | 保留 |
四、与第 19 章(掌柜智库)对比
| 对比维度 | 19 掌柜智库 | 20 掌柜问数 |
|---|---|---|
| 核心任务 | 知识图谱 RAG(文档→图谱→检索) | Text2SQL(自然语言→元数据→SQL) |
| 编排框架 | LangGraph(导入 8 节点 + 查询 9 节点) | LangGraph(12 节点,含条件边回退) |
| 向量库 | Milvus(课程第 3 次出现) | Qdrant(全新,首次) |
| 全文检索 | 无 | Elasticsearch(全新,首次) |
| 知识存储 | Neo4J 知识图谱 | MySQL 元数据库 |
| 检索方式 | 三路检索(向量+图+MCP)→ RRF 融合 → Reranker | 三路召回(列/值/指标)→ 合并过滤 → 生成 SQL |
| 提示词管理 | 少量硬编码 | 7 个独立 .prompt 文件 |
| 部署方式 | Docker 全容器 | FastAPI + Docker 基础设施 |
| 流式输出 | 任务进度 + 结果 | 节点级进度 + 查询结果 SSE |
| 前端 | Streamlit | Vue3 + Vite(基础) |
五、项目文件全景索引
P0 🔥 核心文件(17 个)
| 模块 | 文件 |
|---|---|
| 入口 | main.py |
| 工作流 | app/agent/graph.py / state.py / context.py |
| 节点 | app/agent/nodes/extract_keywords.py / recall_column.py / recall_value.py / recall_metric.py / merge_retrieved_info.py / generate_sql.py / validate_sql.py |
| API | app/api/routers/query_router.py / app/services/query_service.py / app/api/dependencies.py |
| 构建 | app/scripts/build_meta_knowledge.py / app/services/meta_knowledge_service.py |
| 配置 | app/conf/app_config.py + conf/app_config.yaml |
P1 🟡 关键文件(14 个)
| 模块 | 文件 |
|---|---|
| 节点 | filter_table.py / filter_metric.py / add_extra_context.py / correct_sql.py / execute_sql.py |
| 客户端 | app/clients/mysql_client_manager.py / embedding_client_manager.py / qdrant_client_manager.py / es_client_manager.py |
| Repository | meta_mysql_repository.py / dw_mysql_repository.py / column_qdrant_repository.py / metric_qdrant_repository.py / value_es_repository.py |
P2 🟢 辅助文件(15 个)
| 模块 | 文件 |
|---|---|
| Entity | table_info.py / column_info.py / metric_info.py / column_metric.py / value_info.py |
| Model | base.py / table_info_mysql.py / column_info_mysql.py / metric_info_mysql.py / column_metric_mysql.py |
| Mapper | table_info_mapper.py / column_info_mapper.py / metric_info_mapper.py / column_metric_mapper.py |
| 配置 | meta_config.py |
| Core | lifespan.py / context.py / log.py |
| Prompt | prompt_loader.py |
六、AI 面试自测题
- 为什么本项目选择 Qdrant 而不是 Milvus/Chroma?Qdrant 在异步支持上有哪些优势?
- 12 个节点的工作流中,哪些节点是并行执行的?为什么这样设计?
- validate_sql 的条件边如果无限循环(correct_sql 后 validate_sql 又失败),怎么防止?
- 元数据知识库为什么需要三个存储系统(MySQL + Qdrant + ES)?只用 Qdrant 行不行?
- 如果用户说"给我看看数据",LLM 生成的 SQL 可能是什么?怎么兜底?
- LLM 扩展关键词的双阶段模式有什么好处?直接检索有什么问题?