Spaces:
Sleeping
Sleeping
File size: 5,169 Bytes
0a227d1 5ac738d 0a227d1 5ac738d 0a227d1 5ac738d | 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 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | # ENUNCIADO
# rag_engine.py
#
# Este archivo contendrá toda la lógica del motor RAG. Se deben
# implementar obligatoriamente las siguientes funciones (con los nombres y parámetros
# exactos que se indican).
# Al inicio del script se deben cargar:
# • El modelo de embeddings: SentenceTransformer("MongoDB/mdbr-leaf-ir")
# • El modelo de lenguaje: PleIAs/Pleias-RAG350M (usando AutoTokenizer y AutoModelForCausalLM de transformers).
# • Los documentos desde documents.json.
# Función recuperar_documentos(consulta, top_k=2, umbral=0.4)
# Dada una consulta en inglés, recupera los documentos más relevantes de la base de conocimiento.
# • Parámetros:
# o consulta (str): pregunta del usuario.
# o top_k (int): número máximo de documentos a retornar.
# o umbral (float): valor mínimo de similitud (coseno) para considerar un
# documento relevante. Los documentos con similitud inferior a este
# umbral se descartan.
# • Proceso:
# 1. Calcular el embedding de la consulta y de todos los documentos
# (preferiblemente una sola vez al cargar el script y almacenarlos para
# evitar recalcular).
# 2. Calcular la similitud del coseno entre el embedding de la consulta y los
# embeddings de los documentos.
# 3. Ordenar los documentos de mayor a menor similitud.
# 4. Recorrer en ese orden y seleccionar aquellos cuya similitud sea mayor o
# igual al umbral, hasta un máximo de top_k documentos.
# • Retorno: Lista con los textos de los documentos seleccionados.
# Función generar_respuesta(consulta, documentos_recuperados)
# Genera una respuesta usando el modelo de lenguaje, inyectando los documentos
# recuperados como contexto.
# Parámetros:
# o consulta (str): pregunta original del usuario.
# o documentos_recuperados (list): lista de textos con los documentos
# relevantes.
# Proceso:
# 1. Se concatenan todos los documentos en un solo string (por ejemplo,
# separados por espacios).
# 2. Se construye un prompt con el siguiente formato:
# “””
# Answer the question based only on the context provided
# Context: <" ".join(documentos_recuperados)>
# Question: <consulta>
# Answer:
# “””
# 3. Se genera la respuesta con el modelo
# Retorno: Cadena con la respuesta generada.
# Función preguntar(consulta, top_k=2, umbral=0.4)
# • Descripción:
# o Función de alto nivel que une la lógica de recuperar_documentos y
# generar_respuestas
# • Parámetros: los mismos que recuperar_documentos.
# • Retorno: La respuesta generada (cadena).
import json
import torch
from sentence_transformers import SentenceTransformer
from transformers import AutoTokenizer, AutoModelForCausalLM
from sklearn.metrics.pairwise import cosine_similarity
# -----------------------------
# Cargar documentos
# -----------------------------
with open("documents.json", "r") as f:
documents = json.load(f)
# convertir a lista de textos
docs_text = list(documents.values())
# -----------------------------
# Modelo de embeddings
# -----------------------------
embed_model = SentenceTransformer("MongoDB/mdbr-leaf-ir")
# calcular embeddings una sola vez
doc_embeddings = embed_model.encode(docs_text)
# -----------------------------
# Modelo de lenguaje (LLM)
# -----------------------------
model_name = "microsoft/phi-2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
# -------------------------------------------------
# FUNCION 1
# recuperar_documentos
# -------------------------------------------------
def recuperar_documentos(consulta, top_k=2, umbral=0.4):
# embedding de la consulta
query_embedding = embed_model.encode([consulta])
# calcular similitud coseno
similitudes = cosine_similarity(query_embedding, doc_embeddings)[0]
# ordenar índices por similitud
indices_ordenados = similitudes.argsort()[::-1]
docs_relevantes = []
for idx in indices_ordenados:
if similitudes[idx] >= umbral:
docs_relevantes.append(docs_text[idx])
if len(docs_relevantes) >= top_k:
break
return docs_relevantes
# -------------------------------------------------
# FUNCION 2
# generar_respuesta
# -------------------------------------------------
def generar_respuesta(consulta, documentos_recuperados):
contexto = " ".join(documentos_recuperados)
prompt = f"""
Answer the question based only on the context provided
Context: {contexto}
Question: {consulta}
Answer:
"""
inputs = tokenizer(prompt, return_tensors="pt")
outputs = model.generate(**inputs, max_new_tokens=100)
respuesta = tokenizer.decode(outputs[0], skip_special_tokens=True)
return respuesta
# -------------------------------------------------
# FUNCION 3
# preguntar
# -------------------------------------------------
def preguntar(consulta, top_k=2, umbral=0.4):
docs = recuperar_documentos(consulta, top_k, umbral)
respuesta = generar_respuesta(consulta, docs)
return respuesta
|