多模型 Provider 层
学习目标
理解 CrewAI 如何统一管理 20+ LLM 提供商,包括原生 SDK 直连、Prompt 缓存断点标记、各提供商的结构化输出策略。
项目实践
统一抽象层
BaseLLM 是所有提供商的抽象基类:
- 抽象方法
call()定义同步调用契约 - 内置 token 用量追踪(
_token_usage) - 事件发射:call_started / call_completed / call_failed / stream_chunk / thinking_chunk
llm_call_context()上下文管理器为每次调用生成唯一call_id- Hook 集成:
_invoke_before_llm_call_hooks()/_invoke_after_llm_call_hooks()
模型注册与路由
通过字符串 "provider/model" 自动路由到对应 Provider 类:
# 伪代码llm = LLM(model="openai/gpt-4o") # → OpenAICompletionllm = LLM(model="anthropic/claude-opus-4-5") # → AnthropicCompletionllm = LLM(model="bedrock/anthropic.claude-sonnet-4-5-v1") # → BedrockCompletion模型枚举注册表(constants.py)定义了所有支持的提供商和模型:OpenAI、Anthropic、Gemini、Azure、Bedrock、OpenRouter、DeepSeek、Ollama、vLLM 等。
各提供商特点
OpenAI:
- 支持 Chat Completions API 和 Responses API(通过
api字段切换) - Responses API 特性:内置工具(web_search、file_search、code_interpreter)、自动链接、ZDR 推理链
Anthropic:
- Thinking 配置(enabled/disabled + budget_tokens)
- Tool search 配置(regex/bm25 模式)
- Claude 4.5+ 模型的原生结构化输出支持(
structured-outputs-2025-11-13beta) - Prompt 缓存:在内容块上打 cache control 标记
Gemini:
- Vertex AI 双认证模式(API key vs ADC)
- Gemini 2.0 JSON schema 兼容性的属性排序
- gemini-2.5+ 模型的自动 thinking 配置
Bedrock:
- Converse API 跨所有 Bedrock 模型的统一接口
- Guardrail 配置支持
- 模型特定对话格式处理(Cohere 要求 user 消息在最后)
Prompt 缓存断点
mark_cache_breakpoint() 在消息上打缓存断点标记,使得 Anthropic 的 prefix caching 可以在断点处结束缓存:
message = mark_cache_breakpoint(message)结构化输出策略
各提供商使用不同的结构化输出 API:
| 提供商 | 方法 |
|---|---|
| OpenAI | beta.chat.completions.parse() |
| Anthropic | structured-outputs-2025-11-13 beta |
| Gemini | response_schema (1.5) / response_json_schema (2.0+) |
问题与规避
不同提供商的停止词处理差异
- OpenAI、Anthropic、Gemini 的停止词处理方式不同
- 对策:通过
_apply_stop_words()实现位置截断,per-provider 适配
Bedrock 的异步支持
- Bedrock 使用
aiobotocore和AsyncExitStack实现异步 - 陷阱:
AsyncExitStack需要在上下文管理器中使用,否则连接可能泄露
Responses API vs Chat Completions
- OpenAI 的 Responses API 功能更丰富但成本更高
- 对策:通过
api字段切换,简单任务用 Chat Completions
设计取舍
原生 SDK 直连 vs 统一代理层
- CrewAI 选择各提供商直接使用各自的原生 SDK(OpenAI SDK、Anthropic SDK 等)
- 优势:功能完整、性能优、及时跟进各提供商的新特性
- 代价:需要在每个提供商中实现相同的功能(流式、结构化输出、工具调用)
- 替代方案:使用统一代理层(如 litellm)——代码量更少但功能受限
参考来源
- 源码验证:
lib/crewai/src/crewai/llms/base_llm.py - 源码验证:
lib/crewai/src/crewai/llms/constants.py - 源码验证:
lib/crewai/src/crewai/llms/providers/anthropic/completion.py - 源码验证:
lib/crewai/src/crewai/llms/cache.py