1.1 大模型面试题:

LangChain 面试主要考察三个层次:基础概念 (框架定位与核心组件)、核心能力 (LCEL、Memory、RAG、工具调用等实战细节)、以及架构设计(LangGraph、生产部署与风险控制)。以下按面试频率和难度整理核心题目:


一、基础概念篇(一面必问 ★)

1. LangChain 的核心定位是什么?解决了什么问题?

LangChain 是一个专门开发大语言模型应用的框架,主要解决三个问题:

  • 标准化封装:将模型调用、向量库、工具集成等多个环节封装成统一接口,开发者不用关心底层差异。
  • 快速组装:将常见功能抽象成独立组件,像搭积木一样组合,几行代码就能搭出 RAG 或 Agent。
  • 复杂流程编排:提供 Chain、Memory、Agent 等高级能力,让复杂任务的实现变得简单。

加分回答 :补充其核心设计理念是组件化 + 可组合 ,基于 LCEL 实现了统一的 Runnable 接口,所有组件均支持 invoke/stream/batch 三种核心调用方式。相比 LlamaIndex,LangChain 通用性更强,覆盖从基础对话到复杂 Agent 的全场景。

延伸追问:LangChain 的优缺点?优点:生态丰富、组件齐全、快速上手。缺点:过度封装隐藏细节、版本迭代快 API 变化大、生产环境有一定性能开销。


2. LangChain 的五大核心组件是什么?

组件 作用
Models(模型) 封装各类 LLM 和 Embedding 模型,支持 OpenAI、通义千问、本地模型等多种提供商
Prompts(提示词) 提供 PromptTemplate 模板管理,支持变量插值、FewShot 示例、ChatMessage 消息模板等
Chains(链) 把多个组件串联成执行流程,前一个组件的输出作为后一个组件的输入
Memory(记忆) 在对话中保持上下文,支持 BufferMemory、SummaryMemory、VectorStoreMemory 等多种实现
Tools & Agents(工具与智能体) Tools 封装外部功能,Agent 根据用户输入自主决策是否调用工具、调用哪个、传什么参数

延伸追问 :Chain 和 Agent 的区别?Chain 是固定的执行流程 ,数据按预设路径流动;Agent 是动态决策,模型自己判断要不要调用工具,更灵活但也更难控制。


3. LLM 和 ChatModel 有什么区别?

对比维度 LLM ChatModel
输入/输出 纯文本(string → string) 消息列表(ListMessage → Message)
典型模型 早期 GPT-3 ChatGPT、通义千问、文心一言
角色区分 支持 HumanMessage、SystemMessage、AIMessage

实际开发中 ChatModel 是主流用法,因为支持角色区分,可以用 SystemMessage 设定模型行为。


4. 什么是智能体(Agent)?和普通 LLM 应用的本质区别是什么?

Agent 本质上是一个"具备自主决策能力的 LLM 控制器",它不仅生成文本,还能根据当前状态选择工具、决定下一步行为。

普通 LLM 应用是"你问我答 ",而 Agent 是"你给目标,我自己拆解、执行、纠偏"。这也是为什么 Agent 会放大能力,同时也会放大风险------一旦设计不好,它不是答错一句话,而是可能做错一整串事。

加分回答:不是所有 LLM 应用都适合做 Agent。Agent 的代价非常高,不只是算力,还有不确定性成本。如果业务流程是确定的、可枚举的,用 Agent 反而会让系统更不稳定。


二、LCEL 与 Runnable 篇(二面核心 ★★)

5. LCEL 是什么?它的核心优势是什么?

LCEL(LangChain Expression Language)是 LangChain 官方主推的链构建方式,核心语法是通过 | 管道符,将实现了 Runnable 接口的组件按业务逻辑串联,前一个组件的输出自动作为后一个组件的输入。

核心优势

  • 统一接口 :所有 LCEL 链都实现 Runnable 接口,天然支持 invoke/ainvoke/batch/stream
  • 流式输出 :自动实现 stream/astream,可逐 token 输出
  • 并行执行 :通过 RunnableParallel 实现多个组件并行
  • 易于观测:与 LangSmith 深度集成,自动记录每一步

6. Runnable 是什么?和传统 Chain 有何差异?

Runnable 是 LangChain 的标准执行接口,被大多数组件实现(模型、解析器、检索器、甚至编译后的 LangGraph 图)。

它提供一致的 API:

  • invoke / ainvoke:同步/异步调用
  • batch / abatch:批处理
  • stream / astream:流式输出

