# 构建第一个 LangChain RAG 应用
# 问题背景
第一个 RAG 应用要把入库链路和问答链路分开。入库链路负责加载文档、切分、向量化、写入向量库;问答链路负责接收问题、检索、拼接上下文、调用模型、返回答案和来源。
# 工程要点
这部分能力进入生产前,需要把输入、输出、版本和可观测信息设计清楚。输入包括原始文档、用户问题和业务过滤条件;输出包括 chunk、向量、检索结果、答案和引用来源;版本包括模型版本、切分规则、索引版本和文档更新时间。
不要只验证代码能跑通,还要验证结果是否符合业务问题。可以准备一组固定问题,每次调整参数后观察 Top K 是否命中正确资料、答案是否引用正确来源、延迟和成本是否可接受。
# 源码示例
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vectorstore = FAISS.from_documents(chunks, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 4})
prompt = ChatPromptTemplate.from_template("""
请只根据上下文回答问题。
如果上下文没有答案,请说明资料中没有相关信息。
上下文:
{context}
问题:{question}
""")
llm = ChatOpenAI(model="gpt-4o-mini")
question = "产品退款规则是什么?"
docs = retriever.invoke(question)
context = "\n\n".join(doc.page_content for doc in docs)
messages = prompt.invoke({"context": context, "question": question})
answer = llm.invoke(messages)
print(answer.content)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 拓展
这类组件通常不是孤立使用。Embedding 会影响向量库召回,切分会影响 Embedding 表达,metadata 会影响过滤和权限,Prompt 会影响模型是否忠于证据。任何一处改动,都可能改变最终回答质量。
建议把 RAG 当成数据工程、检索工程和生成工程的组合系统。先保证数据正确进入索引,再保证检索能稳定召回,最后再优化模型表达。
# 最新版 LangChain 用法提示
新项目建议使用 ChatPromptTemplate、retriever.invoke()、聊天模型和输出解析器组合,而不是只依赖旧式链。返回结果时最好同时返回 answer 和 sources,方便前端展示引用,也方便排查。
# 常见问题
# 这类组件应该先在什么规模上验证?
先用一小批真实文档和真实问题验证,而不是直接全量入库。验证时至少观察三类结果:检索是否命中正确片段、返回片段是否包含足够上下文、最终回答是否严格基于证据。
# 只看相似度分数够不够?
不够。相似度分数只能说明向量距离,不代表答案一定正确。还要看 chunk 是否完整、metadata 是否正确、过滤条件是否过严或过松,以及 Prompt 是否要求模型只根据上下文回答。
# 参数应该怎么调?
先固定评测问题集,再一次只改一个变量,例如 chunk 大小、overlap、top_k、Embedding 模型或过滤条件。每次改动都记录召回命中率、答案准确率、延迟和成本。
# 面试题
# 1. RAG 链路里最容易被忽略的工程点是什么?
最容易被忽略的是数据处理和评估。很多问题不是 LLM 不会答,而是文档解析错误、chunk 切坏、metadata 丢失、向量版本混乱、检索过滤条件错误,导致模型拿不到正确证据。
# 2. 为什么不能只依赖 LLM 自身参数记忆?
参数记忆存在知识过期、领域知识缺失、事实边界不清和不可追踪的问题。RAG 通过检索外部证据,把回答范围约束在可追踪内容上,适合企业知识库、产品文档和实时资料问答。
# 3. 如何判断一个 RAG 系统的问题出在检索还是生成?
先直接查看检索返回的文档。如果返回内容已经不相关,问题在加载、切分、Embedding、向量库或 Retriever;如果返回内容正确但回答错误,问题多半在 Prompt、上下文压缩、引用组织或模型输出约束。
# 生产问题排查
| 问题 | 常见原因 | 处理方式 |
|---|---|---|
| 回答看起来合理但没有依据 | Prompt 没要求基于上下文,或检索片段不相关 | 增加拒答策略、引用来源、检索结果抽样检查 |
| 召回结果经常跑偏 | chunk 过短、Embedding 模型不适合、query 表达不完整 | 调整切分策略,评估 Embedding,必要时做查询改写 |
| 命中了旧内容 | 文档更新后没有重新入库,或缓存没有区分版本 | 使用文档 hash、版本号、更新时间和重建任务 |
| 多租户数据串库 | metadata filter 缺失或字段设计不严谨 | 强制 tenant_id / dataset_id 过滤,并做权限测试 |
| 成本增长明显 | 重复 Embedding、top_k 过大、无缓存 | 增加缓存、批处理、限流和调用统计 |
| 延迟不稳定 | 向量库网络抖动、LLM 响应慢、检索链路串行 | 并行化可并行步骤,增加超时、重试和降级策略 |