-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
120 lines (99 loc) · 3.89 KB
/
Copy pathmain.py
File metadata and controls
120 lines (99 loc) · 3.89 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import os
import asyncio
import logging
from fastapi import FastAPI, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse # Importação corrigida
from motor.motor_asyncio import AsyncIOMotorClient
from openai import AsyncOpenAI, OpenAIError
from dotenv import load_dotenv
from pydantic import BaseModel
from datetime import datetime
from typing import Dict
# Configuração de logs
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Carregar variáveis de ambiente
load_dotenv()
# Criar instância do FastAPI antes de definir rotas
app = FastAPI()
# Servindo arquivos estáticos
app.mount("/static", StaticFiles(directory="static"), name="static")
# Rota para servir o index.html
@app.get("/")
async def serve_index():
return FileResponse("./static/index.html")
# Configurar API do OpenAI
client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# Conectar ao MongoDB
MONGO_URI = os.getenv("MONGO_URI")
DB_NAME = os.getenv("DB_NAME")
mongo_client = AsyncIOMotorClient(MONGO_URI)
db = mongo_client[DB_NAME]
# Definir coleções
collection_messages = db["messages"]
collection_faq = db["perguntas_respostas"]
# Armazena tarefas ativas
active_tasks: Dict[str, asyncio.Task] = {}
# Modelos de dados
class ChatRequest(BaseModel):
user_id: str
message: str
class ChatResponse(BaseModel):
user_id: str
message: str
response: str
timestamp: datetime
# Timeout máximo da IA
TIMEOUT = 10
async def gerar_resposta_chatgpt(user_id: str, mensagem: str):
"""Executa a IA em segundo plano e permite cancelamento imediato."""
try:
response = await client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": mensagem}]
)
return response.choices[0].message.content
except OpenAIError as e:
logger.error(f"Erro na OpenAI: {e}")
raise HTTPException(status_code=502, detail="Erro ao processar a resposta da IA.")
except asyncio.CancelledError:
logger.info(f"Requisição {user_id} cancelada.")
raise HTTPException(status_code=499, detail="Requisição cancelada pelo usuário.")
except Exception as e:
logger.exception(f"Erro inesperado: {e}")
raise HTTPException(status_code=500, detail="Erro interno.")
# Função para buscar a resposta no MongoDB
async def buscar_resposta_faq(pergunta: str):
"""Consulta a FAQ no MongoDB para encontrar uma resposta registrada."""
pergunta_lower = pergunta.strip().lower()
result = await collection_faq.find_one({"pergunta": {"$regex": pergunta_lower, "$options": "i"}})
if result:
return result.get("resposta", "Resposta não encontrada.")
return None
@app.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
"""Processa a requisição do chatbot e permite cancelamento."""
if request.user_id in active_tasks:
raise HTTPException(status_code=400, detail="Já existe uma requisição em andamento para este usuário.")
# Verificar se a pergunta já está no banco de dados
resposta_faq = await buscar_resposta_faq(request.message)
if resposta_faq:
bot_response = resposta_faq
else:
# Criar e armazenar a tarefa assíncrona para a resposta da IA
task = asyncio.create_task(gerar_resposta_chatgpt(request.user_id, request.message))
active_tasks[request.user_id] = task
try:
bot_response = await asyncio.wait_for(task, timeout=TIMEOUT)
finally:
active_tasks.pop(request.user_id, None) # Remover a tarefa concluída/cancelada
# Salvar a interação no MongoDB
chat_record = {
"user_id": request.user_id,
"message": request.message,
"response": bot_response,
"timestamp": datetime.utcnow()
}
await collection_messages.insert_one(chat_record)
return ChatResponse(**chat_record)