相比传统 Chain,Runnable 更标准化、可组合、可替换,便于在不同组件间灵活组装。

LCEL 的并行与组合原语

  • RunnableSequence:顺序执行
  • RunnableParallel:并行执行

Runnable 是 LangChain 表达语言(LCEL)的核心标准接口,它代表一个可被调用、组合和转换的执行单元传统 Chain 是 LangChain 1.0 时代的遗留设计,它们是特定任务的硬编码类 (如 LLMChainConversationChain)。

为了让你一眼看透,我先用表格对比,再用代码"打脸"式演示:


1. 核心区别对比

对比维度 传统 Chain(旧时代) Runnable(新时代)
本质 特定任务的硬编码类 (需继承 Chain)。 标准接口协议 (任何实现了 invoke/stream 的对象)。
组合方式 SimpleSequentialChainSequentialChain 拼接,语法笨重。 **用 `
输入/输出 强制绑定键名 (如必须传 input,输出必须是 text)。 灵活传递字典 ,每个组件可按需取用或修改 dict 中的字段。
流式支持 很难支持逐 Token 流式输出(需复杂回调)。 原生支持 stream 方法,开箱即用。
批处理 不支持或需要手写循环。 原生支持 batch 方法,自动高效并发。

2. 代码实例:感受"代际碾压"

假设我们要做一个简单的逻辑:用户输入 -> 提示词模板 -> 大模型 -> 输出大写结果

❌ 传统 Chain 的写法(老旧且别扭)
python 复制代码
from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate
from langchain_openai import ChatOpenAI

llm = ChatOpenAI()

# 1. 必须定义一个模板,变量名固定为 "input"
prompt = PromptTemplate.from_template("讲一个关于 {input} 的笑话")

# 2. 必须实例化 LLMChain 这个特定类
chain = LLMChain(llm=llm, prompt=prompt)

# 3. 调用时,键名必须叫 "input",否则报错
result = chain.invoke({"input": "程序员"})
print(result["text"])  # 输出结果,还要从字典里抠出 "text"
✅ Runnable / LCEL 的写法(丝滑且强大)
python 复制代码
from langchain.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

llm = ChatOpenAI()

# 1. 标准组件都实现了 Runnable 接口
prompt = ChatPromptTemplate.from_template("讲一个关于 {topic} 的笑话")

# 2. 直接用 | 管道符串联(完全解耦)
chain = prompt | llm | StrOutputParser()

# 3. 调用极其自然,参数名由你定义(这里叫 topic)
result = chain.invoke({"topic": "程序员"})
print(result)  # 直接打印字符串,不用从字典里挖!

# 🔥 Runnable 的杀手锏:流式输出(传统 Chain 做不到)
for chunk in chain.stream({"topic": "AI"}):
    print(chunk, end="")  # 一个字一个字地往外蹦

3. 为什么说 Runnable 是"降维打击"?(面试深度加分点)

Runnable 带来的不仅是语法糖,而是架构级别的解放

  • 解耦了输入输出键名 :传统 Chain 强制你传 input 和取 text,如果链条长了,你会被各种键名映射搞疯。Runnable 支持任意字段名 ,在复杂 RAG 或 Agent 中,你可以传 {"question": "...", "context": "..."},哪个节点取哪个字段完全自己控制。
  • 统一的基座,让"万物皆可链" :在 Runnable 时代,promptllmretrievervectorstore、甚至编译后的 LangGraph 都是 Runnable。你可以写 vectorstore | llm,这在传统 Chain 时代是完全不敢想的。
  • 批处理性能暴增 :如果用户并发请求(如同时处理 10 个问题),传统链要循环 10 次;Runnable 只需 chain.batch([q1, q2, q3]),底层自动利用线程池并发,时间直接缩短为原来的 1/5。

4. 面试回答话术(让面试官点头)

"Runnable 是 LangChain 的统一执行协议 ,它取代了 1.0 时代那些臃肿的特定 Chain 类。它的核心价值是标准化 :任何组件只要实现了 invokestreambatch 这三个方法,就可以通过 | 管道符无缝组合。这也正是 LangChain 从'一堆工具'进化为'可编程框架'的关键转折点。在实际项目中,我完全使用 LCEL 构建业务逻辑,因为它不仅代码量减少 50%,还能原生支持流式输出和并发批处理,这是传统 Chain 无法企及的。"

三、Chain、Tool、Agent、Memory 篇(二面核心 ★★)

7. Chain、Tool、Agent、Memory 的职责边界如何划分?

这是系统设计的核心问题,职责混乱是 Agent 失控的主要原因:

组件 职责
Chain 确定性的流程,比如固定步骤的数据处理
Tool 明确副作用的能力,比如查库、调接口、下发指令
Agent 在不确定场景下做决策,只做这一件事
Memory 状态管理,不是知识,更不是万能缓存

关键原则:一旦 Tool 里写逻辑、Agent 里塞业务规则,系统后期一定不可维护。


8. LangChain 的 Memory 组件如何工作?有哪些 Memory 类型?

Memory 用于在对话中保持上下文,LangChain 提供多种实现:

Memory 类型 特点 适用场景
ConversationBufferMemory 完整保存所有对话 短对话
ConversationBufferWindowMemory 只保留最近 K 轮 控制 token 消耗
ConversationSummaryMemory 自动总结历史对话 长对话
ConversationSummaryBufferMemory 窗口 + 总结混合 平衡信息与 token
VectorStoreRetrieverMemory 向量检索相关记忆 超长对话、知识库

9. 如何在 LangChain 中集成外部工具?Tool 的定义规范是什么?

Tool 是供模型调用的受控函数(含名称、入参模式与执行体),输出通常回传给模型用于后续推理。

python 复制代码
from langchain.tools import tool

@tool
def get_weather(city: str) -> str:
    """查询指定城市的天气"""
    return f"{city}:晴朗 25°C"

定义规范

  • 函数名作为工具名
  • docstring 作为工具描述(LLM 据此判断是否调用)
  • 参数通过类型注解自动生成 Schema

10. 如何实现一个最小化的 ReAct Agent?

答案要点:用可调用工具 + 具备 tool-calling 的 ChatModel,用 LCEL/Runnable 把"思考→调用→观察→总结"串起来。

python 复制代码
from langchain.agents import create_react_agent
from langchain.tools import tool

@tool
def search(query: str) -> str:
    return f"搜索结果:{query}"

agent = create_react_agent(llm, tools=[search])
agent.invoke({"messages": [HumanMessage(content="查询北京天气")]})

四、RAG 与检索篇(二面核心 ★★)

11. 如何在 LangChain 中实现 RAG?

核心流程:

  1. 加载文档 :使用 PyPDFLoader 等加载器
  2. 文本切分 :使用 RecursiveCharacterTextSplitter 按语义切分
  3. 向量化存储:通过 Embedding 模型将文本转为向量,存入 Vector Store
  4. 检索:将用户问题向量化,从 Vector Store 中检索相似文档
  5. 生成:将检索结果作为上下文,与问题一起交给 LLM 生成回答
python 复制代码
# 伪代码示意
loader = PyPDFLoader("doc.pdf")
docs = loader.load()
splits = text_splitter.split_documents(docs)
vectorstore = Chroma.from_documents(splits, embeddings)
retriever = vectorstore.as_retriever()
qa_chain = RetrievalQA.from_chain_type(llm, retriever=retriever)

12. Retriever 和 Vector Store 的关系是什么?

  • Vector Store 是"向量化存储 + 相似度检索"的实现(如 FAISS、Milvus、Chroma)
  • Retriever 是"给定查询返回文档"的抽象接口

常见做法是把向量库 .as_retriever() 化,便于在链里统一编排。

为什么推荐 RecursiveCharacterTextSplitter 它会按分隔符优先级递归切分(默认 \n\n\n、空格、字符),尽量保持段落/句子/词的语义完整度,是通用文本最推荐的切分器。


为了让你彻底弄懂,我们先看一张关系图,再通过代码实战演示。


🧩 概念关系图(先建立整体认知)

复制代码
┌─────────────────────────────────────────────────────────┐
│                     Retriever                           │
│              (抽象的"问"与"答"接口)                     │
│  职责:接收查询(query),返回文档列表(List[Document])    │
│       可以内部实现任意检索策略(向量、关键词、混合、重排)    │
└────────────────────┬────────────────────────────────────┘
                     │ 通常通过 .as_retriever() 包装
                     │
┌────────────────────▼────────────────────────────────────┐
│                  Vector Store                           │
│         (具体的"存储与向量搜索"引擎)                     │
│  职责:存储文本 + 对应的向量 + 元数据                      │
│       执行 ANN(近似最近邻)搜索                          │
│       实现:Chroma, FAISS, Milvus, Pinecone...           │
└─────────────────────────────────────────────────────────┘

一句话总结

Vector Store 是"数据库",Retriever 是"查询接口"

就像 MySQL 是"数据库",而 ORM 框架的 find() 方法是"查询接口"。Retriever 可以看作是一个策略化的查询器,它不一定非得使用向量检索(也可以加过滤、重排),但在 90% 的 RAG 场景中,它只是对 Vector Store 的简单包装。


💻 代码实战:从存储到检索的完整流程

python 复制代码
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain.schema import Document

# 1. 准备文档
docs = [
    Document(page_content="北京今天晴天,气温25℃", metadata={"city": "北京"}),
    Document(page_content="上海今天多云,气温22℃", metadata={"city": "上海"}),
    Document(page_content="广州今天阵雨,气温28℃", metadata={"city": "广州"}),
]

# 2. 创建 Vector Store(真正的物理存储)
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
vectorstore = Chroma.from_documents(
    documents=docs,
    embedding=embeddings,
    persist_directory="./chroma_db"
)
# 此时 Vector Store 已经建立索引,数据持久化到磁盘

# 3. 从 Vector Store 获取 Retriever(生成查询接口)
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 2}  # 指定返回 Top-2 结果
)

# 4. 通过 Retriever 查询(屏蔽底层细节)
result_docs = retriever.invoke("今天广州天气怎样?")
for doc in result_docs:
    print(doc.page_content)  # 输出: "广州今天阵雨,气温28℃"

关键点

  • vectorstore 负责存储和计算相似度(真正的检索引擎)。
  • retriever 只是封装了调用逻辑 ,让你可以用统一的 invoke 方法,而不用手动写 vectorstore.similarity_search(...)

🔍 为什么 Retriever 不仅仅是"马甲"?

尽管上例中 Retriever 只是简单包装,但在复杂场景中,它可以承载更多职责:

python 复制代码
# 自定义 Retriever:向量检索 + 关键词过滤 + 结果重排
class CustomRetriever(BaseRetriever):
    def __init__(self, vectorstore, keyword_filter):
        self.vectorstore = vectorstore
        self.keyword_filter = keyword_filter

    def _get_relevant_documents(self, query):
        # 先做向量检索
        docs = self.vectorstore.similarity_search(query, k=10)
        # 然后按关键词过滤
        filtered = [d for d in docs if self.keyword_filter in d.page_content]
        # 最后自定义排序
        return filtered[:3]

这时 Retriever 就演变为一个独立的业务逻辑单元,而 Vector Store 只负责纯粹的相似度搜索。


📄 补充:为什么推荐 RecursiveCharacterTextSplitter

原因 :它是最懂"人类语言结构"的切分器。

它按层级 递归切分:优先保段落(\n\n),其次保句子(\n),再保从句(),最后保词( )。这样切分能最大程度保留语义完整性。

python 复制代码
from langchain.text_splitter import RecursiveCharacterTextSplitter

text = """第一章:概述。
这是第一段内容,包含多个句子。这里还有第二个句子。

第二章:细节。
这是第二段的内容。
"""

splitter = RecursiveCharacterTextSplitter(
    chunk_size=20,   # 目标长度
    chunk_overlap=5,
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
)
chunks = splitter.split_text(text)
print(chunks)
# 输出会优先按段落切,如果段落超长,再按句子切,不会在单词中间切断。

面试加分点 :如果换成普通 CharacterTextSplitter(按字符数硬切),可能会把一句话切成两半,导致检索时丢失关键实体。Recursive 版本通过递归分隔符,保证了最小的语义损失,是 RAG 生产环境的默认首选。

五、LangGraph 篇(终面拉分 ★★★)

结合你之前深度学习的 LangGraph,这部分是面试中的高分区域

13. LangGraph 是什么?它与 LangChain 有什么关系?

LangGraph 是 LangChain 生态中用于构建有状态、多步骤复杂工作流的图式编排框架。

  • LangChain:提供基础的"链"和"工具"
  • LangGraph :提供"状态图 "和"状态机 ",原生支持循环、条件分支和复杂的状态管理

LangChain 官方建议新的 Agent 使用 LangGraph 来构建(更灵活/可控),老的 Agents 有迁移指引。

14. LangGraph 的核心概念有哪些?

概念 说明
State(状态) 图的全局共享数据结构,所有节点通过它传递信息
Node(节点) 执行单元,接收状态并返回状态更新
Edge(边) 连接节点,定义工作流走向(普通边 + 条件边)
Checkpointer 状态持久化机制,支持会话记忆和时间旅行

15. LangGraph 的条件边(Conditional Edge)如何使用?

条件边根据当前状态动态决定下一个节点:

python 复制代码
def route_after_agent(state: AgentState) -> Literal["tools", "__end__"]:
    if state["messages"][-1].tool_calls:
        return "tools"
    return "__end__"

builder.add_conditional_edges("agent", route_after_agent, {
    "tools": "tools",
    "__end__": END
})

16. 如何在 LangGraph 中实现记忆(短期/长期)?

  • 短期记忆 :通过 MemorySaverSqliteSaver 保存对话状态(messages),基于 thread_id 隔离会话
  • 长期记忆 :通过 AsyncPostgresStore 等 Store 组件,手动读写跨会话的用户数据

17. 如何在 LangGraph 中实现人工干预(Human-in-the-Loop)?

两种方式:

  • interrupt_before:编译时声明,在指定节点前自动暂停
  • interrupt():在节点内部手动调用,可传递自定义提示并接收用户输入
python 复制代码
# interrupt_before 方式
graph = builder.compile(checkpointer=memory, interrupt_before=["tools"])

# interrupt() 方式
def human_approval(state):
    user_input = interrupt("是否继续执行?")
    if user_input != "y":
        return {"cancel": True}

六、生产部署与可观测性篇(终面拉分 ★★★)

18. 如何把链的每一步"自动打点"到 LangSmith?

配置好 LangSmith 环境变量后,运行 LangChain 代码就会自动产生日志/调用树,也支持分布式链路追踪(跨服务传播 trace)。

bash 复制代码
export LANGCHAIN_TRACING_V2=true
export LANGCHAIN_API_KEY=your_key
export LANGCHAIN_PROJECT=my_project

不用 LangSmith 也能观测吗? 可以,社区也有开源方案(如 Langfuse)接回调/中间件实现 tracing 与指标。

19. LangChain 如何做流式输出?

基于 LCEL 构建的链自动实现 stream/astream,既可流式最终输出 ,也可在 RAG 中流式中间步骤(如改写、检索、整合)。是否能逐 token 还取决于底层模型提供商的原生能力。

20. 如何把 Runnable/链快速对外提供服务?

使用 LangServe,可以将任何 Runnable 链快速部署为 REST API 服务,自动生成 OpenAPI 文档,支持流式响应。


七、MCP 协议篇(加分项 ★★★)

结合你之前学习的 MCP,这是面试中的差异化亮点

21. 什么是 MCP?它解决了什么问题?

MCP(Model Context Protocol)是标准化 AI 工具接入协议,解决以往工具集成"各自为政"、"高耦合"、"难以跨语言复用"的问题。

  • 传统方式 :每接入一个 API,都要写一个 @tool 函数
  • MCP 方式:工具提供方直接启动 MCP Server,Agent 只需连接该 Server,就能自动获取所有工具列表并调用

22. MCP 和 Function Calling 的关系是什么?

对比维度 Function Calling MCP
定位 LLM 决策协议(如何表达"我想调用工具") 工具部署协议(工具在哪、怎么通信)
关注点 模型如何生成 tool_calls 工具如何被注册、发现和调用
通信方式 不规定 stdio / SSE

两者配合:Function Calling 让模型学会"填单子",MCP 帮你去"取工具"。


📊 面试难度速查表

难度 题目编号 考察重点
★ 一面必问 1-4 框架定位、核心组件、Agent 基础概念
★★ 二面核心 5-12 LCEL、Runnable、Chain/Tool/Agent/Memory、RAG
★★★ 终面拉分 13-22 LangGraph 状态流、人工干预、生产部署、MCP

面试策略 :基础题看认知完整性 ,进阶题看理解深度 ,落地题看实战经验 ,场景题看体系化设计能力 。建议先吃透实战内容,再结合本文理解记忆,面试时优先答核心得分点,再结合自己的实战项目补充细节。

嵌入模型(Embedding Model) ,简单来说,是一台将"人类的语言"转换成"数学向量"的翻译机器 。它把文本、图像或音频转换成一组固定长度的数字列表(即向量),让计算机能够理解和比较这些内容的"语义"。

结合你之前学习的 RAG(检索增强生成)和向量数据库(Chroma / Milvus),嵌入模型就是那个负责把所有文字转化成坐标的核心部件。


🧠 1. 核心原理:语义即位置

嵌入模型基于深度学习(通常是 Transformer 架构),其核心思想是:语义越相近的文本,在向量空间中的距离就越近。

  • "国王" - "男人" + "女人" ≈ "女王":这是最经典的类比。嵌入模型通过大量语料学习,能够捕捉到这种深层的语言规律。
  • 不是关键词匹配 :它不依赖"是否包含相同词汇",而是理解"意思是否相同"。
    • "天气很热" 和 "今天温度很高" 这两个句子虽然没有一个字相同,但它们的向量在空间中是紧挨在一起的,这就是语义检索的基础。

🛠️ 2. 嵌入模型 vs. 大语言模型(LLM)

这是面试中经常混淆的点,务必区分清楚:

对比维度 嵌入模型 (Embedding Model) 大语言模型 (LLM / 生成模型)
核心任务 理解与匹配(判别式)。把内容转化成坐标,用于检索、聚类、推荐。 生成与创作(生成式)。根据上文预测下一个字,用于写作、对话、编程。
输入/输出 输入文本,输出固定长度的向量(例如 768 维的浮点数数组)。 输入文本,输出不定长的自然语言文本
典型模型 text-embedding-ada-002 (OpenAI)、BAAI/bge-large-zh (智源)、sentence-transformers/all-MiniLM-L6-v2 GPT-4Claude 3Qwen-PlusDeepSeek-V3
参数量级 通常较小(几百万到几亿参数),推理速度极快。 通常极大(几十亿到上万亿参数),推理速度慢且昂贵。
在你的项目中的位置 在写入向量库前(Indexing)和用户提问时(Querying)使用。 在检索到资料后,负责阅读资料并生成最终回答。

一句话总结嵌入模型决定"找得准不准",大语言模型决定"答得好不好"


🔍 3. 嵌入模型在 RAG 中的具体角色

结合你之前的代码,嵌入模型贯穿了 RAG 的整个流程:

  1. 离线阶段(数据入库)

    • 你加载 PDF 并切分成 Chunks。
    • 调用嵌入模型(如 HuggingFaceEmbeddings)将每个 Chunk 变成向量。
    • 将这些向量存入向量数据库(Chroma/Milvus)。
  2. 在线阶段(用户查询)

    • 用户提问。
    • 调用同一个嵌入模型,将用户的问题也变成一个向量。
    • 拿着这个向量去向量库里进行 相似度计算(如余弦相似度),找出离它最近的 Top-K 个 Chunks。

🎯 4. 如何选择嵌入模型(面试高频考点)

在你本地开发时,用的是 paraphrase-multilingual-MiniLM-L12-v2。而在生产环境中,可以按以下维度选择:

  • 语言支持 :如果处理纯中文,BAAI/bge-large-zhtext-embedding-v3 (阿里云)效果更好;处理多语言,可用 multilingual-e5-large
  • 向量维度:维度越高(如 1024 维 vs 384 维),表达能力越强,但存储和计算开销也越大。
  • 上下文长度 :有些模型只能处理 512 个 token,有些(如 BGE-M3)能处理 8192 个,这对长文档分块很重要。
  • Embedding 模型的"致命伤" :它不知道"新鲜事"。比如 2026 年发生了新事件,如果你用 2023 年训练的嵌入模型去检索,它可能会找不到最相关的资料。解决方案是:用更强的模型微调,或使用支持混合检索(BM25 + 向量)的策略来兜底

💡 5. 面试常见追问与回答话术

Q:既然 LLM 能理解文本,为什么不直接用 LLM 来做检索?

A:LLM 做一次推理耗时约 1~2 秒,成本约 $0.01;而嵌入模型算一次向量仅需 < 10ms,成本几乎为零。在 RAG 系统中,检索阶段要处理海量候选数据(百万级),必须依赖高效的嵌入模型。

Q:为什么每次都要用同一个嵌入模型?

A :因为不同模型生成的向量空间分布不同。如果你用模型 A 给数据库做索引,却用模型 B 给用户提问做查询,那么"风和日丽"和"天气不错"在各自的向量空间中不兼容,会导致检索结果完全错误。必须保持模型版本一致。

Q:如何评估一个嵌入模型的好坏?

A :主要看 MTEB(大规模文本嵌入基准测试) 排行榜。主要关注 检索(Retrieval) 任务的平均准确率(NDCG@10),以及在中文数据集(如 C-MTEB)上的表现。