-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Closed
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation
Description
Currently retrievers are tools that are expected to be benign, e.g. have no side effects, so you don't care if the models chooses to call them or not.
Technically there's nothing to stop you from having retrievers with side-effects, and you could even look in message history to see if they were called.
But what is our recommend way of using tools that do something?
I would suggest something like this:
from typing import Literal
from pydantic import BaseModel
from pydantic_ai import Agent
class CreateTicket(BaseModel):
title: str
description: str
async def run(self):
...
class DeleteTicket(BaseModel):
reason: str
async def run(self):
...
class ChangeSeatTicket(BaseModel):
row: int
seat: Literal['A', 'B', 'C', 'D']
async def run(self):
...
ticket_agent = Agent(result_type=CreateTicket | DeleteTicket | ChangeSeatTicket)
async def main():
result = await ticket_agent.run('I would like to create a ticket')
await result.data.run()This looks like a bit more logic, but it has some nice advtanges:
- you can be very clear about when/if the action is called
- it can take more arguments including agents, or dependencies that let you call other agents
- with this already, each pydantic base model is registered as a tool in the LLM, so it's just as easy for the model
- you could introduce arbitrary extra logic and control flow to
runwithout it being hidden in the "magic" of PydanticAI
RamiAwar and SuperMuel
Metadata
Metadata
Assignees
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation