File size: 3,793 Bytes
00a8468
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import logging
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from contextlib import asynccontextmanager
import uvicorn
import api_logic # Importa nosso módulo com a lógica principal

# Configuração de Logging (opcional, mas útil)
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# --- Modelos Pydantic para Validação de Entrada/Saída ---
class ChatMessage(BaseModel):
    message: str
    # Poderíamos adicionar mais campos como user_id se necessário no futuro

class ChatResponse(BaseModel):
    reply: str

# --- Lifespan: Carregar modelos na inicialização, liberar na finalização ---
# Esta é a forma moderna e recomendada no FastAPI para carregar recursos pesados
@asynccontextmanager
async def lifespan(app: FastAPI):
    logger.info("Executando startup do lifespan...")
    # Carrega os modelos e a memória definidos em api_logic.py
    try:
        api_logic.load_models_and_memory()
        logger.info("Modelos e memória carregados com sucesso.")
    except Exception as e:
        logger.exception("Falha crítica ao carregar modelos na inicialização!")
        # Se falhar aqui, a API provavelmente não funcionará corretamente.
        # Poderíamos impedir o startup, mas vamos deixar iniciar e os endpoints falharão.
    yield
    # Código de limpeza (shutdown) - opcional para este caso
    logger.info("Executando shutdown do lifespan...")
    # Poderia salvar o estado final aqui, mas já salvamos em add_to_memory
    # api_logic.save_state()

# --- Inicialização do App FastAPI ---
# Passamos o lifespan para gerenciar o carregamento dos modelos
app = FastAPI(lifespan=lifespan, title="RPG API Backend", version="0.1.0")

# --- Endpoints da API ---

@app.get("/", summary="Endpoint de Verificação")
async def read_root():
    """Verifica se a API está online."""
    logger.info("Endpoint '/' acessado.")
    return {"status": "RPG API Online", "message": "Use o endpoint POST /chat para interagir."}

@app.post("/chat", response_model=ChatResponse, summary="Processa uma mensagem de chat")
async def process_chat_message(chat_message: ChatMessage):
    """
    Recebe uma mensagem do usuário, processa usando a lógica de IA
    e retorna a resposta do narrador.
    """
    logger.info(f"Endpoint '/chat' recebido: {chat_message.message}")
    try:
        # Chama a função principal da nossa lógica
        reply_text = api_logic.run_chat_logic(chat_message.message)

        if reply_text is None or not isinstance(reply_text, str):
             logger.error(f"run_chat_logic retornou um tipo inesperado: {type(reply_text)}")
             raise HTTPException(status_code=500, detail="Erro interno: A IA não retornou um texto válido.")

        logger.info(f"Resposta gerada: {reply_text[:100]}...") # Loga parte da resposta
        return ChatResponse(reply=reply_text)

    except HTTPException as http_exc:
        # Re-levanta exceções HTTP que já foram tratadas
        raise http_exc
    except Exception as e:
        # Captura qualquer outro erro inesperado
        logger.exception(f"Erro inesperado ao processar /chat para a mensagem: {chat_message.message}")
        raise HTTPException(status_code=500, detail=f"Erro interno no servidor ao processar a mensagem: {e}")

# --- Execução (se rodar localmente, não usado diretamente no Space) ---
# O Hugging Face Space usará o Dockerfile para iniciar o Uvicorn
if __name__ == "__main__":
    # Esta parte é útil para testes locais, mas não será usada no deploy do Space
    print("Iniciando servidor Uvicorn localmente para teste...")
    # Carrega modelos antes de iniciar o servidor localmente
    # api_logic.load_models_and_memory() # Já chamado pelo lifespan
    uvicorn.run(app, host="0.0.0.0", port=7860)