Pydantic AI ModelSettings 全解:跨提供商 LLM 请求参数、Tool Choice 与设置合并机制
2026/9/13 22:03:55 网站建设 项目流程

Pydantic AI ModelSettings 全解:跨提供商 LLM 请求参数、Tool Choice 与设置合并机制

【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-ai

本文以 Pydantic AI 的pydantic_ai.settings模块为核心,系统讲解ModelSettings提供的全部跨提供商请求参数(采样、超时、思考、服务层级、工具选择等)、ToolChoice/ToolOrOutput的取值语义、ThinkingLevelServiceTier统一类型别名,以及merge_model_settings在 Agent、Run 与 Capability 之间的合并规则,帮助你在任何模型提供商下用一套类型安全的方式控制 LLM 行为。

一、pydantic_ai.settings模块总览

pydantic_ai.settings的 API 参考页见 docs/api/settings.md,它通过 mkdocs-autorefs 渲染源码中pydantic_ai.settings模块的四个公开成员:

成员类型职责
ModelSettingsTypedDict(total=False)跨提供商通用的 LLM 请求参数集合
ToolChoiceTypeAliastool_choice字段的全部合法取值
ToolOrOutputdataclass"限定函数工具但保留结构化输出/文本/图片输出"的复合取值
ServiceTierTypeAlias跨提供商的统一服务层级取值集

模块实现位于 pydantic_ai_slim/pydantic_ai/settings.py,仅 500 余行,是 Pydantic AI 中"一次声明、全提供商生效"这一设计的关键枢纽。它的设计约束在ModelSettings的类文档中写得很明确:

  • 只收录跨多个模型/提供商通用的设置——并非每个字段都被所有模型支持;
  • 每个字段的Supported by:列表标注了哪些模型类会真正把这个字段"放上线"(即序列化进请求体)。裸名字(如OpenAI)覆盖该模型提供的全部接口(OpenAIChatModelOpenAIResponsesModel),带接口的名字(如OpenAI Chat Completions)只覆盖单一接口;
  • 列表在"发送"意义上有效,不代表服务商一定"采纳":OpenAI 兼容类模型会把 OpenAI schema 接受的东西原样转发,背后的具体提供商可能忽略或拒绝自己 API 未定义的字段;
  • 所有类型必须可用 Pydantic 序列化。

二、ModelSettings:跨提供商通用参数详解

ModelSettings是一个total=FalseTypedDict,意味着所有字段可选、按需传入,未设置的字段不会进入请求。以下逐字段说明其语义与支持范围。

2.1 采样与生成控制

字段类型说明
max_tokensint停止生成前的最大 token 数。OpenAI、Anthropic、Google、Groq、Cohere、Mistral、Bedrock、MCP Sampling、xAI、HuggingFace、Cerebras、Crusoe、GitHub Copilot、Ollama、OpenRouter、Snowflake、Z.AI、Bedrock Mantle 支持
temperaturefloat注入的随机程度。接近0.0适合分析/选择题,接近模型上限适合生成式任务;注意即使为0.0结果也不完全确定。多数提供商支持(GitHub Copilot 对拒绝采样参数的 Anthropic 模型如claude-opus-4.8不发送)
top_pfloat核采样:只考虑概率质量前top_p的 token,0.1表示只考虑前 10% 概率质量。官方建议temperaturetop_p二选一调整,不要同时改
top_kint每个后续 token 只从 top K 选项中采样,用于剔除长尾低概率响应。仅 Anthropic、Google、Cohere、Bedrock(仅 Anthropic 与 Amazon Nova 模型)支持
seedint随机种子,理论上可得到确定性结果。支持列表限定在 Chat Completions 系接口(OpenAI Chat Completions、Google、Groq、Cohere、Mistral、xAI 等),注意 Responses 接口不在其列
presence_penaltyfloat按 token 是否已出现惩罚新 token
frequency_penaltyfloat按 token 已有出现频率惩罚新 token
logit_biasdict[str, int]修改指定 token 出现在补全中的概率。注意 Anthropic、Cohere、Bedrock、OpenRouter 之外并不普遍支持;Ollama 会发送但文档标注logit_bias不受支持
stop_sequenceslist[str]触发停止生成的序列。支持范围最广的字段之一,含 MCP Sampling

