Spaces:
Sleeping
Sleeping
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 | |
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 --- | |
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."} | |
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) |