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