stop_sequences的端到端行为有真实集成测试佐证:tests/test_settings.py 中test_stop_settings在 openai、anthropic、bedrock、mistral、groq、cohere、google 七个模型上用 VCR cassette 回放验证"回答包含 Paris 但不以 Paris 开头",并特别标注 Bedrock 的行为差异——它会把停止序列包含在响应里result.output.endswith('Paris')),其余提供商则是停止序列不包含在输出中。这是使用该字段时值得记住的边界行为。

2.2 超时、并行工具调用与请求扩展

字段类型说明
timeoutint \| float \| Timeout以秒为单位覆盖客户端级默认超时。数字秒数全平台可用;同时接受遗留的httpx.Timeout,在 SDK 期望httpx2.Timeout的路径上自动转换;Google 与 Mistral 只接受数字秒数
parallel_tool_callsbool是否允许并行工具调用。OpenAI(部分模型,o1 不行)、OpenAI Codex、Anthropic、Groq、Mistral、xAI、Cerebras、Crusoe、GitHub Copilot、Ollama、OpenRouter、Snowflake、Z.AI、Bedrock Mantle 支持
extra_headersdict[str, str]发送到模型请求的额外 HTTP 头
extra_bodyobject追加到请求体中的额外字段,用于传递 Pydantic AI 尚未封装的提供商能力。注意:在 Cerebras、OpenRouter、Snowflake、Z.AI 这些自行构造extra_body的 OpenAI 衍生模型上,模型自有的派生键在键冲突时覆盖你的键

timeout的类型定义本身就体现了对依赖可选性的处理:从源码结构看,settings.py 中当 legacyhttpx未安装时,Timeout别名坍缩为float,使联合类型退化为纯数字——这保证了未安装 httpx 的环境中ModelSettings依然可用。

2.3 thinking:统一的思考/推理开关

thinking字段的类型是ThinkingLevel

ThinkingEffort: TypeAlias = Literal['minimal', 'low', 'medium', 'high', 'xhigh'] ThinkingLevel: TypeAlias = bool | ThinkingEffort

取值语义(见 settings.py 的文档字符串):

  • True:以提供商默认强度启用思考;
  • False:关闭思考(对"始终开启思考"的模型会被静默忽略);
  • 'minimal'/'low'/'medium'/'high'/'xhigh':以指定强度启用思考。

不是所有提供商都支持所有档位。当某个档位不被原生支持时会映射到最接近的可用值,例如不支持'xhigh'的提供商会落到'high',没有 minimal 档的提供商会把'minimal'映射为'low'。各模型类的具体落线方式差异很大,源码文档逐条列出:Cerebras 只转发False(映射为reasoning_effort='none',因其模型默认推理且gpt-oss连关闭也会忽略);OpenRouter 与 Snowflake(Claude 模型)以extra_body['reasoning']承载;Z.AI 以extra_body['thinking']承载;GitHub Copilot 以reasoning_effort发送且不支持的值会收到400 invalid_reasoning_effort;Bedrock Mantle 仅 Responses 接口发送。另外提供商专属思考字段(如anthropic_thinkingopenai_reasoning_effort)优先于这个统一字段

2.4 service_tier:统一服务层级与提供商映射

ServiceTier是一个四值类型别名:'auto' | 'default' | 'flex' | 'priority',语义(见 settings.py):

  • 'auto':交给提供商决定——通常意味着"可用时走高优先级/扩容额度层,否则走标准层"。对服务端没有 auto 概念的提供商会省略该字段,让其默认值生效;
  • 'default':显式请求标准层,退出服务端可能有的自动升级到高级层的行为
  • 'flex':更低成本、延迟容忍型层级(提供商提供时);不支持的提供商(如 Anthropic)静默忽略,也有个别提供商会直接拒绝该字段;
  • 'priority':更高优先级/更低延迟层级(提供商提供时),不支持的提供商静默忽略。

跨提供商映射表(源码文档原表):

