NightmareFox12 commited on
Commit
9242cc0
·
verified ·
1 Parent(s): 071f321

Update rag_api.py

Browse files
Files changed (1) hide show
  1. rag_api.py +54 -17
rag_api.py CHANGED
@@ -1,4 +1,6 @@
1
  import os
 
 
2
  from fastapi import FastAPI
3
  from pydantic import BaseModel
4
  from langchain_community.vectorstores import FAISS
@@ -10,33 +12,61 @@ from langchain_groq import ChatGroq
10
  # --------------------------------------------------------
11
  # 1. CONFIGURACIÓN
12
  # --------------------------------------------------------
13
- # La clave se lee del secreto de Hugging Face. NO PEGAR CLAVE AQUÍ.
14
- os.environ['GROQ_API_KEY'] = os.environ.get('GROQ_API_KEY')
15
- # DB_FAISS_PATH = 'vectorstore/db_faiss'
16
- DB_FAISS_PATH = '/app/vectorstore/db_faiss'
 
 
 
17
 
18
  # --------------------------------------------------------
19
- # 2. CLASES Y CARGA DEL RAG CORE
20
  # --------------------------------------------------------
21
 
22
  class QueryRequest(BaseModel):
23
  """Define el formato de la pregunta que recibirá el endpoint /query."""
24
  query: str
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  def load_and_configure_rag():
27
  """
28
- Carga la base de datos FAISS pre-entrenada y configura el RAG Chain.
29
- Esta función se ejecuta SOLO UNA VEZ al iniciar el servidor.
30
  """
31
  try:
32
- # 1. Cargar Embeddings (necesario para saber cómo buscar)
 
 
 
 
33
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
34
 
35
- # 2. Cargar Vector Store (busca la carpeta que subiste a Hugging Face)
36
- # Esto fallará si la carpeta 'vectorstore/db_faiss' no se sube.
37
- vectorstore = FAISS.load_local(DB_FAISS_PATH, embeddings, allow_dangerous_deserialization=True)
 
 
 
38
 
39
- # 3. Configurar LLM y Prompt
40
  llm_groq = ChatGroq(temperature=0.0, model_name="llama-3.1-8b-instant")
41
 
42
  custom_prompt = """
@@ -51,7 +81,7 @@ def load_and_configure_rag():
51
  """
52
  RAG_PROMPT = PromptTemplate(template=custom_prompt, input_variables=["context", "question"])
53
 
