RAG de producción en Azure: fragmentación, búsqueda híbrida, filtros y citaciones
La recuperación empresarial requiere fragmentos conscientes de la estructura, búsqueda híbrida, filtros ACL, reclasificación, prompts basados en datos concretos y evaluación, no una demostración en PDF.
Las demostraciones de RAG parecen sencillas: PDF → fragmentos → embeddings → base de datos vectorial → hacer la consulta al modelo. Pero luego llegan cinco mil documentos y alguien pide la regla de reembolso para viajes internacionales. La parte difícil es incorporar de manera fiable las pruebas adecuadas al modelo.
1. Comience con los datos, no con el LLM
Evalúe las fuentes, el control de acceso, la actualidad y los formatos antes de elegir un modelo de chat. Un corpus de mala calidad genera respuestas erróneas y coherentes.
2. Fragmentación: no divida ciegamente cada N caracteres
Prefiera divisiones que tengan en cuenta la estructura (títulos, páginas, tablas) con solapamiento. Las tablas de tarifas y las cláusulas de políticas odian los métodos simples basados en caracteres.
3. Generación de embeddings
Utilice siempre la misma implementación para generar embeddings; registre la dimensión y el ID del modelo con cada índice. Mezclar modelos destruye silenciosamente la capacidad de recuperación de información.
document = {
"document_id": "HR-2026-001",
"title": "Employee Benefits Policy",
"department": "HR",
"country": "India",
"version": "2026.1",
"effective_date": "2026-01-01",
"source": "HR Portal"
}
def chunk_text(text, size=1000):
return [
text[i:i + size]
for i in range(0, len(text), size)
]
def chunk_by_sections(document):
chunks = []
for section in document.sections:
chunks.append({
"title": section.title,
"content": section.text,
"document_id": document.id
})
return chunks
pip install openai azure-identity
from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
token_provider = get_bearer_token_provider(
DefaultAzureCredential(),
"https://ai.azure.com/.default"
)
client = OpenAI(
base_url="https://YOUR-RESOURCE.openai.azure.com/openai/v1/",
api_key=token_provider
)
response = client.embeddings.create(
model="text-embedding-3-small",
input="Employees are eligible after completing 12 months of service."
)
vector = response.data[0].embedding
{
"id": "HR-2026-001-004",
"document_id": "HR-2026-001",
"title": "Employee Benefits Policy",
"content": "...",
"country": "India",
"version": "2026.1",
"content_vector": embedding
}
from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizedQuery
query = "Can I work remotely from another country?"
query_vector = client.embeddings.create(
model="text-embedding-3-small",
input=query
).data[0].embedding
vector_query = VectorizedQuery(
vector=query_vector,
k_nearest_neighbors=10,
fields="content_vector"
)
results = search_client.search(
search_text=query,
vector_queries=[vector_query],
top=5,
select=["title", "content", "document_id", "country"]
)
results = search_client.search(
search_text=query,
vector_queries=[vector_query],
filter="country eq 'India'",
top=5
)
context = "\n\n".join(
f"Source: {r['title']}\n{r['content']}"
for r in results
)
prompt = f"""
You are an enterprise policy assistant.
Answer the user's question using only the provided evidence.
If the evidence does not contain the answer, say that you don't have enough information.
Do not invent policies.
Evidence: {context}
Question: {query}
"""
{
"document_id": "HR-2026-001",
"page": 14,
"section": "Eligibility",
"content": "..."
}
def answer_question(question):
# 1. Embed the question
vector = embed(question)
# 2. Hybrid retrieval
candidates = search(
query=question,
vector=vector,
top=20
)
# 3. Apply metadata/business filters
candidates = apply_filters(candidates)
# 4. Rerank
ranked = rerank(question, candidates)
# 5. Keep only useful evidence
evidence = ranked[:5]
# 6. Build grounded prompt
prompt = build_prompt(
question,
evidence
)
# 7. Generate answer
response = generate(prompt)
# 8. Return answer + citations
return {
"answer": response,
"sources": extract_sources(evidence)
}
test_cases = [
{
"question": "What is the India travel allowance?",
"expected_source": "travel-policy-india.pdf"
},
{
"question": "How long is parental leave?",
"expected_source": "leave-policy-2026.pdf"
}
]
4. Almacenar embeddings en Azure AI Search
Conservar texto, vectores y metadatos filtrables (id del documento, producto, región, grupo ACL, updated_at).
5. La búsqueda híbrida supera a la basada únicamente en vectores para la mayoría de las empresas
Combinar similitud densa con BM25/palabras clave para identificadores, códigos y nombres propios poco comunes.
6. Filtrar antes de desperdiciar contexto
Aplicar filtros de seguridad y de arrendamiento en la consulta, no después de que el modelo ya haya procesado fragmentos prohibidos.
7. La recuperación no constituye el contexto final
Volver a clasificar, eliminar duplicados y ajustar según el presupuesto de tokens. Más fragmentos ≠ respuestas mejores.
8. Construir la instrucción a partir de evidencias
Las instrucciones deben requerir respuestas únicamente de los pasajes proporcionados y indicar cuando falte evidencia.
9. Fundamentación con citas
Indique los IDs o páginas de los pasajes para que los usuarios puedan verificarlo. Una fluidez sin citaciones constituye un riesgo.
10. Un proceso listo para implementarse
Ingestión → fragmentación → incrustación → indexación → recuperación híbrida → filtrado → reclasificación → generación de prompts → creación del contenido → citaciones → evaluación.
11. Qué suele fallar
Fragmentación deficiente; metadatos de mala calidad; recuperación solo con vectores; contexto excesivo; falta de conjunto de evaluación; ausencia de citaciones; permisos ACL faltantes; cambios silenciosos en los modelos de incrustación; falta de información sobre actualización.
Cierre
RAG en producción es una recuperación de información con un endpoint de LLM integrado, no al revés. Invierta en fragmentación, búsqueda híbrida, filtros, citaciones y evaluación; el modelo de chat es solo la etapa final.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
Mantenga un conjunto de preguntas estándar por dominio: búsquedas por ID exacto, preguntas para parafrasear y casos negativos de ACL. Automatícelas en CI cada vez que cambien los ajustes de particionamiento o incrustación.
La evaluación debe encontrarse en el mismo repositorio que la configuración de particionamiento: cuando alguien “solo ajusta” los solapamientos, el paquete de referencia debe fallar antes de que los usuarios se den cuenta.
La búsqueda híbrida sigue necesitando buenos analizadores y listas de sinónimos para el jerga del dominio; los embeddings por sí solos no podrán corregir un código de política escrito incorrectamente.
Documente el contrato del campo ACL en una sola página para que cada nueva tarea de ingreso escriba las mismas afirmaciones que espera el filtro de recuperación.
La evaluación debe encontrarse en el mismo repositorio que la configuración de particionamiento: cuando alguien “solo ajusta” los solapamientos, el paquete de referencia debe fallar antes de que los usuarios se den cuenta.
Lecturas relacionadas
- Búsqueda Híbrida para RAG Empresarial: El Dense Solo No Basta — Los IDs exactos y los códigos poco comunes dañan los embeddings; la combinación de BM25 con fusión densa en paralelo abarca la verdadera variedad de consultas.