取值OpenAIAnthropicBedrockGoogle (Gemini API)Google Cloud
'auto''auto''auto'(省略)(省略)无请求头(PT 优先,其后 on-demand)
'default''default''standard_only'{'type': 'default'}'standard'无请求头(PT 优先,其后 on-demand)
'flex''flex'(省略){'type': 'flex'}'flex'请求头Shared-Request-Type: flex(PT 优先,其后 Flex PayGo)
'priority''priority'(省略){'type': 'priority'}'priority'请求头Shared-Request-Type: priority(PT 优先,其后 Priority PayGo)

两个值得注意的实现细节:一是在 Google Cloud 上,统一字段只映射到"安全"的 PT(预留吞吐)溢出变体,以让有 Provisioned Throughput 的账号优先消耗预留容量;若要完全绕过 PT,需用提供商专属字段google_cloud_service_tier'flex_only''priority_only'。二是 Bedrock 的'reserved'、Anthropic 的'standard_only'、Google Cloud 的 PT 路由档位等不在统一取值集内的值只能通过提供商专属字段到达;而所有提供商专属字段(openai_service_tieranthropic_service_tierbedrock_service_tiergoogle_cloud_service_tier)一旦设置,一律优先于统一字段service_tier

2.5 tool_choice:工具选择控制

tool_choice的类型是ToolChoice,这是本模块中最复杂的一个联合类型:

ToolChoiceScalar = Literal['none', 'required', 'auto'] @dataclass class ToolOrOutput: function_tools: list[str] # 模型可用的函数工具名列表 ToolChoice = ToolChoiceScalar | list[str] | ToolOrOutput | None

各取值的语义(见 settings.py 文档):

  • None(默认):等价'auto'行为;
  • 'auto':所有工具可用,由模型自行决定是否调用;
  • 'none':禁用函数工具,模型只以文本响应(输出工具保留,结构化输出不受影响);
  • 'required':强制使用工具;排除输出工具,因此静态设置时 Agent 无法产生最终响应;
  • list[str]:只允许指定工具,同样排除输出工具;
  • ToolOrOutput:指定函数工具子集,同时保留输出工具/文本/图片输出——这是"限制函数工具但不阻断 Agent 收尾"的正确方式。

关键约束:静态'required'list[str]会抛UserError源码文档明确说明:通过Agent.runmodel_settings参数或 Agent 自身的model_settings静态设置这两种取值时,由于会在每一步强制工具调用、阻止 Agent 产生最终响应,Pydantic AI 会直接抛出UserError。如需按步变化tool_choice(例如只在第一步强制某工具),正确路径是让 Capability 的get_model_settings返回可调用对象——这些值被视为"跨步骤自适应"而受信任(见 capabilities/combined.py 中对get_model_settings返回值的解析)。若只是单次 API 调用而不需要 Agent 循环,用pydantic_ai.direct.model_request

各提供商对tool_choice的处理方式差异也在文档中注明:Cohere 与 Mistral 对"命名子集"是通过过滤工具列表实现的,而非作为参数发送;Anthropic 在启用 thinking 时不支持'required'与指定工具;Ollama 会发送但文档标注不受支持。

三、merge_model_settings:Agent、Run 与 Capability 的设置合并

模块末尾的merge_model_settings是所有设置最终生效的汇聚点(settings.py):

def merge_model_settings(base: ModelSettings | None, overrides: ModelSettings | None) -> ModelSettings | None: """Merge two sets of model settings, preferring the overrides. A common use case is: merge_model_settings(<agent settings>, <run settings>) """ if base and overrides: return base | overrides else: return base or overrides

实现极简单:两个字典的浅合并(|运算符),键冲突时overrides胜出;任一为None时返回另一个。源码注释还留了一个演进注记——"如果将来加入非原始值,可能需要递归合并",从源码结构看,当前所有字段均为扁平原始值,浅合并语义恰好够用。

