以编程方式使用文档

这将帮助您开始使用 OpenRouter 聊天模型。OpenRouter 是一个统一 API,通过单一端点提供对多个提供商模型(OpenAI、Anthropic、Google、Meta 等)的访问。

有关可用模型的完整列表,请访问 OpenRouter 模型页面.

概述

集成详情

ClassPackageSerializableJS/TS SupportDownloadsLatest Version
ChatOpenRouterlangchain-openrouterbeta<a href="https://pypi.org/project/langchain-openrouter/" target="_blank"><img src="https://static.pepy.tech/badge/langchain-openrouter/month" alt="Downloads per month" noZoom height="100" class="rounded" /></a><a href="https://pypi.org/project/langchain-openrouter/" target="_blank"><img src="https://img.shields.io/pypi/v/langchain-openrouter?style=flat-square&label=%20&color=orange" alt="PyPI - Latest version" noZoom height="100" class="rounded" /></a>

模型特性

工具调用结构化输出图像输入音频输入视频输入Token 级流式传输原生异步Token 使用量Logprobs

设置

要通过 OpenRouter 访问模型,您需要创建一个 OpenRouter 账户,获取 API 密钥,并安装 langchain-openrouter 集成包。

安装

LangChain OpenRouter 集成位于 langchain-openrouter package:

    pip install -U langchain-openrouter
    
    uv add langchain-openrouter
    

凭证

前往 OpenRouter 密钥页面 注册并生成 API 密钥。完成此操作后,设置 OPENROUTER_API_KEY 环境变量:

if not os.getenv("OPENROUTER_API_KEY"):
    os.environ["OPENROUTER_API_KEY"] = getpass.getpass("Enter your OpenRouter API key: ")

要启用模型调用的自动追踪,请设置您的 LangSmith API 密钥:

os.environ["LANGSMITH_API_KEY"] = getpass.getpass("Enter your LangSmith API key: ")
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,
    # other params...
)

调用

messages = [
    (
        "system",
        "You are a helpful assistant that translates English to French. Translate the user sentence.",
    ),
    ("human", "I love programming."),
]
ai_msg = model.invoke(messages)
ai_msg.content
"J'adore la programmation."

流式传输

stream = model.stream_events("Write a short poem about the sea.", version="v3")
for token in stream.text:
    print(token, end="", flush=True)

也支持异步流式传输:

stream = await model.astream_events("Write a short poem about the sea.", version="v3")
async for token in stream.text:
    print(token, end="", flush=True)

工具调用

OpenRouter 使用 OpenAI 兼容的工具调用格式。您可以描述工具及其参数,让模型返回一个包含要调用的工具及其输入的 JSON 对象。

绑定工具

使用 ChatOpenRouter.bind_tools,您可以将 Pydantic 类、字典模式、LangChain 工具或函数作为工具传递给模型。在底层,这些会被转换为 OpenAI 工具模式,并在每次模型调用时传入。

from pydantic import BaseModel, Field


class GetWeather(BaseModel):
    """Get the current weather in a given location"""

    location: str = Field(description="The city and state, e.g. San Francisco, CA")


model_with_tools = model.bind_tools([GetWeather])
ai_msg = model_with_tools.invoke(
    "what is the weather like in San Francisco",
)
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 属性。这包含以标准化格式的工具调用,这种格式不依赖于模型提供商。

ai_msg.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)

有关绑定工具和工具调用输出的更多信息,请访问 工具调用 docs.

结构化输出

ChatOpenRouter 支持通过以下方式实现结构化输出 with_structured_output 方法。有两种可用方法: function_calling (默认)和 json_schema.

Individual model calls

使用 with_structured_output 生成结构化模型响应。指定 method="json_schema" 使用基于 JSON Schema 的结构化输出;否则该方法默认为函数调用。

from langchain_openrouter import ChatOpenRouter
from pydantic import BaseModel, Field

model = ChatOpenRouter(model="openai/gpt-5.5")

class Movie(BaseModel):
    """A movie with details."""
    title: str = Field(description="The title of the movie")
    year: int = Field(description="The year the movie was released")
    director: str = Field(description="The director of the movie")
    rating: float = Field(description="The movie's rating out of 10")

structured_model = model.with_structured_output(Movie, method="json_schema")  # [!code highlight]
response = structured_model.invoke("Provide details about the movie Inception")
response
Movie(title='Inception', year=2010, director='Christopher Nolan', rating=8.8)

Agent response format

指定 response_formatProviderStrategy 在生成代理的最终响应时启用结构化输出。

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:
    """Get the weather at a location."""
    return "Sunny and 75 degrees F."

