Can you pass in pydantic models to a task context ...
# marvin-ai
j
Can you pass in pydantic models to a task context dict?
j
Yup, they are serialized into the agent's prompt using default pydantic string formatting. If you need custom serializing, you can change the model itself or just convert them to strings yourself!
j
ah, so I need some way to dump it into string format?
j
Only if you don’t like how pydantic dumps to string by default
Which I think includes all field names and values
j
this might be more of a python issue~ but is unhashable type error due to not freezing the pydantic model?
j
it's possible but it might be that we're inadvertently deduping with a set, in which case that's a CF error
can you share a traceback
This seems to run ok
Copy code
import controlflow as cf
from pydantic import BaseModel


class Person(BaseModel):
    name: str
    age: int


cf.run(
    "What's the person's name?",
    context=dict(person=Person(name="John", age=30)),
)
j
Copy code
import typing as t
from datetime import datetime

from pydantic import BaseModel

class Email(BaseModel):
    sender: str
    sent_at: datetime
    body: str
    subject: str


class EmailHistory(BaseModel):
    emails: t.List[Email]
Just a very basic example. I'm passing this into a @cf.flow method
Copy code
@cf.flow
    def process_email(email_history: EmailHistory):
         cf.run(...., context={email_history=email_history})
ah, darnit. πŸ™‚.
context=dict().....
j
ah!
that'll do it!
sometimes it just takes a good copy/paste πŸ™‚ happens to me more often than i care to admit haha
πŸ™‚ 1
@Jason question for you -- in the above example you pasted, the email history will actually be shown twice to the agent. Once because its provided as an arg to the flow (so its automatically put in a flow-wide context) and again since you passed it to the cf.run task. Obviously that's redundant so I want to solve it. The "clever" thing would be to dedupe redundant context items, which is fairly straightforward. However it makes me wonder if maybe automatically putting flow args in context is a little too magic and we should make that more explicit / opt-in. Curious for your thoughts / preferences here?
j
@Jeremiah That's a really good callout. That was actually something that I wasn't 100% certain about
if arguments are passed in at the flow level, does that mean there's no need to provide any context args in the individual Tasks?
πŸ‘ 1
I think either is fine. I like that the method level arguments are implicitly flow-wide. But I wasn't 100% sure still. Maybe its more of a documentation thing
btw, I really like controlflow!
marvin 1
j
Yes, the original thinking was that any args you pass to the flow are kind of like global config, so lets show them to all the tasks, but lately I've been wondering if that would make someone hesitate to pass "normal" arguments into the flow (like things that they actually need to process with python, that may not be relevant to their tasks)
Glad to hear it!
I think maybe the way to do this is to allow a special
flow_context
or
_context
(or somethign) kwarg to be passed whenever you call a flow. Another DX would be
Copy code
@flow(context_kwargs=['x', 'z'])
def demo(x, y, z):
    # x and z are automatically in context, y isnt
actually i kind of like that, it's explicit and opt-in but still lets you do this if you want
i think the explicit instruction is important so people dont accidentally double their token usage
j
Yes, I like that
b/c I am running into that same issue
where one of my args is not really a context arg.
I sort of worked around it by defining the cf.flow as an inner method
j
ok say no more the fact you're working around this implicit behavior automatically means its bad
I'll have this updated in the next release, though heads up it may technically be a breaking behavior hcange (though I think worthwhile)