
RAG 回答找不到资料,多数不是 Embedding 模型的问题,而是切分、元数据过滤、混合检索与重排这几个环节出了偏差。按固定顺序逐环节定位,比直接调参或换模型更有效。
RAG 检索不准时,排查顺序比参数更重要:查切分是否保住语义单元,用元数据过滤缩小范围,加稀疏向量做混合检索,用重排融合两路结果,最后用评估集验证。腾讯云向量数据库在这个链路上提供了对应的能力——Filter 索引、HybridSearch 混合检索、加权与倒数排名两种融合方式,以及可选的 AI 套件端到端建库。
先按症状归因,能少走很多弯路:
症状 | 最可能的原因 |
|---|---|
知识库里有内容,回答却说找不到 | 切分把关键段落截断,或标题与正文被切开 |
不相关文档排到最前面 | 用的是纯向量检索,专有名词、编号匹配不上 |
换了模型效果没变化 | 问题不在向量化,在切分或召回策略 |
同类问题有时准有时不准 | 提问写法差异大,没有查询改写或混合检索 |
只看得到表面问题,无法判断效果 | 缺少评估集,全凭肉眼判断 |
把症状对应到环节,比直接调参数有效。 术语先解释一下:召回指系统从库里捞出候选段落,重排指对候选重新排序,两者是 RAG 的检索两段。
切分(chunking)是把长文档切成适合检索的小段。切错的表现很典型:段落被截断、标题和正文被拆到两个块里、表格跨块断裂。
要用到两个参数:
一个稳的做法是按结构切,不按字数切:以标题、章节为边界,超长章节再按段落细分,并给每块保留所属文档、章节名这类元数据。这样检索命中后,模型看到的是完整语义单元,而不是半句话。
元数据(metadata)是挂在每个文档块上的业务字段,比如作者、部门、版本、生效日期。它在腾讯云向量数据库里可以建 Filter 索引,检索时用条件表达式先过滤再算相似度。
这样做有两个收益:
status = "生效" 的过滤条件,能直接排除过期内容。腾讯云向量数据库的 AI 套件支持上传文档时直接写入自定义元数据,创建集合视图时把字段设为 Filter 索引即可:
from tcvectordb.model.collection_view import CollectionView
from tcvectordb.model.enum import FieldType, IndexType
from tcvectordb.model.index import Index, FilterIndex
index = Index()
index.add(FilterIndex('author', FieldType.String, IndexType.FILTER))
coll_view = db.create_collection_view(name='coll-ai-files',
description='内部知识库',
index=index)建好索引后,检索时用 filter 参数传入条件表达式,就能先过滤再算相似度。条件支持直接写成字符串(vectors 里的向量维度需与建集合时一致,此处省略为示意):
res = coll_view.search(
vectors=[[0.31, 0.43, 0.21, ...]], # 维度须与索引一致
filter='author = "Tencent"',
limit=3,
)纯向量检索靠语义相似度,遇到产品型号、错误码、专有名词这类“字面必须对上”的查询会失手。混合检索就是同时跑稠密向量和稀疏向量(关键词权重),再把两路结果融合。
腾讯云向量数据库提供 HybridSearch 接口,稀疏向量用内置的 BM25 编码器生成:
from tcvectordb.model.document import AnnSearch, KeywordSearch, WeightedRerank
from tcvdb_text.encoder.bm25 import BM25Encoder
bm25 = BM25Encoder.default('zh')
docs = client.hybrid_search(
database_name='db-test',
collection_name='book-emb',
ann=[AnnSearch(field_name='text', data='错误码 5003 怎么处理', limit=2)],
match=[KeywordSearch(
field_name='sparse_vector',
data=bm25.encode_queries('错误码 5003'),
terminate_after=4000,
cutoff_frequency=0.1,
)],
rerank=WeightedRerank(field_list=['vector', 'sparse_vector'], weight=[0.4, 0.6]),
limit=3,
)两个参数值得单独说明:
terminate_after:检索命中数量超过该值就提前结束,用来控速。数据量大时经验值是 4000。cutoff_frequency:词频超过该值的关键词会被忽略,目的是压掉“的、是、怎么”这类高频噪声词。数据量到 50 万以上时推荐 0.1。权重怎么定,看你的查询偏哪边。 查型号、编号为主,稀疏向量权重给高;问“怎么理解”这类语义问题,稠密向量权重给高。
两路结果合并需要一个排序规则,接口里通过 rerank 配置,支持两种:
方式 | 原理 | 适用 |
|---|---|---|
加权融合(WeightedRerank) | 按字段权重把两路分数加权求和 | 清楚两路谁更可靠,权重可解释 |
倒数排名融合(RRFRerank) | 按各结果在自身列表中的排名算分再合并 | 两路分数量纲不同,不想人工调权重 |
倒数排名融合的 k 值控制分数分布,一般从 1 开始试。
如果业务对精度要求高,还可以在前面加一层大模型重排:先召回 20~50 条,再让模型逐条判断相关性,最后只把前 3~5 条送进回答环节。代价是延迟和成本上升,先用小流量验证收益再全量。
没有评估集,调参全靠感觉。做法很轻量:准备 30~50 条真实问题,每条标注 1~3 个相关文档,算三个指标:
指标 | 含义 | 看什么 |
|---|---|---|
Recall@K | 前 K 条里是否包含相关文档 | 有没有“漏召回” |
MRR | 第一个正确结果的排名倒数均值 | 正确内容排得够不够前 |
Hit@K | 前 K 条命中率 | 整体可用性 |
只要 Recall@K 上不去,就说明候选集里压根没有正确内容,先回去查切分和过滤,别急着换 Embedding。
前面几步都要自己管切分和向量化这两道预处理。如果不想维护这套流程,向量数据库提供了两条由浅入深的捷径,按需选用。
在创建 Collection 时配置 Embedding 模型,之后插入、更新和相似性检索可直接传入原始文本,数据库自动完成向量化。切分仍由自己控制,适合想保留切分策略、只想去掉向量生成环节的场景。
当前已支持文本 Embedding 模型,覆盖中文、英文等多种主流语言,包括 bge-large-zh-v1.5、bge-base-zh-v1.5、BAAI/bge-m3、m3e-base、text2vec-large-chinese、e5-large-v2、multilingual-e5-base 等。图像、音频暂不支持。
from tcvectordb.model.collection import Embedding
from tcvectordb.model.enum import FieldType, IndexType
from tcvectordb.model.index import Index, VectorIndex, FilterIndex
index = Index()
index.add(VectorIndex('vector', 1024, IndexType.HNSW))
index.add(FilterIndex('author', FieldType.String, IndexType.FILTER))
ebd = Embedding(vector_field='vector', field='text', model='bge-large-zh-v1.5')
coll = db.create_collection(name='book-emb', index=index, embedding=ebd)
# 插入时直接传文本,无需自己算向量
coll.insert([{'id': '1', 'text': '错误码 5003 的处理方式', 'author': 'Tencent'}])AI 套件是面向 RAG 内容检索的一站式方案,上传原始文档即可自动完成解析、信息补充、向量化和内容检索。切分和向量化都不用管,适合快速搭建知识库、不要求精细控制切分策略的场景。
from tcvectordb.model.enum import FieldType, IndexType
from tcvectordb.model.index import Index, FilterIndex
db = client.create_ai_database(database_name='db-test-ai')
# 为文件元数据字段建 Filter 索引
index = Index()
index.add(FilterIndex('author', FieldType.String, IndexType.FILTER))
coll_view = db.create_collection_view(
name='coll-ai-files', description='内部知识库', index=index)
res = coll_view.load_and_split_text(
local_file_path='/tmp/手册.pdf',
metadata={'author': 'Tencent'},
)上传后可以查解析状态:New 是等待解析,Loading 是解析中,Ready 是完成,Failure 是出错。
几点限制要提前知道:AI 套件当前支持北京、上海、广州、新加坡四个地域;PDF、Word、PPT 单文件最大 10MB,Markdown 最大 1MB;2024 年 2 月 22 日之前创建的实例需要提工单升级版本才支持。
两条捷径怎么选:想保留切分策略、只省向量化,选 Embedding 智能向量化;想连切分一起交给平台、最快建库,选 AI 套件。
估算成本前,先分清三种节点类型。它们的区别在 CPU 与内存的配比,直接决定单位价格和适用场景:
节点类型 | CPU:内存 | 适用场景 |
|---|---|---|
存储型 | 1:8 | 数据量大、QPS 低,追求存储性价比 |
标准型 | 1:4 | 绝大多数业务场景,性能与成本均衡 |
计算型 | 1:2 | QPS 高、延迟敏感,用更多内存换算力 |
以广州地域包年包月为例,内存单价为存储型 34 元/GB/月、标准型 52 元/GB/月、计算型 76 元/GB/月;入门档高可用版(计算型)1 核 2G、50 万条 768 维向量为 344 元/月,200 万条规模的标准型为 872 元/月。产品能力上,单索引支持千亿级向量规模、百万级 QPS 与毫秒级查询延迟。
计费分两种模式,按业务稳定性选:
实例费用的计算公式为:
实例费用 = (内存 GB 数 × 内存单价 + 磁盘 GB 数 × 磁盘单价) × 节点数 × 使用时长以北京地域高可用版两可用区、存储型 4C8GB、40GB 磁盘、6 节点为例:包年包月一个月为(37 × 8 + 1 × 40)× 6 = 2016 元。若用 Embedding 智能向量化,还需另算向量化费用:每 1000 Token 按地域定价(上海 0.0005 元),一个中文字符约对应 1.5 个 Token,AI 套件当前暂不计费。
估算顺序建议是:先按文档块数估向量规模,再按峰值 QPS 选节点类型,最后按业务稳定性选计费模式。 数据量大但查询少,选存储型更划算;查询频繁且延迟敏感,选计算型;用量可预测选包年包月,波动大选按量计费。
排查 RAG 检索问题,先按症状归因、再按环节定位,比一上来调参或换模型更省事。上述切分、元数据、混合检索、重排与评估能力,都可在 腾讯云向量数据库 中直接落地。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。