openai-agents-python 通过 LiteLLM 接入任意大模型:LitellmModel 适配器完整指南
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
openai-agents-python官方内置的Model实现面向 OpenAI 的 Responses API 与 Chat Completions API,而 docs/ref/extensions/models/litellm_model.md 这一参考文档(mkdocstrings 自动生成的模块引用桩)所指向的LitellmModel则是把 OpenAI、Anthropic、Gemini、Mistral 以及大量第三方兼容端点统一收敛到同一套 Agent 编排管线中的适配器。本文以该模块为主体,结合 docs/models/index.md 中 "Third-party adapters" 章节、examples/model_providers/ 下的可运行示例与 tests/models/ 中的测试,完整讲解 LiteLLM 适配器的安装、三种接入方式、构造参数、ModelSettings对接、供应商特化处理、流式与重试机制及其边界限制,读完即可在真实项目中落地"一套代码、任意模型"的混合多供应商工作流。
一、LitellmModel 是什么:一个标准的 Model 适配器实现
LitellmModel继承自 SDK 的Model接口,实现了get_response()、stream_response()与get_retry_advice()三个核心方法,因此对Runner、Agent、工具调用、Guardrail 等上层机制完全透明——它本质上是一个把 SDK 内部表示翻译成 LiteLLM Chat Completions 请求、再把 LiteLLM 响应翻译回 SDKModelResponse的转换层。
从源码 docstring 可以确认其定位(src/agents/extensions/models/litellm_model.py):
This class enables using any model via LiteLLM. LiteLLM allows you to access OpenAI, Anthropic, Gemini, Mistral, and many other models.
在项目文档中,LiteLLM 与 Any-LLM 并列被标注为best-effort、beta 级别的第三方适配器(docs/models/index.md):
- 如果只使用 OpenAI 模型,应优先走内置的
OpenAIResponsesModel路径,而不是 LiteLLM; - 只有在需要"OpenAI 模型 + 非 OpenAI 供应商混用"、或需要 LiteLLM 提供的供应商覆盖与路由能力时,才使用本适配器;
- 适配器相当于在 SDK 与上游模型供应商之间又加了一层兼容层,因此具体功能的支持程度随供应商而异,上线前必须针对目标供应商做验证。
二、安装与前置准备
litellm属于可选依赖组,未安装时导入模块会直接抛出带提示的ImportError(src/agents/extensions/models/litellm_model.py):
pip install 'openai-agents[litellm]'运行前还需要注意以下几点:
- API Key 一律通过环境变量提供。
LitellmProvider的 docstring 明确说明:API Key 必须通过环境变量设置;若模型需要额外配置(如 Azure 的base与version),也必须设置 LiteLLM 期望的环境变量(src/agents/extensions/models/litellm_provider.py)。 - 无 OpenAI Key 时关闭 tracing。非 OpenAI 场景下建议调用
set_tracing_disabled(disabled=True),或配置自定义 tracing processor,否则默认会把 trace 上传到 OpenAI 服务器而报 401。 - 部分供应商默认不返回 usage。文档建议按需传
ModelSettings(include_usage=True)(docs/models/index.md)。
三、三种接入方式
3.1 使用litellm/前缀模型名(最省事)
在Agent(model=...)中直接写litellm/前缀的模型名,Runner 会自动解析为LitellmModel。完整可运行示例见 examples/model_providers/litellm_auto.py:
import asyncio from pydantic import BaseModel from agents import Agent, ModelSettings, Runner, set_tracing_disabled from agents.decorators import tool set_tracing_disabled(disabled=True) @tool def get_weather(city: str): return f"The weather in {city} is sunny." class Result(BaseModel): output_text: str tool_results: list[str] async def main(): agent = Agent( name="Assistant", instructions="You only respond in haikus.", # 前缀 litellm/ 告诉 Runner 使用 LitellmModel model="litellm/openrouter/openai/gpt-5.4-mini", tools=[get_weather], model_settings=ModelSettings(tool_choice="required"), output_type=Result, ) result = await Runner.run(agent, "What's the weather in Tokyo?") print(result.final_output) if __name__ == "__main__": asyncio.run(main())该示例通过 OpenRouter 路由,运行前需设置OPENROUTER_API_KEY。模型名litellm/openrouter/openai/gpt-5.4-mini是 LiteLLM 的标准三段式命名(供应商/模型),LiteLLM 会根据模型名自动选择正确的 SDK 与端点格式。
3.2 使用LitellmProvider作用于单次 Run
LitellmProvider实现了ModelProvider接口,适用于"本次运行中的所有 Agent 统一走 LiteLLM"的场景(src/agents/extensions/models/litellm_provider.py):
from agents import Agent, Runner, RunConfig from agents.extensions.models.litellm_provider import LitellmProvider agent = Agent(name="Assistant", instructions="Be concise.") result = await Runner.run( agent, "Hello", run_config=RunConfig(model_provider=LitellmProvider()), )其内部实现极其简单:get_model(model_name)直接返回LitellmModel(model_name or get_default_model())——未传模型名时回落到 SDK 的默认模型。模块中还保留了向后兼容的DEFAULT_MODEL = "gpt-4.1"常量,但注释建议优先使用get_default_model()。
3.3 直接实例化LitellmModel(最灵活)
当需要为不同 Agent 绑定不同供应商,或需要显式传入base_url/api_key时,直接构造模型对象并赋给Agent.model。完整示例见 examples/model_providers/litellm_provider.py:
import asyncio, os from agents import Agent, Runner, set_tracing_disabled from agents.decorators import tool from agents.extensions.models.litellm_model import LitellmModel set_tracing_disabled(disabled=True) @tool def get_weather(city: str): return f"The weather in {city} is sunny." async def main(model: str, api_key: str): agent = Agent( name="Assistant", instructions="You only respond in haikus.", model=LitellmModel(model=model, api_key=api_key), tools=[get_weather], ) result = await Runner.run(agent, "What's the weather in Tokyo?") print(result.final_output) if __name__ == "__main__": model = os.environ.get("LITELLM_MODEL", "openrouter/openai/gpt-5.4-mini") api_key = os.environ.get("OPENROUTER_API_KEY", "dummy") asyncio.run(main(model, api_key))命令行可直接运行:uv run examples/model_providers/litellm_provider.py --model openrouter/anthropic/claude-4.5-sonnet。
四、构造函数参数详解
LitellmModel.__init__只接收四个参数(src/agents/extensions/models/litellm_model.py):
| 参数 | 类型 | 说明 |
|---|---|---|
model | str | LiteLLM 模型标识符,如"openrouter/openai/gpt-5.4-mini"、"anthropic/claude-4.5-sonnet",格式取决于 LiteLLM 的供应商命名 |
base_url | str \| None | 自定义端点地址,直接透传给litellm.acompletion(base_url=...),适用于 OpenAI 兼容网关或自建代理 |
api_key | str \| None | 显式 API Key,优先于环境变量透传给 LiteLLM |
should_replay_reasoning_content | ShouldReplayReasoningContent \| None | 回调,控制对话历史中推理内容(reasoning content)是否在后续请求中重放,透传给消息转换器(litellm_model.py) |
注意:LitellmModel的get_response()/stream_response()签名中previous_response_id与conversation_id参数标注为 unused——这是 Chat Completions 路径的固有限制,Responses API 专属的状态续接能力在此不可用。
五、与 ModelSettings 的完整对接
LitellmModel._fetch_response()会把ModelSettings中的字段逐一映射到litellm.acompletion()的具名参数(src/agents/extensions/models/litellm_model.py):
| ModelSettings 字段 | 透传目标 | 备注 |
|---|---|---|
temperature/top_p | acompletion(temperature=..., top_p=...) | 采样控制 |
frequency_penalty/presence_penalty | 同名参数 | 频率/存在惩罚 |
max_tokens | max_tokens | 输出上限 |
tool_choice | tool_choice | 经Converter.convert_tool_choice转换,omit/NotGiven会被归一为None |
parallel_tool_calls | parallel_tool_calls | 仅当存在已转换工具时才发送 |
top_logprobs | top_logprobs+ 自动补logprobs=True | Chat Completions 要求设置logprobs=True时top_logprobs才生效;若用户已在extra_args中显式传logprobs则不覆盖,避免重复键冲突 |
include_usage | 流式时构造stream_options={"include_usage": ...} | 控制流式响应的 usage chunk |
extra_body | extra_body(深拷贝) | 供应商级请求体扩展;若同时解析出reasoning_effort会先从其中弹出避免重复 |
extra_args | 直接展开为acompletion的 kwargs | 过滤None值;reasoning_effort会被弹出(因为已提升为顶层参数) |
extra_headers | 合并进请求头 | 合并顺序:SDK 默认头 →extra_headers→ 全局覆盖头(litellm_model.py) |
extra_query/metadata | extra_query/metadata | 深拷贝后透传 |
reasoning.effort | 顶层reasoning_effort | 见下方说明 |
timeout | 由外层 Runner 统一实施 | 每次模型调用尝试的完整超时 |
reasoning_effort 的解析优先级
_get_reasoning_effort()按以下优先级解析(litellm_model.py):
model_settings.reasoning.effort(最高优先级);model_settings.extra_body["reasoning_effort"];model_settings.extra_args["reasoning_effort"]。
同时注意:LiteLLM 的 Chat Completions 路径不会转发Reasoning.summary,设置后会打印 warning 并忽略,仅传递reasoning_effort。reasoning.effort支持非 OpenAI 兼容取值(如"none"),可通过上述 escape hatch 传入。
另外两个值得注意的实现细节:
- MCP 代理处理:当存在已转换工具时,
_fetch_response会设置_skip_mcp_handler=True,因为 SDK 工具已被转换为普通 function tool,若让 LiteLLM 代理侧再做 MCP 发现会引入未处理的服务器依赖(litellm_model.py)。 - Runner 重试接管:当 SDK 的 runner-managed retry 启用时(
should_disable_provider_managed_retries()返回 True),会强制num_retries=0、max_retries=0,把 LiteLLM 自带的供应商重试关掉,保证重试只发生在 Runner 层(litellm_model.py)。
六、请求构造与响应转换的底层实现
6.1 消息与工具转换
get_response()内部调用_fetch_response(),核心流程(litellm_model.py):
Converter.items_to_messages(input, ...)把 SDK 的TResponseInputItem列表转换为 Chat Completions 消息;开启 reasoning 时设置preserve_thinking_blocks=True,以支持 Claude 4 Sonnet/Opus 这类交错思维模型的思维块保留;system_instructions以{"role": "system"}插入到消息最前;tool_choice与response_format(结构化输出)分别经Converter.convert_tool_choice/convert_response_format转换;- Agent 的
tools与handoffs全部经Converter.tool_to_openai/Converter.convert_handoff_tool归一为 function tool 格式; - 最终调用
litellm.acompletion(...),非流式返回litellm.types.utils.ModelResponse,流式返回(Response, AsyncStream[ChatCompletionChunk])。
调试日志在未设置_debug.DONT_LOG_MODEL_DATA时会完整打印模型名、消息、工具与响应 JSON,便于排查(litellm_model.py)。
6.2 响应处理:usage、拒绝与 logprobs
拿到 LiteLLM 响应后,适配器做了三件重要的事:
- usage 统计:从
response.usage提取prompt_tokens/completion_tokens/total_tokens,并进一步解析cached_tokens、cache_write_tokens(提示词缓存)与reasoning_tokens;供应商未返回 usage 时,仅计Usage(requests=1)并打印 warning"No usage information returned from Litellm"(litellm_model.py)。 - content_filter 拒绝合成:部分供应商(如 Amazon Bedrock 上的 Anthropic)安全拦截时只给
finish_reason == "content_filter"且消息为空,若不处理会导致 Agent 循环空转重试。适配器会合成一条refusal消息写入provider_specific_fields,从而触发 SDK 下游的ResponseOutputRefusal处理(litellm_model.py)。 - logprobs 附加:当
choice_logprobs.content存在时,转换为ResponseOutputText.logprobs并附加到输出消息(litellm_model.py)。
6.3 LitellmConverter:LiteLLM 消息 → OpenAI 消息
LitellmConverter.convert_message_to_openai()负责把litellm.types.utils.Message转换为 SDK 内部使用的InternalChatCompletionMessage(litellm_model.py),要点包括:
- 非
assistant角色直接抛ModelBehaviorError; - 透传
content、refusal(来自provider_specific_fields)、audio、annotations(URL 引用标注); reasoning_content与thinking_blocks作为额外字段携带,兼容 DeepSeek 与 Anthropic 的推理内容;thinking_blocks支持 dict、__dict__对象、model_dump()对象三种形态的归一化;- 工具调用经
convert_tool_call_to_openai转换,其中对 Gemini 模型会清理 LiteLLM 在tool_call.id后追加的__thought__后缀(litellm_model.py),并把provider_specific_fields中的 Geminithought_signature转换回extra_content={"google": {...}}内部格式。
七、流式输出机制
stream_response()通过ChatCmplStreamHandler.handle_stream()消费 LiteLLM 流式 chunk,向上层产出 SDK 的TResponseStreamEvent(litellm_model.py)。三个值得关注的细节:
- span 填充时机:在 yield
response.completed终止事件之前就填充 generation span 的 usage——因为调用方可能在收到终止事件后立即关闭生成器,导致 span 永远没有 usage 数据(litellm_model.py); - 取消安全关闭:收到
asyncio.CancelledError时,把流关闭任务调度到后台执行并重新抛出,避免aclose()半途被中断;正常结束时用asyncio.shield保护关闭任务,防止重复关闭不可幂等的供应商流(litellm_model.py); - 流式调用同样要求
include_usage通过stream_options传递,测试覆盖见 tests/models/test_litellm_chatcompletions_stream.py。
八、供应商特化适配(Anthropic / Gemini)
这是适配器最有价值的部分,针对不同供应商的协议差异做了显式处理:
8.1 工具消息排序修正
Anthropic 与 Vertex AI Gemini 严格要求 conversation 历史中tool_use必须紧跟在对应的tool_result之前。_fix_tool_message_ordering()会:
- 把多工具调用的 assistant 消息按
tool_call_id拆分为单条消息,仅第一条保留文本/思维块/推理内容(避免重复携带带签名的 thinking blocks 被 Anthropic 拒绝); - 将
tool_use → tool_result配对重排,未匹配的 tool result 单独保留,避免重复(litellm_model.py)。
该逻辑仅当模型名包含anthropic、claude或gemini时启用。
8.2 Gemini thought signatures 双向转换
- 出站:
_convert_gemini_extra_content_to_provider_specific_fields()把内部格式extra_content={"google": {"thought_signature": "..."}}转换为 LiteLLM 的provider_specific_fields={"thought_signature": "..."},仅处理最后一个 user 消息之后的 assistant 工具调用,无有效签名时使用skip_thought_signature_validator占位(litellm_model.py); - 入站:
convert_tool_call_to_openai()反方向把thought_signature还原进extra_content,供 Agent 工具调用上下文使用。
配套测试包括 tests/models/test_gemini_thought_signatures.py、tests/models/test_gemini_thought_signatures_stream.py 与 tests/models/test_extended_thinking_message_order.py。
8.3 推理内容保留与重放
消息转换时通过preserve_thinking_blocks保留 Claude 4 系列的交错思维块;should_replay_reasoning_content回调控制历史推理内容的重放策略,相关行为由 tests/models/test_reasoning_content_replay_hook.py 与 tests/models/test_anthropic_thinking_blocks.py 覆盖。DeepSeek 等模型的reasoning_content处理见 tests/models/test_deepseek_reasoning_content.py。
九、重试与错误处理
LitellmModel.get_retry_advice()直接复用get_openai_retry_advice()(litellm_model.py)——因为 LiteLLM 的异常镜像了 OpenAI 风格的status/header字段,可以复用同一套归一化逻辑提取retry-after与显式的重试/不重试提示。
当启用 Runner 层重试时,适配器会关闭 LiteLLM 自身的重试旋钮(num_retries=0、max_retries=0),把重试决策完全交给 SDK 的ModelRetrySettings与retry_policies。LiteLLM 场景的重试配置示例见 examples/basic/retry_litellm.py,provider_suggested()策略会优先采纳来自本适配器的重试建议。
十、已知限制与注意事项
| 限制 | 说明与应对 |
|---|---|
| usage 可能缺失 | 部分经 LiteLLM 访问的供应商不填充 usage 指标;需要用量统计时传ModelSettings(include_usage=True),并对目标供应商后端单独验证 |
| 结构化输出能力差异 | 部分供应商只支持json_object而不支持json_schema,可能报'response_format.type' : value is not one of the allowed values ['text','json_object'];文档建议优先选择支持 JSON Schema 输出的供应商,否则易产出畸形 JSON |
| beta 状态 | LiteLLM 集成属于 best-effort beta,功能支持与请求语义随供应商而异,上线前需验证结构化输出、工具调用、用量上报与路由行为 |
| 无 Responses API 状态续接 | previous_response_id/conversation_id在适配器中 unused |
| LiteLLM 序列化告警补丁 | 若 LiteLLM 对响应对象发出 Pydantic serializer 警告,可在导入适配器前设置export OPENAI_AGENTS_ENABLE_LITELLM_SERIALIZER_PATCH=true开启 SDK 的兼容补丁;补丁默认关闭、仅对1/true生效,且依赖 LiteLLM 的私有日志辅助函数,升级 LiteLLM 后需重新验证(litellm_model.py) |
| 禁用跟踪 | 无 OpenAI Key 时应set_tracing_disabled(True)或配置自定义 trace processor |
十一、测试与验证路径
适配器行为在仓库中有充分的测试保障,可按需查阅:
- 用量:
tests/models/test_litellm_usage_requests.py - extra_body / kwargs 透传:
tests/models/test_litellm_extra_body.py、tests/models/test_kwargs_functionality.py - 流式:
tests/models/test_litellm_chatcompletions_stream.py - logprobs:
tests/models/test_litellm_logprobs.py - 内容过滤拒绝:
tests/models/test_litellm_content_filter.py - 序列化补丁:
tests/models/test_litellm_logging_patch.py - User-Agent:
tests/models/test_litellm_user_agent.py - 供应商特化:
tests/models/test_anthropic_thinking_blocks.py、tests/models/test_gemini_thought_signatures.py等
需要系统化了解适配器在整条模型选型路径中的位置时,可对照 docs/models/index.md 的 "Third-party adapters" 章节;参考文档 docs/ref/extensions/models/litellm_model.md 本身由 docs/scripts/generate_ref_files.py 生成,内容即本模块的 API 文档。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考