上周我的一个同事去面蚂蚁,岗位跟大模型应用相关。前面两轮聊得还行,到了三面,面试官抛了一个挺有意思的问题:“假设你有上万个skill,每个skill都有描述和触发条件,但它们的token总量远超模型的上下文窗口,你怎么检索?”
他脱口而出:"RAG,向量检索。"面试官笑了,说:"就这?"他愣了一下,反问:"还有哪些?"面试官没有直接回答,而是让他先把RAG的流程讲一遍。他讲完之后,面试官说:“方向没问题,但你只说了其中一种。这个场景下至少有六种不同的方案,而且它们不互斥。”
他后来跟我说,当时脑子一片空白——他以为RAG就是唯一答案,没想到面试官一口气说出了向量检索、分层索引、BM25、分类路由、工具调用、混合策略,每种都有适用场景和踩坑点。他全程听得一愣一愣的,觉得自己在RAG这个领域只学了个皮毛。
今天把这个话题展开聊聊。面试官说的六种方案到底是什么?每种方案的适用场景和瓶颈又在哪里?
方案一:向量检索(RAG)
这个方案呢,说白了就是蚂蚁面试官问的第一个方向,也是大多数人的第一反应。
核心思路就是这么个事:把每个 skill 的元信息——也就是名称、描述、再加上两三个触发示例——给拼接在一起,然后转成一个固定维度的向量。用户发过来的 query 也一样,转成向量。接着在高维空间里去做最近邻搜索,把相似度最高的那几个 skill 给捞出来,塞到上下文里去。
先说离线阶段要做的事哈:
首先呢,得对每个 skill 构建一个"索引文档"。通常是把名称、描述、还有两到三个触发示例拼在一起,这么做的效果比只用描述来搞要好很多,召回率会高不少。
然后呢,用 embedding 模型把这些文档都转成向量。常见的模型有 OpenAI 的 text-embedding-3-small、Cohere Embed v3、BGE 这些,选一个就行。
最后把这些向量存到向量数据库里。常见的选择嘛,Pinecone 是托管的,Weaviate 可以自己部署,Chroma 比较轻量适合本地跑,还有 pgvector——这个是 PostgreSQL 的扩展,如果你不想引入额外依赖的话,用它就对了。
再说在线阶段,也就是请求来了之后怎么处理:
第一步,把用户输入用同一个 embedding 模型转成 query 向量。第二步,向向量库发一次 ANN 查询,也就是近似最近邻搜索,取 Top-5 到 Top-10 的结果。第三步呢,把返回的 skill 名称和描述注入到 context 里,让模型自己去决定用哪个。
这里有个关键细节要注意哈。embedding 的粒度对效果影响很大。如果一个 skill 有多种触发场景的话,最好把它拆成多条索引文档,每条对应一种场景。这样的话,召回的时候只要命中任意一条就能找到这个 skill。另外呢,向量检索对于近义词和语义变体的覆盖确实很好,但是对于精确关键词——比如特定的技术术语、产品名之类的——表现就不那么稳定了,这时候就需要跟方案三结合起来用。
那问这个方案的主要瓶颈在哪里呢?embedding 调用有延迟也有成本,向量库需要去维护。还有一点,当 skill 描述本身写得比较模糊或者相互之间有重叠的时候,余弦相似度就会失效,出现那种"全部都相似"的情况,这就比较尴尬了。
方案二:分层索引(Two-stage Retrieval)
这个方案是面试官说的第二种思路,跟向量检索完全不同。
核心思路是把检索问题拆成两步来做。第一步叫"粗筛",靠的是目录,这个很轻量,能放进 context 里。第二步叫"按需加载",靠的是完整内容。
先说第一层,也就是轻量目录。每条 skill 只保留名称和一句话的触发描述,整个目录控制在几百 token 以内就差不多了。这就是本系统那个 available_skills 的设计——你现在看到的那个 XML 块,其实就是第一层。
再说第二层,也就是完整内容。模型看完目录之后,判断要用哪个 skill,然后用 view 工具——或者等价的文件读取方式——把完整的 SKILL.md 给加载进来,再按照里面的指引去执行任务。完整的 SKILL.md 可能有几千 token,但是只需要加载命中的那一两个就行了,不需要全部都加载。
那为什么这个设计有效呢?目录的核心价值在于"路由",而不是"执行"。只要目录能让模型做出正确的选择,执行细节就可以延迟到第二步再去做。这跟数据库的"索引"思想是完全一样的——你不需要去扫描整张表,只需要索引足够小、查询足够快就行了。
面试官当时跟他说了一句:"你现在看的那个系统提示里的skill列表,其实就是分层索引的第一层。"他才恍然大悟——原来自己天天在用的东西,背后是这个原理。
不过这个方案也有它的扩展极限。当 skill 数量到达几百个的时候,连目录本身都放不进 context 了,那这个方案就需要在目录层之上再加一层——也就是"目录的目录",或者说在目录层引入向量检索,也就是方案一,来替代"把所有目录都塞进 context"这种做法。
方案三:倒排索引(BM25)
这个方案是面试官提到的第三种,也是最经典的搜索引擎基础算法。
核心思路是对每个 skill 的文本做词级别的倒排索引,检索的时候用 BM25 算法来计算查询词跟文档的相关性打分,然后取 Top-K。Elasticsearch 和 Lucene 的默认排序就是用的 BM25。
那 BM25 的直觉是什么呢?就是这么个道理:一个词在某个 skill 里出现得越多——也就是词频越高——那这个 skill 就越可能跟查询相关。但是呢,如果这个词在所有 skill 里都很常见,比如说"数据"这种词,那它的权重就会被压低,这叫逆文档频率惩罚。最终的分数就是 TF 乘以 IDF 的一个加权组合,外加文档长度的归一化处理。
这个方案适合什么场景呢?就是 query 里包含明确的领域词的时候,比如"Excel"、“PDF”、"docx"这种。这些词在少数几个 skill 里高频出现,BM25 就能精准命中。跟向量检索比起来呢,BM25 的实现成本和调试成本都低很多,不需要 embedding 模型,用 Python 的 rank_bm25 库几十行代码就能搞定。
但是它的主要缺陷也很明显,就是纯关键词匹配,没办法处理语义上的近义关系。比如说用户说"把表格存成文件",BM25 就不知道这跟 xlsx skill 有关系,因为"表格"这个词可能根本就没出现在 skill 描述里。这恰恰是向量检索的优势所在,所以两种方案经常是组合着来用的——先用 BM25 召回一批候选,再用向量相似度去重排。
方案四:分类树 / 路由模型
这个方案的思路跟前面三个都不太一样,面试官说这个是"换个角度看问题"。
核心思路是不做相似度检索,而是先把用户意图归到某个类别里去,然后在对应类别内做精确匹配。你可以理解为"先走哪个部门,再找哪个人"。
分类树有两种实现方式。第一种是规则或者关键词路由,就是维护一个意图到类别的映射表。比如说看到"Excel"就路由到"文档处理"这个类,看到"画图"就路由到"可视化"类。这种方式实现起来简单,可解释性也好,但是覆盖率比较差,容易漏掉那些措辞不太标准的 query。
第二种是小型分类模型路由。就是用一个轻量的文本分类模型——比如 BERT 级别的,几十 MB 大小——来预测意图类别,然后在类别内做检索。这个模型可以用 skill 的触发 case 来做微调,准确率比纯规则的方式高不少。
那为什么比全库检索快呢?假设 skill 分成 10 个类,每类平均 100 个 skill。路由到某个类之后,只需要在 100 个 skill 里检索就行了,检索空间缩小了 10 倍,速度和精度都会更好。
不过这个方案有个适用前提,就是 skill 之间的类别边界要比较清晰。如果 skill 大量跨类——比如说一个 skill 既做文档处理又做数据分析——那分类路由的收益就会下降,因为一旦路由错了,就会直接漏掉候选。
方案五:工具调用 + 外部检索服务
这个方案是面试官重点展开讲的,因为他觉得这个思路最值得深入理解。
核心思路是让模型自己不做检索,而是把检索能力封装成一个工具。比如说搞一个 search_skills(query: str) -> List[Skill] 这样的工具,模型通过调用这个工具来获取候选 skill。
这么做的价值在哪里呢?在于架构分离。检索逻辑完全放在外部服务里,模型只需要知道工具的签名就行了。外部服务可以用任意技术来实现——向量库、BM25、数据库全文检索——而且可以独立升级和调优,完全不影响模型那一侧。
在 MCP 生态里怎么体现的呢?其实就是 MCP 的核心设计哲学。本对话里的那个 search_mcp_registry 工具,实际上就是这种模式。模型调用工具,工具在外部服务里搜索,然后把结果返回给模型。在这种方式下,即使 skill 库有几十万条,模型自身的 context 窗口也完全不是瓶颈了。
面试官跟他说:"你看,这个方案的好处是,模型根本不需要知道检索是怎么实现的。它只需要知道有个工具叫 search_skills,传个 query 进去就能拿到结果。"这个架构分离的思路,其实不只是用在 skill 检索上,很多大模型应用的场景都适用。
当然了,这个方案也有它的挑战。首先是增加了一次网络往返,延迟会变高。工具调用本身也消耗 token。外部服务的维护和可靠性成了新的依赖。另外呢,模型需要能正确判断"什么时候该搜索、搜什么关键词",这其实也是一个需要去设计的问题——query 写得不好的话,检索质量就差,这跟人用搜索引擎是一个道理。
方案六:混合组合策略
最后面试官说了一句让他印象很深的话:“以上五种方案并不互斥,生产环境里几乎都是组合着来用的。”
几种常见的搭配方式。第一种是 BM25 加向量重排。先用 BM25 召回 50 个候选,这个又快又便宜,然后再用向量相似度对这 50 个做重排,取 Top-5。这样就兼顾了精确词匹配和语义理解,是目前 RAG 系统的事实标准做法。
第二种是分类路由加分层索引。先路由到某个类别,类别里再用分层索引——先看目录,再按需加载完整内容。适合 skill 数量中等、几百个左右、分类比较清晰的场景。
最后说说对于此问题实际演进路径。可以先是纯方案二,就是目录加按需 view。如果 skill 规模扩大到目录也塞不进 context 了,下一步自然就是在目录上加向量检索——模型调用一个 search_skills() 工具,也就是方案五,工具内部用向量库,也就是方案一,在目录里检索,返回 3 到 5 条候选描述,模型再决定加载哪个完整的 SKILL.md。这是一条低成本的渐进式演进路径,不需要一开始就把整套 RAG 基础设施都建好。
面试官最后跟他说:"你答出RAG没问题,但要知道RAG只是其中一种。真正的工程能力是知道什么时候用什么方案,以及怎么组合。"这句话值得每个做大模型应用的人好好想想。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋
📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~