51dc8dc4f6
- FastAPI + Qdrant + Redis + Ollama 技术栈 - L1→L2→L3→chunk 四层分层检索(dense + sparse RRF 融合) - 文档三级总结与 2.5 级回退 - query 解析路由与分类 - /admin 管理页面
5.9 KiB
5.9 KiB
Tasks
- Task 1: 扩展配置与数据模型:config 增加 taxonomy/各层 top-k/sparse 开关/缓存 TTL 等参数;新建
app/models/knowledge.py(TaxonomyCategory、CategoryResult)与app/models/search.py(SearchRequest/SearchResponse/SearchHit);app/models/document.py增加 ChunkModel(doc_id、text、section_path、chunk_index)- SubTask 1.1: config.py 增加 taxonomy_path、classify_confidence_threshold、l1_doc_top_n、l2_section_top_n、l3_top_n、sparse_enabled、cache_ttl 等配置项,同步更新 .env.example
- SubTask 1.2: 新建 taxonomy 默认配置文件(内置通用类目集 + uncategorized),提供加载与校验函数
- SubTask 1.3: 新建 knowledge.py / search.py 模型,document.py 增加 ChunkModel 与 CategoryResult 引用
- Task 2: 向量服务:
app/core/embeddings.py(dense,openai | local 双 provider 统一异步接口,批量编码)+app/core/sparse.py(本地分词 + 特征哈希 BM25 稀疏向量,输出 Qdrant sparse vector 格式,不依赖外部模型)- SubTask 2.1: EmbeddingService 抽象 + openai provider 实现 + local provider(Ollama embedding 接口)实现
- SubTask 2.2: SparseEncoder(中文分词 + BM25 权重 + 特征哈希到固定维度),单测验证输出稀疏格式合法
- Task 3: Qdrant 服务封装
app/services/qdrant.py:启动时初始化 4 个集合(doc_l1 / doc_l2 / doc_l3 / chunks,chunks 与 doc_l1 带 sparse 向量配置),建立 category/tags/doc_id/section_path payload 索引;提供 upsert 与按层检索(支持 payload 过滤 + dense/sparse/hybrid 查询)接口- SubTask 3.1: 集合初始化与 payload 索引(幂等,应用启动时执行)
- SubTask 3.2: upsert 接口(按层写入,chunk 携带 dense+sparse)
- SubTask 3.3: 分层查询接口(dense 过滤查询 / hybrid 查询)
- Task 4: summarizer 改造 + chunk 切分器:L2 大纲优先解析原生标题树(Markdown 标题 + 编号标题正则),无结构回退现有 LLM 生成;新建
app/core/chunker.py按标题树切分 chunk(超长 section 按长度二次切分,短文本整篇单 chunk),chunk 记录 section_path 与 L2 节点对应关系- SubTask 4.1: 标题树解析器(Markdown ATX 标题 + 中文编号标题),输出 section 树
- SubTask 4.2: summarizer 接入标题树:有结构时 L2 直接用标题树生成大纲文本,无结构走原 prompt;L3 保持不变
- SubTask 4.3: Chunker 实现与单测(结构化/非结构化/短文本三种输入)
- Task 5: 分类器 + ingestion 全链路补全:
app/core/classifier.py(基于 L1 总结,Ollama JSON 约束输出主类+多标签+置信度,低置信归 uncategorized);改造app/core/ingestion.py串起 总结→分类→chunk 切分→双向量化→Qdrant 写入,返回真实 document_id 与集合信息- SubTask 5.1: Classifier 实现(taxonomy 注入 prompt,JSON 解析容错,置信度阈值判兜底)
- SubTask 5.2: Ingester 全链路串联(总结→分类→切 chunk→embedding→sparse→upsert 四层)
- SubTask 5.3: 入库失败处理:Qdrant 写入失败不丢已生成总结,返回明确错误码与可重试标识
- Task 6: 入库与类目 API:
app/api/v1/document.py(POST /api/v1/documents)、app/api/v1/knowledge.py(GET /api/v1/knowledge/categories),统一响应包装与错误码,main.py 注册路由 - Task 7: query 解析与分类路由:
app/core/query_parser.py(Ollama 小模型 JSON 约束输出:命中类目+置信度、rewrite query、关键词;解析失败/低置信/命中过多类目→全库兜底)- SubTask 7.1: QueryParser 实现与 JSON 容错解析
- SubTask 7.2: 路由决策函数(主类硬过滤 + 多标签软召回合并为 Qdrant payload filter + 兜底判定),单测覆盖三类分支
- Task 8: 分层检索引擎 + 重排 + 检索 API:
app/core/retriever.py(L1→L2→L3→chunk 逐层剪枝,2.5 级文档跳过 L2,空召回回退上一层直搜 chunk)+app/core/ranker.py(RRF 融合 + final_k 截断)+app/api/v1/search.py(POST /api/v1/search)- SubTask 8.1: Retriever 逐层 drill-down 主流程
- SubTask 8.2: 降级路径(2.5 级跳层、空召回回退、路由兜底直通)
- SubTask 8.3: Ranker RRF 融合与单测
- SubTask 8.4: 检索 API 与统一响应
- Task 9: Redis 缓存
app/services/redis.py:query 解析结果与检索结果缓存(短 TTL 可配置),缓存键含 query 与路由类目;Redis 不可用时降级直连不报错 - Task 10: 评测脚本骨架
scripts/eval/:回归集 JSON 格式定义与样例(≥5 篇文档、每篇 35 条应检出 query + 12 条不应检出 query,标注 golden doc/section/chunk);指标实现 Entity Recall、Routing F1、Pruning Loss、Precision@5/Recall@10;Hallucination Rate 用 Ollama LLM-as-judge 反查;支持平铺 chunk baseline 对比并输出 Markdown 报告(含门槛标红:L1 Entity Recall≥0.85、L3≥0.9、幻觉率<2%、Pruning Loss<8%)- SubTask 10.1: 回归集 schema + 样例数据
- SubTask 10.2: 摘要质量指标(Entity Recall / Hallucination Rate)
- SubTask 10.3: 检索效用指标(Routing F1 / Pruning Loss / Precision@5)+ baseline 对比报告
- Task 11: 端到端验证:docker compose 起 Qdrant/Redis/Ollama,走通 入库→检索→评测 全链路;
uv run pytest全绿;修复发现的问题
Task Dependencies
- [Task 2] depends on [Task 1]
- [Task 3] depends on [Task 1]
- [Task 4] depends on [Task 1]
- [Task 5] depends on [Task 2, Task 3, Task 4]
- [Task 6] depends on [Task 5]
- [Task 7] depends on [Task 1]
- [Task 8] depends on [Task 3, Task 7]
- [Task 9] depends on [Task 7, Task 8]
- [Task 10] depends on [Task 5, Task 8]
- [Task 11] depends on [Task 6, Task 9, Task 10]
Parallelizable
- Task 2 / Task 3 / Task 4 / Task 7 互相独立,可并行
- Task 6 与 Task 8 可并行(依赖均已满足后)