Simplificando la investigación jurídica con RAG, Milvus y Ollama
En esta publicación de blog, veremos cómo podemos aplicar RAG a datos legales.
La investigación legal puede llevar mucho tiempo. Por lo general, necesitas revisar una gran cantidad de documentos para encontrar las respuestas que necesitas. Retrieval-Augmented Generation (RAG) puede ayudar a optimizar tu proceso de investigación.
¿Qué es RAG?
Retrieval Augmented Generation (RAG) es una técnica que mejora los LLMs al integrar fuentes de datos adicionales. Una aplicación típica de RAG implica:
Indexación - una canalización para ingerir datos desde una fuente e indexarlos, que generalmente consiste en cargar, dividir y ordenar los datos en Milvus.
Recuperación y generación - En tiempo de ejecución, RAG procesa la consulta del usuario, obtiene datos relevantes del índice almacenado en Milvus, y el LLM genera una respuesta basada en este contexto enriquecido.
En esta guía práctica exploraremos cómo configurar un sistema de Retrieval Augmented Generation (RAG) usando Ollama, centrándonos en datos legales y aprovechando Milvus como nuestra base de datos vectorial.
Las herramientas:
Ollama: Lleva el poder de los LLMs a tu portátil, simplificando la operación local.
Milvus: La base de datos vectorial que usamos para almacenar y recuperar tus datos de manera eficiente.
Llama 3: La iteración más reciente de Meta de una línea de modelos de lenguaje grandes.
Voyage AI - Proporciona modelos de embeddings especializados en dominios específicos. Estamos usando su embedding legal especializado, optimizado para la recuperación legal y de contexto largo.
Preparación
Dependencias y datos
Primero, instala las dependencias necesarias:
! pip install --upgrade pymilvus ollama tqdm pypdf voyageai openai wget
Importar claves de API
Si tienes tu clave de API configurada en un archivo .env, puedes cargarla usando dotenv para evitar filtrar la clave cuando subas tu notebook.
import os
from dotenv import load_dotenv
load_dotenv()
VOYAGE_API_KEY = os.getenv('VOYAGE_API_KEY')
Si no tienes un archivo .env, simplemente omite la importación de dotenv.
Preparar los datos
Para este tutorial, usaremos datos de las Royal Courts of Justice en Londres. Descárgalos usando wget y guárdalos localmente:
! wget https://www.judiciary.uk/wp-content/uploads/2024/07/Final-Judgment-CA-2023-001978-BBC-v-BBC-Pension-Trust-another.pdf
A continuación, lee el archivo PDF y extrae su contenido para usarlo en nuestra aplicación RAG:
from pypdf import PdfReader
reader = PdfReader("Final-Judgment-CA-2023-001978-BBC-v-BBC-Pension-Trust-another.pdf")
pages = [page.extract_text() for page in reader.pages]
print(pages[0])
Esto debería darte el siguiente resultado:
Neutral Citation Number [2024] EWCA Civ 767
Case No: CA-2023 -001978
IN THE COURT OF APPEAL ( CIVIL DIVISION)
ON APPEAL FROM THE HIGH COURT OF JUSTICE
BUSINESS AND PROPERTY COURTS OF ENGLAND AND WALES
BUSINESS LIST : PENSIONS (ChD)
The Hon Mr Justice Adam Johnson
[2023] EWHC 1965 (Ch)
Royal Courts of Justice
Strand, London, WC2A 2LL
Date: 09/07 /2024
Before :
LORD JUSTICE LEWISON
LADY JUSTICE FALK
and
SIR CHRISTOPHER FLOYD
Incrustar tus documentos
Usaremos voyage-law-2, un modelo de embeddings especializado para el dominio legal.
Primero, define una función para generar embeddings de texto usando la API de Voyage AI:
import voyageai
voyage_client = voyageai.Client()
def embed_text(text: str) -> str:
return voyage_client.embed([text], model="voyage-law-2").embeddings[0]
Genera un embedding de prueba e imprime su dimensión y sus primeros elementos.
result = voyage_client.embed(["hello world"], model="voyage-law-2")
embedding_dim = len(result.embeddings[0])
print(embedding_dim)
print(result.embeddings[0][:10])
1024
[0.000756315013859421, -0.02162403240799904, 0.0052010356448590755, -0.02917512319982052, -0.00796651840209961, -0.03238343447446823, 0.0660339742898941, 0.03845587745308876, -0.01913367211818695, 0.05562642216682434]
Cargar datos en Milvus
Crear la colección en Milvus
from pymilvus import MilvusClient
milvus_client = MilvusClient(uri="./milvus_legal.db")
collection_name = "my_rag_collection"
Establecer el URI como un archivo local, por ejemplo, ./milvus_legal.db, es conveniente, ya que usa automáticamente Milvus Lite para almacenar todos los datos en este archivo. Para datos a gran escala, puedes configurar un servidor Milvus de mayor rendimiento en Docker o Kubernetes.
Elimina la colección si ya existe y luego crea una nueva:
if milvus_client.has_collection(collection_name):
milvus_client.drop_collection(collection_name)
milvus_client.create_collection(
collection_name=collection_name,
dimension=embedding_dim,
metric_type="IP", # Inner product distance
consistency_level="Strong", # Strong consistency level
)
Si no especificamos ninguna información de campos, Milvus creará automáticamente un campo id predeterminado para la clave primaria y un campo vectorial para almacenar los datos vectoriales. Se usa un campo JSON reservado para almacenar campos no definidos por el esquema y sus valores.
Insertar datos
Itera por las páginas de nuestro documento, crea los embeddings y luego inserta los datos en Milvus.
Introducimos un nuevo campo llamado text, un campo no definido en el esquema de la colección. Se añadirá automáticamente al campo dinámico JSON reservado, que puede tratarse como un campo normal a alto nivel.
from tqdm import tqdm
data = []
for i, page in enumerate(tqdm(pages, desc="Creating embeddings")):
data.append({"id": i, "vector": embed_text(page), "text": page})
milvus_client.insert(collection_name=collection_name, data=data)
Creating embeddings: 100%|███████████████████████████████████████████████████████████████████████████████████████| 20/20 [00:08<00:00, 2.45it/s]
{'insert_count': 20,
'ids': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
'cost': 0}
Construir el sistema RAG básico
A continuación, definamos una consulta sobre el contenido de la audiencia judicial:
question = "who are the lawyers?"
Usaremos Milvus para buscar en nuestros datos indexados. Más adelante, integraremos esto con un LLM.
search_res = milvus_client.search(
collection_name=collection_name,
data=[
embed_text(question)
], # Use the `embed_text` function to convert the question to an embedding vector
limit=3, # Return top 3 results
search_params={"metric_type": "IP", "params": {}}, # Inner product distance
output_fields=["text"], # Return the text field
)
Imprime las líneas recuperadas con sus distancias:
import json
retrieved_lines_with_distances = [
(res["entity"]["text"], res["distance"]) for res in search_res[0]
]
print(json.dumps(retrieved_lines_with_distances, indent=4))
```
El texto asociado con nuestros embeddings es bastante largo, pero aquí hay un ejemplo de lo que devuelve Milvus
[" n nNúmero de cita neutral [2024] EWCA Civ 767 n nN.º de caso: CA-2023 -001978 nEN EL TRIBUNAL DE APELACIÓN ( DIVISIÓN CIVIL) nEN APELACIÓN DESDE EL TRIBUNAL SUPERIOR DE JUSTICIA nTRIBUNALES DE NEGOCIOS Y PROPIEDAD DE INGLATERRA Y GALES nLISTA DE NEGOCIOS : PENSIONES (ChD) nEl Honorable Sr. Justice Adam Johnson n[2023] EWHC 1965 (Ch) nRoyal Courts of Justice nStrand, Londres, WC2A 2LL n nFecha: 09/07 /2024 nAnte : n nLORD JUSTICE LEWISON nLADY JUSTICE FALK ny nSIR CHRISTOPHER FLOYD n n- - - - - - - - - - - - - - - - - - - - - n nEntre : n n BRITISH BROADCASTING CORPORATION Apelante n - y - n (1) BBC P ENSION TRUST LIMITED n(2) CHRISTINA BURNS nDemandado s n n- - - - - - - - - - - - - - - - - - - - - n n Michael Tennet KC y Edward Sawyer (instruidos por Linklaters LLP ) npor la Apelante n Brian Green KC y Joseph Steadman (instruidos por Slaughter and May Solicitors ) npor el Primer Demandado nAndrew Spink KC y Saul Margo (instruidos por Stephenson Harwood LLP ) npor el Segundo Demandado n nFechas de la audiencia: 25, 26 & 27/06/2024 n- - - - - - - - - - - - - - - - - - - - - n nSentencia aprobada n nEsta sentencia se dictó de forma remota a las 11.00am del 09/07/2024 mediante circulación a las npartes o sus representantes por e -mail y mediante su publicación en los Archivos Nacionales. n n............................. n",
0.1101425364613533
],
Usar un LLM para obtener una respuesta RAG
Combine los documentos recuperados en un contexto y defina indicaciones del sistema y del usuario para el modelo de lenguaje:
context = "n".join(
[line_with_distance[0] for line_with_distance in retrieved_lines_with_distances]
)
SYSTEM_PROMPT = """
Human: You are an AI assistant. You are able to find answers to the questions from the contextual passage snippets provided.
"""
USER_PROMPT = f"""
Use the following pieces of information enclosed in <context> tags to provide an answer to the question enclosed in <question> tags.
<context>
{context}
</context>
<question>
{question}
</question>
"""
Ollama tiene una API de OpenAI totalmente compatible, lo que significa que podemos usar el SDK de Python de OpenAI para llamar a Ollama:
from openai import OpenAI
client = OpenAI(
base_url = 'http://localhost:11434/v1',
api_key='ollama', # required, but unused
)
response = client.chat.completions.create(
model="llama3",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": USER_PROMPT},
],
)
print(response.choices[0].message.content)
Según el texto, los abogados implicados en este caso son:
* Andrew Spink KC (instruido por Stephenson Harwood LLP) por el Primer Demandado
* Saul Margo (también instruido por Stephenson Harwood LLP) por el Primer Demandado
* Sr. Tennet (en representación del Segundo Demandado)
* Sr. Spink KC (también en representación del Segundo Demandado)
* Arden LJ (mencionado como quien dictó una sentencia anterior en Stena Line)
Tenga en cuenta que "KC" significa King's Counsel, que es un título de distinción conferido a ciertos barristers sénior en Inglaterra y Gales.
Conclusión
Configurar RAG con Milvus y Ollama para datos jurídicos puede hacer que la investigación jurídica sea mucho más fácil y eficiente.
No dude en consultar Milvus, el código en Github, y compartir sus experiencias con la comunidad uniéndose a nuestro Discord.
Más recursos sobre Milvus y Ollama:
Sigue leyendo

The Real Bottlenecks in Autonomous Driving — And How AI Infrastructure Can Solve Them
Autonomous driving faces a data bottleneck. Learn how AI-native vector databases like Zilliz solve scale, cost, and insight challenges across AV pipelines.

Zilliz Cloud Delivers Better Performance and Lower Costs with Arm Neoverse-based AWS Graviton
Zilliz Cloud adopts Arm-based AWS Graviton3 CPUs to cut costs, speed up AI vector search, and power billion-scale RAG and semantic search workloads.

Proactive Monitoring for Vector Database: Zilliz Cloud Integrates with Datadog
we're excited to announce Zilliz Cloud's integration with Datadog, enabling comprehensive monitoring and observability for your vectorDB deployments.



