
Pydantic AI 多模态输入完全指南图片、音频、视频、文档与上传文件的类型化处理【免费下载链接】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 中Agent 的输入并不局限于纯文本——只要模型支持你可以直接向 Agent 传递图片、音频、视频和文档等多模态内容。本文基于仓库 docs/input.md 展开系统讲解ImageUrl、AudioUrl、VideoUrl、DocumentUrl、BinaryContent、TextContent与UploadedFile七种输入类型的用法、各模型对 URL 直传/本地下载的支持矩阵、force_download的安全语义以及 Anthropic、OpenAI、Google、Bedrock、xAI 五个提供商的已上传文件Uploaded File接入方式。读完本文你将掌握如何在 Agent 中正确处理任意形态的多模态用户输入并理解 URL 直传与字节下发两条路径的底层原理。一、多模态输入类型体系总览在 pydantic_ai_slim/pydantic_ai/messages.py 中所有多模态内容被统一建模为MultiModalContent联合类型第 966 行由kind字段作为判别器ImageUrl | AudioUrl | DocumentUrl | VideoUrl | BinaryContent | UploadedFile按数据来源可划分为三类类别类型数据形态URL 引用ImageUrl、AudioUrl、VideoUrl、DocumentUrl指向远程文件的 URL 字符串本地字节BinaryContent含BinaryImage、BinaryAudio子类内存中的原始字节 media type平台文件UploadedFile提供商文件存储 API 返回的文件 ID而普通文本既可以直接以str传入也可以通过带元数据的TextContent传入。这些类型共同组成了UserContent第 991 行str | TextContent | MultiModalContent | CachePoint即Agent.run_sync/Agent.run中用户消息列表的元素类型。值得注意的实现细节ForceDownloadMode被定义为bool | Literal[allow-local]messages.py 第 179 行这一三态设计直接决定了 URL 是否被本地下载以及 SSRF 防护的严格程度将在后文详述。二、图片输入Image Input注意部分模型不支持图片输入请先查阅所用模型的官方文档确认。2.1 使用远程 URLImageUrl如果图片有可直接访问的 URL使用ImageUrlfrom pydantic_ai import Agent, ImageUrl agent Agent(modelopenai:gpt-5.2) result agent.run_sync( [ What company is this logo from?, ImageUrl(urlhttps://iili.io/3Hs4FMg.png), ] ) print(result.output) # This is the logo for Pydantic, a data validation and settings management library in Python.2.2 使用本地文件BinaryContent如果图片在本地用BinaryContent直接携带字节数据import httpx from pydantic_ai import Agent, BinaryContent image_response httpx.get(https://iili.io/3Hs4FMg.png) # Pydantic logo agent Agent(modelopenai:gpt-5.2) result agent.run_sync( [ What company is this logo from?, BinaryContent(dataimage_response.content, media_typeimage/png), ] ) print(result.output) # This is the logo for Pydantic, a data validation and settings management library in Python.上例通过httpx从网络下载图片仅为保证示例可运行真实场景中更推荐直接用Path().read_bytes()读取本地文件内容。2.3 源码侧的类型化细节ImageUrl继承自FileUrl基类messages.pyurl为必填字段同时接受可选的media_type、identifier、force_download、vendor_metadata参数media_type未指定时会通过 Pythonmimetypes从 URL 扩展名自动推断无法推断时抛出ValueError。BinaryContentmessages.py除data与media_type外还提供base64、data_uri属性以及is_image/is_audio/is_video/is_document四个类型判定属性并内置了两个便捷工厂方法BinaryContent.from_path(path)从文件路径读取media type 无法推断时回退为application/octet-stream、BinaryContent.from_data_uri(uri)从data:URI 解析。传入image/*media type 的字节时BinaryContent.narrow_type会自动将实例收窄为BinaryImage从而在后续消息处理中获得更精确的类型保证。三、音频输入Audio Input注意部分模型不支持音频输入请先查阅所用模型的官方文档确认。音频与图片的处理方式完全对称使用AudioUrl或BinaryContentfrom pydantic_ai import Agent, AudioUrl agent Agent(modelopenai:gpt-5.2) result agent.run_sync( [ Transcribe this audio clip, AudioUrl(urlhttps://example.com/audio.mp3), ] )本地音频则同样走BinaryContent(data..., media_typeaudio/mpeg)路径。在源码中AudioUrlmessages.py的_infer_media_type依赖mimetypes.guess_type解析扩展名BinaryAudio子类则在__post_init__中强制校验 media type 必须以audio/开头messages.py。四、视频输入Video Input注意部分模型不支持视频输入请先查阅所用模型的官方文档确认。视频使用VideoUrl或BinaryContentfrom pydantic_ai import Agent, VideoUrl agent Agent(modelgoogle:gemini-2.5-flash) result agent.run_sync( [ Summarize what happens in this video, VideoUrl(urlhttps://example.com/video.mp4), ] )关于VideoUrl有两个源码级细节值得注意messages.pyYouTube 特判VideoUrl.is_youtube属性只对youtu.be、youtube.com、www.youtube.com、m.youtube.com四个精确 host 返回True故意排除music.youtube.com因为 Google 会以 400 INVALID_ARGUMENT 拒绝它作为file_uri。YouTube 视频的 media type 被假定为video/mp4因为其 URL 没有可推断的扩展名。不可本地下载在 models/init.py 的download_item中对is_youtube的VideoUrl会直接抛出UserError——YouTube 视频只能由支持它的模型如 Google直接解析不能下载字节。五、文档输入Document Input注意部分模型不支持文档输入请先查阅所用模型的官方文档确认不同模型支持的文档格式PDF、TXT、DOCX、CSV、HTML 等各不相同。5.1 通过 URL 传入from pydantic_ai import Agent, DocumentUrl agent Agent(modelanthropic:claude-sonnet-4-6) result agent.run_sync( [ What is the main content of this document?, DocumentUrl(urlhttps://storage.googleapis.com/cloud-samples-data/generative-ai/pdf/2403.05530.pdf), ] ) print(result.output) # This document is the technical report introducing Gemini 1.5, Googles latest large language model...5.2 通过二进制内容传入from pathlib import Path from pydantic_ai import Agent, BinaryContent pdf_path Path(document.pdf) agent Agent(modelanthropic:claude-sonnet-4-6) result agent.run_sync( [ What is the main content of this document?, BinaryContent(datapdf_path.read_bytes(), media_typeapplication/pdf), ] ) print(result.output) # The document discusses...5.3 文本提取的兜底方案如果DocumentUrl和BinaryContent都不适合你的场景例如模型不支持DocumentUrl或你想以非二进制格式提供文档可以自己提取文档文本作为普通字符串或TextContent传入。DocumentUrl在 messages.py 中维护了一张 media type → 格式的映射表PDF→pdf、TXT→txt、CSV→csv、DOCX→docx、XLSX→xlsx、HTML→html等未知 media type 会抛出ValueError。六、文本输入与 TextContent 元数据TextContent让你在传文本的同时附加仅供程序访问的元数据from pydantic_ai import Agent, TextContent agent Agent(modelopenai:gpt-5.2) result agent.run_sync([ Summarize the key points from this text., TextContent( content( Pydantic AI is a Python agent framework. It supports text, image, audio, video, and document input. ), metadata{source: pydantic_ai_inputs.txt}, ), ])这与直接传str等价但允许携带额外的metadata。从 messages.py 的定义可以看到TextContent只有三个字段content发送给模型的正文、metadata任意类型与kind判别器。需要特别强调的是content字段会作为模型输入发送而metadata不会发送给模型它只保存在消息历史中供应用程序编程访问。metadata是纯应用侧数据ModelMessagesTypeAdapter会保留它但不能保证经过 UI 适配器往返后依然存在参见 消息历史的存储与加载。七、用户侧下载还是直传文件 URL这是多模态输入中最关键的行为决策点当使用ImageUrl/AudioUrl/VideoUrl/DocumentUrl时Pydantic AI默认将 URL 直接发送给模型提供商由提供商侧自行下载文件。文件 URL 的支持情况因类型和提供商而异下表完整总结了各模型的能力矩阵模型直传 URL下载后传字节不支持OpenAIChatModelImageUrlAudioUrl、DocumentUrlVideoUrlDocumentUrl在 AzureProvider 与 AlibabaProvider 下不受支持OpenAIResponsesModelImageUrl、AudioUrl、DocumentUrl—VideoUrlAnthropicModelImageUrl、DocumentUrlPDFDocumentUrltext/plainAudioUrl、VideoUrlGoogleModelGoogle Cloud全部 URL 类型——GoogleModelGemini APIYouTube 与 Files API URL其余全部 URL—XaiModelImageUrlDocumentUrlAudioUrl、VideoUrlMistralModelImageUrl、DocumentUrlPDFDocumentUrltext/plainAudioUrl、VideoUrl、DocumentUrl非 PDF/非文本BedrockConverseModelS3 URLs3://ImageUrl、DocumentUrl、VideoUrlAudioUrlOpenRouterModelImageUrl、DocumentUrl、VideoUrlAudioUrl—即使模型支持文件 URL其 API 也可能无法完成下载例如受爬取或访问限制。一个已知限制是Google Cloud 上的GoogleModel对 YouTube 视频 URL 限制为每个请求最多一个。7.1 使用 force_download 强制本地下载当模型侧下载失败或不适用时可以在 URL 对象上设置force_download让 Pydantic AI 先在本地下载文件内容再以字节形式发送给提供商from pydantic_ai import ImageUrl, AudioUrl, VideoUrl, DocumentUrl ImageUrl(urlhttps://example.com/image.png, force_downloadTrue) AudioUrl(urlhttps://example.com/audio.mp3, force_downloadTrue) VideoUrl(urlhttps://example.com/video.mp4, force_downloadTrue) DocumentUrl(urlhttps://example.com/doc.pdf, force_downloadTrue)force_download的三个取值False/True/allow-local在 messages.py 中有精确的语义定义False默认URL 直传给支持它的提供商对不支持的提供商文件会被下载且下载过程启用 SSRF 防护拦截私有 IP 与云 metadata。True始终下载文件启用 SSRF 防护。allow-local始终下载文件允许访问私有 IP但仍拦截云 metadata。底层实现位于 models/init.py 的download_item它调用_ssrf.safe_download并具备以下 SSRF 防护清单仅允许http://与https://协议默认拦截私有/内网 IP 地址始终拦截云 metadata 端点169.254.169.254请求前先解析 hostname防止 DNS rebinding响应体大小上限为50 MiB对is_youtube的VideoUrl直接抛出UserErrorYouTube 不支持下载。7.2 安全警告信任模型对文件 URL 的约束当 URL 被转发给提供商时提供商是用它自己的凭证去抓取文件的。对于s3://Bedrock和gs://Google Cloud这类云存储 scheme那些凭证就是你服务器上的 IAM 角色或服务账号——因此谁控制了 URL谁就控制了提供商在你的授权下能读取到什么。这意味着不要直接用不可信的用户输入构造ImageUrl、AudioUrl、VideoUrl或DocumentUrl除非你验证过 URL 的 scheme 与作用域。对于前端发起上传到云存储的场景应在服务端把s3://bucket/key之类的引用转换为预签名的https://URL 后再构造文件 URL part。同时注意force_downloadTrue仅对http(s)://URL 生效它经由库内部的 HTTP 客户端且应用 SSRF 防护s3://、gs://等云存储 scheme 不走本地下载路径会原样转发给提供商force_downloadallow-local只应用于服务端自行生成的 URL因为它放开了本地网络访问。在 UI 场景中UI 适配器 会自动对客户端提交的消息做此类净化通过UIAdapter.allowed_file_url_schemes与UIAdapter.allowed_file_url_force_download两个配置控制如果你通过自定义客户端 API 接收序列化的message_history请务必在将历史传给 Agent 之前调用sanitize_messagespydantic_ai.messages.sanitize_messages。八、已上传文件UploadedFile部分模型提供商提供自己的文件存储 API你可以先把文件上传到平台再通过 ID 或 URL 引用它。此时应使用UploadedFile。提示对于会返回文件 URL 的提供商如 Google Files API、Bedrock 的 S3 URL你也可以直接用DocumentUrl、ImageUrl或VideoUrl。不过推荐统一使用UploadedFile以获得跨提供商一致的 API 和一致的提供商名校验。8.1 支持的模型模型支持方式AnthropicModel✅ 通过 Anthropic Files APIOpenAIChatModel✅ 通过 OpenAI Files APIOpenAIResponsesModel✅ 通过 OpenAI Files APIGoogleModel✅ 通过 Google Files APIBedrockConverseModel✅ 通过 S3 URLs3://bucket/keyXaiModel✅ 通过 xAI Files API其他模型❌ 不支持8.2 provider_name 必填要求使用UploadedFile时必须设置provider_name。已上传文件只属于其上传目标系统不可跨提供商转移把包含UploadedFile的消息用于其他提供商会导致错误。在 messages.py 中UploadedFileProviderName被限定为anthropic | openai | google | google-cloud | google-gla | google-vertex | bedrock | xai其中google-gla、google-vertex是为 v2 提供商重命名前的旧消息历史保留的兼容值新代码统一使用google与google-cloud。提示用model.system动态获取正确的提供商名可保证代码在提供商名变化时依然正确。下文所有示例均采用这一模式。如果希望同一份提示历史在不同提供商后端之间可移植可以使用 history processor 在消息发送给不支持UploadedFile的提供商之前移除或改写其中的UploadedFileparts。需要注意剥离UploadedFile可能让模型困惑尤其是当文本中仍存在对文件的引用时。8.3 media_type 推断规则UploadedFile的media_type参数是可选的。未指定时Pydantic AI 会尝试从file_id推断messages.py若file_id是带可识别扩展名如.pdf、.png的 URL 或路径自动推断 media type对于不透明 file ID如file-abc123media type 默认为application/octet-stream。提示虽然media_type可选但已知时仍建议显式指定以确保提供商正确处理文件。8.4 Anthropic按 Anthropic Files API 文档上传文件底层 Anthropic 客户端可通过provider.client访问注意Anthropic Files API 目前处于 beta 阶段。当请求中包含 AnthropicUploadedFile时AnthropicModel会自动添加anthropic-beta: files-api-2025-04-14请求头无需手动设置。import asyncio from pydantic_ai import Agent, UploadedFile from pydantic_ai.models.anthropic import AnthropicModel from pydantic_ai.providers.anthropic import AnthropicProvider async def main(): provider AnthropicProvider() model AnthropicModel(claude-sonnet-4-5, providerprovider) # Upload a file using the providers client (Anthropic client) with open(document.pdf, rb) as f: uploaded_file await provider.client.beta.files.upload(filef) # Reference the uploaded file; the beta header is added automatically agent Agent(model) result await agent.run( [ Summarize this document, UploadedFile(file_iduploaded_file.id, provider_namemodel.system), ] ) print(result.output) # The document discusses the main topics and key findings... asyncio.run(main())8.5 OpenAI按 OpenAI Files API 文档上传文件import asyncio from pydantic_ai import Agent, UploadedFile from pydantic_ai.models.openai import OpenAIChatModel from pydantic_ai.providers.openai import OpenAIProvider async def main(): provider OpenAIProvider() model OpenAIChatModel(gpt-5, providerprovider) # Upload a file using the providers client (OpenAI client) with open(document.pdf, rb) as f: uploaded_file await provider.client.files.create(filef, purposeuser_data) # Reference the uploaded file agent Agent(model) result await agent.run( [ Summarize this document, UploadedFile(file_iduploaded_file.id, provider_namemodel.system), ] ) print(result.output) # The document discusses the main topics and key findings... asyncio.run(main())引用已上传图片的注意事项OpenAIChatModel只能通过file_id引用已上传的文档。引用已上传图片image/*media type会抛出UserError因为 Chat Completions API 不接受图片部分的file_id。图片请改用ImageUrl或BinaryContent或改用支持已上传图片的OpenAIResponsesModel。使用OpenAIResponsesModel时可通过给UploadedFile传vendor_metadata{detail: high}或low控制图片细节等级默认auto。使用OpenAIChatModel、GroqModel、MistralModel、XaiModel时同样通过给ImageUrl或BinaryContent传vendor_metadata{detail: high}或low控制图片细节等级默认auto。8.6 Google按 Google Files API 文档上传文件底层 Google GenAI 客户端通过provider.client访问import asyncio from pydantic_ai import Agent, UploadedFile from pydantic_ai.models.google import GoogleModel from pydantic_ai.providers.google import GoogleProvider async def main(): provider GoogleProvider() model GoogleModel(gemini-2.5-flash, providerprovider) # Upload a file using the providers client (Google GenAI client) with open(document.pdf, rb) as f: file await provider.client.aio.files.upload(filef) assert file.uri is not None # Reference the uploaded file by URI (media_type is optional for Google) agent Agent(model) result await agent.run( [ Summarize this document, UploadedFile(file_idfile.uri, media_typefile.mime_type, provider_namemodel.system), ] ) print(result.output) # The document discusses the main topics and key findings... asyncio.run(main())从源码看GoogleModel对file_id的取值有明确约束messages.pyGoogle Cloud 场景必须是 GCS URIgs://bucket/pathGemini API 场景必须是 Google Files API URIhttps://generativelanguage.googleapis.com/...。8.7 BedrockS3Bedrock 场景下文件必须单独上传到 S3例如使用 boto3 的put_object且运行角色的 IAM 需要对 bucket 拥有s3:GetObject权限。注意当文件扩展名不明确或缺失时Bedrock要求提供media_type对于.pdf、.png等扩展名清晰的 S3 URL 可以自动推断。import asyncio from pydantic_ai import Agent, UploadedFile from pydantic_ai.models.bedrock import BedrockConverseModel async def main(): model BedrockConverseModel(us.anthropic.claude-sonnet-4-20250514-v1:0) agent Agent(model) result await agent.run([ Summarize this document, UploadedFile( file_ids3://my-bucket/document.pdf, provider_namemodel.system, # bedrock media_typeapplication/pdf, # Optional for .pdf, but recommended ), ]) print(result.output) # The document discusses the main topics and key findings... asyncio.run(main())提示如果 bucket 不属于发起请求的账号可以在 URL 上附加bucketOwner查询参数s3://my-bucket/document.pdf?bucketOwner123456789012。8.8 xAI按 xAI Files API 文档上传文件底层 xAI 客户端通过provider.client访问import asyncio from pydantic_ai import Agent, UploadedFile from pydantic_ai.models.xai import XaiModel from pydantic_ai.providers.xai import XaiProvider async def main(): provider XaiProvider() model XaiModel(grok-4.3, providerprovider) # Upload a file using the providers client (xAI client) with open(document.pdf, rb) as f: uploaded_file await provider.client.files.upload(f, filenamedocument.pdf) # Reference the uploaded file agent Agent(model) result await agent.run( [ Summarize this document, UploadedFile(file_iduploaded_file.id, provider_namemodel.system), ] ) print(result.output) # The document discusses the main topics and key findings... asyncio.run(main())九、总结与选型建议面对多模态输入可按以下次序决策文件已在提供商平台或 S3/GCS优先UploadedFile配合model.system设置provider_name跨提供商移植历史时用 history processor 清理。文件有公开 HTTP(S) URL 且模型支持直传使用对应的ImageUrl/AudioUrl/VideoUrl/DocumentUrl对照上文支持矩阵确认该模型的能力若模型侧无法抓取则加force_downloadTrue改为本地下载后传字节。文件在本地或字节已在内存用BinaryContent配合from_path/from_data_uri便捷方法显式给出media_type。纯文本直接传str需要附加程序元数据时用TextContent。最后请始终牢记安全边界URL 直传意味着把下载动作和你的云存储凭证暴露给 URL 控制者因此对外部用户输入构造的文件 URL 必须校验 scheme 与作用域并用sanitize_messages或依赖 UI 适配器的allowed_file_url_schemes配置做净化force_download是本地下载路径的开关仅对http(s)://生效并内置 SSRF 防护allow-local只应出现在服务端自产 URL 上。【免费下载链接】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),仅供参考