首页
/ CrewAI crewai-files 多模态文件输入全解:从文件自动识别到按 Provider 自适应上传

CrewAI crewai-files 多模态文件输入全解:从文件自动识别到按 Provider 自适应上传

2026-09-05 18:28:48作者:牧宁李

crewai-files 是 CrewAI 仓库中专门负责多模态文件处理的独立包,它让 Agent 可以直接接收图片、PDF、文本、音频和视频,并自动完成类型识别、体积校验、按需压缩/分片,以及向各 LLM Provider 的自适应投递(URL 引用、内联 Base64 或文件上传)。读完本文,你将掌握在 Crew 与 Task 层传入 input_files 的完整用法,并理解从 README.md 中的三行示例背后,整个“识别 → 处理 → 解析 → 上传”的源码级执行链路。

包定位与依赖

crewai-files 作为 monorepo 中 lib/ 下的独立分发包存在,其包元信息定义在 pyproject.toml

  • 包名 crewai-files,描述为 “File handling utilities for CrewAI multimodal inputs”;
  • Python 版本要求 >=3.10, <3.14
  • 运行时依赖与文件处理能力一一对应:
    • Pillow~=12.3.0:图片读取、缩放与压缩;
    • pypdf~=6.14.2:PDF 页数解析与按页分片;
    • python-magic>=0.4.27:基于魔数(magic number)的 MIME 内容嗅探;
    • aiocache~=0.12.3:上传结果缓存;
    • aiofiles~=24.1.0:异步文件读写;
    • tinytag~=2.2.1av~=13.0.0:音频/视频元信息(时长)提取。

包的公开 API 集中在 src/crewai_files/init.py 中导出,包括五类文件类型、FileProcessorFileResolver、各 Provider 约束常量与上传器,当前包版本为 1.15.18(版本值定义于同文件的 __version__)。

支持的文件类型与 File 类体系

README 给出的支持类型概览:

类型 支持格式(README 列举)
ImageFile PNG、JPEG、GIF、WebP
PDFFile PDF 文档
TextFile 纯文本文件
AudioFile MP3、WAV、FLAC、OGG、M4A
VideoFile MP4、WebM、MOV、AVI

源码中每个类别的扩展名白名单比 README 更宽,定义在 core/types.py

  • 图片额外支持 .bmp.tiff/.tif.svg.heic/.heif
  • 文本扩展 .txt.md.rst.csv.json.xml.yaml/.yml.html/.htm.log.ini.cfg/.conf
  • 音频扩展 .mp3.wav.ogg.flac.aac.m4a.wma.aiff.opus
  • 视频扩展 .mp4.avi.mkv.mov.webm.flv.wmv.m4v.mpeg/.mpg

所有具体类型都继承自抽象基类 BaseFile,它只有两个公开字段:

class BaseFile(ABC, BaseModel):
    source: CoercedFileSource = Field(description="The underlying file source.")
    mode: FileMode = Field(
        default="auto",
        description="How to handle if file exceeds limits: strict, auto, warn, chunk.",
    )
  • source:底层文件来源,支持 str(路径或 URL)、Pathbytes、二进制流等原始输入,Pydantic 校验时会被强制转换为内部的 FileSource 类型(见下一节);
  • mode:该文件超出 Provider 限制时的处理策略,取值为 Literal["strict", "auto", "warn", "chunk"],默认 "auto"——这是逐文件(per-file)的开关,而非全局配置。

BaseFile 还提供两个实用能力(定义在 core/types.py):

  1. 内容读取read() 返回字节、read_text() 返回解码文本、aread() 异步读取;
  2. 字典解包:实现 keys()__getitem__(),使 {**ImageFile(source="./chart.png")} 可以解包为 {"chart": <ImageFile 实例>}——键名取文件名去掉扩展名的部分(stem),无文件名时回退为 "file"。这正好对应 README 中 input_files={"chart": ImageFile(...)} 的写法。

File 是泛型入口,用于不想显式指定类型时的自动识别:

from crewai_files import File, ImageFile, PDFFile

# 自动识别文件类型
file = File(source="document.pdf")  # 解析为 PDFFile

# 或者直接使用具体类型
image = ImageFile(source="chart.png")
pdf = PDFFile(source="report.pdf")

文件来源:五种 FileSource 与内容识别

source 字段接受 str | Path | bytes | IOBase | FileSource,由 _FileSourceCoercercore/types.py)统一转换为五种内部来源类型,全部定义在 core/sources.py

来源类型 触发条件 行为要点
FilePath str(非 URL)或 Path 校验后读取磁盘文件,支持同步/异步/分块读取
FileBytes bytes 内容已在内存,MIME 即时嗅探
FileStream 具备 read()/seek() 的二进制流 首次读取时回卷到头部嗅探 MIME,读取结果缓存
AsyncFileStream 具备 async read() 的对象 纯异步场景,需先 aread() 才能取 content_type
FileUrl http:// / https:// 开头的字符串 延迟抓取;支持 URL 的 Provider 可直接引用

几个值得注意的实现细节:

MIME 检测策略detect_content_type() 优先调用 python-magic 对前 2048 字节(MAGIC_BUFFER_SIZE)做内容嗅探;若 python-magic 不可用或返回 application/octet-stream,则回退到 _fallback_content_type():先按文件扩展名查 mimetypes 表(保证 text/csv 等精确类型不被降级为 text/plain),再尝试字节级嗅探(PNG/JPEG/PDF 魔数、JSON 结构、可解码 UTF-8 纯文本),最终兜底为 application/octet-stream

FilePath 的安全校验。构造 FilePath 时的 @model_validator 会依次执行:

  1. 路径字符串含 .. 直接拒绝(防路径穿越);
  2. 符号链接解析后必须落在当前工作目录之内,否则拒绝;
  3. 文件必须存在且是普通文件;
  4. 文件实际大小不得超过 max_size_bytes,默认值为 DEFAULT_MAX_FILE_SIZE_BYTES = 524_288_000(500 MB,定义在 core/constants.py),超限抛出 FileTooLargeError

FileUrl 的延迟抓取。只有在不支持 URL 引用的 Provider 上,FileUrl.read()/aread() 才会通过 httpx 实际下载内容并采用响应头中的 Content-Type;支持 URL 引用的 Provider 可以直接把 URL 透传给模型侧。

实战:把文件传给 Crew 和 Task

README 给出了两个核心用法,它们与 crewai 主包的 Crew.kickoff()Task 参数直接对接。

传给 Crew

crew.kickoff(
    input_files={"chart": ImageFile(source="chart.png")}
)

kickoffinput_files 是「名称 → 文件对象」的字典。名称会成为提示词上下文中引用该文件的锚点。若不想手写键名,可利用 BaseFile** 解包能力:

crew.kickoff(input_files={**ImageFile(source="chart.png")})
# 等价于 input_files={"chart": ImageFile(source="chart.png")}

在主包 lib/crewai 中可以看到这些入口的真实消费方:Crew 的 A2A 委托层(lib/crewai/src/crewai/a2a/utils/delegation.py)会调用 _create_file_parts(input_files) 把每个 FileInput 转换为可发送给远端 Agent 的 Part 对象;lib/crewai/src/crewai/a2a/wrapper.py 中的 kickoff 包装函数同样贯穿 input_files 参数传递。

传给 Task

task = Task(
    description="Analyze the chart",
    expected_output="Analysis",
    agent=agent,
    input_files=[ImageFile(source="chart.png")],
)

Task 层的 input_files 接收文件对象列表,仅对该任务可见,适合多任务 Crew 中按任务分发不同材料的场景;Crew 层的 input_files 则是整次 kickoff 的共享材料。

仓库测试目录中的 fixtures 覆盖了五类文件的真实样例:revenue_chart.pngagents.pdfreview_guidelines.txtsample_audio.wavsample_video.mp4quarterly_report.csv,可作为本地联调的输入素材。

处理模式 mode:strict / auto / warn / chunk

每个文件携带的 mode 字段决定了它超出 Provider 限制时的行为,核心调度逻辑在 processing/processor.pyFileProcessor.process()

if not errors:
    return file                      # 校验通过,原样返回
if mode == FileHandling.STRICT:      # 严格:直接抛 FileValidationError
    raise FileValidationError(...)
if mode == FileHandling.WARN:        # 警告:记录 warning 后原样返回
    for error in errors:
        logger.warning(error)
    return file
if mode == FileHandling.AUTO:        # 自动:尝试缩放/压缩
    return self._auto_process(file)
if mode == FileHandling.CHUNK:      # 分片:拆成多个文件
    return self._chunk_process(file)

四种模式的语义:

  • strict:任何校验失败立即抛错(FileValidationError),适合对输入质量有硬性要求的离线批处理;
  • auto(默认):对图片尝试自动缩放(超过 max_width/max_height 时调用 resize_image)与压缩(超过 max_size_bytes 时调用 optimize_image);对 PDF 仅记录 warning 建议改用 CHUNK 模式(源码注释明确 “Cannot auto-compress PDF”);对音视频不处理并记录 warning;
  • warn:只记日志、原样放行,交给 Provider 自行拒绝或容忍;
  • chunk:PDF 超过 max_pages 时按页拆分为多个文件;TextFile 超过体积上限时按字符数拆分。分片后的文件在 process_files() 中会被展开为 原名_chunk_0原名_chunk_1 … 的多个字典条目。

FileProcessor 接受 ProviderConstraints 实例或 Provider 名字符串(经 get_constraints_for_provider() 解析);传入未知 Provider 名时仅记录 warning 并关闭校验,不会中断运行。批量场景还有 aprocess_files() 异步版本,内部用信号量限制并发(默认 10)。

Provider 约束:内置的各家上限表

processing/constraints.py 内置了六套 Provider 约束,这是本包与具体 LLM 服务商之间的契约层:

