import os import sys from dotenv import load_dotenv import edgedb from openai import OpenAI from qdrant_client import QdrantClient import streamlit as st # Add the parent directory to the Python path sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from pipelines.message import send_message # noqa # st.set_page_config(page_title="Carlos AI Agent") load_dotenv() @st.cache_resource def connect_to_services(): oa_client = OpenAI( api_key=os.environ.get("OPENAI_API_KEY") ) qdrant_client = QdrantClient( url=os.environ.get("QDRANT_URL"), api_key=os.environ.get("QDRANT_KEY") ) edgedb_client = edgedb.create_client() return oa_client, qdrant_client, edgedb_client class Chatbot: def __init__(self): # Conteúdo dos botões do sidebar if "topics" not in st.session_state: st.session_state.topics = [ "Níveis da conta govbr.", "Dúvidas no reconhecimento facial.", "Como recuperar minha conta gov.br", "Dúvidas para aumentar o nível com a CIN." ] if "services" not in st.session_state: oa_client, qdrant_client, edgedb_client = connect_to_services() st.session_state.services = { "oa_client": oa_client, "qdrant_client": qdrant_client, "edgedb_client": edgedb_client } if "chat" not in st.session_state and st.session_state.get('username'): chat = st.session_state.services["edgedb_client"].query(''' Select Chat { id } filter .user.username = $username ''', username=st.session_state.username) if not chat: chat = self._create_default_chat() else: chat = chat[0] self.update_messages(chat) st.session_state.chat = chat if "is_feedback_active" not in st.session_state: st.session_state.is_feedback_active = False self.user_button_input = "" # Pergunta do usuário no chat # self.is_feedback_active = False # Flag para ativar o feedback do o def _create_default_chat(self): chat = st.session_state.services["edgedb_client"].query(''' INSERT Chat { user := (SELECT User FILTER .username = $username) } ''', username=st.session_state.username) message = st.session_state.services["edgedb_client"].query(''' SELECT ( INSERT Message { content := "Como eu posso ajudar?", role := "assistant", chat := (SELECT Chat FILTER .id = $chat_id) } ) { content, role } ''', chat_id=chat[0].id) st.session_state.chat_history = message return chat[0] def _save_msg_to_db(self, msg, role): st.session_state.services["edgedb_client"].query(''' INSERT Message { content := $content, chat := (SELECT Chat FILTER .id = $chat_id), role := $role } ''', content=msg, chat_id=st.session_state.chat.id, role=role) def mount_chatbot(self): # Exibição do título e subtítulo st.title("Bem-vindo à ajuda do gov.br") st.caption("💬 Qual a sua dificuldade hoje? Estou aqui para ajudar!") # Exibição do espaço para mandar mensagem if user_query := st.chat_input(placeholder="Digite sua mensagem"): st.session_state.is_feedback_active = False # Desativando o feedback return user_query def create_sidebar(self): st.image('https://www.gov.br/++theme++padrao_govbr/img/govbr-logo-large.png', width=200) st.header("Tópicos frequentes") for topic in st.session_state.topics: if st.button(topic, key=topic): self.user_button_input = topic st.session_state.is_feedback_active = False # Desativando o feedback # Espaços em branco para organização for _ in range(5): st.write("") # Botão centralizado col1, col2, col3 = st.columns([1, 2, 1]) with col2: if st.button("LIMPAR HISTÓRICO"): st.session_state.services["edgedb_client"].query(''' DELETE Chat FILTER .id = $chat_id; ''', chat_id=st.session_state.chat.id) st.session_state.chat = self._create_default_chat() st.session_state.is_feedback_active = False # Desativando o feedback def send_message_for_ai(self, prompt): with st.spinner("Obtendo conteúdo da página..."): embedding = st.session_state.services["oa_client"].embeddings.create( input=[prompt], model=os.environ.get("OPENAI_MODEL_EMBEDDING") ).data[0].embedding child_texts = st.session_state.services["qdrant_client"].search( collection_name=os.environ.get("COLLECTION_NAME"), query_vector=embedding, limit=3 ) contexts = [] for child_text in child_texts: parent_text = st.session_state.services["edgedb_client"].query(''' SELECT Pattern { content, url, parent_id } FILTER .id = $parent_id ''', parent_id=child_text.payload["parent_id"])[0] context = { "content": parent_text.content, "url": parent_text.url, "parent_id": parent_text.parent_id } contexts.append(context) formatted_messages = [{"content": msg.content, "role": msg.role} for msg in st.session_state.chat_history] self._save_msg_to_db(prompt, "user") stream_response = send_message( st.session_state.services["oa_client"], contexts, prompt, formatted_messages ) return stream_response def generate_answer(self, prompt): with st.chat_message("assistant"): stream_response = self.send_message_for_ai(prompt) response = st.write_stream(stream_response) self._save_msg_to_db(response, "assistant") self.update_messages(st.session_state.chat) def display_chat(self): for message in st.session_state.chat_history: st.chat_message(message.role).write(message.content) def update_messages(self, chat): messages = st.session_state.services["edgedb_client"].query(''' SELECT Message { id, content, role } FILTER .chat.id = $chat_id ORDER BY .created_at ASC; ''', chat_id=chat.id) st.session_state.chat_history = messages def display_feedback(self): user_input = st.session_state.chat_history[-2].content bot_output = st.session_state.chat_history[-1].content with st.expander("Avaliação do atendimento"): st.write(f'O que achou da resposta para a pergunta "{user_input}"?') rate = st.feedback("stars") # rate = st.feedback("faces") text_feedback = st.text_input("Comentários extras:") # Botão para confirmar a avaliação if rate is not None: if st.button("Enviar Avaliação"): try: feedback_rate = rate + 1 st.session_state.services["edgedb_client"].query(''' INSERT Feedback { rating := $rating, content := $content, message := (SELECT Message FILTER .id = $message_id) } ''', message_id=st.session_state.chat_history[-1].id, rating=feedback_rate, content=text_feedback, ) st.session_state.chat_history st.success(f"Avaliação enviada!") except Exception as e: print(e) st.error("Erro ao enviar avaliação!") st.session_state.is_feedback_active = False # Desativando o feedback # TODO Colocar nessa parte a estrutura para adicionar o feedback_data ao banco de dados