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处理流式工具调用增量