agent = create_agent(
    model="openrouter:openai/gpt-5.5",
    tools=[weather_tool],
    response_format=ProviderStrategy(Weather),  # [!code highlight]
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "What's the weather in SF?"}]
})

result["structured_response"]
Weather(temperature=75.0, condition='Sunny')

您可以传递 strict=Truefunction_callingjson_schema 方法来强制严格遵循 schema。该 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("What is the square root of 529?")

# Access reasoning content via content_blocks
for block in ai_msg.content_blocks:
    if block["type"] == "reasoning":
        print(block["reasoning"])

有关内容块的更多信息,请参阅 标准内容块 guide.

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': ...}}

多模态输入

OpenRouter 支持 多模态输入 适用于接受它们的模型。可用的模态取决于您选择的模型——请查看 OpenRouter 模型页面 了解更多详情。

支持的输入方法

方法图像音频视频PDF
HTTP/HTTPS URLs
Base64 内联数据

图像输入

使用 HumanMessage 的列表内容格式提供图像输入和文本。

    from langchain_openrouter import ChatOpenRouter
    from langchain.messages import HumanMessage

    model = ChatOpenRouter(model="openai/gpt-4o")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe this image."},
            {
                "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])
    
    from langchain_openrouter import ChatOpenRouter
    from langchain.messages import HumanMessage

    model = ChatOpenRouter(model="openai/gpt-4o")

    image_url = "https://picsum.photos/id/237/200/300"
    image_data = base64.b64encode(httpx.get(image_url, follow_redirects=True).content).decode("utf-8")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe this image."},
            { # [!code highlight]
                "type": "image", # [!code highlight]
                "base64": image_data, # [!code highlight]
                "mime_type": "image/jpeg", # [!code highlight]
            }, # [!code highlight]
        ]
    )
    response = model.invoke([message])
    

音频输入

提供音频输入和文本。音频以 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": "Transcribe this audio."},
        { # [!code highlight]
            "type": "audio", # [!code highlight]
            "base64": audio_data, # [!code highlight]
            "mime_type": "audio/wav", # [!code highlight]
        }, # [!code highlight]
    ]
)
response = model.invoke([message])

视频输入

视频输入会自动转换为 OpenRouter 的 video_url format.

    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": "Describe this video."},
            {
                "type": "video",
                "url": "https://example.com/video.mp4",
            },
        ]
    )
    response = model.invoke([message])
    
    from pathlib import Path
    from langchain_openrouter import ChatOpenRouter
    from langchain.messages import HumanMessage

    model = ChatOpenRouter(model="google/gemini-2.5-pro-preview")

    video_data = base64.b64encode(Path("/path/to/video.mp4").read_bytes()).decode("utf-8")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Describe this video."},
            { # [!code highlight]
                "type": "video", # [!code highlight]
                "base64": video_data, # [!code highlight]
                "mime_type": "video/mp4", # [!code highlight]
            }, # [!code highlight]
        ]
    )
    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": "Summarize this document."},
            {
                "type": "file",
                "url": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
                "mime_type": "application/pdf",
            },
        ]
    )
    response = model.invoke([message])
    
    from pathlib import Path
    from langchain_openrouter import ChatOpenRouter
    from langchain.messages import HumanMessage

    model = ChatOpenRouter(model="google/gemini-2.5-pro-preview")

    pdf_data = base64.b64encode(Path("/path/to/document.pdf").read_bytes()).decode("utf-8")

    message = HumanMessage(
        content=[
            {"type": "text", "text": "Summarize this document."},
            { # [!code highlight]
                "type": "file", # [!code highlight]
                "base64": pdf_data, # [!code highlight]
                "mime_type": "application/pdf", # [!code highlight]
            }, # [!code highlight]
        ]
    )
    response = model.invoke([message])
    

Token 使用量元数据

调用后,token 使用量信息可在 usage_metadata 响应的属性上获取:

ai_msg = model.invoke("Tell me a joke.")
ai_msg.usage_metadata
{'input_tokens': 12,
 'output_tokens': 25,
 'total_tokens': 37}

当底层提供商在其响应中包含详细的 token 细分时,会自动显示这些字段。当提供商不报告这些信息或其值为零时,这些字段会被省略。

推理 token

