Agente-Turistico / calendar_tools.py
mariemerenc's picture
Upload 15 files
b2437ae verified
import json
import time
from pydantic import BaseModel, Field, ValidationError
from typing import List
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import ChatPromptTemplate
from google_apis import create_service
from langchain_google_genai import (
ChatGoogleGenerativeAI,
HarmBlockThreshold,
HarmCategory,
)
client_secret = 'client_secret.json'
class Evento(BaseModel):
calendar_id: str = Field(default="primary", description="Identificador do calendário do Google Agenda onde o evento será criado. Por padrão, utiliza o calendário principal do usuário ('primary'). Para usar um calendário diferente, forneça o ID do calendário específico.")
summary: str = Field(description="Título ou resumo conciso do evento, que será exibido no Google Agenda.")
location: str = Field(description="Localização do evento. Pode ser um endereço físico ou um nome de local.")
description: str = Field(description="Descrição detalhada do evento, incluindo informações adicionais, agenda, objetivos.")
start: str = Field(description="Data e hora de início do evento no formato ISO 8601 (Exemplo: '2023-10-27T10:00:00').")
end: str = Field(description="Data e hora de término do evento no formato ISO 8601 (Exemplo: '2023-10-27T11:00:00').")
timezone: str = Field(default="America/Fortaleza", description="Fuso horário do evento, utilizando a nomenclatura da IANA Time Zone Database (e.g., 'America/Sao_Paulo', 'Europe/London'). O padrão é 'America/Fortaleza'.")
def construct_google_calendar_client(client_secret):
"""
Constrói um cliente para a API Google Calendar.
Parâmetros:
- client_secret (str): O caminho para o arquivo client secret JSON.
Retorna:
- service: A instância de serviço com o API do Google Calendar.
"""
API_NAME = 'calendar'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/calendar']
service = create_service(client_secret, API_NAME, API_VERSION, SCOPES)
return service
calendar_service = construct_google_calendar_client(client_secret)
def create_calendar(calendar_name):
"""
Criar uma nova lista de calendários.
Parâmetros:
- calendar_name (str): O nome da nova lista de calendário.
Retorno:
- dict: Um dicionário contendo o ID da nova lista de calendário.
"""
calendar_name = calendar_name.replace("'", "").replace('"', "")
calendar_list = {
'summary': calendar_name
}
created_calendar_list = calendar_service.calendars().insert(body=calendar_list).execute()
return created_calendar_list
def list_calendar_list(max_capacity=200):
"""
Lista todas as listas de calendários disponíveis, com limite de capacidade.
Parâmetros:
- max_capacity (int, opcional): O número máximo de calendários a serem retornados.
Padrão: 200.
Retorna:
- list: Uma lista de dicionários, onde cada dicionário contém os detalhes
de um calendário (ID, nome e descrição).
"""
if isinstance(max_capacity, str):
max_capacity = int(max_capacity)
all_calendars = []
all_calendars_cleaned = []
next_page_token = None
capacity_tracker = 0
while True:
calendar_list = calendar_service.calendarList().list(
maxResults = min(200, max_capacity - capacity_tracker),
pageToken = next_page_token
).execute()
calendars = calendar_list.get('items', [])
all_calendars.extend(calendars)
capacity_tracker += len(calendars)
if capacity_tracker >= max_capacity:
break
next_page_token = calendar_list.get('nextPageToken')
if not next_page_token:
break
for calendar in all_calendars:
all_calendars_cleaned.append(
{
'id': calendar['id'],
'name': calendar['summary'],
'description': calendar.get('description', '')
})
return all_calendars_cleaned
def list_calendar_events(calendar_id, max_capacity=20):
"""
Lista os eventos de um calendário específico.
Parâmetros:
- calendar_id (str): O ID do calendário para listar os eventos.
- max_capacity (int, opcional): O número máximo de eventos a serem retornados.
Padrão: 20.
Retorna:
- list: Uma lista de dicionários contendo os detalhes dos eventos.
"""
if isinstance(max_capacity, str):
max_capacity = int(max_capacity)
all_events = []
next_page_token = None
capacity_tracker = 0
while True:
events_list = calendar_service.events().list(
calendarId=calendar_id,
maxResults=min(250, max_capacity - capacity_tracker),
pageToken=next_page_token
).execute()
events = events_list.get('items', [])
all_events.extend(events)
capacity_tracker += len(events)
if capacity_tracker >= max_capacity:
break
if not next_page_token:
break
return all_events
def extract_event_parameters(query):
"""
Extrai parâmetros de um evento a partir de uma descrição em linguagem natural.
Esta função utiliza um modelo de linguagem grande para interpretar a descrição do evento
fornecida e extrair informações como resumo, local, descrição, horário de início e fim,
e fuso horário. A resposta é formatada como um JSON de acordo com o esquema definido pela
classe `Evento`.
Args:
query (str): A descrição do evento em linguagem natural.
Exemplo: "Marcar reunião com o time de marketing amanhã às 10h na sala de conferência."
Returns:
str: Uma string JSON contendo os parâmetros extraídos do evento, ou None se a extração falhar.
O JSON terá a seguinte estrutura:
{
"calendar_id": "ID do calendário Google (padrão: 'primary')",
"summary": "Resumo do evento",
"location": "Local do evento",
"description": "Descrição do evento",
"start": "Hora de início do evento",
"end": "Hora de término do evento",
"timezone": "Fuso horário do evento (padrão: 'America/Fortaleza')"
}
"""
llm = ChatGoogleGenerativeAI(
model="gemini-1.5-flash",
convert_system_message_to_human=True,
handle_parsing_errors=True,
temperature=0.6,
max_tokens= 1000,
safety_settings = {
HarmCategory.HARM_CATEGORY_HARASSMENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
HarmCategory.HARM_CATEGORY_HATE_SPEECH: HarmBlockThreshold.BLOCK_ONLY_HIGH,
HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT: HarmBlockThreshold.BLOCK_ONLY_HIGH,
},
)
parser = PydanticOutputParser(pydantic_object=Evento)
prompt = ChatPromptTemplate.from_messages([
("system", "Você é um assistente especialista em extrair informações de eventos de textos. Extraia os parâmetros necessários para criar um evento, incluindo data e hora de início e fim. Retorne a resposta formatada em JSON de acordo com o esquema fornecido.\n\n{format_instructions}\n"),
("human", "{user_query}")
])
chain = prompt | llm | parser
resposta = chain.invoke({
"language": "Portuguese",
"user_query": query,
"format_instructions": parser.get_format_instructions(),
})
resposta_dict = {
'summary': resposta.summary,
'location': resposta.location,
'description': resposta.description,
'start': {
"dateTime": resposta.start,
"timeZone": resposta.timezone
},
'end': {
"dateTime": resposta.end,
"timeZone": resposta.timezone
},
'attendees': []
}
resposta_json = json.dumps(resposta_dict, ensure_ascii=False)
return resposta.calendar_id, resposta_json
def insert_calendar_event(event):
"""
Insere um evento em um calendário Google.
Parâmetros:
- event (str): Uma descrição em linguagem natural do evento a ser criado.
A função `extract_event_parameters` será utilizada para extrair os detalhes
do evento a partir desta descrição e convertê-los em um objeto `Evento`.
Exemplos:
- "Agendar almoço com a Maria na sexta-feira ao meio-dia no restaurante X."
- "Criar um lembrete para pagar as contas no dia 10 às 9h da manhã."
- "Bloquear minha agenda para foco no projeto Y na próxima segunda das 14h às 17h."
Retorna:
- dict: Detalhes do evento criado no Google Agenda ou mensagem de erro.
Em caso de sucesso, o dicionário conterá informações sobre o evento criado,
incluindo o ID do evento. Em caso de erro, retornará uma mensagem descrevendo
o problema encontrado durante o processamento ou inserção do evento.
"""
extracted_data = extract_event_parameters(event)
if not extracted_data:
return "Erro: Não foi possível extrair os detalhes do evento da descrição fornecida."
calendar_id, event_details = extracted_data
request_body = json.loads(event_details)
time.sleep(1) ## Evitar limites de requisições do plano gratuito
event = calendar_service.events().insert(
calendarId = calendar_id,
body = request_body
).execute()
return event