Spaces:
Sleeping
Sleeping
| import os | |
| from datetime import datetime | |
| from langchain import hub | |
| from langchain.agents import Tool, AgentExecutor | |
| from langchain.agents.format_scratchpad import format_log_to_str | |
| from langchain.agents.output_parsers import ReActSingleInputOutputParser | |
| from langchain.memory import ChatMessageHistory, ConversationBufferWindowMemory | |
| from langchain.tools.render import render_text_description | |
| from langchain.utilities import DuckDuckGoSearchAPIWrapper | |
| from langchain_google_genai import ( | |
| ChatGoogleGenerativeAI, | |
| HarmBlockThreshold, | |
| HarmCategory, | |
| ) | |
| import streamlit as st | |
| from planing_tools import weatherapi_forecast_periods, query_rag | |
| from calendar_tools import list_calendar_list, list_calendar_events, insert_calendar_event, create_calendar | |
| from dotenv import load_dotenv | |
| hoje = datetime.today() | |
| data_formatada = hoje.strftime("%Y/%m/%d") | |
| # Pega o dia da semana em inglês | |
| dia_da_semana_ingles = hoje.strftime("%A") | |
| # Dicionário para mapear os dias da semana de inglês para português | |
| dias_da_semana_pt = { | |
| "Monday": "segunda-feira", | |
| "Tuesday": "terça-feira", | |
| "Wednesday": "quarta-feira", | |
| "Thursday": "quinta-feira", | |
| "Friday": "sexta-feira", | |
| "Saturday": "sábado", | |
| "Sunday": "domingo" | |
| } | |
| # Traduz o dia da semana para português | |
| dia_da_semana_pt = dias_da_semana_pt.get(dia_da_semana_ingles, dia_da_semana_ingles) | |
| # Formata a data para utilizar no prompt | |
| data_atual = f"{dia_da_semana_pt}, {data_formatada}" | |
| load_dotenv() | |
| os.environ["GOOGLE_API_KEY"] = os.getenv('GOOGLE_API_KEY') | |
| os.environ["LANGCHAIN_API_KEY"] = os.getenv('LANGCHAIN_API_KEY') | |
| 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, | |
| }, | |
| ) | |
| def transfer_to_calendar_agent(input_str): | |
| return calendar_agent_executor.invoke({"input": input_str}) | |
| def transfer_to_travel_agent(input_str): | |
| return travel_agent_executor.invoke({"input": input_str}) | |
| ddg_search = DuckDuckGoSearchAPIWrapper() | |
| travel_planing_tools = [ | |
| Tool( | |
| name="DuckDuckGo Search", | |
| func=ddg_search.run, | |
| description="""Essa ferramenta DEVE ser utilizada para buscar eventos relevantes no período fornecido pelo usuário. | |
| Ela é útil para obter informações sobre eventos ou atividades especiais que estão acontecendo na cidade de destino nas datas que o usuário informou. | |
| O modelo deve usá-la para complementar as sugestões de atividades.""" | |
| ), | |
| Tool( | |
| name="Weather Forecast", | |
| func=lambda date_string: weatherapi_forecast_periods(date_string, st.session_state.selected_destino), | |
| description="""Esta ferramenta DEVE ser usada obrigatoriamente *antes* de gerar o roteiro turístico, e somente após coletar todas as informações necessárias do usuário, incluindo o intervalo exato de datas. | |
| A consulta do clima deve ser feita separadamente para cada dia do período informado, garantindo que as atividades planejadas no roteiro sejam compatíveis com as condições climáticas previstas. | |
| **Quando usar:** | |
| - O clima é um fator relevante para a definição de atividades no roteiro. | |
| - O usuário especificou o intervalo de datas para o planejamento. | |
| **Instruções:** | |
| 1. Certifique-se de coletar as datas exatas do período solicitado pelo usuário. | |
| 2. Consulte a previsão do tempo para cada dia separadamente no intervalo de datas fornecido. | |
| 3. Use o resultado da previsão para ajustar o planejamento das atividades de acordo com as condições climáticas. | |
| **Exemplo de uso:** | |
| - Entrada do usuário: "Planeje um roteiro entre os dias 1º de agosto e 4 de março." | |
| - Ações do modelo: | |
| Action input: 2025/08/01 | |
| Action input: 2025/08/02 | |
| Action input: 2025/08/03 | |
| Action input: 2025/08/04 | |
| """ | |
| ), | |
| Tool( | |
| name="Query RAG", | |
| func=lambda query_text: query_rag(query_text, st.session_state.selected_destino), | |
| description="""Esta ferramenta deve ser usada quando o modelo souber a cidade de destino e os interesses do usuário, com o objetivo de fornecer informações sobre pontos turísticos e atrações que se alinham com esses interesses. | |
| O modelo deve utilizar essa ferramenta para sugerir atividades e lugares específicos a visitar, baseados na cidade e nos interesses fornecidos.""" | |
| ), | |
| Tool( | |
| name="Calendar Agent", | |
| func=transfer_to_calendar_agent, | |
| description="Esse agente lida com tudo relacionado ao calendário. As mensagens enviadas a ele devem estar em Português." | |
| ), | |
| ] | |
| from calendar_tools import list_calendar_list, list_calendar_events, insert_calendar_event, create_calendar | |
| google_calendar_tools = [ | |
| Tool( | |
| name="Create Calendar List", | |
| func=create_calendar, | |
| description=""" | |
| Use a função create_calendar_list para criar um novo calendário. | |
| Forneça o resumo (título) do calendário que você deseja criar. | |
| - Exemplo de uso: 'Meu Calendário de Viagens' | |
| - Essa função vai criar um novo calendário com o resumo fornecido. | |
| """ | |
| ), | |
| Tool( | |
| name="List Calendar List", | |
| func=list_calendar_list, | |
| description=""" | |
| Use a função list_calendar_list para obter a lista dos seus calendários disponíveis no Google Calendar. | |
| Se você quiser limitar o número de calendários retornados, forneça o número máximo desejado. | |
| - Exemplo de uso: Forneça o número máximo de calendários a serem listados, como 50. Se não quiser um limite, apenas diga para listar 200 o máximo por padrão. | |
| """ | |
| ), | |
| Tool( | |
| name="List Calendar Events", | |
| func=list_calendar_events, | |
| description=""" | |
| Use a função list_calendar_events para obter a lista de eventos de um calendário específico. | |
| Você precisa fornecer o ID do calendário e, opcionalmente, o número máximo de eventos a serem listados. | |
| - Exemplo de uso para o calendário principal: forneça 'primary' como o ID do calendário. | |
| - Exemplo de uso com limite: forneça o ID do calendário e o número máximo de eventos, como 'primary', 20. | |
| - Para listar eventos de um calendário específico, primeiro liste seus calendários para encontrar o ID correto. | |
| """ | |
| ), | |
| Tool( | |
| name="Insert Calendar Event", | |
| func=insert_calendar_event, | |
| description=""" | |
| Use a função Insert Calendar Event para adicionar **um único evento** a um calendário Google. | |
| Esta função deve ser chamada **uma vez para cada evento** que precisa ser agendado. | |
| A entrada para esta função deve ser uma descrição clara e completa de **um único evento** | |
| em linguagem natural, contendo todas as informações necessárias para agendá-lo individualmente. | |
| Se o usuário pediu para criar um novo calendário, você DEVE utilizar o calendar_id desse novo calendário para a inserção dos eventos. | |
| **Formato de entrada esperado:** | |
| **Descrição em Linguagem Natural (obrigatório):** | |
| Forneça uma descrição textual detalhada para **um único evento**. Inclua o calendar_id (se fornecido pelo usuário), o que será feito, | |
| quando (data e hora específicas), onde (local exato) e quaisquer detalhes adicionais relevantes | |
| para esse evento em particular. | |
| **Exemplos de descrições de eventos individuais:** | |
| - "Agendar almoço com a Maria na sexta-feira ao meio-dia no restaurante X." | |
| - "Criar um compromisso para pagar as contas no dia 10 de janeiro às 9h da manhã." | |
| - "Bloquear minha agenda para foco no projeto Y na próxima segunda-feira, das 14h às 17h, na minha mesa." | |
| **Como usar esta função corretamente:** | |
| 1. **Identifique cada evento individualmente:** Se a intenção é agendar múltiplos eventos, | |
| trate cada um como uma chamada separada para esta função. | |
| 2. **Obtenha o ID do calendário (se necessário):** Se o usuário mencionar um nome de | |
| calendário específico, use a função 'list_calendar_list' **primeiro** para obter | |
| o 'calendar_id' correspondente. | |
| 3. **Chame esta função com a descrição de um único evento:** Forneça a descrição completa | |
| em linguagem natural para o evento específico que você deseja agendar. | |
| **Informações essenciais para cada descrição de evento:** | |
| - **O que:** Uma descrição concisa do evento (ex: "Reunião de equipe", "Consulta médica"). | |
| - **Quando:** A data e hora de início e fim **precisas** do evento. | |
| - **Onde:** O local **específico** do evento. | |
| - **Fuso Horário (opcional):** Se aplicável, mencione o fuso horário se for diferente | |
| de "America/Fortaleza". | |
| **Exemplo de uso** | |
| *Usuário: Agendar visita ao Aquário Natal sábado das 9h às 12h.* | |
| *Agente:* (Chama 'Insert Calendar Event' com a Action Input: "Agendar visita ao Aquário Natal sábado das 9h às 12h.") | |
| **Observação IMPORTANTE:** Esta função **NÃO** deve ser usada para criar múltiplos eventos | |
| com uma única chamada. Cada chamada deve corresponder a **um único evento**. | |
| Ao final da execução desta função, você DEVE fornecer ao usuário a confirmação do agendamento | |
| desse evento específico, incluindo o título, data, hora. | |
| No final forneça o link para o calendário google: [https://www.google.com/calendar] | |
| """ | |
| ) | |
| ] | |
| travel_planing_prompt = hub.pull("tales/agente_turismo") | |
| google_calendar_prompt = hub.pull("tales/agente_calendario") | |
| llm_with_stop = llm.bind(stop=["\nObservation"]) | |
| planing_prompt = travel_planing_prompt.partial( | |
| tools=render_text_description(travel_planing_tools), | |
| tool_names=", ".join([t.name for t in travel_planing_tools]), | |
| ) | |
| calendar_prompt = google_calendar_prompt.partial( | |
| tools=render_text_description(google_calendar_tools), | |
| tool_names=", ".join([t.name for t in google_calendar_tools]), | |
| ) | |
| history = ChatMessageHistory() | |
| memory = ConversationBufferWindowMemory( | |
| k=20, | |
| chat_memory=history, | |
| memory_key="chat_history", | |
| input_key="input", | |
| other_memory_key=["destino"]) | |
| travel_planing_agent = ( | |
| { | |
| "input": lambda x: x["input"], | |
| "destino": lambda x: x.get("destino"), | |
| "agent_scratchpad": lambda x: format_log_to_str(x["intermediate_steps"]), | |
| "chat_history": lambda x: x["chat_history"], | |
| "data_atual": lambda x: data_atual, | |
| } | |
| | planing_prompt | |
| | llm_with_stop | |
| | ReActSingleInputOutputParser() | |
| ) | |
| travel_agent_executor = AgentExecutor(agent=travel_planing_agent, tools=travel_planing_tools, verbose=True, memory=memory, handle_parsing_errors=True) | |
| google_calendar_agent = ( | |
| { | |
| "input": lambda x: x["input"], | |
| "agent_scratchpad": lambda x: format_log_to_str(x["intermediate_steps"]), | |
| "chat_history": lambda x: x["chat_history"], | |
| "data_atual": lambda x: data_atual, | |
| } | |
| | calendar_prompt | |
| | llm_with_stop | |
| | ReActSingleInputOutputParser() | |
| ) | |
| calendar_agent_executor = AgentExecutor(agent=google_calendar_agent, tools=google_calendar_tools, verbose=True, memory=memory) |