介绍
Agent 框架 / 用于将 Pydantic 与 LLM 结合使用的垫片
Pydantic AI 是一个 Python Agent 框架,旨在减轻使用生成式 AI 构建生产级应用程序的痛苦。
FastAPI 通过提供创新且符合人体工程学的设计,彻底改变了 Web 开发,其基础是 Pydantic Validation。
同样,几乎所有 Python 中的 Agent 框架和 LLM 库都使用 Pydantic Validation,然而当我们在 Pydantic Logfire 中开始使用 LLM 时,我们找不到任何能给我们同样感觉的东西。
我们构建 Pydantic AI 的目标很简单:将 FastAPI 的那种感觉带入 GenAI 应用开发中。
为何使用 Pydantic AI
-
由 Pydantic 团队打造:由 Pydantic Validation(OpenAI SDK、Anthropic SDK、LangChain、LlamaIndex、AutoGPT、Transformers、CrewAI、Instructor 等众多项目的验证层)背后的团队打造。
-
模型无关:支持 OpenAI、Anthropic、Gemini、Deepseek、Ollama、Groq、Cohere 和 Mistral,并提供一个简单的接口来实现对其他模型的支持。
-
Pydantic Logfire 集成:与 Pydantic Logfire 无缝集成,用于对您的 LLM 驱动的应用程序进行实时调试、性能监控和行为跟踪。
-
类型安全:旨在使类型检查对您尽可能强大和信息丰富。
-
以 Python 为中心的设计:利用 Python 熟悉的控制流和 Agent 组合来构建您的 AI 驱动项目,使其易于应用您在任何其他(非 AI)项目中使用的标准 Python 最佳实践。
-
结构化响应:利用 Pydantic Validation 的强大功能来验证和结构化模型输出,确保响应在不同运行中保持一致。
-
依赖注入系统:提供一个可选的依赖注入系统,为您的 Agent 的系统提示、工具和输出验证器提供数据和服务。这对于测试和评估驱动的迭代开发非常有用。
-
流式响应:提供流式传输 LLM 响应的能力,并进行即时验证,确保实时访问经过验证的输出。
-
图支持:Pydantic Graph 提供了一种使用类型提示定义图的强大方式,这在标准控制流可能退化为意大利面条式代码的复杂应用中非常有用。
Hello World 示例
以下是 Pydantic AI 的一个最小示例
from pydantic_ai import Agent
agent = Agent( # (1)!
'google-gla:gemini-1.5-flash',
system_prompt='Be concise, reply with one sentence.', # (2)!
)
result = agent.run_sync('Where does "hello world" come from?') # (3)!
print(result.output)
"""
The first known use of "hello, world" was in a 1974 textbook about the C programming language.
"""
- 我们配置 Agent 使用 Gemini 1.5 的 Flash 模型,但您也可以在运行 Agent 时设置模型。
- 使用 Agent 的关键字参数注册一个静态系统提示。
- 同步运行 Agent,与 LLM 进行对话。
(这个例子是完整的,可以“按原样”运行)
这次交流应该非常简短:Pydantic AI 会将系统提示和用户查询发送给 LLM,模型将返回一个文本响应。
目前还不是很有趣,但我们可以轻松添加“工具”、动态系统提示和结构化响应来构建更强大的 Agent。
工具与依赖注入示例
这是一个使用 Pydantic AI 为银行构建支持 Agent 的简洁示例
from dataclasses import dataclass
from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext
from bank_database import DatabaseConn
@dataclass
class SupportDependencies: # (3)!
customer_id: int
db: DatabaseConn # (12)!
class SupportOutput(BaseModel): # (13)!
support_advice: str = Field(description='Advice returned to the customer')
block_card: bool = Field(description="Whether to block the customer's card")
risk: int = Field(description='Risk level of query', ge=0, le=10)
support_agent = Agent( # (1)!
'openai:gpt-4o', # (2)!
deps_type=SupportDependencies,
output_type=SupportOutput, # (9)!
system_prompt=( # (4)!
'You are a support agent in our bank, give the '
'customer support and judge the risk level of their query.'
),
)
@support_agent.system_prompt # (5)!
async def add_customer_name(ctx: RunContext[SupportDependencies]) -> str:
customer_name = await ctx.deps.db.customer_name(id=ctx.deps.customer_id)
return f"The customer's name is {customer_name!r}"
@support_agent.tool # (6)!
async def customer_balance(
ctx: RunContext[SupportDependencies], include_pending: bool
) -> float:
"""Returns the customer's current account balance.""" # (7)!
return await ctx.deps.db.customer_balance(
id=ctx.deps.customer_id,
include_pending=include_pending,
)
... # (11)!
async def main():
deps = SupportDependencies(customer_id=123, db=DatabaseConn())
result = await support_agent.run('What is my balance?', deps=deps) # (8)!
print(result.output) # (10)!
"""
support_advice='Hello John, your current account balance, including pending transactions, is $123.45.' block_card=False risk=1
"""
result = await support_agent.run('I just lost my card!', deps=deps)
print(result.output)
"""
support_advice="I'm sorry to hear that, John. We are temporarily blocking your card to prevent unauthorized transactions." block_card=True risk=8
"""
- 这个Agent 将作为银行的一线支持。Agent 在其接受的依赖类型和返回的输出类型方面是通用的。在这种情况下,支持 Agent 的类型为
Agent[SupportDependencies, SupportOutput]
。 - 这里我们配置 Agent 使用 OpenAI 的 GPT-4o 模型,您也可以在运行 Agent 时设置模型。
SupportDependencies
数据类用于将数据、连接和逻辑传递到模型中,这些信息在运行系统提示和工具函数时会用到。Pydantic AI 的依赖注入系统提供了一种类型安全的方式来自定义 Agent 的行为,在运行单元测试和评估时尤其有用。- 静态系统提示可以通过 Agent 的
system_prompt
关键字参数进行注册。 - 动态系统提示可以通过
@agent.system_prompt
装饰器注册,并且可以利用依赖注入。依赖项通过RunContext
参数传递,该参数使用上面的deps_type
进行参数化。如果这里的类型注解错误,静态类型检查器会捕获它。 tool
允许您注册函数,LLM 在响应用户时可能会调用这些函数。同样,依赖项通过RunContext
传递,任何其他参数都将成为传递给 LLM 的工具模式。Pydantic 用于验证这些参数,错误会返回给 LLM,以便其重试。- 工具的文档字符串也会作为工具的描述传递给 LLM。参数描述会从文档字符串中提取并添加到发送给 LLM 的参数模式中。
- 异步运行 Agent,与 LLM 进行对话,直到达成最终响应。即使在这种相当简单的情况下,Agent 也会在调用工具以获取输出时与 LLM 交换多条消息。
- Agent 的响应将保证是
SupportOutput
,如果验证失败,反思机制将意味着 Agent 会被提示重试。 - 输出将使用 Pydantic 进行验证,以保证它是一个
SupportOutput
。由于 Agent 是通用的,它也会被类型化为SupportOutput
,以帮助进行静态类型检查。 - 在实际用例中,您会向 Agent 添加更多工具和更长的系统提示,以扩展其所具备的上下文和可提供的支持。
- 这是一个数据库连接的简单示意,用于保持示例简短易读。实际上,您会连接到外部数据库(例如 PostgreSQL)以获取有关客户的信息。
- 这个 Pydantic 模型用于约束 Agent 返回的结构化数据。从这个简单的定义中,Pydantic 构建了 JSON Schema,它告诉 LLM 如何返回数据,并在运行结束时执行验证以保证数据的正确性。
完整的 bank_support.py
示例
为简洁起见,此处包含的代码不完整(缺少 DatabaseConn
的定义);您可以在这里找到完整的 bank_support.py
示例。
使用 Pydantic Logfire 进行检测
为了理解上述运行的流程,我们可以使用 Pydantic Logfire 观察 Agent 的运行情况。
为此,我们需要设置 logfire,并将以下内容添加到我们的代码中
...
from pydantic_ai import Agent, RunContext
from bank_database import DatabaseConn
import logfire
logfire.configure() # (1)!
logfire.instrument_asyncpg() # (2)!
...
support_agent = Agent(
'openai:gpt-4o',
deps_type=SupportDependencies,
output_type=SupportOutput,
system_prompt=(
'You are a support agent in our bank, give the '
'customer support and judge the risk level of their query.'
),
instrument=True,
)
- 配置 logfire,如果项目未设置,此操作将失败。
- 在我们的演示中,
DatabaseConn
使用asyncpg
连接到 PostgreSQL 数据库,因此使用logfire.instrument_asyncpg()
来记录数据库查询。
这样就足以让您看到 Agent 运行时的以下视图
请参阅监控和性能以了解更多信息。
llms.txt
Pydantic AI 文档以 llms.txt 格式提供。此格式在 Markdown 中定义,适用于大型语言模型。
提供两种格式
- llms.txt:一个包含项目简要描述以及文档不同部分链接的文件。该文件的结构在这里有详细描述。
- llms-full.txt:与
llms.txt
文件类似,但包含了每个链接的内容。请注意,此文件对于某些 LLM 可能过大。
截至今日,这些文件不能被 LLM 框架或 IDE 原生利用。或者,可以实现一个 MCP 服务器来正确解析 llms.txt
文件。
后续步骤
要亲自尝试 Pydantic AI,请按照示例中的说明操作。
阅读文档以了解更多关于使用 Pydantic AI 构建应用程序的信息。
阅读API 参考以了解 Pydantic AI 的接口。