LangChain / LlamaIndex 接入多个大模型 —— 一份代码跑通 Claude、GPT、Gemini
用过 LangChain 的人都踩过这个坑:
from langchain_anthropic import ChatAnthropic
from langchain_openai import ChatOpenAI
from langchain_google_genai import ChatGoogleGenerativeAI
三个 provider 包,三份 pip 依赖,三份 API Key,三份限流和错误码的坑,升级一次
LangChain 大概率有一个 provider 包会跟不上。你的 requirements.txt 越来越大,
真正的业务代码反而只占几行。
这篇文章给你一个更简单的做法:只用 langchain-openai,通过统一 OpenAI 兼容
网关调用 Claude、GPT、Gemini。全文代码都能直接复制运行。
为什么只装一个 provider 包就够了
LangChain 的 ChatOpenAI 默认连的是 api.openai.com,但它支持把 base_url
改到任意兼容 OpenAI 协议的服务。这是 LangChain 早就支持的特性,只是很多人
没注意到。
我们需要的只是一个兼容 OpenAI 协议、背后能调用 Claude/GPT/Gemini 的网关。
nucleus-llm 就是这样一个网关 —— 部署在新加坡,接受人民币付款,协议完全兼容 OpenAI
/v1/chat/completions。
最终的依赖只剩一行:
langchain-openai
没了。不再需要 langchain-anthropic、langchain-google-genai,不再需要各家的
原生 SDK。
最小可运行示例
环境
pip install "langchain-openai>=0.1.0" "langchain-core>=0.3.0"
export NLLM_API_KEY="sk-proxy-你的key"
调用 Claude(通过 LangChain)
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(
model="claude-sonnet-4-6",
base_url="https://llm.nucleusenterprise.ai/v1",
api_key=os.environ["NLLM_API_KEY"],
)
reply = llm.invoke([HumanMessage(content="用一句话介绍你自己,并告诉我你是哪个模型")])
print(reply.content)
注意三点:
- import 的是
ChatOpenAI,但运行的是 Claude。这是因为 nucleus-llm 把 OpenAI 请求格式转成了 Anthropic 的原生 Messages API,再把响应转回来。 - 所有 LangChain 的链式操作(
|、with_structured_output、bind_tools)都 仍然可用,因为它们只依赖ChatOpenAI的接口。 - 切换到 GPT 或 Gemini,只改
model一个字段。
一个工厂函数,动态切换模型
实际项目里你很可能想根据任务类型动态选模型。比如:分类用 Haiku,代码生成用 Codex,长文总结用 Gemini Pro。下面是一个极简的工厂:
import os
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
BASE_URL = "https://llm.nucleusenterprise.ai/v1"
API_KEY = os.environ["NLLM_API_KEY"]
def make_llm(model: str, **kwargs) -> ChatOpenAI:
return ChatOpenAI(
model=model,
base_url=BASE_URL,
api_key=API_KEY,
**kwargs,
)
# 按任务类型选模型
llms = {
"classify": make_llm("claude-haiku-4-5", temperature=0),
"codegen": make_llm("gpt-5.3-codex", temperature=0.2),
"longtext": make_llm("gemini-3.1-pro", temperature=0.7),
"reasoning": make_llm("claude-opus-4-6", temperature=0.0),
}
def route(task: str) -> ChatOpenAI:
# 你的路由逻辑,这里只是示例
if "代码" in task or "code" in task.lower():
return llms["codegen"]
if len(task) > 4000:
return llms["longtext"]
if "分类" in task:
return llms["classify"]
return llms["reasoning"]
tasks = [
"把这段代码重构成 async:...",
"帮我分类以下用户反馈是 bug 还是功能请求:...",
"总结这篇 20000 字的论文的核心观点:..." + " 论文内容 " * 500,
]
for t in tasks:
llm = route(t)
print(f"[{llm.model_name}] {llm.invoke([HumanMessage(content=t[:100])]).content[:80]}")
同样的代码,如果用各家原生 SDK 写,至少要多写 100 行样板。
流式输出
LangChain 的 .stream() 方法在 nucleus-llm 上同样工作:
llm = ChatOpenAI(
model="claude-sonnet-4-6",
base_url="https://llm.nucleusenterprise.ai/v1",
api_key=os.environ["NLLM_API_KEY"],
)
for chunk in llm.stream([HumanMessage(content="写一首关于新加坡的五言绝句")]):
print(chunk.content, end="", flush=True)
print()
Tool Calling / Function Calling
OpenAI 格式的 tool calling 在 nucleus-llm 上对 Claude 和 Gemini 同样生效 —— 网关
会把 OpenAI 的 tools 字段翻译成各家原生的工具调用格式。
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
@tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"{city} is sunny, 28°C"
llm = ChatOpenAI(
model="claude-sonnet-4-6",
base_url="https://llm.nucleusenterprise.ai/v1",
api_key=os.environ["NLLM_API_KEY"],
).bind_tools([get_weather])
reply = llm.invoke("新加坡今天天气怎么样?")
print(reply.tool_calls)
LlamaIndex 同样适用
LlamaIndex 有 OpenAILike 专门为兼容网关设计:
from llama_index.llms.openai_like import OpenAILike
llm = OpenAILike(
model="claude-sonnet-4-6",
api_base="https://llm.nucleusenterprise.ai/v1",
api_key=os.environ["NLLM_API_KEY"],
is_chat_model=True,
)
print(llm.complete("Hello, who are you?"))
LlamaIndex 的所有上层 abstraction(RAG、Index、Query Engine)都建立在
LLM 接口之上,所以换到 OpenAILike 之后整个 pipeline 零改动。
Dify / FastChat / AutoGen 等其他框架
只要框架支持"自定义 OpenAI endpoint",就能直接用 nucleus-llm 作为后端:
- Dify: 在模型供应商设置里选 "OpenAI-API-compatible",填
https://llm.nucleusenterprise.ai/v1 - FastChat: 启动时加
--api-base https://llm.nucleusenterprise.ai/v1 - AutoGen:
config_list里把base_url指过去 - Continue.dev(VS Code 插件): 在配置里设
"apiBase"
可用模型速查
| 模型 | 适合场景 | LangChain 里怎么写 |
|---|---|---|
claude-opus-4-6 |
复杂推理、agent | ChatOpenAI(model="claude-opus-4-6", ...) |
claude-sonnet-4-6 |
日常开发首选 | ChatOpenAI(model="claude-sonnet-4-6", ...) |
claude-haiku-4-5 |
分类、抽取、批量 | ChatOpenAI(model="claude-haiku-4-5", ...) |
gpt-5.4 |
通用 + 强 tool calling | ChatOpenAI(model="gpt-5.4", ...) |
gpt-5.3-codex |
代码生成 | ChatOpenAI(model="gpt-5.3-codex", ...) |
gpt-5.4-mini |
低成本通用 | ChatOpenAI(model="gpt-5.4-mini", ...) |
gemini-3.1-pro |
超长上下文 | ChatOpenAI(model="gemini-3.1-pro", ...) |
gemini-3-flash |
快速/批量 | ChatOpenAI(model="gemini-3-flash", ...) |
限制和注意事项
- 并非所有 OpenAI-only 的参数都透传 —— 比如
logit_bias、logprobs对 Claude 和 Gemini 来说没有对应概念,设了也不会生效。 - function calling 的 schema 略有差异 —— OpenAI 的 JSON Schema 在 Claude
上可以用,但非常复杂的嵌套(尤其
oneOf/anyOf)可能需要简化。 - 本文的集成路径只针对后端服务(你自己写的 Python / Node 代码)。不要把它 用于 Claude Code / Codex CLI 这类客户端工具,那不是 nucleus-llm 的支持场景。
下一步
- 在 llm.nucleusenterprise.ai 注册 获取 API Key
- Clone
nucleus-llm-examplesGitHub 仓库,运行python/04_langchain.py - 读续篇:《从 OpenAI 官方 API 迁移到统一网关的 5 分钟指南》