document/content/guide/dataset/dataset_engine.mdx
FastGPT 采用了 RAG 中的 Embedding 方案构建知识库,要使用好 FastGPT 需要简单的理解 Embedding 向量是如何工作的及其特点。
人类的文字、图片等媒介是无法直接被计算机理解的,要想让计算机理解两段文字是否有相似性、相关性,通常需要将它们转成计算机可以理解的语言,向量是其中的一种方式。
向量可以简单理解为一个数字数组,两个向量之间可以通过数学公式得出一个 距离,距离越小代表两个向量的相似度越大。从而映射到文字、图片等媒介上,可以用来判断两个媒介之间的相似度。向量搜索便是利用了这个原理。
而由于文字是有多种类型,并且拥有成千上万种组合方式,因此在转成向量进行相似度匹配时,很难保障其精确性。在向量方案构建的知识库中,通常使用 topk 召回的方式,也就是查找前 k 个最相似的内容,丢给大模型去做更进一步的 语义判断、逻辑推理 和 归纳总结,从而实现知识库问答。因此,在知识库问答中,向量搜索的环节是最为重要的。
影响向量搜索精度的因素非常多,主要包括:向量模型的质量、数据的质量(长度,完整性,多样性)、检索器的精度(速度与精度之间的取舍)。与数据质量对应的就是检索词的质量。
检索器的精度比较容易解决,向量模型的训练略复杂,因此数据和检索词质量优化成了一个重要的环节。
index 的内容,减少向量内容的长度:当 index 的内容更少,更准确时,检索精度自然会提高。但与此同时,会牺牲一定的检索范围,适合答案较为严格的场景。index 的数量,可以为同一个 chunk 内容增加多组 index。在 FastGPT 中,整个知识库由库、集合和数据 3 部分组成。集合可以简单理解为一个 文件。一个 库 中可以包含多个 集合,一个 集合 中可以包含多组 数据。最小的搜索单位是 库,也就是说,知识库搜索时,是对整个 库 进行搜索,而集合仅是为了对数据进行分类管理,与搜索效果无关。(起码目前还是)
FastGPT 采用了 PostgresSQL 的 PG Vector 插件作为向量检索器,索引为 HNSW。且 PostgresSQL 仅用于向量检索(该引擎可以替换成其它数据库),MongoDB 用于其他数据的存取。
在 MongoDB 的 dataset.datas 表中,会存储向量原数据的信息,同时有一个 indexes 字段,会记录其对应的向量 ID,这是一个数组,也就是说,一组数据可以对应多个向量。除默认文本索引外,如果模型能力支持,图片内容也可以生成图片描述索引或图片向量索引。
在 PostgresSQL 的表中,设置一个 vector 字段用于存储向量。在检索时,会先召回向量,再根据向量的 ID,去 MongoDB 中寻找原数据内容,如果对应了同一组原数据,则进行合并,向量得分取最高得分。
在一组向量中,内容的长度和语义的丰富度通常是矛盾的,无法兼得。因此,FastGPT 采用了多向量映射的方式,将一组数据映射到多组向量中,从而保障数据的完整性和语义的丰富度。
你可以为一组较长的文本,添加多组向量,从而在检索时,只要其中一组向量被检索到,该数据也将被召回。
意味着,你可以通过标注数据块的方式,不断提高数据块的精度。
一次知识库检索不是简单的“用户问题 -> 向量库 -> 返回结果”。FastGPT 会根据输入内容和搜索参数,将文本、图片、语义召回、全文召回、问题优化和重排等能力组合起来,最后再把多路结果融合成引用内容。
问题优化 实现指代消除和问题扩展,从而增加连续对话的检索能力以及语义丰富度。语义检索、全文检索 或 混合检索 召回候选内容。RRF 合并方式,综合多个渠道的检索效果。Rerank 来二次排序,提高文本结果的相关性。在知识库搜索中,除了文本问题外,也可以让图片参与检索。FastGPT 会根据当前模型能力,对图片进行不同处理。
图片检索主要有两种方式:
因此,图片检索不是独立于知识库之外的一套能力,而是在原有知识库搜索链路上增加了图片输入的处理路径。
常见使用方式包括:
图片检索效果通常取决于图片清晰度、图片内容是否容易被模型理解、是否配置了视觉模型,以及向量模型是否支持图片向量。
需要注意的是,图片能否被检索到,不只取决于搜索时是否上传了图片,也取决于入库时是否建立了对应索引:
| 知识库能力 | 纯文本查询 | 纯图片查询 | 图文混合查询 |
|---|---|---|---|
| 普通向量模型,无视觉模型 | 正常文本检索 | 基本不可用 | 主要使用文字部分 |
| 普通向量模型,有视觉模型 | 正常文本检索 | 图片先转成描述,再参与文本检索 | 文字 + 图片描述共同参与检索 |
| 支持图片的向量模型,无视觉模型 | 正常文本检索 | 图片向量检索 | 文本检索 + 图片向量检索 |
| 支持图片的向量模型,有视觉模型 | 文本检索,也可命中图片描述 | 图片描述 + 图片向量双路检索 | 文本 + 图片描述 + 图片向量多路检索 |
所以,图搜图效果不理想时,除了调整搜索参数,也要确认当前知识库是否配置了视觉模型或支持图片的向量模型,以及图片入库时是否生成了有效的图片索引。
FastGPT 会把不同召回路径的结果进行融合,而不是简单采用某一路结果。常见路径包括文本向量召回、全文召回、图片描述召回、图片向量召回和重排结果。
因此,最终排序需要这样理解:
语义检索 更依赖向量相似度,适合自然语言问题和语义相近内容。全文检索 更依赖关键词命中,适合编号、型号、专有名词、错误码等精确查询。混合检索 会同时使用语义召回和全文召回,再通过 RRF 融合结果。Rerank 会对候选文本进行二次排序,更适合文本问题明确、候选结果较多的场景。这意味着,最终引用内容不一定严格按照单一向量相似度排序。某条内容如果同时被多路召回命中,通常会更容易排在前面。
语义检索是通过向量距离,计算用户问题与知识库内容的距离,从而得出“相似度”,当然这并不是语文上的相似度,而是数学上的。
优点:
缺点:
采用传统的全文检索方式。适合查找关键的主谓语等。
同时使用向量检索和全文检索,并通过 RRF 公式进行两个搜索结果合并,一般情况下搜索结果会更加丰富准确。
由于混合检索后的查找范围很大,并且无法直接进行相似度过滤,通常需要进行利用重排模型进行一次结果重新排序,并利用重排的得分进行过滤。
利用 ReRank 模型对搜索结果进行重排,绝大多数情况下,可以有效提高搜索结果的准确率。不过,重排模型与问题的完整度(主谓语齐全)有一些关系,通常会先走问题优化后再进行搜索 - 重排。重排后可以得到一个 0-1 的得分,代表着搜索内容与问题的相关度,该分数通常比向量的得分更加精确,可以根据得分进行过滤。
FastGPT 会使用 RRF 对重排结果、向量搜索结果、全文检索结果进行合并,得到最终的搜索结果。
每次搜索最多引用 n 个 tokens 的内容。
之所以不采用 top k,是发现在混合知识库(问答库、文档库)时,不同 chunk 的长度差距很大,会导致 top k 的结果不稳定,因此采用了 tokens 的方式进行引用上限的控制。
一个 0-1 的数值,会过滤掉一些低相关度的搜索结果。
该值仅在 语义检索 或使用 结果重排 时生效。
需要注意的是,最低相关度是过滤阈值,不是最终排序规则。开启问题优化、混合检索、图片检索或结果重排后,最终结果可能会经过多路召回融合,不一定严格按照单一向量相似度排序。
在 RAG 中,我们需要根据输入的问题去数据库里执行 embedding 搜索,查找相关的内容,从而查找到相似的内容(简称知识库搜索)。
在搜索的过程中,尤其是连续对话的搜索,我们通常会发现后续的问题难以搜索到合适的内容,其中一个原因是知识库搜索只会使用“当前”的问题去执行。看下面的例子:
用户在提问“第二点是什么”的时候,只会去知识库里查找“第二点是什么”,压根查不到内容。实际上需要查询的是“QA 结构是什么”。因此我们需要引入一个【问题优化】模块,来对用户当前的问题进行补全,从而使得知识库搜索能够搜索到合适的内容。使用补全后效果如下:
在进行 数据检索 前,会先让模型进行 指代消除 与 问题扩展,一方面可以可以解决指代对象不明确问题,同时可以扩展问题的语义丰富度。你可以通过每次对话后的对话详情,查看补全的结果。
问题优化会在正式检索前增加一次模型调用,因此通常会提升连续对话检索效果,但也会增加整体耗时。如果当前问题本身已经非常明确,或对响应速度要求更高,可以根据实际效果决定是否开启。
如果搜索结果不符合预期,可以先根据现象定位问题,不建议一次性调整所有参数。
| 现象 | 优先检查和调整 |
|---|---|
| 搜不到内容 | 确认数据是否已完成训练;适当降低最低相关度;提高引用上限;检查问题是否过短或缺少主体 |
| 结果太泛、答非所问 | 提高最低相关度;减少引用上限;优化数据分块;检查召回内容是否包含过多无关片段 |
| 编号、型号、专有名词搜不准 | 使用全文检索或混合检索;降低语义检索权重;避免对精确编号类问题过度使用问题优化 |
| 自然语言问法搜不准 | 使用语义检索或混合检索;开启问题优化;补充更准确的数据索引 |
| 开启问题优化后变慢 | 问题优化会额外调用模型,可以换更快的优化模型,或只在多轮追问、短问题场景中开启 |
| Rerank 后仍然排序不准 | 确认用户问题是否完整;检查召回候选是否足够;适当调整最低相关度和引用上限 |
| 图搜图效果弱 | 确认向量模型是否支持图片输入;确认入库时是否生成图片向量索引;检查图片是否清晰、主体是否明确 |
| 图文混合结果不稳定 | 明确文字和图片哪个更重要;如果只想找视觉相似图片,减少额外文字约束 |