- Implemented tenant and user management features including: - Tenant creation and management with associated migrations. - User creation and management with associated migrations. - Tenant membership management with associated migrations. - Platform user roles management with associated migrations. - Quota management with associated migrations. - Article and template management with associated migrations. - Added HTTP handlers for templates and workspaces. - Created tests for protected and public routes. - Introduced a script to check tenant scope in SQL queries. - Documented task plan for backend completion and frontend foundation.
14 KiB
GEO 平台 Qdrant 版 RAG 架构设计 V1
1. 文档信息
| 项目 | 内容 |
|---|---|
| 文档名称 | GEO 平台 Qdrant 版 RAG 架构设计 V1 |
| 文档版本 | V1.0 |
| 文档状态 | 待评审 |
| 创建日期 | 2026-03-25 |
| 适用范围 | GEO 平台 V1 知识库与高精度 RAG 检索 |
| 关联文档 | docs/geo-platform-tech-architecture-v1-50k.md |
| 关联文档 | docs/geo-platform-prd-v1.md |
2. 设计目标
本文档用于定义 GEO 平台在 V1 阶段的 RAG 技术方案,目标是:
- 让知识库检索结果足够精准,支持品牌内容生成和问答增强。
- 将事务型业务数据与向量检索能力解耦。
- 在 5 万在线用户前提下,保证知识库查询链路稳定、可扩展。
- 为后续多品牌、多租户、多知识源、多平台内容生成打好基础。
3. 设计结论
V1 的 RAG 主方案建议为:
PostgreSQL负责知识元数据、权限、品牌、分组、任务状态Qdrant负责向量索引和向量检索对象存储负责原始文档和解析中间产物Worker负责解析、切片、Embedding、写入、重建索引
检索链路建议为:
- 查询预处理
- 过滤条件构造
- Qdrant dense / hybrid 检索
- rerank 精排
- 上下文拼装
- 提交给大模型生成
4. 为什么选 Qdrant
4.1 业务需求决定
GEO 平台的 RAG 检索不是简单的“全文找相似段落”,而是带强业务约束的检索:
- 只检索当前租户数据
- 只检索当前品牌或选定品牌数据
- 只检索指定知识分组或文档类型
- 需要按更新时间、来源、文档权重做过滤或排序
- 后续要支持 hybrid search 和 rerank
因此检索系统必须同时擅长:
- 高效向量召回
- 高效 payload filter
- 后续高精度搜索演进
4.2 相比 pgvector 的优势
Qdrant 更适合做 V1 主方案,原因如下:
- 向量检索从 PostgreSQL 主交易链路中解耦
- metadata filter 能力更适合 RAG 场景
- 后续扩容路径清晰
- 更方便演进到 hybrid search、多向量和 rerank 方案
4.3 pgvector 的角色
pgvector 仍可作为轻量备选方案:
- 数据量较小
- 团队只有单数据库运维能力
- 只是验证 MVP
但如果目标是“RAG 要精准好用”,Qdrant 更适合作为长期主方案。
5. RAG 场景定义
5.1 主要使用场景
A. 文章生成增强
在生成品牌文章时,从品牌知识库中召回相关背景材料、产品说明、FAQ、历史内容和网页资料,为模型生成提供高质量上下文。
B. 品牌问答增强
当系统生成“问题集答案”“趋势分析”“竞品分析”类内容时,先检索品牌知识和文档片段,再交给模型组织答案。
C. 内容优化增强
对已有文章做优化时,检索品牌标准话术、产品卖点、平台规范、历史高质量文章片段。
5.2 不适合 V1 的场景
- 跨品牌全局开放检索
- 实时抓取网页后秒级入库并立刻高质量检索
- 十亿级向量规模
- 强知识图谱推理
6. 数据分层设计
6.1 PostgreSQL 存储内容
PostgreSQL 中保存:
knowledge_basesknowledge_groupsknowledge_itemsknowledge_parse_tasksknowledge_chunks_metabrandtenantdocument_aclretrieval_logsrag_eval_cases
PostgreSQL 的职责
- 保存业务主数据
- 控制权限与租户隔离
- 提供后台列表页查询
- 保存 chunk 元数据和状态
- 保存评测数据和命中日志
6.2 Qdrant 存储内容
Qdrant 中保存:
- chunk 向量
- chunk payload
- 文档级过滤字段
- chunk 排序辅助字段
Qdrant 的职责
- 相似度召回
- filter + ANN 检索
- hybrid search
- rerank 前候选集召回
6.3 对象存储内容
- 原始 PDF / DOCX / TXT / HTML
- 提取后的 Markdown / 纯文本
- 清洗后的中间文件
7. Collection 设计
7.1 设计原则
V1 不建议每个品牌一个 collection,也不建议每个租户大量拆 collection。
推荐策略:
- 按业务域建立少量 collection
- 通过 payload filter 做租户、品牌、分组隔离
- 避免 collection 数量过多导致管理复杂
7.2 推荐 collection
collection 1: kb_chunk_main
用途:
- 存放知识库标准 chunk
- 支撑文章生成、优化、品牌问答等主要检索
collection 2: content_example_main
用途:
- 存放历史优质文章片段
- 支撑风格参考、结构参考、示例生成
V1 如果要尽量简单,也可以先只保留一个 kb_chunk_main。
7.3 向量字段建议
主向量
dense_vector- 维度按所选 embedding 模型决定
- 距离建议优先
Cosine
预留向量
后续可扩展:
title_vectorsummary_vectorsparse_vector
V1 可以先只落一个 dense vector。
8. Payload 设计
8.1 必须字段
每个 chunk 在 Qdrant 中建议至少带以下 payload:
| 字段 | 类型 | 说明 |
|---|---|---|
tenant_id |
keyword | 租户隔离 |
brand_id |
keyword | 品牌过滤 |
kb_id |
keyword | 知识库 ID |
group_id |
keyword | 分组过滤 |
item_id |
keyword | 文档 ID |
chunk_id |
keyword | chunk 唯一 ID |
doc_type |
keyword | 文档类型 |
source_type |
keyword | 来源类型,如上传文档/网页/手输 |
language |
keyword | 语言 |
status |
keyword | 是否可检索 |
priority |
integer | 文档优先级 |
published_at |
integer | 发布时间时间戳 |
updated_at |
integer | 更新时间时间戳 |
token_count |
integer | chunk token 数 |
title |
text/keyword | 文档标题 |
tags |
keyword[] | 标签 |
8.2 推荐扩展字段
| 字段 | 类型 | 说明 |
|---|---|---|
is_official_doc |
bool | 是否官方资料 |
is_product_doc |
bool | 是否产品文档 |
author |
keyword | 作者 |
source_url |
keyword | 来源链接 |
quality_score |
float | 文档质量分 |
freshness_score |
float | 时效性分 |
manual_boost |
float | 人工加权 |
8.3 索引建议
Qdrant 中对高频 filter 字段建立 payload index,优先包括:
tenant_idbrand_idgroup_iddoc_typestatussource_type
如果查询高频使用时间和标签,也可以增加:
updated_attags
9. Chunk 设计
9.1 核心原则
RAG 准确率很多时候不是输在向量库,而是输在 chunk 切分。
切分原则:
- 按语义结构切,不按固定字数硬切
- 保持 chunk 语义完整
- 控制 chunk 粒度不要过大
- 保留上下文关联信息
9.2 推荐切分策略
文档型内容
优先按以下结构切分:
- 一级标题
- 二级标题
- 段落簇
- 列表块
- 表格说明块
网页型内容
优先清洗掉:
- 导航
- 页脚
- 广告
- 无意义重复区域
保留:
- 标题
- 摘要
- 正文
- FAQ
- 参数表
9.3 V1 chunk 参数建议
- 目标 token:
300 ~ 600 - overlap:
50 ~ 100 - 对 FAQ 场景可更短:
100 ~ 250 - 对长报告场景可按标题段落聚合到
500 ~ 800
说明
- 太短会导致上下文碎片化,召回噪音高
- 太长会导致 embedding 表达不准,且浪费上下文窗口
9.4 特殊处理建议
FAQ 文档
按 问题 + 答案 成对切 chunk,不要拆开。
产品参数文档
按“模块 + 参数块”切分,并保留型号、版本、发布时间。
品牌官网介绍
品牌介绍、品牌故事、产品卖点、售后说明应分开切分。
10. 入库流程设计
10.1 标准流程
- 用户上传文档或录入网页。
- 文件进入对象存储。
- 创建解析任务。
- Worker 提取文本并清洗。
- 按规则切 chunk。
- 为每个 chunk 生成 embedding。
- chunk 写入 PostgreSQL 元数据表。
- 向量和 payload 写入 Qdrant。
- 更新知识条目状态为可用。
10.2 幂等要求
- 同一文档重复上传要可识别
- chunk 重建时采用版本号或软删除策略
- 文档更新后需支持全量替换对应 chunk
10.3 文档版本策略
推荐方案:
knowledge_item保存文档主记录knowledge_item_version保存版本记录knowledge_chunk_meta带 version 字段- Qdrant payload 中写入
item_version
检索时仅查询当前生效版本。
11. 检索流程设计
11.1 标准检索链路
- 接收用户查询或文章生成任务上下文
- 做 query rewrite
- 构造 filter 条件
- 从 Qdrant 召回 topK 候选 chunk
- 使用 reranker 精排
- 去重与多样性控制
- 拼接最终上下文
- 返回给大模型
11.2 查询预处理
建议包含:
- 去除无意义词
- 标准化品牌名、产品名、简称
- 同义词扩展
- 根据任务类型追加意图词
例如:
- “帮我写某品牌数字时尚趋势文章”
- 可以扩展为:
- “数字时尚 品牌趋势 新趋势 消费者关注点 产品风格 设计趋势”
11.3 filter 策略
RAG 结果想精准,必须优先加 filter,而不是裸搜。
推荐默认过滤条件:
tenant_id = 当前租户status = active
可选过滤条件:
brand_id in 当前品牌集合group_id in 指定知识分组doc_type in 允许文档类型updated_at > 某时间
11.4 召回策略
V1 基础版
- dense retrieval
- topK = 30 ~ 50
V1 推荐版
- dense retrieval + BM25 或 sparse retrieval
- hybrid merge
- rerank top 30
- 最终输出 top 5 ~ 10
11.5 去重与多样性
召回后应做:
- 同文档 chunk 去重
- 相邻 chunk 合并
- 标题级去重
- 不同来源混排
防止最终上下文全部来自同一篇文档的连续片段。
12. rerank 设计
12.1 为什么必须 rerank
向量召回解决的是“先找一批可能相关的候选”,不是最终最准排序。
如果不做 rerank,常见问题包括:
- 语义相近但不回答问题
- 命中了品牌,但不是当前主题
- 召回结果太泛
12.2 V1 rerank 方案
推荐两级:
方案 A:轻量版
- dense topK 召回
- 用 cross-encoder reranker 排序
- 取前 5 到 8 个 chunk
方案 B:增强版
- dense + sparse hybrid
- rerank
- 基于来源权重、官方文档权重、时效权重做分数融合
12.3 打分建议
最终分数建议由以下部分组成:
- semantic_score
- rerank_score
- quality_score
- freshness_score
- manual_boost
可采用线性融合,V1 不必一开始做复杂学习排序。
13. 上下文拼装策略
13.1 拼装原则
- 少而准优于多而杂
- 优先保留完整意义块
- 优先官方和高质量来源
- 记录引用来源,方便可解释
13.2 推荐拼装方式
每个返回 chunk 建议带:
- 文档标题
- 来源类型
- 来源 URL
- chunk 正文
- 更新时间
拼装给模型时,建议按主题分组,而不是简单拼接长文本。
13.3 token 控制
不同任务控制不同上下文预算:
- 短文章生成:
1000 ~ 2000 tokens - 长文章生成:
2000 ~ 5000 tokens - 问答增强:
800 ~ 1500 tokens
14. 多租户与权限设计
14.1 隔离原则
所有检索必须带 tenant_id 过滤,不允许裸查询。
14.2 品牌隔离
如果一个用户一次只操作一个品牌,检索时默认加:
brand_id = current_brand
如果是跨品牌分析,再显式放开。
14.3 文档权限
如果后续支持团队协作,可增加:
- 可见范围
- 部门范围
- 角色范围
V1 可以先在 PostgreSQL 中控制可见性,再把最终允许检索的 payload 写入 Qdrant。
15. 性能设计
15.1 查询延迟目标
| 项目 | 目标 |
|---|---|
| query rewrite | < 50ms |
| Qdrant topK 检索 | < 100ms |
| rerank | < 200ms |
| 检索总耗时 | < 400ms |
说明
以上是服务端目标,前端或模型生成耗时不包含在内。
15.2 并发策略
- 热门品牌查询走缓存
- 高频 filter 字段建立 payload index
- rerank 单独走线程池或独立服务
- query rewrite 和 rerank 限并发,避免放大成本
15.3 写入策略
- 文档上传与知识学习异步处理
- 向量写入批量提交
- 文档更新采用分批重建
16. 精准度评测体系
16.1 为什么必须做评测
RAG 不评测,精准度一定会失控。
V1 至少需要建立一套小型评测集。
16.2 评测集构成
每个品牌至少准备:
- 20 个高频问题
- 20 个内容生成主题
- 10 个产品对比问题
- 10 个品牌介绍问题
总计每品牌建议至少 50 条评测 query。
16.3 评测指标
推荐指标:
- Recall@5
- Recall@10
- Precision@5
- MRR
- NDCG
- Answer groundedness
- 人工满意度
16.4 人工评测维度
每条 query 至少看:
- 是否命中正确文档
- 是否命中正确片段
- 是否出现品牌错配
- 是否出现过期内容
- 是否出现无关噪音
16.5 评测流程
- 固定查询集
- 固定期望命中文档
- 跑召回与 rerank
- 输出命中率报表
- 低分案例人工复盘
- 调整 chunk、payload、topK、rerank 策略
17. 监控与日志
17.1 监控指标
- Qdrant 查询延迟
- Qdrant 查询 QPS
- payload filter 命中比例
- topK 平均耗时
- rerank 平均耗时
- 检索空结果率
- 检索后回答满意度
17.2 日志记录
每次检索建议记录:
- query
- rewrite_query
- filter 条件
- topK 召回结果
- rerank 结果
- 最终返回 chunk
- 生成任务 ID 或问答 ID
方便后续做 badcase 分析。
18. 风险与边界
18.1 常见风险
- chunk 切分不合理,导致检索效果差
- payload 设计不完整,导致过滤能力不足
- 只做召回不做 rerank,结果不稳定
- 知识库内容脏乱,导致“检索准但答案差”
18.2 V1 边界
- V1 不要求做复杂多跳推理
- V1 不要求做全自动 query rewrite 学习
- V1 不要求做复杂学习排序
19. V1 最终建议
如果你的目标是“RAG 精准好用”,V1 建议采用这套最实用组合:
PostgreSQL做业务主存储和知识元数据Qdrant做向量检索RabbitMQ做知识学习与检索相关任务队列对象存储做原始文档存储dense + filter + rerank做主检索链路
同时一定要配套以下机制:
- 合理 chunk 切分
- 完整 payload 字段
- payload index
- rerank
- 评测集
- badcase 回放
没有这些,单纯换向量库也不可能让 RAG 自动变得精准。