54
- # 4. Crear la cadena de RAG
55
  qa_chain = RetrievalQA.from_chain_type(
56
  llm=llm_groq,
57
  chain_type="stuff",
@@ -62,26 +92,33 @@ def load_and_configure_rag():
62
  return qa_chain
63
 
64
  except Exception as e:
65
- print(f"Error crítico al cargar la configuración RAG: {e}")
66
- return None
 
67
 
68
  # --------------------------------------------------------
69
  # 3. CONFIGURACIÓN DE FASTAPI Y ENDPOINTS
70
  # --------------------------------------------------------
71
 
 
72
  app = FastAPI(title="NutriActive RAG API")
73
- qa_chain = load_and_configure_rag() # Carga la cadena al iniciar
 
 
 
74
 
75
  @app.get("/")
76
  def home():
77
  """Verifica que el servidor está corriendo."""
 
 
78
  return {"message": "API de NutriActive RAG operativa. Usa el endpoint /query."}
79
 
80
  @app.post("/query")
81
  async def process_query(request: QueryRequest):
82
  """Endpoint principal para recibir la pregunta y devolver la respuesta."""
83
  if qa_chain is None:
84
- return {"error": "El sistema RAG no se pudo cargar. Verifique que la carpeta 'vectorstore' existe."}
85
 
86
  try:
87
  result = qa_chain.invoke({"query": request.query})
 
1
  import os
2
+ import requests
3
+ import shutil
4
  from fastapi import FastAPI
5
  from pydantic import BaseModel
6
  from langchain_community.vectorstores import FAISS
 
12
  # --------------------------------------------------------
13
  # 1. CONFIGURACIÓN
14
  # --------------------------------------------------------
15
+ # URLs DE DESCARGA DIRECTA DE GOOGLE DRIVE (construidas con las IDs)
16
+ URL_FAISS = "https://drive.google.com/uc?export=download&id=1bFLDqk0fEsdJlxjYPnxIqOUxagO7qcy3"
17
+ URL_PKL = "https://drive.google.com/uc?export=download&id=1D0JGeRft3798x-rsTam1s_2lVhjC9yTR"
18
+
19
+ # Directorio donde guardaremos los archivos dentro del contenedor Docker
20
+ DOWNLOAD_DIR = "/tmp/db_faiss"
21
+ DB_FAISS_PATH = DOWNLOAD_DIR
22
 
23
  # --------------------------------------------------------
24
+ # 2. FUNCIONES DE DESCARGA Y CARGA DEL RAG CORE
25
  # --------------------------------------------------------
26
 
27
  class QueryRequest(BaseModel):
28
  """Define el formato de la pregunta que recibirá el endpoint /query."""
29
  query: str
30
 
31
+ def download_file(url, local_path):
32
+ """Descarga un archivo desde una URL y lo guarda localmente en /tmp."""
33
+ print(f"Descargando: {os.path.basename(local_path)} desde la nube...")
34
+ # Usar headers de agente de usuario para evitar bloqueos 403 de Google Drive
35
+ headers = {'User-Agent': 'Mozilla/5.0'}
36
+ response = requests.get(url, stream=True, headers=headers)
37
+
38
+ # Manejar errores de descarga (ej. si el archivo no es público)
39
+ if response.status_code == 403:
40
+ raise PermissionError(f"Error 403: El archivo {os.path.basename(local_path)} no es público en Google Drive.")
41
+ response.raise_for_status()
42
+
43
+ # Asegurar que el directorio de destino exista
44
+ os.makedirs(os.path.dirname(local_path), exist_ok=True)
45
+
46
+ with open(local_path, 'wb') as f:
47
+ shutil.copyfileobj(response.raw, f)
48
+ print("Descarga completada.")
49
+
50
  def load_and_configure_rag():
51
  """
52
+ Descarga la base de datos FAISS de la nube y la configura.
 
53
  """
54
  try:
55
+ # 1. Descargar los archivos y guardarlos en /tmp/db_faiss
56
+ download_file(URL_FAISS, os.path.join(DOWNLOAD_DIR, 'index.faiss'))
57
+ download_file(URL_PKL, os.path.join(DOWNLOAD_DIR, 'index.pkl'))
58
+
59
+ # 2. Cargar Embeddings (el mismo modelo que usaste)
60
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
61
 
62
+ # 3. Cargar Vector Store (desde la ruta temporal /tmp/db_faiss)
63
+ vectorstore = FAISS.load_local(
64
+ DB_FAISS_PATH,
65
+ embeddings,
66
+ allow_dangerous_deserialization=True
67
+ )
68
 
69
+ # 4. Configurar LLM y Prompt
70
  llm_groq = ChatGroq(temperature=0.0, model_name="llama-3.1-8b-instant")
71
 
72
  custom_prompt = """
 
81
  """
82
  RAG_PROMPT = PromptTemplate(template=custom_prompt, input_variables=["context", "question"])
83
 
84
+ # 5. Crear la cadena de RAG
85
  qa_chain = RetrievalQA.from_chain_type(
86
  llm=llm_groq,
87
  chain_type="stuff",
 
92
  return qa_chain
93
 
94
  except Exception as e:
95
+ print(f"Error CRÍTICO al descargar/cargar FAISS desde la nube: {e}")
96
+ # Esta es la excepción que verás en los logs si falla la descarga
97
+ raise RuntimeError(f"Falla al cargar FAISS: {e}")
98
 
99
  # --------------------------------------------------------
100
  # 3. CONFIGURACIÓN DE FASTAPI Y ENDPOINTS
101
  # --------------------------------------------------------
102
 
103
+ # Iniciar servidor y RAG (manejo de errores de carga)
104
  app = FastAPI(title="NutriActive RAG API")
105
+ try:
106
+ qa_chain = load_and_configure_rag()
107
+ except RuntimeError:
108
+ qa_chain = None
109
 
110
  @app.get("/")
111
  def home():
112
  """Verifica que el servidor está corriendo."""
113
+ if qa_chain is None:
114
+ return {"error": "El servidor está activo, pero el RAG no se pudo inicializar. Revisa los logs de inicio para ver el error de descarga."}
115
  return {"message": "API de NutriActive RAG operativa. Usa el endpoint /query."}
116
 
117
  @app.post("/query")
118
  async def process_query(request: QueryRequest):
119
  """Endpoint principal para recibir la pregunta y devolver la respuesta."""
120
  if qa_chain is None:
121
+ return {"error": "El sistema RAG no se pudo cargar. Revisa los logs de inicio para ver el error específico."}
122
 
123
  try:
124
  result = qa_chain.invoke({"query": request.query})