QA 问答对管理
这是知识库的一部分
本页讲 QA 对子系统。完整的知识库(含文档 RAG、知识图谱、知识库编排器)请看 知识库总览。
QA 对是结构化的"标准问 + 标准答",用于:
- 客服 FAQ
- 政策 / 合规口径(必须返回固定答案)
- 高频确定性问题(不应让 LLM 自由发挥)
每条 QA 都索引了 问题向量 和 答案向量,命中阈值高时直接返回,绕过 LLM 推理。
数据结构
| 字段 | 说明 |
|---|---|
id | BIGINT 主键 |
kb_id | 所属知识库 |
category_id | 关联到 qa_categories 树 |
question / answer | 必填 |
question_vector | Vector(1024)(取决于嵌入模型) |
answer_vector | Vector(1024) |
channel | 渠道隔离:all / pc / mobile / hotline |
extra_metadata | JSONB(API 暴露为 metadata) |
source_id | 外部业务标识(用于回溯) |
tags | TEXT[] |
status | active / archived / draft |
priority | 整数(不是 high/medium/low 字符串) |
view_count | 累计被列出次数 |
match_count | 累计被命中次数 |
feedback_score | DECIMAL(3,2),反馈打分 |
last_matched_at | 最近一次命中时间 |
created_at / updated_at | 时间戳 |
向量列上有
ivfflat + cosine索引,所以即便表大几十万条,相似度搜索仍是亚秒级。
类目(Category)
qa_categories 是树形结构,使用 parent_id + 物化路径 path(如 /1/3/7):
| 字段 | 说明 |
|---|---|
name / description | 显示信息 |
parent_id | 自引用 FK |
level | 层级深度 |
path | /祖先1/祖先2/.../自身 |
sort_order | 同级排序 |
icon / color | UI 装饰 |
qa_count | 子树总 QA 数(含子类) |
direct_qa_count | 仅本级 QA 数 |
获取整棵树:
GET /knowledge-bases/{kb_id}/qa-categories/tree创建 QA
单个手动创建
进入知识库详情 → "QA 管理"标签 → "新建"。表单字段对应上面的列。
批量导入 JSON
POST /knowledge-bases/{kb_id}/qa-pairs/batch-import
Body: [ { "question": "...", "answer": "...", ... }, ... ]批量导入 CSV
POST /knowledge-bases/{kb_id}/qa-pairs/batch-import-csv
Multipart: file=<csv>
Query (可选): category_id=<int>&channel=allCSV 列实际支持:
| 列名 | 是否支持 | 说明 |
|---|---|---|
question | ✅ 必填 | |
answer | ✅ 必填 | |
tags | ✅ | 用 | 或 , 分隔 |
priority | ✅ | 整数 |
source_id | ✅ | 业务侧 ID |
category / category_name | ❌ | CSV 不解析;用 query 参数 category_id 指定 |
channel | ❌ | CSV 不解析;用 query 参数 channel 指定 |
UTF-8 BOM 容忍。
如何按类目区分导入
不同类目分多次 CSV 导入,每次带不同的 ?category_id=xxx。
渠道隔离
channel 字段控制这条 QA 在哪些前端可见:
| Channel | 含义 |
|---|---|
all | 所有渠道都可命中(默认) |
pc | 仅 PC 端检索可命中 |
mobile | 仅手机端 |
hotline | 仅热线 / 电话客服 |
查询时通过 ?channel= 参数过滤。没有应用级(Application 维度)QA filter 配置——隔离粒度是 QA 行 × 渠道字符串。
优先级
priority 是整数;检索结果按相似度排序后,同相似度的 QA 用 priority 排序。
旧文档提到的 "high / medium / low" 字符串值在代码里不被识别——传字符串会写入失败或丢弃。
状态
| Status | 含义 |
|---|---|
active | 参与检索(默认) |
draft | 不参与检索(编辑中) |
archived | 不参与检索(已下线) |
没有审批工作流
旧文档描述过 "草稿 → 待审核 → 已发布 → 已下线" 流转——代码里不存在。status 是自由设置的字符串,无审批人、无评论流、无时间戳。
检索
直接 QA 搜索
POST /knowledge-bases/{kb_id}/qa-pairs/search
{
"query": "如何重置密码?",
"top_k": 5
}返回 QA 对列表 + 相似度。
走混合检索
更常用的方式是把 QA 流当作知识库的一部分,由编排器或 Agent 触发 知识库统一查询接口,传 mode=hybrid:
向量化 query
│
▼
QA 对 pgvector 余弦搜(threshold 0.7 召回)
│
├─ 最高相似度 ≥ 0.9 → 直接返回 QA 答案(短路,省 LLM 调用)
│
└─ 否则 → 调 LightRAG 文档检索
│
▼
LLM 融合两路结果mode=qa_only 强制只走 QA,无 LLM 兜底。
阈值是固定的
0.7 / 0.9 是 services/hybrid_kb_service.py 里的常量,不可配置。如需更严格"必须精确",用 mode=qa_only + 自己的阈值后处理。
检索后的统计回写
每命中一次:
match_count+1last_matched_at= now
view_count、feedback_score 由前端按需更新(例如用户给答案打分时)。
已实现 vs 未实现
| 项 | 状态 |
|---|---|
| 双向量索引 | ✅ |
| 多类目(树形) | ✅ |
渠道隔离(channel 字段) | ✅ |
| 整数优先级 | ✅ |
| CSV 批量导入 | ✅(仅识别 5 列) |
| JSON 批量导入 | ✅ |
| 命中统计 / 反馈分 | ✅ 字段存在;UI 调用待补 |
| 完全字面匹配(exact match) | ❌(全部走向量) |
| 关键字检索(不向量化) | ❌ |
| 审批工作流 | ❌(status 自由设置) |
| 版本历史 / 还原 | ❌(QA 没有 version 表) |
| 同义 / 多语言变体合并 | ❌ |
| 重复检测 / 自动去重 | ❌ |
| 应用级(Application)QA 过滤 | ❌(隔离粒度是 channel 字符串) |
QA 间权重融合(qa_weight / rag_weight) | ❌(混合是阈值短路,不是加权融合) |
与 Application / Agent 的连接
QA 对随知识库挂载到 Agent:
{
"knowledge_base_ids": ["kb-uuid"],
"retrieval_config": {
"mode": "qa_only",
"top_k": 3,
"similarity_threshold": 0.7
}
}或者把 QA 对所在的知识库直接绑到 KnowledgeBase 编排器,跳过 Agent 直答。
相关文档
- 知识库总览 —— 双流架构、文档 RAG、混合模式
- DeepAgents 编排 —— Agent 调 KB 的检索方式
- 模板变量