它在代码库中的调用点勾勒出完整的优先级链:

  1. Agent 层:agent/init.py 中 Agent 级model_settings作为 base;agent/init.py 中先并入 Agent 设置、再并入本次run()传入的model_settings——即Run 参数 > Agent 参数
  2. Capability 层:capabilities/combined.py 在每步执行时,把各 Capabilityget_model_settings解析出的设置再次并入ctx.model_settings,能力返回的可调用对象在此被调用并解析;
  3. 模型层:各模型实现(如 models/openai.py、models/anthropic.py、models/bedrock.py)在构造请求前把实例级self.settings与本次请求的model_settings再合并一次,请求参数 > 模型实例参数

合并语义有专门的单元测试覆盖:tests/test_settings.py 的TestMergeModelSettingsThinkingTestMergeModelSettingsServiceTier验证了thinking布尔/强度档的覆盖、无关字段(max_tokenstemperature)在合并中保留、以及None边界的三种组合(base 为 None、overrides 为 None、双 None 返回 None)。

四、提供商专属设置:前缀命名的扩展体系

ModelSettings只覆盖通用参数。各提供商自己的参数(如anthropic_thinkingopenai_reasoning_effort)定义在各自模型模块中以提供商名作前缀的ModelSettings子类中。tests/test_settings.py 通过动态发现机制强制执行这一命名纪律:_discover_model_settings()遍历pydantic_ai.models包下所有子模块,用__orig_bases__找出每个ModelSettings子类(因为TypedDict子类的__bases__只报告dict,真实继承链要取__orig_bases__),然后断言所有不属于全局ModelSettings的字段名必须以"{模块名}_"开头(mcp_sampling是例外,用mcp_前缀,因为它是 MCP sampling 伪模型而非真正的提供商集成)。test_model_settings_discovery还设置了模块遍历数量的腐烂守卫,防止包结构变动导致前缀检查静默失效。

五、实战:组合使用这些设置

把上述能力组合起来,典型的 Agent 配置如下:

from pydantic_ai import Agent from pydantic_ai.settings import ModelSettings, ToolOrOutput agent = Agent( 'openai:gpt-4o', model_settings=ModelSettings( temperature=0.3, max_tokens=2000, tool_choice=ToolOrOutput(function_tools=['get_weather', 'get_time']), thinking='high', service_tier='auto', stop_sequences=['[END]'], ), ) # Run 级覆盖:只需给出要改的键,其余沿用 Agent 设置 result = await agent.run( '明天天气如何?', model_settings=ModelSettings(temperature=0.1, timeout=30), )

这段示例的每个行为点都对应前文的实现证据:ToolOrOutput让模型在两个函数工具与"直接给出结构化输出"之间选择而不强制工具调用;Run 级model_settingsmerge_model_settings与 Agent 设置浅合并,仅temperature与新增的timeout生效,其余键原样保留;thinking='high'会按各提供商的映射规则落到其支持的档位;service_tier='auto'按第二节映射表翻译为各提供商的具体线格式。

需要按步动态调整tool_choice时,参考 docs/tools-advanced.md 中 Tool Choice 一节的完整示例,核心手段是 Capability 的get_model_settings钩子而非静态model_settings

六、验证与深入阅读的路径

  • 源码定义:pydantic_ai_slim/pydantic_ai/settings.py(约 534 行,含全部字段文档与Supported by列表);
  • 合并行为测试:tests/test_settings.py(stop_sequences跨 7 提供商集成回放 + 合并语义单测 + 前缀命名契约测试);
  • 设置"是否真正上线"的逐线核对:ModelSettings文档字符串声明其Supported by列表由 tests/models/test_model_settings_support.py 解析并对照真实 wire 请求校验,因此文档中的支持列表是有测试背书的实现事实,而非口头承诺。

适用前提提示:本文所有字段语义与提供商映射均取自当前仓库源码文档,Supported by列表描述的是 Pydantic AI"发送"该设置的范围;个别提供商背后的实际接受行为以其自身 API 参考为准,文档中已知会被拒绝或忽略的字段(如 Snowflake Cortex 拒绝service_tier、Cerebras 的层级处于私有预览)均已按源码原文注明。

【免费下载链接】pydantic-aiHow Python does AI. Agents, realtime voice, image generation, embeddings. Every model, every interface, typed end to end.项目地址: https://gitcode.com/GitHub_Trending/py/pydantic-ai

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询