morenomp commited on
Commit
5ac738d
·
1 Parent(s): 0a227d1

HF - PARTE 1

Browse files
Files changed (3) hide show
  1. __pycache__/rag_engine.cpython-313.pyc +0 -0
  2. app.py +50 -3
  3. rag_engine.py +116 -3
__pycache__/rag_engine.cpython-313.pyc ADDED
Binary file (2.64 kB). View file
 
app.py CHANGED
@@ -1,6 +1,6 @@
1
  # ENUNCIADO
2
  # app.py
3
- #
4
  # Este archivo construirá la interfaz web con Gradio.
5
  # Función principal ask:
6
  # Se debe definir una función ask(query, top_k, umbral) que:
@@ -13,7 +13,7 @@
13
  # • Formatee los documentos recuperados para mostrarlos de forma legible (por
14
  # ejemplo, uniendo los textos con separadores como \n\n---\n\n).
15
  # • Retorne (respuesta, docs_formateados).
16
- #
17
  # Interfaz Gradio
18
  # • Utilizar gr.Blocks con un título y descripción.
19
  # • Tiene:
@@ -26,4 +26,51 @@
26
  # máximo 15).
27
  # o Un botón Enviar que al hacer clic ejecute la función ask con los valores
28
  # de entrada y actualice las salidas.
29
- # • Por último, lanzar la interfaz con .launch().
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # ENUNCIADO
2
  # app.py
3
+ #
4
  # Este archivo construirá la interfaz web con Gradio.
5
  # Función principal ask:
6
  # Se debe definir una función ask(query, top_k, umbral) que:
 
13
  # • Formatee los documentos recuperados para mostrarlos de forma legible (por
14
  # ejemplo, uniendo los textos con separadores como \n\n---\n\n).
15
  # • Retorne (respuesta, docs_formateados).
16
+ #
17
  # Interfaz Gradio
18
  # • Utilizar gr.Blocks con un título y descripción.
19
  # • Tiene:
 
26
  # máximo 15).
27
  # o Un botón Enviar que al hacer clic ejecute la función ask con los valores
28
  # de entrada y actualice las salidas.
29
+ # • Por último, lanzar la interfaz con .launch().
30
+
31
+ import gradio as gr
32
+ from rag_engine import recuperar_documentos, generar_respuesta
33
+
34
+
35
+ def ask(query, top_k, umbral):
36
+
37
+ docs = recuperar_documentos(query, top_k, umbral)
38
+
39
+ respuesta = generar_respuesta(query, docs)
40
+
41
+ docs_formateados = "\n\n---\n\n".join(docs)
42
+
43
+ return respuesta, docs_formateados
44
+
45
+
46
+ with gr.Blocks() as demo:
47
+
48
+ gr.Markdown("# Hospital RAG Chatbot")
49
+
50
+ gr.Markdown("Ask questions about the hospital knowledge base.")
51
+
52
+ query = gr.Textbox(
53
+ label="Question", placeholder="Ask something about the hospital..."
54
+ )
55
+
56
+ top_k = gr.Slider(minimum=1, maximum=5, value=5, step=1, label="Top K Documents")
57
+
58
+ umbral = gr.Slider(
59
+ minimum=0.0, maximum=1.0, value=0.55, step=0.05, label="Similarity Threshold"
60
+ )
61
+
62
+ respuesta = gr.Textbox(label="Answer", lines=3)
63
+
64
+ documentos = gr.Textbox(label="Retrieved Documents", lines=6, max_lines=15)
65
+
66
+ boton = gr.Button("Enviar")
67
+
68
+ boton.click(
69
+ fn=ask,
70
+ inputs=[query, top_k, umbral],
71
+ outputs=[respuesta, documentos],
72
+ api_name="ask",
73
+ )
74
+
75
+
76
+ demo.launch()
rag_engine.py CHANGED
@@ -1,6 +1,6 @@
1
  # ENUNCIADO
2
  # rag_engine.py
3
- #
4
  # Este archivo contendrá toda la lógica del motor RAG. Se deben
5
  # implementar obligatoriamente las siguientes funciones (con los nombres y parámetros
6
  # exactos que se indican).
@@ -25,7 +25,7 @@
25
  # 3. Ordenar los documentos de mayor a menor similitud.
26
  # 4. Recorrer en ese orden y seleccionar aquellos cuya similitud sea mayor o
27
  # igual al umbral, hasta un máximo de top_k documentos.
28
- # • Retorno: Lista con los textos de los documentos seleccionados.
29
  # Función generar_respuesta(consulta, documentos_recuperados)
30
  # Genera una respuesta usando el modelo de lenguaje, inyectando los documentos
31
  # recuperados como contexto.