output_token_details.reasoning 报告模型用于内部思维链推理的 token 数量。这在使用推理模型时出现(例如, 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("What is the square root of 529?")
ai_msg.usage_metadata
{'input_tokens': 39,
 'output_tokens': 98,
 'total_tokens': 137,
 'output_token_details': {'reasoning': 62}}

缓存的输入 token

input_token_details.cache_read 报告从提供商的提示缓存中提供的输入 token 数量, input_token_details.cache_creation 报告在首次调用时写入缓存的 token。

提示缓存需要显式 cache_control 消息内容块中的断点。传递 {"cache_control": {"type": "ephemeral"}} 在您想要缓存的内容块上:

from langchain_openrouter import ChatOpenRouter

model = ChatOpenRouter(model="anthropic/claude-sonnet-4.5")

long_system = "You are a helpful assistant. " * 200
messages = [
    ("system", [{"type": "text", "text": long_system, "cache_control": {"type": "ephemeral"}}]),
    ("human", "Say hi."),
]

# First call writes to cache
ai_msg = model.invoke(messages)
ai_msg.usage_metadata
{'input_tokens': 1210,
 'output_tokens': 12,
 'total_tokens': 1222,
 'input_token_details': {'cache_creation': 1201}}
# Second call reads from cache
ai_msg = model.invoke(messages)
ai_msg.usage_metadata
{'input_tokens': 1210,
 'output_tokens': 12,
 'total_tokens': 1222,
 'input_token_details': {'cache_read': 1201}}

流式传输时,从完整输出中访问 token 使用量:

stream = model.stream_events("Tell me a joke.", version="v3")
full = stream.output
full.usage_metadata
{'input_tokens': 12,
 'output_tokens': 25,
 'total_tokens': 37}

响应元数据

调用后,提供商和模型元数据可在 response_metadata attribute:

ai_msg = model.invoke("Tell me a joke.")
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,  # default; fall back beyond the order list if needed
    },
)

要仅限制对特定提供商的请求,请使用 only。要排除某些提供商,请使用 ignore:

# Only use these providers (no fallback to others)
model = ChatOpenRouter(
    model="openai/gpt-4o",
    openrouter_provider={"only": ["OpenAI", "Azure"]},
)

# Use any provider except DeepInfra
model = ChatOpenRouter(
    model="meta-llama/llama-4-maverick",
    openrouter_provider={"ignore": ["DeepInfra"]},
)

按成本、速度或延迟排序

默认情况下,OpenRouter 在提供商之间进行负载均衡,偏好更低成本。使用 sort 来更改优先级:

# Prefer the fastest providers (highest tokens/second)
model = ChatOpenRouter(
    model="openai/gpt-4o",
    openrouter_provider={"sort": "throughput"},
)

# Prefer the lowest-latency providers
model = ChatOpenRouter(
    model="openai/gpt-4o",
    openrouter_provider={"sort": "latency"},
)

数据收集策略

如果您的用例要求提供商不存储或训练您的数据,请设置 data_collection to "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,       # strict—only use providers in order
        "require_parameters": True,     # skip providers that don't support all params
        "data_collection": "deny",
    },
)

参见 OpenRouter 提供商路由文档 以获取完整的选项列表。

应用归属

OpenRouter 支持通过 HTTP 头进行应用归属。您可以通过初始化参数或环境变量来设置这些:

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4.5",
    app_url="https://myapp.com",   # or OPENROUTER_APP_URL env var
    app_title="My App",            # or OPENROUTER_APP_TITLE env var
)

可观测性与追踪

OpenRouter 可以将请求数据广播到配置的可观测性目标。 ChatOpenRouter 暴露了两个相关参数: session_id 用于将相关请求分组到单个逻辑工作流中,以及 trace 用于每个请求的追踪元数据。参见 OpenRouter 广播文档 了解更多详情。

使用 session_id

传递一个 session_id 来将多个请求关联到同一工作流(对话、代理运行、批处理作业、CI 运行等)。最多 256 个字符。

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4.5",
    session_id="workflow-abc-123",   # or OPENROUTER_SESSION_ID env var
)

OPENROUTER_SESSION_ID 环境变量在实例化时读取,当没有显式 session_id 提供时,这允许进程为每个请求打标签,而无需在应用代码中传递该值。

您也可以在每次调用时覆盖该值:

model.invoke("Summarize the doc", session_id="workflow-abc-123-step-1")

使用 trace

传递 trace 来附加每个请求的元数据,OpenRouter 会将其转发到广播目标。支持的键包括 trace_id, trace_name, span_name, generation_nameparent_span_id;其他键会作为自定义元数据传递。

model = ChatOpenRouter(
    model="anthropic/claude-sonnet-4.5",
    trace={
        "trace_id": "trace-789",
        "span_name": "summarize",
    },
)

session_idtrace 是独立的—— session_id 在 OpenRouter 端将请求分组到逻辑工作流中,而 trace 为单个请求添加注解。

API 参考

获取所有 ChatOpenRouter 功能和配置的详细文档,请前往 ChatOpenRouter API 参考。

了解更多关于 OpenRouter 平台、模型和功能的信息,请参阅 OpenRouter 文档.