0
respostas

Etapa 3

import os
import hashlib
from datetime import datetime, timezone

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.chat_history import InMemoryChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

DEFAULT_MODEL = "gpt-3.5-turbo"
DEFAULT_TEMPERATURE = 0.7

memoria_sessoes = {}

PROMPT_TEMPLATE = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "Você é o 'GeoAI Mentor', um assistente especializado em ajudar geocientistas a migrar para a área de Ciência de Dados. Seja amigável e didático.",
        ),
        ("placeholder", "{historico}"),
        ("human", "{query}"),
    ]
)


def build_model() -> ChatOpenAI:
    load_dotenv()

    api_key = os.getenv("OPENAI_API_KEY")
    if not api_key:
        raise RuntimeError(
            "OPENAI_API_KEY no está configurada. Agrégala a tu archivo .env."
        )

    model_name = os.getenv("OPENAI_MODEL", DEFAULT_MODEL)
    temperature = float(os.getenv("OPENAI_TEMPERATURE", str(DEFAULT_TEMPERATURE)))

    return ChatOpenAI(
        api_key=api_key,
        model=model_name,
        temperature=temperature,
    )


def obter_historico_por_sessao(session_id: str) -> InMemoryChatMessageHistory:
    if not isinstance(session_id, str) or not session_id.strip():
        raise ValueError("session_id deve ser uma string não vazia.")

    try:
        if session_id not in memoria_sessoes:
            memoria_sessoes[session_id] = InMemoryChatMessageHistory()
        return memoria_sessoes[session_id]
    except Exception as exc:
        raise RuntimeError(
            f"Falha ao obter/criar histórico para a sessão '{session_id}'."
        ) from exc


def gerar_session_id() -> str:
    agora = datetime.now(timezone.utc).isoformat()
    return hashlib.sha256(agora.encode("utf-8")).hexdigest()[:16]


def chat(pergunta: str, session_id: str) -> None:
    llm = build_model()
    cadeia = PROMPT_TEMPLATE | llm | StrOutputParser()
    cadeia_com_memoria = RunnableWithMessageHistory(
        cadeia,
        obter_historico_por_sessao,
        input_messages_key="query",
        history_messages_key="historico",
    )

    print(f"Usuario: {pergunta}\n")
    if pergunta:

        response = cadeia_com_memoria.invoke(
            {"query": pergunta},
            config={"configurable": {"session_id": session_id}},
        )
        print(f"Mentor: {response}\n")
    else:
        print("Chat mentor listo. Escribe 'salir' para terminar.")

        while True:
            user_message = input("Usuario: ").strip()
            if not user_message:
                continue

            if user_message.lower() in {"salir", "exit", "quit"}:
                print("Fin.")
                break

            response = cadeia_com_memoria.invoke(
                {"query": user_message},
                config={"configurable": {"session_id": session_id}},
            )
            print(f"Mentor: {response}\n")


# pra executar o chat interativo, basta rodar o script sem argumentos. Para perguntas rápidas, passe a pergunta como argumento.
if __name__ == "__main__":
    perguntas = [
        "Eu sou geofísico e quero migrar para a área de dados. Qual linguagem de programação devo aprender primeiro?",
        "E que tipo de projeto de portfólio eu poderia criar usando essa linguagem?",
    ]
    session_id = gerar_session_id()

    try:
        for pergunta in perguntas:
            try:
                chat(pergunta, session_id)
            except Exception as e:
                print(f"Erro ao processar pergunta: {e}\n")
    except RuntimeError as e:
        print(f"Erro de configuração: {e}")
    except Exception as e:
        print(f"Erro inesperado: {e}")