四、向量数据库
向量数据库是专门用来存储和高效查询向量的数据库。面对海量向量,如果逐一遍历比较相似度,速度会非常慢。因此向量数据库会预先构建 ANN(Approximate Nearest Neighbor,近似最近邻)索引,用空间换时间,快速定位最相似的向量。
以"爱丽丝喜欢吃水果"这句话为例,做了 Embedding 后得到一个向量,存入向量数据库时,通常至少包含以下几列:向量(用于相似度计算)、原始文本(用于最终发给大模型)、ID,以及元数据(如文档来源、页码、章节、时间戳等)。这样,当通过向量相似度找到最相近的向量后,就能同时把对应的原始文本和元信息一并提取出来。
五、回答阶段:查询处理、召回、重排与生成
用户提问后,首先进入查询处理。在实际工程中,召回之前通常还有一个查询处理步骤,包括查询重写(把口语化、模糊的问题改写成更适合检索的表达)、查询扩展(补充同义词、相关术语)等,以提高召回质量。
接下来是召回(Retrieval)。召回是搜索与用户问题相关片段的过程:用户问题会先发给 Embedding 模型转换为向量,再发送给向量数据库。向量数据库利用 ANN 索引快速检索,返回与用户问题最相似的 Top-K 个片段(例如 50~100 个)。召回通常使用 Bi-Encoder(双编码器),分别把问题和片段编码成向量,再计算相似度,这种方式速度快、成本低,适合做粗筛;但缺点是问题和片段在编码时“互不照面”,缺乏直接交互,精度相对较粗。例如,问题问的是"苹果手机的缺点",召回结果里可能会混入"苹果(水果)的营养价值"。因此召回阶段宁可多取一些,把可能相关的都纳入候选,为后续精筛留足空间。
召回的结果会进入重排(Rerank)阶段。重排的全称是重新排序,作用是从召回结果中进一步筛选出与用户问题最相关的少数片段(例如 3 个),作为最终送入模型的上下文。重排则通常使用 Cross-Encoder,将用户问题和每个片段拼接在一起作为一个整体输入模型,由模型直接输出相关性分数。这使得它能捕捉到问题与片段之间的深层交互关系,精度更高,但每对(问题+片段)都要过一次模型,计算量大、耗时长,适合精挑细选。
如果把两者比作相亲:Bi-Encoder 像是“看简历”——男女双方各自填表,系统比对条件,效率高但可能错过细节;Cross-Encoder 像是“面对面聊天”——双方直接对话,模型判断合不合适,精准但耗时。
召回的 Top-K 数量(如 50、100、200)和重排后送入模型的 Top-N 数量(如 3、5、10)都是可配置的超参数,需要根据文档总量、片段质量、模型上下文长度和成本来权衡。重排后只取最相关的少量片段,一方面是因为大模型有上下文长度限制,另一方面是片段过多会引入噪声,反而干扰模型判断。
最后是生成(Generation)。重排选出的最相关的片段会和用户问题一起发送给大模型,由模型基于这些上下文生成最终答案。
夜雨聆风