本文将帮助您开始使用 OpenRouter 聊天模型。OpenRouter 是一个统一的 API,通过单一端点提供对多个提供商(OpenAI、Anthropic、Google、Meta 等)模型的访问。
有关可用模型的完整列表,请访问 OpenRouter 模型页面。
集成详情
模型特性
要通过 OpenRouter 访问模型,您需要创建一个 OpenRouter 账户,获取 API 密钥,并安装 langchain-openrouter 集成包。
LangChain OpenRouter 集成位于 langchain-openrouter 包中:
pip install -U langchain-openrouter
前往 OpenRouter 密钥页面 注册并生成 API 密钥。完成后,设置 OPENROUTER_API_KEY 环境变量:
import getpass
import os
if not os.getenv("OPENROUTER_API_KEY"):
os.environ["OPENROUTER_API_KEY"] = getpass.getpass("输入您的 OpenRouter API 密钥:")
要启用模型调用的自动追踪,请设置您的 LangSmith API 密钥:
os.environ["LANGSMITH_API_KEY"] = getpass.getpass("输入您的 LangSmith API 密钥:")
os.environ["LANGSMITH_TRACING"] = "true"
实例化
现在我们可以实例化模型对象并生成聊天补全:
from langchain_openrouter import ChatOpenRouter
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
temperature=0,
max_tokens=1024,
max_retries=2,
# 其他参数...
)
messages = [
(
"system",
"你是一个将英语翻译成法语的助手。翻译用户的句子。",
),
("human", "I love programming."),
]
ai_msg = model.invoke(messages)
ai_msg.content
"J'adore la programmation."
流式传输
for chunk in model.stream("写一首关于大海的短诗。"):
print(chunk.text, end="", flush=True)
也支持异步流式传输:
async for chunk in model.astream("写一首关于大海的短诗。"):
print(chunk.text, end="", flush=True)
工具调用
OpenRouter 使用 OpenAI 兼容的工具调用格式。您可以描述工具及其参数,让模型返回一个包含要调用工具及其输入参数的 JSON 对象。
绑定工具
使用 ChatOpenRouter.bind_tools,您可以将 Pydantic 类、字典模式、LangChain 工具或函数作为工具传递给模型。在底层,这些会被转换为 OpenAI 工具模式,并在每次模型调用中传递。
from pydantic import BaseModel, Field
class GetWeather(BaseModel):
"""获取指定地点的当前天气"""
location: str = Field(description="城市和州,例如 San Francisco, CA")
model_with_tools = model.bind_tools([GetWeather])
ai_msg = model_with_tools.invoke(
"旧金山的天气怎么样",
)
ai_msg
AIMessage(content='', response_metadata={'finish_reason': 'tool_calls'}, tool_calls=[{'name': 'GetWeather', 'args': {'location': 'San Francisco, CA'}, 'id': 'call_abc123', 'type': 'tool_call'}], usage_metadata={'input_tokens': 68, 'output_tokens': 17, 'total_tokens': 85})
工具调用
AIMessage 有一个 tool_calls 属性。它包含一个与模型提供商无关的标准化格式的工具调用。
[{'name': 'GetWeather',
'args': {'location': 'San Francisco, CA'},
'id': 'call_abc123',
'type': 'tool_call'}]
严格模式
传递 strict=True 以保证模型输出与工具定义中提供的 JSON Schema 完全匹配:
model_with_tools = model.bind_tools([GetWeather], strict=True)
有关绑定工具和工具调用输出的更多信息,请查阅 工具调用 文档。
结构化输出
ChatOpenRouter 通过 with_structured_output 方法支持结构化输出。有两种方法可用:function_calling(默认)和 json_schema。
使用 with_structured_output 生成结构化的模型响应。指定 method="json_schema" 以使用基于 JSON Schema 的结构化输出;否则方法默认为函数调用。from langchain_openrouter import ChatOpenRouter
from pydantic import BaseModel, Field
model = ChatOpenRouter(model="openai/gpt-4.1")
class Movie(BaseModel):
"""包含详细信息的电影。"""
title: str = Field(description="电影标题")
year: int = Field(description="电影发行年份")
director: str = Field(description="电影导演")
rating: float = Field(description="电影的评分(满分10分)")
structured_model = model.with_structured_output(Movie, method="json_schema")
response = structured_model.invoke("提供电影《盗梦空间》的详细信息")
response
Movie(title='Inception', year=2010, director='Christopher Nolan', rating=8.8)
使用 ProviderStrategy 指定 response_format,以便在生成智能体最终响应时启用结构化输出。from langchain.agents import create_agent
from langchain.agents.structured_output import ProviderStrategy
from pydantic import BaseModel
class Weather(BaseModel):
temperature: float
condition: str
def weather_tool(location: str) -> str:
"""获取某个地点的天气。"""
return "Sunny and 75 degrees F."
agent = create_agent(
model="openrouter:openai/gpt-4.1",
tools=[weather_tool],
response_format=ProviderStrategy(Weather),
)
result = agent.invoke({
"messages": [{"role": "user", "content": "旧金山的天气怎么样?"}]
})
result["structured_response"]
Weather(temperature=75.0, condition='Sunny')
您可以在 function_calling 和 json_schema 方法中传递 strict=True 以强制完全遵循模式。strict 参数不支持 json_mode。
structured_model = model.with_structured_output(Movie, method="json_schema", strict=True)
推理输出
对于支持推理的模型(例如 anthropic/claude-sonnet-4.5、deepseek/deepseek-r1),您可以通过 reasoning 参数启用推理令牌。详情请参阅 OpenRouter 推理文档:
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
max_tokens=16384,
reasoning={"effort": "high", "summary": "auto"},
)
ai_msg = model.invoke("529 的平方根是多少?")
# 通过 content_blocks 访问推理内容
for block in ai_msg.content_blocks:
if block["type"] == "reasoning":
print(block["reasoning"])
有关内容块的更多信息,请参阅 标准内容块 指南。
reasoning 字典支持两个键:
effort:控制推理令牌预算。值:"xhigh"、"high"、"medium"、"low"、"minimal"、"none"。
summary:控制响应中返回的推理摘要的详细程度。值:"auto"、"concise"、"detailed"。
推理令牌使用量包含在 usage_metadata 中:
print(ai_msg.usage_metadata)
# {'input_tokens': ..., 'output_tokens': ..., 'total_tokens': ...,
# 'output_token_details': {'reasoning': ...}}
努力程度到预算的映射取决于模型。例如,Google Gemini 模型将努力程度映射到内部的 thinkingLevel 而不是精确的令牌预算。详情请参阅 OpenRouter 推理文档。
多模态输入
OpenRouter 支持接受多模态输入的模型的 多模态输入。可用的模态取决于您选择的模型——请查看 OpenRouter 模型页面 了解详情。
支持的输入方法
| 方法 | 图像 | 音频 | 视频 | PDF |
|---|
| HTTP/HTTPS URL | ✅ | ❌ | ✅ | ✅ |
| Base64 内联数据 | ✅ | ✅ | ✅ | ✅ |
图像输入
使用带有列表内容格式的 HumanMessage 提供图像输入以及文本。
from langchain_openrouter import ChatOpenRouter
from langchain.messages import HumanMessage
model = ChatOpenRouter(model="openai/gpt-4o")
message = HumanMessage(
content=[
{"type": "text", "text": "描述这张图片。"},
{
"type": "image",
"url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg",
},
]
)
response = model.invoke([message])
音频输入
提供音频输入以及文本。音频以 base64 内联数据形式传递。
import base64
from pathlib import Path
from langchain_openrouter import ChatOpenRouter
from langchain.messages import HumanMessage
model = ChatOpenRouter(model="google/gemini-2.5-flash")
audio_data = base64.b64encode(Path("/path/to/audio.wav").read_bytes()).decode("utf-8")
message = HumanMessage(
content=[
{"type": "text", "text": "转录这段音频。"},
{
"type": "audio",
"base64": audio_data,
"mime_type": "audio/wav",
},
]
)
response = model.invoke([message])
视频输入
视频输入会自动转换为 OpenRouter 的 video_url 格式。
from langchain_openrouter import ChatOpenRouter
from langchain.messages import HumanMessage
model = ChatOpenRouter(model="google/gemini-2.5-pro-preview")
message = HumanMessage(
content=[
{"type": "text", "text": "描述这个视频。"},
{
"type": "video",
"url": "https://example.com/video.mp4",
},
]
)
response = model.invoke([message])
PDF 输入
提供 PDF 文件输入以及文本。
from langchain_openrouter import ChatOpenRouter
from langchain.messages import HumanMessage
model = ChatOpenRouter(model="google/gemini-2.5-pro-preview")
message = HumanMessage(
content=[
{"type": "text", "text": "总结这个文档。"},
{
"type": "file",
"url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
"mime_type": "application/pdf",
},
]
)
response = model.invoke([message])
令牌使用量元数据
调用后,令牌使用量信息可在响应的 usage_metadata 属性中找到:
ai_msg = model.invoke("讲个笑话。")
ai_msg.usage_metadata
{'input_tokens': 12,
'output_tokens': 25,
'total_tokens': 37}
当底层提供商在其响应中包含详细的令牌细分时,它们会自动显示。当提供商未报告这些字段或其值为零时,这些字段会被省略。
推理令牌
output_token_details.reasoning 报告模型用于内部思维链推理的令牌数量。这在使用推理模型(例如 deepseek/deepseek-r1、openai/o3)或显式启用推理时出现:
from langchain_openrouter import ChatOpenRouter
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
reasoning={"effort": "high"},
)
ai_msg = model.invoke("529 的平方根是多少?")
ai_msg.usage_metadata
{'input_tokens': 39,
'output_tokens': 98,
'total_tokens': 137,
'output_token_details': {'reasoning': 62}}
缓存的输入令牌
input_token_details.cache_read 报告从提供商的提示缓存中提供的输入令牌数量,input_token_details.cache_creation 报告首次调用时写入缓存的令牌数量。
提示缓存需要在消息内容块中显式的 cache_control 断点。在要缓存的内容块上传递 {"cache_control": {"type": "ephemeral"}}:
from langchain_openrouter import ChatOpenRouter
model = ChatOpenRouter(model="anthropic/claude-sonnet-4.5")
long_system = "你是一个乐于助人的助手。 " * 200
messages = [
("system", [{"type": "text", "text": long_system, "cache_control": {"type": "ephemeral"}}]),
("human", "打个招呼。"),
]
# 第一次调用写入缓存
ai_msg = model.invoke(messages)
ai_msg.usage_metadata
{'input_tokens': 1210,
'output_tokens': 12,
'total_tokens': 1222,
'input_token_details': {'cache_creation': 1201}}
# 第二次调用从缓存读取
ai_msg = model.invoke(messages)
ai_msg.usage_metadata
{'input_tokens': 1210,
'output_tokens': 12,
'total_tokens': 1222,
'input_token_details': {'cache_read': 1201}}
如果消息内容块上没有 cache_control,提供商将不会缓存提示,这些字段也不会出现。
流式传输时,从最终块聚合令牌使用量:
stream = model.stream("讲个笑话。")
full = next(stream)
for chunk in stream:
full += chunk
full.usage_metadata
{'input_tokens': 12,
'output_tokens': 25,
'total_tokens': 37}
响应元数据
调用后,提供商和模型元数据可在 response_metadata 属性中找到:
ai_msg = model.invoke("讲个笑话。")
ai_msg.response_metadata
{'model_name': 'anthropic/claude-sonnet-4.5',
'id': 'gen-1771043112-yLUz3txgvHSjkyCQK8KQ',
'created': 1771043112,
'object': 'chat.completion',
'finish_reason': 'stop',
'logprobs': None,
'model_provider': 'openrouter'}
如果存在,native_finish_reason 字段包含底层提供商的原始完成原因,可能与标准化的 finish_reason 不同。
提供商路由
OpenRouter 上的许多模型由多个提供商提供服务。openrouter_provider 参数让您可以控制哪些提供商处理您的请求以及如何选择它们。
排序和过滤提供商
使用 order 设置首选提供商序列。OpenRouter 按顺序尝试每个提供商,如果某个提供商不可用,则回退到下一个:
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
openrouter_provider={
"order": ["Anthropic", "Google"],
"allow_fallbacks": True, # 默认值;如果需要,可以回退到顺序列表之外
},
)
要仅将请求限制在特定提供商,请使用 only。要排除某些提供商,请使用 ignore:
# 仅使用这些提供商(不回退到其他提供商)
model = ChatOpenRouter(
model="openai/gpt-4o",
openrouter_provider={"only": ["OpenAI", "Azure"]},
)
# 使用除 DeepInfra 之外的任何提供商
model = ChatOpenRouter(
model="meta-llama/llama-4-maverick",
openrouter_provider={"ignore": ["DeepInfra"]},
)
按成本、速度或延迟排序
默认情况下,OpenRouter 在提供商之间进行负载均衡,优先考虑较低成本。使用 sort 更改优先级:
# 优先选择最快的提供商(最高的令牌/秒)
model = ChatOpenRouter(
model="openai/gpt-4o",
openrouter_provider={"sort": "throughput"},
)
# 优先选择延迟最低的提供商
model = ChatOpenRouter(
model="openai/gpt-4o",
openrouter_provider={"sort": "latency"},
)
数据收集策略
如果您的用例要求提供商不存储或训练您的数据,请将 data_collection 设置为 "deny":
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
openrouter_provider={"data_collection": "deny"},
)
按量化过滤
对于开放权重模型,您可以限制路由到特定的精度级别:
model = ChatOpenRouter(
model="meta-llama/llama-4-maverick",
openrouter_provider={"quantizations": ["fp16", "bf16"]},
)
路由参数
route 参数控制高级路由行为:
"fallback":启用跨提供商的自动故障转移(默认行为)。
"sort":基于 openrouter_provider 中配置的排序策略进行路由。
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
route="fallback",
)
组合选项
提供商选项可以组合使用:
model = ChatOpenRouter(
model="openai/gpt-4o",
openrouter_provider={
"order": ["OpenAI", "Azure"],
"allow_fallbacks": False, # 严格——仅使用顺序中的提供商
"require_parameters": True, # 跳过不支持所有参数的提供商
"data_collection": "deny",
},
)
有关完整选项列表,请参阅 OpenRouter 提供商路由文档。
应用归属
OpenRouter 通过 HTTP 标头支持应用归属。您可以通过初始化参数或环境变量设置这些:
model = ChatOpenRouter(
model="anthropic/claude-sonnet-4.5",
app_url="https://myapp.com", # 或 OPENROUTER_APP_URL 环境变量
app_title="My App", # 或 OPENROUTER_APP_TITLE 环境变量
)
API 参考
有关 ChatOpenRouter 所有功能和配置的详细文档,请查阅 ChatOpenRouter API 参考。
有关 OpenRouter 平台、模型和功能的更多信息,请参阅 OpenRouter 文档。