LLM Agent 框架对比分析
Related topics: [[republic-architecture]], [[pydantic-ai-patterns]], [[litai-design]], [[kimi-cli-structure]]
Overview
本文对比分析四个 Python LLM/Agent 框架的设计理念与实现差异:
- LitAI - Lightning AI 的 LLM router + minimal agent framework
- Pydantic AI - Pydantic 官方的 GenAI agent framework
- Republic - Tape-first LLM client (derived from LitAI)
- Kimi CLI - Moonshot AI 的终端 AI agent
1. LLM/VLM 输入输出处理
LitAI: 统一路由 + 后台加载
# 核心: 后台线程预加载模型,同步/异步统一接口
class LLM:
def __init__(self):
threading.Thread(target=self._load_models, daemon=True).start()
def chat(self, prompt, images=None, stream=False):
self._wait_for_model() # 等待后台加载
# 支持 images 参数处理 VLM 输入
特点:
- 后台线程预加载模型缓存
- 统一的
chat()方法处理文本和多模态 images参数支持List[str]或str- 返回
str或Iterator[str](流式)
Pydantic AI: 类型安全 + 结构化输出
# 核心: 泛型 Agent[AgentDepsT, OutputDataT]
class AbstractAgent(Generic[AgentDepsT, OutputDataT]):
def run(self, user_prompt: str | Sequence[UserContent]) -> AgentRunResult[OutputDataT]:
# UserContent = str | ImageUrl | AudioUrl | VideoUrl | BinaryContent | DocumentUrl
特点:
- 强类型泛型系统
Agent[AgentDepsT, OutputDataT] UserContent支持多种多模态类型(ImageUrl, AudioUrl, VideoUrl, BinaryContent, DocumentUrl)output_type参数支持 Pydantic 模型进行结构化输出- 消息历史使用
ModelMessage类型化系统
Republic: 结构化输出 + Tape 记录
# 核心: 结构化结果 + 错误分类
@dataclass(frozen=True)
class ToolAutoResult:
kind: Literal["text", "tools", "error"]
text: str | None
tool_calls: list[dict[str, Any]]
tool_results: list[Any]
error: ErrorPayload | None
特点:
StructuredOutput返回类型,始终包含 error 信息ErrorKind枚举分类所有错误类型TapeEntry记录所有输入输出TapeContext支持上下文窗口管理
Kimi CLI: 运行时组合 + MCP 协议
# 核心: Runtime 组合多个组件
@dataclass(slots=True, kw_only=True)
class Runtime:
config: Config
oauth: OAuthManager
llm: LLM | None
session: Session
builtin_args: BuiltinSystemPromptArgs
denwa_renji: DenwaRenji
approval: Approval
labor_market: LaborMarket
特点:
Runtimedataclass 组合所有运行时依赖BuiltinSystemPromptArgs注入系统变量(时间、工作目录等)- 支持 MCP (Model Context Protocol) 工具
- Jinja2 模板渲染系统提示
2. Tool Trigger 和 Callback 机制
LitAI: 装饰器 + 手动/自动模式
@tool
def get_weather(location: str):
return f"The weather in {location} is sunny"
# 方式 A: 自动执行
result = llm.chat("What's the weather?", tools=[get_weather], auto_call_tools=True)
# 方式 B: 手动控制
chosen_tool = llm.chat("What's the weather?", tools=[get_weather])
result = llm.call_tool(chosen_tool, tools=[get_weather])
设计哲学: "Zero magic, just plain Python"
@tool装饰器转换函数LitTool基类支持有状态工具auto_call_tools=False默认手动控制
Pydantic AI: 依赖注入 + 装饰器注册
class SupportDependencies:
customer_id: int
db: DatabaseConn
support_agent = Agent(deps_type=SupportDependencies, output_type=SupportOutput)
@support_agent.tool
async def customer_balance(ctx: RunContext[SupportDependencies], include_pending: bool) -> float:
return await ctx.deps.db.customer_balance(id=ctx.deps.customer_id)
设计哲学: "FastAPI feeling"
RunContext泛型携带依赖@agent.tool装饰器注册工具ToolManager管理验证和执行- 支持
parallel_execution_mode(parallel/sequential) - Human-in-the-loop approval:
requires_approval
Republic: ToolExecutor + ToolContext
class ToolExecutor:
def execute(self, response, tools, *, context: ToolContext | None) -> ToolExecution:
for tool_response in tool_calls:
result = self._handle_tool_response(tool_response, tool_map, context)
设计哲学: "Tools without magic"
ToolContext传递上下文信息ToolSet区分 runnable 和 non-runnable 工具- 三种模式:
tool_calls()/run_tools()/stream_events() ToolCallAssembler处理流式工具调用增量
Kimi CLI: Toolset + 依赖注入
@dataclass(frozen=True, slots=True, kw_only=True)
class Agent:
name: str
system_prompt: str
toolset: Toolset
runtime: Runtime
# 工具加载
tool_deps = {
KimiToolset: toolset,
Runtime: runtime,
Session: session,
Approval: approval,
}
toolset.load_tools(tools, tool_deps)
设计哲学: "Production CLI agent"
KimiToolset封装工具加载Approval系统处理危险操作确认LaborMarket管理子 agent- 支持 MCP server 工具
3. 多模型输出 Merge 策略
LitAI: Fallback 链式尝试
llm = LLM(
model="openai/gpt-5",
fallback_models=["google/gemini-2.5-flash", "anthropic/claude-3-5-sonnet"],
max_retries=4,
)
# 同一对话使用不同模型
llm.chat("Is this a number?", model="google/gemini-2.5-flash", conversation="story")
llm.chat("Create a story about that number", conversation="story") # 回到主模型
特点:
fallback_models链式降级max_retries单模型重试- 按请求切换模型
- 无内置 merge 策略,每个模型独立调用
Pydantic AI: Fallback Model 包装
# pydantic_ai/models/fallback.py
class FallbackModel:
"""尝试多个模型直到成功"""
特点:
FallbackModel作为模型包装器- 验证失败会重试而非切换模型
- 结构化输出强制验证
Republic: 同 LitAI 模式
llm = LLM(
model="openrouter:openrouter/free",
fallback_models=fallback_models,
max_retries=3,
)
特点:
- 继承 LitAI 的 fallback 机制
LLMCore统一处理重试逻辑
Kimi CLI: 单一 LLM 实例
@dataclass(slots=True, kw_only=True)
class Runtime:
llm: LLM | None # 单一 LLM 实例
特点:
- 运行时只持有一个 LLM 实例
- 通过
LaborMarket管理子 agent 并行 - 无内置模型 merge
4. 独特设计模式和理念
LitAI: Zero Magic Philosophy
✅ Use any AI model (OpenAI, etc.) ✅ Unified billing dashboard
✅ Auto retries and fallback ✅ No MLOps glue code
✅ Tool use ✅ Start instantly
核心模式:
- Agentic if statement: LLM 参与条件判断
- Background model loading: 线程预加载提升响应
- Unified billing: Lightning AI 统一计费
Pydantic AI: Type-Safe Agent Framework
✅ Built by Pydantic Team ✅ Model-agnostic
✅ Seamless Observability ✅ Fully Type-safe
✅ Powerful Evals ✅ MCP, A2A, and UI
核心模式:
- Graph-based execution:
pydantic_graph支持复杂流程 - Durable execution: 支持 Temporal/Prefect/DBOS
- Stream events:
AgentStreamEvent完整事件流 - OpenTelemetry: 内置可观测性
Republic: Tape-First Architecture
✅ Plain Python ✅ Structured Result
✅ Tools without magic ✅ Tape-first memory
✅ Event streaming ✅ Error classification
核心模式:
- Tape-first: 所有交互记录为
TapeEntry - ErrorKind: 结构化错误分类
- Anchor/Handoff: 上下文窗口管理
- Event streaming:
StreamEvents完整事件流
Kimi CLI: Terminal-First Agent
✅ Shell command mode ✅ VS Code extension
✅ IDE integration (ACP) ✅ Zsh integration
✅ MCP support ✅ Skills system
核心模式:
- DenwaRenji: 电话交接模式(子 agent 协作)
- LaborMarket: 劳动力市场(动态/固定子 agent)
- Skills: 技能发现和加载
- Approval: 危险操作审批系统
5. Middleware 和 Streaming TTS 扩展性
LitAI 扩展方案
# 现有 streaming
for chunk in llm.chat("hello", stream=True):
print(chunk, end="", flush=True)
# 添加 TTS Middleware 的可能方式
class TTSStreamingMiddleware:
def __init__(self, tts_client):
self.tts = tts_client
def wrap_stream(self, stream):
for chunk in stream:
self.tts.speak_async(chunk) # 异步 TTS
yield chunk
扩展点:
stream=True返回Iterator[str]- 无内置 middleware 机制
- 需要包装返回的 iterator
Pydantic AI 扩展方案
# 现有 streaming events
async for event in agent.run_stream_events('Hello'):
if isinstance(event, PartDeltaEvent):
# 实时处理文本增量
pass
# 添加 TTS Middleware
async def tts_event_handler(ctx: RunContext, events: AsyncIterable[AgentStreamEvent]):
async for event in events:
if isinstance(event, PartDeltaEvent) and isinstance(event.delta, TextPartDelta):
await tts_client.speak(event.delta.content_delta)
yield event
agent = Agent('openai:gpt-5.2', event_stream_handler=tts_event_handler)
扩展点:
event_stream_handler参数run_stream_events()返回完整事件流AgentStreamEvent包含PartStartEvent,PartDeltaEvent,PartEndEvent- 天然支持 middleware 模式