Dafne00 commited on
Commit
39d6011
·
verified ·
1 Parent(s): 348734d

Upload 5 files

Browse files
Files changed (5) hide show
  1. README.md +27 -12
  2. app.py +43 -0
  3. documents.json +7 -0
  4. rag_engine.py +88 -0
  5. requirements.txt +8 -0
README.md CHANGED
@@ -1,12 +1,27 @@
1
- ---
2
- title: Chatbot
3
- emoji: 👁
4
- colorFrom: indigo
5
- colorTo: pink
6
- sdk: gradio
7
- sdk_version: 6.10.0
8
- app_file: app.py
9
- pinned: false
10
- ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # RAG Question Answering System
2
+
3
+ ## Descripción del proyecto
4
+
5
+ Este proyecto implementa un sistema de **Retrieval-Augmented Generation (RAG)** que permite responder preguntas en inglés basándose exclusivamente en una base de conocimiento local.
6
+
7
+ El sistema combina:
8
+ - Un modelo de **embeddings** para recuperar documentos relevantes.
9
+ - Un modelo de **lenguaje (LLM)** para generar respuestas basadas en esos documentos.
10
+
11
+ Flujo del sistema:
12
+ 1. El usuario introduce una pregunta.
13
+ 2. Se recuperan los documentos más relevantes mediante similitud coseno.
14
+ 3. Se construye un prompt con ese contexto.
15
+ 4. El modelo genera una respuesta basada únicamente en los documentos.
16
+
17
+ La interfaz se implementa con **Gradio**.
18
+
19
+ ---
20
+
21
+ ## ⚙️ Instalación
22
+
23
+ ### 1. Clonar el repositorio
24
+
25
+ ```bash
26
+ git clone <repo-url>
27
+ cd <repo-name>
app.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from rag_engine import recuperar_documentos, generar_respuesta
3
+
4
+ def ask(query, top_k, umbral):
5
+ docs = recuperar_documentos(query, int(top_k), float(umbral))
6
+ respuesta = generar_respuesta(query, docs)
7
+
8
+ if docs:
9
+ docs_formateados = "\n\n---\n\n".join(docs)
10
+ else:
11
+ docs_formateados = "No relevant documents found."
12
+
13
+ return respuesta, docs_formateados
14
+
15
+
16
+ with gr.Blocks() as demo:
17
+ gr.Markdown("# RAG Question Answering System")
18
+ gr.Markdown("Ask a question based on the provided documents.")
19
+
20
+ query = gr.Textbox(
21
+ label="Your Question",
22
+ placeholder="Type your question..."
23
+ )
24
+
25
+ top_k = gr.Slider(1, 5, value=5, step=1, label="Top K Documents")
26
+
27
+ umbral = gr.Slider(0.0, 1.0, value=0.55, step=0.05, label="Similarity Threshold")
28
+
29
+ respuesta = gr.Textbox(label="Answer", lines=3)
30
+
31
+ docs = gr.Textbox(label="Retrieved Documents", lines=6, max_lines=15)
32
+
33
+ boton = gr.Button("Enviar")
34
+
35
+ boton.click(
36
+ fn=ask,
37
+ inputs=[query, top_k, umbral],
38
+ outputs=[respuesta, docs]
39
+ )
40
+
41
+
42
+ if __name__ == "__main__":
43
+ demo.launch()
documents.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "doc1": "Hospital contact details: You can contact the hospital at email testing@gmail.com, phone +911234567890, or visit us at xyz, abc, 1234, Nepal.",
3
+ "doc2": "Hospital's working hours: The hospital's working hours are 7:00 AM - 8:00 PM daily.",
4
+ "doc3": "Official email address: The official email address to contact the hospital is testing@gmail.com.",
5
+ "doc4": "Main services: We provide comprehensive healthcare services including emergency care, diagnostic testing, surgical procedures, maternity services, and specialized treatments.",
6
+ "doc5": "Hospital location: The hospital is located at xyz, abc, 1234, Nepal."
7
+ }
rag_engine.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import torch
3
+ import numpy as np
4
+ from sentence_transformers import SentenceTransformer
5
+ from transformers import AutoTokenizer, AutoModelForCausalLM
6
+
7
+ # ================================
8
+ # CARGA DE MODELOS
9
+ # ================================
10
+
11
+ embedding_model = SentenceTransformer("MongoDB/mdbr-leaf-ir")
12
+
13
+ tokenizer = AutoTokenizer.from_pretrained("PleIAs/Pleias-RAG-350M")
14
+ llm_model = AutoModelForCausalLM.from_pretrained("PleIAs/Pleias-RAG-350M")
15
+
16
+ # ================================
17
+ # CARGA DE DOCUMENTOS (FIX AQUÍ)
18
+ # ================================
19
+
20
+ with open("documents.json", "r", encoding="utf-8") as f:
21
+ documents_dict = json.load(f)
22
+
23
+ # 🔥 IMPORTANTE: convertir dict → lista de textos
24
+ documents = list(documents_dict.values())
25
+
26
+ # ================================
27
+ # PRECOMPUTO DE EMBEDDINGS
28
+ # ================================
29
+
30
+ doc_embeddings = embedding_model.encode(documents, convert_to_tensor=True)
31
+
32
+ # ================================
33
+ # RECUPERAR DOCUMENTOS
34
+ # ================================
35
+
36
+ def recuperar_documentos(consulta, top_k=2, umbral=0.4):
37
+ query_embedding = embedding_model.encode(consulta, convert_to_tensor=True)
38
+
39
+ similitudes = torch.nn.functional.cosine_similarity(
40
+ query_embedding.unsqueeze(0),
41
+ doc_embeddings,
42
+ dim=1
43
+ )
44
+
45
+ indices_ordenados = torch.argsort(similitudes, descending=True)
46
+
47
+ resultados = []
48
+ for idx in indices_ordenados:
49
+ if similitudes[idx].item() >= umbral:
50
+ resultados.append(documents[idx])
51
+ if len(resultados) >= top_k:
52
+ break
53
+
54
+ return resultados
55
+
56
+ # ================================
57
+ # GENERAR RESPUESTA
58
+ # ================================
59
+
60
+ def generar_respuesta(consulta, documentos_recuperados):
61
+ contexto = " ".join(documentos_recuperados)
62
+
63
+ prompt = f"""Answer the question based only on the context provided
64
+ Context: {contexto}
65
+ Question: {consulta}
66
+ Answer:"""
67
+
68
+ inputs = tokenizer(prompt, return_tensors="pt")
69
+
70
+ outputs = llm_model.generate(
71
+ **inputs,
72
+ max_new_tokens=150
73
+ )
74
+
75
+ respuesta = tokenizer.decode(outputs[0], skip_special_tokens=True)
76
+
77
+ # eliminar el prompt del output
78
+ respuesta = respuesta.replace(prompt, "").strip()
79
+
80
+ return respuesta
81
+
82
+ # ================================
83
+ # FUNCIÓN FINAL
84
+ # ================================
85
+
86
+ def preguntar(consulta, top_k=2, umbral=0.4):
87
+ docs = recuperar_documentos(consulta, top_k, umbral)
88
+ return generar_respuesta(consulta, docs)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ torch
2
+ transformers
3
+ sentence-transformers
4
+ scikit-learn
5
+ fastapi
6
+ uvicorn
7
+ gradio
8
+ pydantic