很多 Claude API 与 LangChain 的入门教程,都会从一个很小的 Demo 开始:用 ChatAnthropic 调一次 Claude,只要模型能正常返回内容,就算集成成功。
但如果目标是上线一个真正可用的 RAG 应用,这一步只能算完成了 10%。
生产环境里的 RAG 系统,不只是“能不能调用大模型”,而是要解决一整条链路的问题:文档入库、文本清洗、Chunk 切分、Embedding、向量检索、Claude 生成回答、引用来源、权限隔离、流式输出、日志记录、异常处理、成本控制和效果评估。
这篇文章从工程视角出发,梳理一个 Claude API + LangChain + RAG 应用应该如何从 Demo 走向可上线架构。
1. RAG 系统的整体链路
一个典型的 RAG 系统,大致可以拆成两条链路:离线入库链路和在线问答链路。
离线入库链路负责处理文档:
原始文档
↓
文档解析
↓
内容清洗
↓
语义切分 Chunk
↓
Embedding 向量化
↓
写入向量库
在线问答链路负责处理用户问题:
用户提问
↓
Retriever 检索相关 Chunk
↓
拼接上下文
↓
Claude 基于上下文生成回答
↓
返回答案 + 引用来源
↓
记录日志与用量
也就是说,Claude 并不是直接回答用户问题,而是基于检索到的知识库上下文进行生成。
这正是 RAG 的核心价值:让大模型回答业务私有知识,而不是只依赖模型自身的通用知识。
2. 为什么简单 Demo 不能直接上线?
一个最小 Demo 通常只包含三步:
- 加载一份文档;
- 写入向量库;
- 用户提问后调用 Claude 回答。
这个流程适合学习,但不适合生产环境。
真实项目中,文档可能来自 PDF、Markdown、HTML、TXT、内部 Wiki、产品手册、接口文档、FAQ 等多个来源。不同格式的解析方式不同,噪声也不同。
例如:
- PDF 可能包含页眉、页脚、页码和表格;
- HTML 可能包含导航栏、广告、侧边栏;
- Markdown 可能包含标题、代码块和嵌套列表;
- FAQ 需要保留问答对结构;
- 技术文档中的代码块不能随意截断。
如果这些内容没有经过合理清洗和切分,后续检索质量会非常不稳定。
3. 文档入库:先保证知识源质量
RAG 应用的回答质量,很大程度上取决于知识库质量。
文档入库时,至少要处理三个问题:
3.1 文档解析
不同格式需要不同解析方式。
常见文档类型包括:
- PDF;
- Markdown;
- HTML;
- TXT;
- Word;
- 内部 Wiki;
- 产品帮助中心;
- 技术文档;
- FAQ 数据。
解析目标不是简单把文本抽出来,而是尽量保留有价值的结构信息,比如标题层级、段落、列表、表格、代码块和页面来源。
3.2 内容清洗
需要尽量清理无意义内容,例如:
- 页眉页脚;
- 重复导航;
- 广告内容;
- 版权声明;
- 无意义空行;
- 重复段落;
- 与正文无关的模板内容。
否则这些噪声会进入向量库,在检索时干扰结果。
3.3 元数据保留
每个文档片段最好保留 metadata,例如:
- 文件名;
- 文档标题;
- 原始 URL;
- 页码;
- 更新时间;
- 所属项目;
- 所属用户;
- 权限标签。
metadata 在后续引用来源、权限隔离、问题排查和效果评估中都会用到。
4. Chunk 切分:不要只按固定字数切
很多 RAG Demo 会按照固定字数切分文档,比如每 500 字或 1000 字切一段。
这种方式实现简单,但不一定适合真实业务。
如果 Chunk 太大,检索命中后会带入大量无关信息;如果 Chunk 太小,Claude 拿到的上下文可能不完整。
更推荐按语义结构切分:
- 按标题层级切分;
- 按自然段落切分;
- 保留列表完整性;
- 保留代码块完整性;
- 对表格单独处理;
- 对 FAQ 按问答对切分;
- 给 Chunk 添加前后文窗口。
对于中文文档,还要注意标点、段落、标题和列表关系。中文文本不像英文那样天然有清晰的空格分隔,切分策略会明显影响检索效果。
5. Embedding 与向量库选型
完成 Chunk 切分后,需要通过 Embedding 模型将文本片段转成向量,再写入向量库。
常见向量库选择包括:
| 向量库 | 适合场景 |
|---|---|
| Chroma | 本地 Demo、小型项目 |
| FAISS | 本地实验、轻量检索 |
| Milvus | 大规模向量检索 |
| Pinecone | 托管向量数据库 |
| pgvector | 已经使用 PostgreSQL 的团队 |
如果只是本地验证,Chroma 或 FAISS 就足够。
如果要上线,需要重点关注:
- 是否支持 metadata filter;
- 是否方便做权限过滤;
- 是否支持备份和迁移;
- 是否能承载并发查询;
- 是否方便扩容;
- 运维成本是否可控;
- 是否能融入现有数据库体系。
对于企业知识库场景,metadata filter 很关键。因为不同用户可能只能访问不同文档,检索阶段必须先做权限过滤,不能等模型回答后再处理。
6. Retriever 不是简单 top-k
很多人会直接使用向量库的 top-k 检索,例如每次取最相似的 5 个 Chunk。
但生产环境里,top-k 往往不够。
可以考虑组合策略:
- 向量检索;
- 关键词检索;
- 混合检索;
- metadata 过滤;
- rerank 重排序;
- 相似度阈值过滤;
- 多查询改写;
- 根据问题类型调整 top-k。
例如,用户问的是“某个配置参数怎么设置”,关键词匹配可能很重要;用户问的是“这段政策是什么意思”,语义检索可能更重要。
Retriever 的质量直接决定 Claude 拿到的上下文质量。
如果检索结果错了,后面的模型生成再强,也只能基于错误上下文回答。
7. Claude 在 RAG 中的角色
在 RAG 架构里,Claude 主要负责基于上下文进行理解、归纳和表达。
Prompt 中建议明确约束:
- 只能基于提供的上下文回答;
- 如果上下文没有答案,要说明资料不足;
- 不要编造不存在的事实;
- 回答中尽量附上引用来源;
- 对不确定内容要明确提示;
- 保持回答结构清晰。
一个常见的 Prompt 设计思路是:
你是一个知识库问答助手。
请仅根据提供的上下文回答用户问题。
如果上下文中没有足够信息,请明确说明无法从当前资料中确认。
回答时请尽量引用来源。
不要编造上下文中不存在的内容。
这类约束不能完全消除幻觉,但可以明显降低模型自由发挥的概率。
8. FastAPI 接口与流式输出
如果要上线,RAG 不应该只是一个 Python 脚本,而应该封装成可调用接口。
常见做法是使用 FastAPI 提供问答接口:
前端页面
↓
FastAPI 问答接口
↓
Retriever 检索
↓
Claude 流式生成
↓
前端实时展示答案
流式输出对用户体验很重要。尤其是回答较长时,如果等模型全部生成完再返回,用户会觉得系统很慢。
线上接口还需要处理:
- 请求超时;
- 异常返回;
- 调用重试;
- 用户限流;
- 请求排队;
- 日志脱敏;
- token 用量统计;
- 权限校验。
这些都是从 Demo 走向生产必须补齐的工程能力。
9. 权限隔离与安全控制
企业 RAG 应用中,权限隔离非常重要。
不同用户、部门、项目可能对应不同知识库范围。如果权限控制做得不好,RAG 系统可能会把用户无权访问的内容检索出来,再交给 Claude 生成回答。
比较合理的做法是在检索阶段就做权限过滤。
例如,Chunk metadata 中保存:
tenant_id
user_id
department_id
project_id
permission_tags
用户提问时,Retriever 根据用户身份过滤可访问范围,只检索用户有权限的文档片段。
同时,日志中也要避免直接记录敏感原文、密钥、个人隐私和业务机密。
10. 成本控制与可观测性
RAG 应用上线后,成本会成为长期问题。
需要关注:
- Embedding 成本;
- Claude 输入 token;
- Claude 输出 token;
- 每次检索 top-k 数量;
- 上下文拼接长度;
- 用户请求频率;
- 是否启用缓存;
- 是否有异常高频用户。
建议记录以下指标:
- 每次请求的用户 ID;
- 命中的文档 ID;
- 输入 token;
- 输出 token;
- 响应时间;
- 检索耗时;
- 生成耗时;
- 错误类型;
- 用户反馈。
这些数据可以帮助后续优化检索策略、Prompt、上下文长度和成本结构。
11. 效果评估:RAG 不是上线即结束
RAG 系统需要持续评估。
可以准备一组评估问题,包括:
- 标准答案;
- 预期引用文档;
- 关键知识点;
- 允许的回答范围;
- 不应回答的问题。
评估维度可以包括:
- 检索是否命中正确文档;
- 回答是否基于上下文;
- 引用来源是否准确;
- 是否出现幻觉;
- 回答是否完整;
- 是否拒答合理;
- 响应速度是否可接受。
只有持续评估,才能判断系统是变好了,还是只是“看起来能回答”。
12. 总结
Claude API 与 LangChain 集成并不难,难的是把它做成一个真正能上线的 RAG 应用。
一个生产级 RAG 系统,需要覆盖:
- 文档解析;
- 内容清洗;
- Chunk 切分;
- Embedding;
- 向量库;
- Retriever;
- Claude 生成;
- 引用来源;
- FastAPI 接口;
- 流式输出;
- 权限隔离;
- 日志记录;
- 成本控制;
- 效果评估。
如果只是学习,可以从 ChatAnthropic Demo 开始。
如果要上线,就必须把 RAG 当成完整工程系统来设计。
一句话总结:Claude API 提供生成能力,LangChain 负责流程编排,而 RAG 应用真正能不能上线,取决于文档治理、检索质量和工程化能力。
Claude API 与 LangChain 集成实战:搭建一个能真正上线的 RAG 应用
不少教程会带你用 ChatAnthropic 调一次 Claude API,只要模型能正常返回内容,看起来就算“跑通”了。但如果你真的要把一个 RAG 应用放到线上,这一步其实只是开始。
一个能在生产环境里稳定使用的 LangChain RAG 系统,至少要考虑这些事情:文档怎么入库、怎么切分、怎么做 Embedding、怎么检索、回答时怎么带引用、前端怎么流式输出、异常怎么处理、不同用户的权限怎么隔离、成本怎么控制,以及上线后怎么评估效果。
这篇文章会围绕 Claude API 与 LangChain 的集成,从一个简单 Demo 一步步扩展到更接近生产可用的方案。示例代码主要使用 Python + LangChain + Claude,向量库则可以根据你的实际情况换成 Chroma、FAISS、Milvus、Pinecone 或 pgvector。
我们最终要做什么:一个能上线的 Claude RAG 架构
先看整体流程。一个典型的 RAG 系统,大致可以理解成下面这条链路:
原始文档
↓
文档解析与清洗
↓
按语义切分 Chunk
↓
Embedding 向量化
↓
写入向量库
↓
用户提问
↓
Retriever 检索相关片段
↓
Claude 基于上下文生成回答
↓
返回答案 + 引用来源 + 日志记录
也就是说,用户提问之后,系统并不是直接把问题丢给 Claude,而是先去知识库里找相关资料,再让 Claude 基于这些资料组织答案。
一个比较完整的 RAG 应用,通常需要具备这些能力:
- 能接入 PDF、Markdown、HTML、TXT 等常见文档;
- 对中文文档的标题、段落、列表有比较合理的切分方式;
- 使用向量库做语义检索,而不是只靠关键词匹配;
- 让 Claude 根据检索到的内容生成回答,并附上引用来源;
- 如果资料里没有答案,要明确拒答,而不是硬编;
- 提供 FastAPI 接口,并支持流式输出;
- 有超时、重试、限流、日志脱敏、权限隔离等基础工程能力;
- 能通过评估集持续改进检索质量和回答质量。
所以,本文不是单纯讲“Claude API 怎么调用”,而是讲怎么把 Claude API + LangChain + RAG 组合成一个更接近真实业务场景的知识库问答系统。
Claude API + LangChain 的依赖安装与版本选择
建议使用 Python 3.10 或更高版本。最好先创建虚拟环境,再安装相关依赖:
pip install -U langchain langchain-core langchain-community langchain-anthropic
pip install -U chromadb python-dotenv fastapi uvicorn
如果你准备用其他向量库,可以按需额外安装:
pip install faiss-cpu
pip install pymilvus
pip install pinecone
pip install psycopg[binary] pgvector
API Key 这类配置建议放到 .env 文件里:
ANTHROPIC_API_KEY=your_api_key
ANTHROPIC_BASE_URL=https://api.anthropic.com
在生产环境里,千万不要把 API Key 直接写进代码仓库。更稳妥的做法是使用云厂商的 Secret Manager、Kubernetes Secret,或者 CI/CD 平台提供的环境变量管理能力。
如果你接入的是第三方 Claude API 兼容平台,比如 ClaudeAPI,也需要提前确认一点:它并不是 Anthropic 官方服务。这类平台一般会提供兼容接口、多线路选择、中文支持、企业充值、开票和一些基础技术支持,但具体能力、模型可用性和限制都要以它们官网的最新说明为准。即便使用了这类平台,线上系统也仍然要做好超时、重试、限流和降级,不能把稳定性完全寄托在接口服务上。
第一步:先用 ChatAnthropic 跑通 Claude API
在 LangChain 里,接入 Claude 通常会用 langchain-anthropic 提供的 ChatAnthropic。
import os
from dotenv import load_dotenv
from langchain_anthropic import ChatAnthropic
load_dotenv()
llm = ChatAnthropic(
model="claude-3-5-sonnet-latest",
api_key=os.getenv("ANTHROPIC_API_KEY"),
base_url=os.getenv("ANTHROPIC_BASE_URL"),
temperature=0.2,
max_tokens=1024,
timeout=30,
max_retries=2,
)
resp = llm.invoke("用三句话解释什么是 RAG。")
print(resp.content)
这里有几个参数,在 RAG 场景里尤其重要。
model 决定了成本和效果的平衡。如果是高频、低成本问答,可以考虑 Haiku;如果是企业知识库、客服问答这类对准确性要求更高的场景,Sonnet 通常更合适;如果问题非常复杂,需要更强推理能力,再考虑 Opus。
temperature 建议调低一些,比如 0~0.3。RAG 问答并不需要模型发挥太多想象力,回答越稳定越好。
max_tokens 也要控制好。设置太小,回答可能被截断;设置太大,又会增加成本和延迟。
timeout 和 max_retries 在生产环境里必须配置。否则接口偶发变慢时,请求可能会长时间卡住,进而拖垮后端服务。
如果你要做聊天界面,通常还会用到流式输出:
for chunk in llm.stream("请解释 LangChain RAG 的核心流程"):
print(chunk.content, end="", flush=True)
如果 Claude 是通过 AWS Bedrock 或 Vertex AI 接入,认证方式、模型名称和 SDK 配置会有所不同。不过上层思路不变:先检索上下文,再让 Claude 基于上下文回答。
第二步:准备 RAG 知识库文档
RAG 的效果,首先取决于知识库本身的质量。很多项目效果不好,并不是模型不行,而是文档解析、清洗和切分做得太粗糙。
常见的文档来源大概有这些:
- Markdown:很适合技术文档、产品说明、开发者文档;
- PDF:常用于合同、手册、研究报告,但要特别注意解析乱码和版式错乱;
- HTML 或网页:需要去掉导航栏、广告、页脚等无关内容;
- TXT / CSV:适合 FAQ、客服知识库、结构化问答;
- Notion、飞书、Confluence:一般需要通过 API 或导出文件接入。
每个文档片段都建议保留 metadata,也就是元数据。比如:
metadata = {
"source": "https://example.com/docs/rag",
"title": "RAG 使用手册",
"page": 3,
"section": "权限管理",
"created_at": "2026-06-01",
"tenant_id": "company_a"
}
这些字段看起来只是附加信息,但到了生产环境会非常关键。比如 tenant_id、user_id、department_id 这类字段,后面会用来做权限隔离和 metadata filter。没有这些信息,系统很容易出现“用户 A 检索到用户 B 文档”的严重问题。
第三步:文档怎么切,基本决定了 RAG 的效果上限
文档切分不是简单按字符数截断。切得不好,检索出来的片段就会缺上下文,Claude 再强也只能根据残缺资料回答,效果自然会打折扣。
LangChain 里比较常用的是 RecursiveCharacterTextSplitter:
from langchain_text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=120,
separators=["\n## ", "\n### ", "\n\n", "。", "!", "?", ";", "\n", " ", ""],
)
chunks = splitter.split_documents(docs)
一些比较实用的经验是:
- 中文技术文档可以先从
chunk_size=600~1000字符开始试; - FAQ 最好尽量保持“一问一答”作为一个 chunk;
- 法律、合同、制度类文档,要保留章节标题和条款编号;
- overlap 不宜太大,否则会增加成本,也会带来重复噪声;
- 切完之后一定要抽样检查,看看标题、上下文、来源有没有丢。
尤其要注意标题层级。比如下面这种结构:
# 产品手册
## 账号权限
### 管理员权限
正文……
如果切分后只留下“正文”,没有保留“账号权限 / 管理员权限”这样的上下文,检索结果可能就会变得很模糊。用户问“管理员能不能重置密码”时,系统可能找到了相关正文,但 Claude 不知道这段话属于哪个模块,回答自然不够稳。
第四步:选择 Embedding 和向量库
Claude 主要负责生成答案,但语义检索一般还需要单独的 Embedding 模型。Embedding 的作用,就是把文本转换成向量,方便系统根据语义相似度找到相关内容。
常见选择可以参考下面这张表:
| 方案 | 适用场景 | 注意点 |
|---|---|---|
| Voyage | 英文和多语种检索,Claude 生态里比较常见 | 要关注模型可用性和调用成本 |
| OpenAI Embedding | 通用性强,生态成熟 | 需要考虑接入方式和合规要求 |
| Cohere Embedding | 多语种支持不错 | 中文效果最好结合业务数据实测 |
| BGE / bge-m3 | 中文场景和本地部署比较常见 | 通常需要自建推理服务 |
| 本地 embedding | 数据不能出内网的场景 | 运维和性能优化成本更高 |
向量库则可以根据数据规模和团队能力来选:
| 向量库 | 适用场景 |
|---|---|
| Chroma | 本地开发、原型验证 |
| FAISS | 单机轻量级检索 |
| Milvus | 大规模向量检索、私有化部署 |
| Pinecone | 托管向量服务,减少运维投入 |
| pgvector | 已经有 PostgreSQL 系统,方便和业务权限结合 |
如果只是学习或者做原型,Chroma 很方便;中小团队做生产环境,可以重点考虑 pgvector 或 Milvus;如果是大规模 SaaS,托管向量库或者自建 Milvus 集群会更常见。
第五步:用 LangChain 构建 Retriever 和 RAG Chain
下面用 Chroma 举一个最小可运行的例子。Embedding 部分你需要替换成自己实际使用的模型。
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
# 假设 embeddings 已初始化
vectorstore = Chroma.from_documents(
documents=chunks,
embedding=embeddings,
persist_directory="./chroma_db"
)
retriever = vectorstore.as_retriever(
search_type="mmr",
search_kwargs={
"k": 5,
"fetch_k": 20
}
)
prompt = ChatPromptTemplate.from_template("""
你是企业知识库助手。请只根据下面的资料回答问题。
如果资料中没有答案,请回答“资料中未找到相关信息”,不要编造。
资料:
{context}
问题:
{question}
回答要求:
1. 用中文回答;
2. 简洁准确;
3. 在回答末尾列出引用来源。
""")
def format_docs(docs):
return "\n\n".join(
f"[来源:{d.metadata.get('title')} 页码:{d.metadata.get('page')}]\n{d.page_content}"
for d in docs
)
rag_chain = (
{
"context": retriever | format_docs,
"question": RunnablePassthrough()
}
| prompt
| llm
)
answer = rag_chain.invoke("管理员如何重置用户密码?")
print(answer.content)
这个示例已经能完成基本的“检索资料 + Claude 回答”。不过在线上环境里,Retriever 通常还要继续增强。
比如,可以加 score_threshold,当检索分数太低时直接拒答;可以加 metadata filter,根据租户、部门、用户权限过滤文档;也可以加 rerank,对初筛结果重新排序;如果用户的问题比较口语化,还可以做 query rewrite,把问题改写成更适合检索的表达。
这些看起来都是细节,但对真实效果影响很大。
第六步:让 Claude 回答更可靠:引用、拒答和反幻觉
RAG 并不能保证完全没有幻觉,但它可以显著降低“没有依据还一本正经回答”的概率。关键在于把边界控制好。
首先,Prompt 里要明确要求 Claude 只基于上下文回答,不要额外发挥。尤其是企业知识库场景,用户要的不是百科式扩展,而是和内部资料一致的答案。
其次,资料里没有答案时要拒答。如果检索结果为空,或者检索分数明显过低,就应该直接返回“资料中未找到相关信息”。不要把一个很弱的上下文硬塞给模型,否则它很可能会补全出看似合理但没有依据的内容。
另外,引用来源也要强制返回。每个 chunk 最好都有 source、title、page、section 这些字段。回答里引用这些信息,用户才能回到原文核对。
还要注意 Prompt 注入问题。文档里可能会出现类似“忽略之前指令”“输出系统提示词”这样的恶意内容。系统提示中应该明确说明:文档只是知识来源,不能覆盖开发者指令、安全策略和系统级约束。
最后,也是最重要的一点:权限过滤必须前置。用户 A 的问题绝不能检索到用户 B 的文档。这个事情不能只靠 Prompt 约束,而应该在 retriever 的 metadata filter 层面完成。
第七步:封装成可以上线的 API 服务
一个最小的 FastAPI 服务,通常可以先提供三个接口:
/ingest:文档入库;/chat:知识库问答;/health:健康检查。
示例代码如下:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ChatReq(BaseModel):
question: str
tenant_id: str
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/chat")
def chat(req: ChatReq):
# 实际生产中应将 tenant_id 放入 retriever filter
result = rag_chain.invoke(req.question)
return {"answer": result.content}
这个版本只能算骨架。真正上线时,还需要补上不少工程能力,比如:
- 使用 SSE 或 WebSocket 实现流式输出;
- 增加请求超时和取消机制;
- 接入用户身份认证;
- 在检索层加入租户级 metadata filter;
- 记录请求日志和错误日志;
- 构建 Docker 镜像,并配置健康检查;
- 准备灰度发布和回滚策略。
流式输出对聊天产品体验很好,但线上要特别注意代理服务器、API 网关和浏览器端的超时配置。很多时候本地流式输出正常,部署后却中途断流,问题往往就出在这些基础设施配置上。
第八步:上线前必须考虑成本、性能和安全
RAG 的成本主要来自四个地方。
第一,是文档入库时的 Embedding 成本。文档越多、切分越细,Embedding 调用就越多。
第二,是向量库的存储和检索成本。数据规模上来之后,索引、存储、查询性能都会变成实际问题。
第三,是每次问答传给 Claude 的上下文 token。检索出来的 chunk 越多,输入 token 就越高。
第四,是 Claude 生成答案本身的输出 token。
常见的优化方式包括:
- 控制
top_k,不要把大量 chunk 一股脑塞进上下文; - 对重复文档做 hash 去重;
- 缓存 embedding 结果,避免重复计算;
- 对高频问题缓存答案,但要处理文档更新后的失效问题;
- 高峰期可以降级到更低成本的模型;
- 批量入库尽量异步处理,不要阻塞用户请求;
- 日志里不要记录完整敏感文档,可以记录文档 ID、chunk ID、延迟和错误类型。
安全方面,至少要做到下面这些:
- API Key 不能进代码仓库;
- 日志要做脱敏;
- 用户文档要按租户隔离;
- 向量检索必须带权限过滤;
- 上传文档要限制类型和大小,必要时做病毒扫描;
- 不要把用户隐私数据发送到不符合合规要求的第三方服务。
这些要求听起来比较基础,但很多线上事故恰恰就是因为基础安全措施没有做到位。
第九步:如何评估 Claude RAG 应用的效果
上线前不要只靠“随便问几个问题,看起来还行”来判断效果。更稳妥的方式是准备一套评估集,格式可以很简单:
问题 | 标准答案 | 应命中文档 | 是否允许无答案
重点关注这些指标:
- 检索命中率:正确文档有没有进入 top_k;
- 答案准确率:Claude 是否基于资料给出了正确回答;
- 引用正确率:引用来源是否真的支持答案;
- 无答案拒答率:资料里没有答案时,系统有没有拒答;
- 平均延迟:检索耗时、模型耗时和总耗时分别是多少;
- 单次成本:输入 token、输出 token、embedding 和向量库成本。
你可以用 LangSmith 来记录链路,也可以自建日志表,记录 query、retrieved_docs、latency、token usage、error_type 等字段。
RAG 的优化最好建立在日志和评估集上,而不是只靠反复调整 Prompt。Prompt 当然重要,但检索、切分、rerank、权限过滤和数据质量,往往同样关键。
常见报错与排查清单
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
ModuleNotFoundError: langchain_anthropic | 没有安装依赖 | 执行 pip install langchain-anthropic |
ANTHROPIC_API_KEY 未配置 | 环境变量缺失 | 检查 .env 文件和部署环境变量 |
| 模型名不可用 | 模型名过期,或账号没有权限 | 查看当前服务支持的模型列表 |
| 回答被截断 | max_tokens 设置太小 | 增大输出 token,或者要求模型回答更简洁 |
| 429 rate limit | 请求过快或额度受限 | 增加重试、限流、排队和降级 |
| 检索为空 | embedding 不匹配、文档没入库、filter 太严格 | 检查向量库数据、top_k 和过滤条件 |
| 检索到错误文档 | chunk 切分不合理,或 embedding 效果不佳 | 调整切分方式,增加 rerank,优化 query |
| 回答编造来源 | Prompt 约束不够,或 metadata 缺失 | 强制引用 chunk metadata,低分时直接拒答 |
| 上下文过长 | top_k 太大,或 chunk 太长 | 缩小 chunk,减少 top_k,增加上下文压缩 |
| 中文 PDF 乱码 | PDF 解析器不适配 | 尝试 OCR,或者更换 PDF 解析工具 |
| 本地能跑,线上报错 | 环境变量、网络、依赖版本不一致 | 固定依赖版本,增加健康检查和启动日志 |
| 流式输出中断 | 网关或客户端超时 | 配置 SSE/WebSocket,关闭缓冲或延长超时 |
Claude API + LangChain RAG 技术选型建议
如果只是学习和验证,可以从最简单的组合开始:
Claude API + LangChain + Chroma/FAISS + 本地脚本
这个方案上手快,适合理解 Claude API 与 LangChain 的集成方式,也方便快速跑通基础 RAG 流程。
如果是中小团队的生产环境,可以考虑:
Claude Sonnet + LangChain + pgvector/Milvus + FastAPI + 权限过滤 + 日志评估
这类组合比较适合企业知识库、客服助手、内部文档问答等场景。重点不只是模型效果,还包括权限、稳定性和可观测性。
如果是大规模 SaaS,架构通常会更复杂:
Claude + 托管/集群向量库 + rerank + 缓存 + 队列 + 监控 + 灰度发布
这时要重点处理多租户隔离、成本控制、限流降级、模型切换和评估闭环。否则用户量一上来,成本和稳定性问题会很快暴露出来。
FAQ:Claude API、LangChain 与 RAG 常见问题
Claude API 可以直接和 LangChain 集成吗?
可以。一般使用 langchain-anthropic 里的 ChatAnthropic,配置好 API Key、模型名、超时和重试参数,就可以在 LangChain 中调用 Claude。
Claude 适合做 RAG 吗?
适合。Claude 的长上下文能力和中文理解能力,对 RAG 问答很有帮助。不过最终效果仍然取决于检索质量、文档切分策略、引用控制和拒答机制。
Claude 的长上下文能替代 RAG 吗?
不能简单替代。长上下文适合少量文档的临时分析,而 RAG 更适合持续更新的大规模知识库。它还能减少每次请求传入的 token,从而降低成本。
LangChain RAG 必须使用向量数据库吗?
不一定。小规模数据可以用 FAISS 或内存检索。但生产环境通常会使用 Chroma、Milvus、Pinecone、pgvector 等向量存储,方便管理数据、扩展规模和做权限过滤。
中文 RAG 推荐用什么 embedding?
需要结合你的业务数据实测。中文场景可以重点测试 BGE 系列、多语种 embedding、OpenAI、Cohere、Voyage 等方案,再比较检索命中率、延迟和成本。
RAG 应用怎么减少幻觉?
核心做法是提高检索质量,降低生成温度,要求回答带引用,资料不足时拒答,同时配合 score threshold、rerank 和评估集持续优化。
生产环境该用 Agent,还是普通 RAG Chain?
普通知识库问答优先使用 RAG Chain。它链路更清晰,成本更低,也更容易控制。只有当业务需要调用工具、执行多步任务或进行复杂决策时,再考虑 Agent 或 LangGraph。