from stringdale import Define,V,E, Condition
from stringdale.chat import Chat
from pydantic import BaseModel,Field
from typing import Optional
Filling out missing user data
class User(BaseModel):
str] = Field(None, description='The name of the user')
name: Optional[int] = Field(None, description='The age of the user')
age: Optional[str] = Field(None, description='The email of the user') email: Optional[
= Chat(
ask_missing_data ='gpt-4o-mini',
model=[
messages'role':'system','content':'''
{ You are a helpful assistant asks the user for missing information.
Do not ask for keys if they are not a part of the missing keys
Ask the user for the following missing keys:
{{missing_keys}}
'''}])
= Chat(
format_new_info ='gpt-4o-mini',
model=[
messages'role':'system','content':'''
{ You are a helpful assistant that gets user data and makes sure it is complete.
If you are not sure that you were given the relevant information, put None in the relevant field.
Fill part of the missing keys based on the user data.
If the user didnt provide info an a given missing key, leave it empty
{% if current_info %}
The information we have so far is:
{{current_info}}
{% endif %}
The missing keys are:
{{missing_keys}}
'''},
'role':'user','content':'{{input}}'},
{
],=User) output_schema
class MissingKeys():
def __init__(self,keys):
self.keys = keys
def get_missing_keys(self,obj):
return [key for key in self.keys if getattr(obj,key,None) is None]
def has_missing_keys(self,obj):
return len(self.get_missing_keys(obj)) > 0
= MissingKeys(['name','age']) missing
with Define('collect user data',type='decision') as UserQA:
'Start',
V(=[
outputs'get_missing_keys',missing.has_missing_keys),
('End',),
('state/current_info',)
(
])
'get_missing_keys',missing.get_missing_keys,
V(=[
outputs'ask_missing_data(missing_keys)',
'state/missing_keys'
])
'ask_missing_data',ask_missing_data,
V(=['state/current_info(current_info)'],
inputs=['break'] )
outputs
'break',is_break=True,outputs=['format_new_info(input)'])
V(
'format_new_info',format_new_info,
V(=[
inputs'state/current_info(current_info)',
'state/missing_keys(missing_keys=.)'
],=[
outputs'get_missing_keys(0=content)',Condition(missing.has_missing_keys,'(0=content)')),
('End',
'state/current_info'
])
='TB') UserQA.draw(direction
= UserQA()
d
for trace in d.run(None):
trace.pprint() d.output
Node Start:
{'input': {0: None}, 'output': None}
================================================================================
Node get_missing_keys:
{'input': {0: None}, 'output': ['name', 'age']}
================================================================================
Node ask_missing_data:
{ 'input': {'current_info': None, 'missing_keys': ['name', 'age']},
'output': { 'content': 'Please provide your name and age.',
'meta': {'input_tokens': 151, 'output_tokens': 11},
'role': 'assistant'}}
================================================================================
{'role': 'assistant',
'content': 'Please provide your name and age.',
'meta': {'input_tokens': 151, 'output_tokens': 11}}
for trace in d.run('my name is brian'):
trace.pprint() d.output
Node break:
{'input': {0: 'my name is brian'}, 'output': 'my name is brian'}
================================================================================
Node format_new_info:
{ 'input': { 'current_info': None,
'input': 'my name is brian',
'missing_keys': ['name', 'age']},
'output': { 'content': User(name='brian', age=None, email=None),
'meta': {'input_tokens': 342, 'output_tokens': 22},
'role': 'assistant'}}
================================================================================
Node get_missing_keys:
{'input': {0: User(name='brian', age=None, email=None)}, 'output': ['age']}
================================================================================
Node ask_missing_data:
{ 'input': { 'current_info': { 'content': User(name='brian', age=None, email=None),
'meta': { 'input_tokens': 342,
'output_tokens': 22},
'role': 'assistant'},
'missing_keys': ['age']},
'output': { 'content': 'Please provide your age.',
'meta': {'input_tokens': 148, 'output_tokens': 9},
'role': 'assistant'}}
================================================================================
{'role': 'assistant',
'content': 'Please provide your age.',
'meta': {'input_tokens': 148, 'output_tokens': 9}}
for trace in d.run('25 yo'):
trace.pprint() d.output
Node break:
{'input': {0: '25 yo'}, 'output': '25 yo'}
================================================================================
Node format_new_info:
{ 'input': { 'current_info': { 'content': { 'age': None,
'email': None,
'name': 'brian'},
'meta': { 'input_tokens': 342,
'output_tokens': 22},
'role': 'assistant'},
'input': '25 yo',
'missing_keys': ['age']},
'output': { 'content': User(name='brian', age=25, email=None),
'meta': {'input_tokens': 388, 'output_tokens': 23},
'role': 'assistant'}}
================================================================================
Node End:
{ 'input': { 0: { 'content': User(name='brian', age=25, email=None),
'meta': {'input_tokens': 388, 'output_tokens': 23},
'role': 'assistant'}},
'output': { 'content': User(name='brian', age=25, email=None),
'meta': {'input_tokens': 388, 'output_tokens': 23},
'role': 'assistant'}}
================================================================================
{'role': 'assistant',
'content': User(name='brian', age=25, email=None),
'meta': {'input_tokens': 388, 'output_tokens': 23}}