LangChain 本身不是模型服务,它负责把提示词、模型、工具和输出解析器串成应用。只要目标服务提供 OpenAI 兼容接口,就可以用 langchain-openai 里的 ChatOpenAI 接进来,把请求指向自己的 Base URL。实际卡住人的往往不是框架,而是三个字段:地址填到哪一层、Key 从哪里读、模型名和网关上架的是否一致。
本文按“安装—最小示例—环境变量—链—流式—Agent—排错—迁移”的顺序讲一遍。LangChain 版本迭代较快,类名和参数以你安装的版本文档为准。
说明:LangChain 是 LangChain, Inc. 的商标,OpenAI 为其权利人的商标;本文与相关厂商无隶属关系。模型名称与价格以站内模型价格为准,接口细节以官方文档为准。
一、安装:核心是两个包
新建虚拟环境后安装:
python -m venv .venv
source .venv/bin/activate
pip install -U langchain langchain-openai
langchain-openai 是 OpenAI 及兼容接口的集成包,langchain 提供链、Agent 等上层能力,langchain-core 会作为依赖一起安装。生产环境建议在 requirements.txt 里固定版本,避免不同机器装出不一致的 API。旧教程里常见的 langchain.chat_models.ChatOpenAI 已经迁移,新的导入路径是 langchain_openai。
二、最小示例:ChatOpenAI 指向自定义地址
核心就是三个参数:model、base_url、api_key。base_url 一般填到 /v1,不要带 /chat/completions,客户端会自己拼接路径。
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="你的模型名",
base_url="https://你的网关地址/v1",
api_key="sk-你的Key",
temperature=0.3,
timeout=60,
)
resp = llm.invoke("用一句话解释什么是 OpenAI 兼容接口。")
print(resp.content)
先跑通这一段,再接提示词和工具。建议按下面的顺序验证:
- 用 curl 请求
base_url加/chat/completions,确认地址和 Key 可用。 - 在 Python 里创建
ChatOpenAI,只调用一次invoke。 - 打印
resp.content和resp.response_metadata,核对模型名与用量字段。 - 跑通后再加提示词模板、输出解析器和工具。
若这里就报 404,先核对地址层级;报 401,先核对 Key 和鉴权头;报模型不存在,请求 /v1/models 对照名称。模型名必须和网关返回的完全一致,大小写、日期后缀和别名都算差异。
三、参数与环境变量怎么管
不要把 Key 硬编码进代码。OpenAI SDK 会读取 OPENAI_API_KEY,也可以读取 OPENAI_BASE_URL;部分旧代码和文档使用 OPENAI_API_BASE。不同版本行为略有差异,最稳妥的做法是显式传参,环境变量只作为默认值。
| 参数 | 作用 | 常见写法 |
|---|---|---|
model |
模型标识 | 与 /v1/models 返回一致 |
base_url |
接口根地址 | https://host/v1 |
api_key |
鉴权密钥 | 显式传入或读 OPENAI_API_KEY |
temperature |
采样随机性 | 按模型支持范围设置 |
timeout |
单次请求超时 | 按任务长度调整 |
max_retries |
客户端重试次数 | 一般 2 次左右 |
本地开发可以用 .env 文件配合 python-dotenv,但 .env 必须加入 .gitignore。团队场景建议按项目和环境拆分 Key,生产和测试分开限额,出问题时可单独停用。
四、链:用 LCEL 把提示词和模型串起来
LangChain 表达式语言(LCEL)用管道符组合组件,最基本的链是“提示词 → 模型 → 输出解析器”:
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
prompt = ChatPromptTemplate.from_messages([
("system", "你是技术支持助手,回答要具体,先给结论。"),
("user", "{question}"),
])
chain = prompt | llm | StrOutputParser()
print(chain.invoke({"question": "Base URL 应该填到哪一层?"}))
invoke 接收一个输入返回一个结果,batch 接收列表批量处理,stream 逐块返回。输出解析器负责把模型消息转成字符串或结构化对象;需要 JSON 时,优先使用模型支持的结构化输出,再叠加解析和校验,不要只靠提示词。
五、流式输出与批量调用
流式输出适合聊天界面和长回答:
for chunk in chain.stream({"question": "解释一下什么是工具调用"}):
print(chunk, end="", flush=True)
如果 invoke 正常而 stream 没有逐字输出,通常是链路上有代理开启了缓冲,或者上游不支持流式。检查网关是否返回 text/event-stream,反向代理是否关闭了 buffering。批量调用要注意并发:batch 默认可能并发发送,遇到 429 时降低并发数或分批执行,并保留失败项以便重跑。
六、Agent:模型加工具加循环
Agent 的本质是一个循环:模型判断是否需要调用工具,运行时执行工具并把结果回传,模型再决定下一步,直到给出最终回答。LangChain 1.x 提供 create_agent 等高层接口;0.3 及更早版本常用 AgentExecutor,两者写法不同,照抄旧教程容易导入失败。
工具用装饰器定义即可,函数名、参数类型和文档字符串都会影响模型选择:
from langchain_core.tools import tool
@tool
def get_order_status(order_id: str) -> str:
"""根据订单号查询物流状态。"""
return "已发货,预计三天内送达"
接自定义网关时要注意:工具调用依赖上游完整支持 tools、tool_choice 和结果回传格式。部分兼容服务只实现了基础对话,遇到工具调用会忽略参数或直接报错。先用一个工具、一个简单问题验证,再增加工具数量和并行调用。
七、常见报错与排查
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 401 Unauthorized | Key 无效、未传入或多了空格 | 显式传 api_key,核对环境变量 |
| 404 model_not_found | 模型名不一致或地址多了路径 | 请求 /v1/models,base_url 只到 /v1 |
| 429 Too Many Requests | 并发过高或配额耗尽 | 降低并发、分批、退避重试 |
| 400 context_length_exceeded | 输入超过上下文上限 | 截断历史、拆分文档、先摘要 |
| OutputParserException | 模型输出不符合预期格式 | 限定格式、加校验、失败重试一次 |
| APIConnectionError / 超时 | 网络、代理、证书或上游故障 | 检查代理变量、DNS、超时设置 |
| 工具调用无反应 | 上游不支持 tools 协议 | 换支持工具调用的模型或改用普通链 |
排查时先绕过 LangChain,用 curl 或 OpenAI SDK 直接请求同一地址。直连成功而 LangChain 失败,问题多在参数名、环境变量或版本;两边都失败,问题在网关、Key 或网络。
八、从旧写法迁移
- 导入路径:
langchain.chat_models.ChatOpenAI改为langchain_openai.ChatOpenAI。 - 参数名:
model_name改为model,openai_api_base改为base_url。 - 旧版
OpenAI文本补全类逐步让位于聊天模型,新项目直接用ChatOpenAI。 - 旧链和旧 Agent 在 1.x 中部分迁入兼容包,迁移前先看官方迁移说明,不要混装多个大版本。
- 依赖管理:升级前锁定版本并在测试环境跑一遍核心链路,重点验证流式、工具调用和结构化输出。
常见问题
base_url 到底要不要带 /v1?
多数 OpenAI 兼容服务要求带到 /v1,客户端再拼接 /chat/completions。也有网关把版本前缀放在别的路径下,以服务商文档为准。判断标准很简单:用 curl 请求 base_url + /chat/completions 能通即可。
可以用 OPENAI_BASE_URL 环境变量吗?
可以,OpenAI SDK 会读取它;部分旧文档写作 OPENAI_API_BASE。不同版本支持情况不完全一致,生产代码建议显式传 base_url,避免环境差异导致请求发错地址。
为什么 invoke 正常,stream 却没有输出?
常见原因是代理缓冲、上游不支持流式,或代码里把流式结果当成完整字符串处理。先确认响应类型是事件流,再检查反向代理配置和读取方式。
LangChain 能接 Claude、DeepSeek 等非 OpenAI 模型吗?
可以。若服务提供 OpenAI 兼容接口,用 ChatOpenAI 改地址和模型名即可;若使用厂商原生协议,则用对应的集成包。两种方式的参数和工具调用能力不同,需要分别验证。
Agent 调工具时报参数错误怎么办?
先看模型返回的工具调用结构是否符合协议,再检查工具函数的参数类型和必填项。部分兼容网关对并行工具调用支持不完整,可以关闭并行调用、一次只给一个工具,逐步排查。
下一步
LangChain 接入自定义 API 的关键,是把地址、Key、模型名三件事固定下来,再用最小请求验证,最后才加链和工具。需要统一的 OpenAI 兼容入口、虚拟 Key 和用量记录,可以先注册中商起航 AI 网关,模型与价格以模型价格为准。
相关阅读:
