这道题其实问的是[[RAG]]落地的核心工程问题,怎么把非结构化的文档和用户查询,转成计算机能高效检索的向量。说白了,这中间每一步都有取舍,不是一个模型一套流程走到底的。
先说文本预处理。很多人觉得就是切切文档,但这里有个挺关键的边界:固定长度切分和语义切分的区别。固定切分简单,但照搬一个固定长度很容易把一句话或者一个逻辑断成两半,检索的时候召回的内容不完整。语义切分就好很多,比如按段落、按标题层级来分,甚至可以用LLM辅助判断自然断点。但语义切分也有代价,就是计算开销大,而且有些文档结构不清晰,反而切不好。所以真正落地的时候,我倾向混合策略:对结构清晰的文档用语义切分,对纯文本或结构混乱的,也要把多组固定长度与无重叠、短重叠、较长重叠作为候选,用同一评测集验证断句、召回、答案质量和成本。另外元数据一定要保留,比如来源、标题层级、时间戳,这能让后面的过滤和[[重排]]事半功倍。举个例子,在客服退款场景里,用户问的是'退款流程',如果文档切分时把标题'退款政策'和正文'退款流程'分到不同块,检索时就可能只召回标题块,内容不全。所以我会把标题、层级这些元数据绑到每个块上,检索时优先返回。
接下来说[[嵌入]]模型选择。这块很多人有个误区,觉得模型越新越大越好。其实选模型要看三个前提:语言、上下文长度、领域。中英混合的场景,我会优先选bge-m3或者gte-large,它们在双语上都比较均衡;纯英文场景,OpenAI的text-embedding-3-large效果很好,但私有化部署成本高。上下文长度是关键,如果文档块超过模型支持的长度,直接截断会丢失信息,所以要么选支持8K甚至32K的模型,要么先做摘要。领域适配更是个坑,垂直领域比如医学、法律,通用模型的效果可能很差,我见过一个医疗合同检索项目,用通用模型召回率不到60%,换成PubMedBERT微调后直接拉到85%以上。所以选型时我会先拿业务数据跑个benchmark,不盲目跟风。
再一个,向量生成和归一化。批量编码是必须的,batch_size设到32到64,能充分利用GPU。但这里有个工程细节:同批次里的文档长度差异太大,短的会被大量padding浪费计算,所以我会做动态批处理,按长度排序分组,让相近长度的一起编码。归一化也很关键,L2归一化之后,余弦相似度就等于点积,这样在Milvus或者PGVector里检索时,计算更快,而且索引结构也更稳定。如果不做归一化,不同向量的模长差异会影响相似度排序,导致长文档天然容易被召回,这在很多场景下是灾难。
最后说落地风险和工程注意。版本管理是个大坑,模型更新后,新老向量分布不同,直接混用会导致检索质量崩盘。我一般会做全量重刷,或者用双版本并行,灰度切换,等新版本稳定了再下掉旧的。还有一个常见失败场景是维度不对齐,不同模型输出维度不一样,768、1024、3072都有,入库前必须校验,否则查询时会直接报错。上线后我会特别关注监控埋点,比如编码耗时、缓存命中率、向量分布漂移,如果分布漂移太快,说明业务数据变了,可能需要重新切分或微调模型。
说到监控,我发现很多团队只关注召回率,但其实检索延迟和存储成本的平衡才是线上真正的瓶颈。比如[[HNSW]]索引参数调不好,召回率再高,延迟超标也上不了线。这块其实可以深挖一下。
所以整体上,我会把向量化流程看成一个根据业务场景不断迭代的工程系统,而不是一套固定的脚本。预处理、模型选择、归一化、版本管理,每一步都要和业务数据对齐,上线后持续观测,才不至于变成'离线跑分高、线上效果差'的尴尬局面。