Contexto
Experimento usando OpenAI - Assistants (Tools com LLM ) para um bot que faz agendamentos de consultas médicas com verificação de disponibilidade de agenda.
Exemplo da conversa do resultado do experimento:
USER> Olá! Gostaira de marcar uma consulta para João
BOT> Claro, posso ajudar com isso. Você tem alguma data e horário em mente para a consulta? E qual seria o procedimento? (consulta, exame, etc..)
USER> Uma consulta mesmo, as 10h na terça feira
BOT> Infelizmente, a Dra. Maria está disponível apenas à tarde na terça-feira, 6 de agosto de 2024. Você gostaria de sugerir outro horário ou talvez escolher outra data?
USER> pode ser as 14h então
BOT> A consulta para João foi agendada com sucesso para o dia 6 de agosto de 2024, às 14h. Se precisar de mais alguma coisa, estarei à disposição!
Implementação
Dependências usando pipenv
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
requests = "*"
python-dotenv = "*"
openai = "*"
icecream = "*"
prompt-toolkit = "*"
ipdb = "*"
[dev-packages]
flake8 = "*"
[requires]
python_version = "3.10"
Código
from datetime import date
import json
import logging
from prompt_toolkit import PromptSession
from prompt_toolkit.history import FileHistory
from openai import OpenAI
from icecream import ic
logger = logging.getLogger(__name__)
client = OpenAI()
#current_date = date.today().isoformat()
current_date = '2024-08-03'
model = 'gpt-4o'
prompt_instructions = f'''Você é um secretário responsável por gerenciar a agenda de uma médica.
Auxilie a pessoa paciente a marcar uma consulta com a Dra. Maria, pergutando o que
for necessário para marcar a consulta. Basicamente uma data e qual o procedimento
(consulta, exame, etc), não esqueça de confirmar qual o nome do paciente.
Considere a data de hoje como {current_date}.'''
assistant = client.beta.assistants.create(
name='Gustavo, secretário assistente para marcar consultas',
instructions=prompt_instructions,
tools=[
{
"type": "function",
"function": {
"name": "schedule_appointment",
"description": "Agenda uma consulta com a médica para o paciente.",
"parameters": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Nome da pessoa paciente",
},
"date_and_time": {
"type": "string",
"description": "Data e hora desejada para a consulta, YYYY-MM-DD HH:MM",
},
'procedure': {
'type': 'string',
'description': 'Procedimento que será realizado (exame, consulta, etc..).'
}
},
"required": ["date_and_time", "procedure"]
}
}
},
{
"type": "function",
"function": {
"name": "get_calendar_availability",
"description": "Retorna a disponibilidade da médica na agenda dada uma data.",
"parameters": {
"type": "object",
"properties": {
"date": {
"type": "string",
"description": "A data (YYYY-MM-DD) para verificar a disponibilidade.",
},
},
"required": ["date_period"]
}
}
},
],
model=model,
)
def get_calendar_availability(date):
results = {
'2024-08-05': 'disponivel o dia todo',
'2024-08-06': 'disponivel apenas a tarde',
'2024-08-07': 'indisponivel',
'2024-08-08': 'disponivel apenas de manha',
'2024-08-09': 'disponivel o dia todo',
}
if date not in results:
result = f'em {date} o médico não está disponível'
else:
result = f'em {date} o médico está {results[date]}'
return result
def schedule_appointment(name, date_and_time, procedure):
print(f'Agendando consulta para o paciente {name}, em', date_and_time, 'com procedimento:', procedure)
return f'Consulta agendada para o paciente {name}, {date_and_time} com procedimento {procedure}'
tools_available = {
'get_calendar_availability': get_calendar_availability,
'schedule_appointment': schedule_appointment,
}
def main():
'''Simple method to show current assistant'''
exit_strings = set(['exit', 'quit', 'bye', 'goodbye', 'sair'])
session = PromptSession()
our_history = FileHistory(".example-history-file")
session = PromptSession(history=our_history)
text = session.prompt('USER> ')
thread = client.beta.threads.create()
while text.lower() not in exit_strings:
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=text)
running = client.beta.threads.runs.create_and_poll(
thread_id=thread.id,
assistant_id=assistant.id)
while running.status == 'requires_action':
tool_outputs = []
for tool_call in running.required_action.submit_tool_outputs.tool_calls:
arguments = json.loads(tool_call.function.arguments)
result = tools_available[tool_call.function.name](**arguments)
tool_outputs.append({
'tool_call_id': tool_call.id,
'output': result
})
try:
print('Tools outputs:', tool_outputs)
running = client.beta.threads.runs.submit_tool_outputs_and_poll(
thread_id=thread.id,
run_id=running.id,
tool_outputs=tool_outputs)
print("Tool outputs submitted successfully.")
except Exception as e:
print("Failed to submit tool outputs:", e)
while running.status != 'completed':
print('status:', running.status)
messages = [msg for msg in client.beta.threads.messages.list(
thread_id=thread.id)]
content = messages[0].content
print('BOT>', '\n'.join([c.text.value for c in content]))
text = session.prompt('USER> ')
if __name__ == '__main__':
main()