Provider 图片上限 PDF 上限 音频上限 视频上限 文件上传 API URL 引用
anthropic 5 MB/张,≤8000×8000 像素,≤100 张 32 MB、≤100 页 支持(阈值 5 MB) 支持
openai(completions) 20 MB/张、≤10 张 支持(阈值 5 MB) 支持
openai_responses 20 MB/张、≤10 张 32 MB、≤100 页 25 MB、≤25 分钟 支持(阈值 5 MB) 支持
gemini 100 MB(含 HEIC/HEIF) 50 MB 100 MB、≤9.5 小时 2 GB、≤1 小时 支持(阈值 20 MB) 支持
bedrock 4.5 MB,≤8000×8000 像素 3.67 MB、≤100 页 不支持 支持(S3 URI)
azure 20 MB/张、≤10 张 25 MB、≤25 分钟 不支持 支持

(表中“—”表示该 Provider 未配置对应类别约束,即不做该类校验。)

get_constraints_for_provider() 支持大小写不敏感的模糊匹配,并内置别名映射:claude → anthropicgpt → openaigoogle → geminiaws → bedrock(结果带 lru_cache 缓存)。另有 uses_openai_responses_api() 判定是否走 Responses API 的文件能力集,get_supported_content_types() 可按 Provider 返回其接受的 MIME 前缀列表(如 ["image/", "application/pdf"]),供上层做前置过滤。

约束类本身是 frozen dataclass,字段含义清晰:ImageConstraints(体积/宽高/单请求图片数/格式白名单)、PDFConstraints(体积/页数)、AudioConstraintsVideoConstraints(体积/时长/格式)、TextConstraints(体积/格式),以及顶层 ProviderConstraintssupports_file_uploadfile_upload_threshold_bytessupports_url_references 三个能力位。

文件解析与上传:FileResolver 的三级投递决策

处理完之后,文件还要以 Provider 能接受的形式投出去。resolution/resolver.py 中的 FileResolver.resolve(file, provider) 按以下决策树执行:

  1. URL 引用:来源本身是 FileUrl 且 Provider supports_url_references=True(且非 Bedrock/AWS 系)时,直接返回 UrlReference,零下载、零编码;
  2. 文件上传:Provider 支持 File API 且满足 _should_upload() 条件时走上传。判定逻辑:prefer_upload=True 一律上传;否则文件体积超过「该类型约束的 max_size_bytes」或超过「配置/Provider 默认的 file_upload_threshold_bytes」时上传;
  3. 内联:其余情况返回 InlineBase64(Base64 编码内容);Bedrock 在 use_bytes_for_bedrock=True(默认)时返回 InlineBytes 原始字节。

上传链路有三个可靠性设计:

  • 内容寻址缓存UploadCache 以「SHA-256 内容哈希 + Provider」为键缓存 file_id(缓存 TTL 默认 86400 秒、最多 1000 条,见 core/constants.py),同一文件在同一次运行中对同一 Provider 只上传一次;
  • 指数退避重试_upload_with_retry() 最多 UPLOAD_MAX_RETRIES=3 次,重试间隔为 2**attempt 秒;PermanentUploadError(如文件超限)立即放弃,TransientUploadError(网络抖动)才进入重试;
  • 工厂化上传器get_uploader(provider) 返回对应实现(OpenAI Files API、Gemini Files API、Anthropic、Bedrock 等),均继承自 uploaders/base.pyFileUploader 抽象基类,统一提供 upload/auploaddelete/adeleteget_file_infolist_files 接口,返回值为 UploadResult(file_id, provider, content_type, file_uri?, expires_at?)

create_resolver() 工厂函数把以上能力装配起来:传入 provider 名即可自动带上该 Provider 的默认上传阈值,prefer_uploadupload_threshold_bytesenable_cache 均可覆盖。

测试覆盖与延伸阅读

crewai-files 的测试位于 lib/crewai-files/tests,按模块划分:

  • test_resolver.py:解析决策树各分支(URL 引用、上传命中缓存、内联回退);
  • test_file_url.py:URL 来源的校验与抓取行为;
  • test_resolved.py:四种 ResolvedFile 形态(FileReference/InlineBase64/InlineBytes/UrlReference);
  • test_upload_cache.py:上传缓存的读写与过期;
  • tests/processing/test_processor.pytest_constraints.pytest_transformers.pytest_validators.py,覆盖模式调度、各 Provider 约束、图片缩放/压缩与 PDF/文本分片。

小结

crewai-files 的抽象层次可以概括为一句话:File 家族负责“装得进”(来源与类型),FileProcessor 负责“变得合规”(校验与变换),FileResolver 负责“送得出去”(URL/上传/内联三级投递)。在 Crew 层用 kickoff(input_files=...)、在 Task 层用 input_files=[...] 即可接入;而当你需要自定义 Provider 行为时,正确姿势是构造一份 ProviderConstraints 传给 FileProcessorFileResolver,而不是自行绕过该包重写文件编码逻辑。所有阈值、常量与默认值均可在 core/constants.pyprocessing/constraints.py 中查证,本文数据以当前仓库版本(crewai-files 1.15.18)为准。

登录后查看全文
热门项目推荐
相关项目推荐