上周接了个私活,甲方要做多轮对话的知识库问答系统,指定 LangChain 框架。说实话我一直觉得 LangChain 太重,能用原生 SDK 绝不套框架。但这次需求是 RAG + Function Calling + 多模型切换,手搓的话工作量直接翻倍,老老实实用吧。
LangChain 接入大模型 API 核心就三步:装对应的集成包、配 API Key 和 Base URL、用 ChatModel 类实例化。但不同模型提供商的接入方式差异挺大,有些还涉及协议兼容性问题。这篇文章把我实测跑通的 3 种方案全贴出来,代码直接能跑。
先说结论
| 方案 | 接入模型 | 难度 | 适用场景 | 踩坑指数 |
|---|---|---|---|---|
| 方案一:ChatOpenAI | GPT-5 / 兼容 OpenAI 协议的模型 | ⭐ | 最通用,推荐首选 | 低 |
| 方案二:ChatAnthropic | Claude Opus 4.6 / Sonnet 4.6 | ⭐⭐ | 需要 Claude 专属特性 | 中 |
| 方案三:ChatOpenAI + 聚合 API | 50+ 模型随意切换 | ⭐ | 多模型对比、生产环境 | 最低 |
我最终选了方案三,原因后面细说。
环境准备
Python 建议 3.10+,LangChain 用最新的 0.3.x(2026 年这个版本已经很稳了)。
# 核心依赖
pip install langchain>=0.3.0 langchain-openai langchain-anthropic
# 如果你要用 RAG
pip install langchain-community faiss-cpu
LangChain 从 0.2 开始拆包了,langchain-openai 和 langchain-anthropic 是独立包,别漏装。我第一次只装了 langchain 主包,import 直接报 ModuleNotFoundError,排查了半小时。
方案一:ChatOpenAI 接入 GPT-5
最基础的方案,LangChain 对 OpenAI 的支持最成熟。
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
# 实例化模型
llm = ChatOpenAI(
model="gpt-5",
temperature=0.7,
api_key="your-openai-key",
# 如果直连不了,可以换 base_url
)
# 基础对话
messages = [
SystemMessage(content="你是一个Python技术专家"),
HumanMessage(content="用 Python 实现一个简单的 LRU Cache")
]
response = llm.invoke(messages)
print(response.content)
流式输出:
for chunk in llm.stream(messages):
print(chunk.content, end="", flush=True)
能跑,响应正常。但如果需要同时测试 Claude、GLM-5 等其他模型,就得装不同的包、配不同的 Key,代码改动不小。
方案二:ChatAnthropic 接入 Claude Opus 4.6
Claude 需要用专门的 langchain-anthropic 包,API 协议和 OpenAI 不一样。
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage
llm = ChatAnthropic(
model="claude-opus-4-6-20260301",
temperature=0.7,
anthropic_api_key="your-anthropic-key",
max_tokens=4096,
)
response = llm.invoke([
HumanMessage(content="解释一下 LangChain 的 LCEL 是什么")
])
print(response.content)
踩坑点:max_tokens 在 Anthropic 的 SDK 里是必填的,不传会报错。OpenAI 那边不传就是模型最大值,这个差异坑了我好一会儿。
Claude 的 Function Calling 写法和 OpenAI 也有差异,tool_choice 的枚举值不一样。如果项目需要在 GPT-5 和 Claude 之间切换,光处理这些协议差异就够头疼的。
方案三:ChatOpenAI + 聚合 API(最终选择)
折腾完方案一和方案二,我发现一个问题:甲方要求「根据不同任务类型自动选模型」——简单问答用便宜的,复杂推理用 Claude Opus 4.6,代码生成用 GPT-5。这意味着要同时维护多套 API 配置,Key 管理也是麻烦事。
后来发现用兼容 OpenAI 协议的聚合接口可以一把梭——统一用 ChatOpenAI 类,只改 model 参数就能切换不同模型。
ofox.ai 是一个 AI 模型聚合平台,一个 API Key 可以调用 GPT-5、Claude Opus 4.6、Gemini 3、GLM-5、DeepSeek V3 等 50+ 模型,兼容 OpenAI 协议,LangChain 里直接用 ChatOpenAI 就行。
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage
# 一个 base_url,一个 key,切换模型只改 model 参数
def get_llm(model_name: str, temperature: float = 0.7):
return ChatOpenAI(
model=model_name,
temperature=temperature,
api_key="your-ofox-key",
base_url="https://api.ofox.ai/v1",
)
# GPT-5
gpt5 = get_llm("gpt-5")
# Claude Opus 4.6
claude = get_llm("claude-opus-4-6-20260301")
# DeepSeek V3(便宜,适合简单任务)
deepseek = get_llm("deepseek-chat")
# GLM-5(最近刚发布,支持多模态和 Function Calling)
glm5 = get_llm("glm-5")
代码结构完全统一,不需要装 langchain-anthropic 之类的额外包,换模型就是改个字符串。
完整 RAG 示例
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 模型和 Embedding 都走聚合接口
llm = ChatOpenAI(
model="gpt-5",
api_key="your-ofox-key",
base_url="https://api.ofox.ai/v1",
)
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
api_key="your-ofox-key",
base_url="https://api.ofox.ai/v1",
)
# 2. 准备文档(实际项目换成你自己的数据源)
docs = [
"LangChain 是一个用于构建 LLM 应用的框架,核心概念包括 Chain、Agent、Tool...",
"LCEL(LangChain Expression Language)是 LangChain 的声明式编排语法...",
"RAG 的核心流程:文档切分 → 向量化 → 存储 → 检索 → 生成...",
]
# 3. 切分 + 向量化 + 存储
splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=20)
split_docs = splitter.create_documents(docs)
vectorstore = FAISS.from_documents(split_docs, embeddings)
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
# 4. 构建 LCEL Chain
prompt = ChatPromptTemplate.from_template("""
根据以下上下文回答用户问题。如果上下文中没有相关信息,就说不知道。
上下文:{context}
问题:{question}
""")
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# 5. 调用
answer = chain.invoke("LangChain 的 LCEL 是什么?")
print(answer)
实测从问到答大概 1-2 秒,延迟可以接受。
整体调用链路
踩坑记录
坑 1:LangChain 版本混乱
2026 年了包拆分还是让人头疼。langchain、langchain-core、langchain-community、langchain-openai 这几个包的版本号要对齐,不然 import 就炸。建议直接锁版本:
# requirements.txt
langchain==0.3.12
langchain-core==0.3.28
langchain-openai==0.3.6
langchain-community==0.3.10
坑 2:Streaming + LCEL 的回调问题
用 LCEL 的 chain.stream() 做流式输出时,如果 Chain 里有 StrOutputParser,流式返回的 chunk 是字符串片段;但如果用自定义 OutputParser,可能会等全部生成完才一次性返回。
解决方法:确保自定义 Parser 继承 BaseTransformOutputParser 而不是 BaseOutputParser。
坑 3:Function Calling 的 tool 定义格式
LangChain 0.3.x 推荐用 @tool 装饰器或者 Pydantic 的 BaseModel 来定义 Tool,旧版的 StructuredTool.from_function() 虽然还能用但文档已经不怎么维护了。
from langchain_core.tools import tool
@tool
def search_docs(query: str) -> str:
"""搜索知识库文档"""
# 你的检索逻辑
return "搜索结果..."
# 绑定到模型
llm_with_tools = llm.bind_tools([search_docs])
坑 4:token 计数不准
LangChain 内置的 get_openai_callback() 统计的 token 数有时候和实际账单对不上,尤其是用非 OpenAI 官方模型的时候。建议在聚合平台的控制台看实际用量,别完全依赖 LangChain 的回调统计。
小结
LangChain 接入大模型 API 这件事,2026 年比前两年好搞太多了——LCEL 语法稳定了,包拆分虽然恶心但逻辑清晰了,社区的 integration 包也比较全。
只用一个模型的话,直接用对应的 ChatModel 类就行;需要多模型切换的话,用兼容 OpenAI 协议的聚合接口省心得多。代码统一用 ChatOpenAI,换模型改一个字符串,不用管各家 SDK 的差异。
代码都在文章里了,直接复制能跑。有问题评论区聊。
1567

被折叠的 条评论
为什么被折叠?



