Calvoloncio commited on
Commit
e581cb0
·
verified ·
1 Parent(s): 6b1d3e6

Upload 4 files

Browse files
Files changed (4) hide show
  1. app.py +45 -0
  2. documents.json +7 -0
  3. rag_engine.py +73 -0
  4. requirements.txt +8 -0
app.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import rag_engine
3
+
4
+ def ask(pregunta, num_docs, similitud):
5
+ """ Esta función conecta la web con nuestro motor RAG """
6
+
7
+ respuesta, docs = rag_engine.preguntar(pregunta, top_k=int(num_docs), umbral=float(similitud))
8
+
9
+
10
+ if not docs:
11
+ contexto_visible = "No se encontró información relevante."
12
+ else:
13
+
14
+ contexto_visible = "\n\n---\n\n".join(docs)
15
+
16
+ return respuesta, contexto_visible
17
+
18
+
19
+ with gr.Blocks() as interfaz:
20
+ gr.Markdown("# Asistente del Hospital")
21
+ gr.Markdown("Escribe tu pregunta para buscar en los documentos del hospital.")
22
+
23
+ with gr.Row():
24
+
25
+ with gr.Column():
26
+ entrada_texto = gr.Textbox(label="Tu pregunta:", placeholder="Ej: Where is the hospital?")
27
+ slider_k = gr.Slider(1, 5, value=2, step=1, label="Cuantos documentos buscar")
28
+ slider_u = gr.Slider(0.0, 1.0, value=0.4, step=0.1, label="Nivel de parecido (minimo)")
29
+ boton = gr.Button("Preguntar", variant="primary")
30
+
31
+
32
+ with gr.Column():
33
+ salida_ia = gr.Textbox(label="Respuesta:", lines=4)
34
+ salida_docs = gr.Textbox(label="Informacion utilizada:", lines=8)
35
+
36
+
37
+ boton.click(
38
+ fn=ask,
39
+ inputs=[entrada_texto, slider_k, slider_u],
40
+ outputs=[salida_ia, salida_docs]
41
+ )
42
+
43
+
44
+ if __name__ == "__main__":
45
+ interfaz.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,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import torch
3
+ from transformers import AutoTokenizer, AutoModelForCausalLM
4
+ from sentence_transformers import SentenceTransformer, util
5
+
6
+ # --- 1. CARGA DE MODELOS ---
7
+ # Usamos un modelo para buscar informacion en los documentos
8
+ print("Cargando el modelo de busqueda...")
9
+ embed_model = SentenceTransformer("MongoDB/mdbr-leaf-ir")
10
+
11
+ # Usamos un modelo para que nos ayude a redactar la respuesta
12
+ print("Cargando el modelo de lenguaje...")
13
+ model_id = "microsoft/Phi-2"
14
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
15
+ llm_model = AutoModelForCausalLM.from_pretrained(model_id)
16
+
17
+ # --- 2. BASE DE CONOCIMIENTO ---
18
+ # Leemos los documentos que tenemos guardados en el archivo JSON
19
+ with open("documents.json", "r", encoding="utf-8") as f:
20
+ docs_dict = json.load(f)
21
+ documents = list(docs_dict.values())
22
+
23
+ # Preparamos los datos para que el ordenador pueda buscar en ellos rapidamente
24
+ print("Preparando los documentos para la busqueda...")
25
+ docs_embeddings = embed_model.encode(documents, convert_to_tensor=True)
26
+
27
+ # --- 3. FUNCIONES DEL SISTEMA ---
28
+
29
+ def recuperar_documentos(consulta, top_k=2, umbral=0.4):
30
+ """ Busca en nuestra base de datos los textos que mas se parecen a la pregunta """
31
+ # Pasamos la pregunta a un formato que el modelo entienda
32
+ query_embedding = embed_model.encode(consulta, convert_to_tensor=True)
33
+
34
+ # Comparamos la pregunta con todos los documentos para ver cuales coinciden mejor
35
+ cos_scores = util.cos_sim(query_embedding, docs_embeddings)[0]
36
+
37
+ # Nos quedamos con los mejores resultados segun lo que hayamos configurado
38
+ top_results = torch.topk(cos_scores, k=min(top_k, len(documents)))
39
+
40
+ final_docs = []
41
+ for score, idx in zip(top_results[0], top_results[1]):
42
+ # Solo guardamos el documento si se parece lo suficiente a la pregunta
43
+ if score >= umbral:
44
+ final_docs.append(documents[idx])
45
+
46
+ return final_docs
47
+
48
+ def generar_respuesta(consulta, documentos_recuperados):
49
+ """ Redacta una respuesta usando la pregunta y la informacion encontrada """
50
+ # Si no hemos encontrado nada, usamos un texto por defecto
51
+ contexto = " ".join(documentos_recuperados) if documentos_recuperados else "No se ha encontrado informacion relevante."
52
+
53
+ # Preparamos las instrucciones para el modelo
54
+ prompt = f"Context: {contexto}\nQuestion: {consulta}\nAnswer:"
55
+
56
+ # Convertimos el texto a un formato que el modelo pueda procesar
57
+ inputs = tokenizer(prompt, return_tensors="pt")
58
+
59
+ # El modelo genera el texto de la respuesta
60
+ with torch.no_grad():
61
+ outputs = llm_model.generate(**inputs, max_new_tokens=100)
62
+
63
+ # Limpiamos el texto generado para quedarnos solo con lo importante
64
+ resultado_total = tokenizer.decode(outputs[0], skip_special_tokens=True)
65
+ respuesta_limpia = resultado_total.split("Answer:")[-1].strip()
66
+
67
+ return respuesta_limpia
68
+
69
+ def preguntar(consulta, top_k=2, umbral=0.4):
70
+ """ Funcion principal que busca la informacion y redacta la respuesta """
71
+ docs = recuperar_documentos(consulta, top_k, umbral)
72
+ respuesta = generar_respuesta(consulta, docs)
73
+ return respuesta, 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