CubePi vs PydanticAI
PydanticAI 和 CubePi 共享同一基础 —— Pydantic v2、asyncio 原生设计,以及"Agent 应该是普通 Python 而非基于图的状态机"的理念。两者的分歧在于在此之上构建的抽象。
PydanticAI 聚焦于通过 `RunContext` 实现类型安全的结构化输出和依赖注入。CubePi 聚焦于持久化多轮对话、可组合的中间件钩子和厂商中立的 OpenTelemetry 追踪。以下是两者的详细对比。
并排对比
| PydanticAI | CubePi | |
|---|---|---|
| 核心抽象 | 带依赖注入的类型化 Agent[OutputType] | 有状态 Agent,核心为 while 循环 —— 通过中间件可组合 |
| 结构化输出 | Agent 级 —— Agent[Deps, OutputType] 把整个 run 类型化;支持 NativeOutput / PromptedOutput / ToolOutput 三种模式 | 调用级 —— BoundModel.generate_structured(Pydantic, …) 返回已校验的实例;底层走 tool-output 模式(与 pydantic-ai 默认相同) |
| 依赖注入 | RunContext[Deps] —— 运行时注入依赖 | 通过工具闭包或中间件传递上下文;无 DI 容器 |
| Checkpointing | 无内置持久化层 | 追加式 —— O(1) DB I/O;后端:memory、SQLite、Postgres、MySQL |
| 流式输出 | async for chunk in agent.run_stream() | async for event in stream —— 11 种类型化事件,含工具生命周期 |
| 多 Provider | Anthropic、OpenAI、Gemini、Groq 等 | 内置 Anthropic 和 OpenAI;Provider 协议支持自定义后端 |
| Provider 故障转移 | 无内置支持 | FallbackBoundModel —— 限速或故障时自动切换 |
| 可观测性 | Logfire(Pydantic 自有平台) | 原生 OpenTelemetry —— GenAI 语义约定,OTLP / JSONL;厂商中立 |
| 中间件 | 无中间件系统 | 8 个类型化钩子,带声明式组合规则 |
| 测试 | TestModel 用于确定性测试 | FauxProvider —— 真实流式仿真,无需 API Key |
| 核心依赖 | pydantic-ai-slim + provider 适配器 | pydantic、anthropic、openai —— 其余皆为可选 extra |
结构化输出在 API 里的位置
两者都把结构化输出做成一等公民、并以 Pydantic 为校验后端。CubePi 0.10 加了 `BoundModel.generate_structured(Pydantic, ...)`:它从模型的 JSON schema 注入一个合成 tool、通过 `tool_choice` 强制调用、再用 `output_type.model_validate()` 校验回来——这正是 PydanticAI 默认的 `ToolOutput` 模式。
真正的差异是「契约绑在哪个抽象上」。PydanticAI 把输出类型抬到 Agent 本身:`Agent[Deps, Sentiment].run(...)` 把整个 run 的类型签到 `Sentiment`,且除了 `ToolOutput` 之外还提供 `NativeOutput`(Provider 的 `response_format` / JSON schema 端点)和 `PromptedOutput` 两种备选。CubePi 保持 agent 循环为自由文本 + 工具调用,把结构化输出做成一次性的 `BoundModel` 调用——适合作为多轮 agent 里的「抽取子例程」按需取用。
CubePi 的主轴在另一边:可在重启后存活的多轮对话。追加式 checkpointing 让单线程的写入成本不随对话长度增长,在你有数千个并发长存会话时尤其重要。
依赖注入 vs 中间件
PydanticAI 的 `RunContext[Deps]` 是将服务(数据库、HTTP 客户端)注入工具函数的简洁模式。CubePi 通过闭包实现同样效果 —— 在定义工具函数时捕获依赖 —— 无需学习新抽象。
CubePi 在横切关注点上增加了结构:中间件钩子(`before_tool_call`、`transform_context`、`should_stop_after_turn` 等)让你在不触碰核心 agent 循环的情况下添加限速、安全检查、上下文压缩或子 Agent 编排。
可观测性:Logfire vs 厂商中立的 OTel
PydanticAI 与 Logfire(Pydantic 自有的可观测性平台)集成。如果 Logfire 适合你的技术栈,效果很好。CubePi 输出带有 GenAI 语义约定属性的标准 OpenTelemetry span,可以落入任何 OTLP 兼容后端 —— Jaeger、Grafana Tempo、Honeycomb、Datadog、AWS X-Ray —— 无厂商依赖。`cubepi trace` CLI 也可以让你在没有后端的情况下从 JSONL 文件本地检查追踪。
PydanticAI 更适合的场景
如果你希望 agent 本身被它的输出类型化(`Agent[Deps, OutputType]`)、需要 Provider 原生 JSON-schema 端点(`NativeOutput`)而不是 CubePi 现在用的 tool-output 模式、或者你已经在 Logfire 上希望紧密集成,那么 PydanticAI 是更强的选择。当你需要生产级多轮持久化、可组合中间件、Provider 故障转移或厂商中立可观测性,并且能接受用 `BoundModel.generate_structured(...)` 作为一次性子例程获取已校验的 Pydantic 实例时,选择 CubePi。