@@ -50,4 +50,117 @@
50
  # o Función de alto nivel que une la lógica de recuperar_documentos y
51
  # generar_respuestas
52
  # • Parámetros: los mismos que recuperar_documentos.
53
- # • Retorno: La respuesta generada (cadena).
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # ENUNCIADO
2
  # rag_engine.py
3
+ #
4
  # Este archivo contendrá toda la lógica del motor RAG. Se deben
5
  # implementar obligatoriamente las siguientes funciones (con los nombres y parámetros
6
  # exactos que se indican).
 
25
  # 3. Ordenar los documentos de mayor a menor similitud.
26
  # 4. Recorrer en ese orden y seleccionar aquellos cuya similitud sea mayor o
27
  # igual al umbral, hasta un máximo de top_k documentos.
28
+ # • Retorno: Lista con los textos de los documentos seleccionados.
29
  # Función generar_respuesta(consulta, documentos_recuperados)
30
  # Genera una respuesta usando el modelo de lenguaje, inyectando los documentos
31
  # recuperados como contexto.
 
50
  # o Función de alto nivel que une la lógica de recuperar_documentos y
51
  # generar_respuestas
52
  # • Parámetros: los mismos que recuperar_documentos.
53
+ # • Retorno: La respuesta generada (cadena).
54
+
55
+ import json
56
+ import torch
57
+
58
+ from sentence_transformers import SentenceTransformer
59
+ from transformers import AutoTokenizer, AutoModelForCausalLM
60
+
61
+ from sklearn.metrics.pairwise import cosine_similarity
62
+
63
+
64
+ # -----------------------------
65
+ # Cargar documentos
66
+ # -----------------------------
67
+
68
+ with open("documents.json", "r") as f:
69
+ documents = json.load(f)
70
+
71
+ # convertir a lista de textos
72
+ docs_text = list(documents.values())
73
+
74
+
75
+ # -----------------------------
76
+ # Modelo de embeddings
77
+ # -----------------------------
78
+
79
+ embed_model = SentenceTransformer("MongoDB/mdbr-leaf-ir")
80
+
81
+ # calcular embeddings una sola vez
82
+ doc_embeddings = embed_model.encode(docs_text)
83
+
84
+
85
+ # -----------------------------
86
+ # Modelo de lenguaje (LLM)
87
+ # -----------------------------
88
+
89
+ model_name = "microsoft/phi-2"
90
+
91
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
92
+ model = AutoModelForCausalLM.from_pretrained(model_name)
93
+
94
+
95
+ # -------------------------------------------------
96
+ # FUNCION 1
97
+ # recuperar_documentos
98
+ # -------------------------------------------------
99
+
100
+
101
+ def recuperar_documentos(consulta, top_k=2, umbral=0.4):
102
+
103
+ # embedding de la consulta
104
+ query_embedding = embed_model.encode([consulta])
105
+
106
+ # calcular similitud coseno
107
+ similitudes = cosine_similarity(query_embedding, doc_embeddings)[0]
108
+
109
+ # ordenar índices por similitud
110
+ indices_ordenados = similitudes.argsort()[::-1]
111
+
112
+ docs_relevantes = []
113
+
114
+ for idx in indices_ordenados:
115
+
116
+ if similitudes[idx] >= umbral:
117
+ docs_relevantes.append(docs_text[idx])
118
+
119
+ if len(docs_relevantes) >= top_k:
120
+ break
121
+
122
+ return docs_relevantes
123
+
124
+
125
+ # -------------------------------------------------
126
+ # FUNCION 2
127
+ # generar_respuesta
128
+ # -------------------------------------------------
129
+
130
+
131
+ def generar_respuesta(consulta, documentos_recuperados):
132
+
133
+ contexto = " ".join(documentos_recuperados)
134
+
135
+ prompt = f"""
136
+ Answer the question based only on the context provided
137
+
138
+ Context: {contexto}
139
+
140
+ Question: {consulta}
141
+
142
+ Answer:
143
+ """
144
+
145
+ inputs = tokenizer(prompt, return_tensors="pt")
146
+
147
+ outputs = model.generate(**inputs, max_new_tokens=100)
148
+
149
+ respuesta = tokenizer.decode(outputs[0], skip_special_tokens=True)
150
+
151
+ return respuesta
152
+
153
+
154
+ # -------------------------------------------------
155
+ # FUNCION 3
156
+ # preguntar
157
+ # -------------------------------------------------
158
+
159
+
160
+ def preguntar(consulta, top_k=2, umbral=0.4):
161
+
162
+ docs = recuperar_documentos(consulta, top_k, umbral)
163
+
164
+ respuesta = generar_respuesta(consulta, docs)
165
+
166
+ return respuesta