Semplificare la ricerca legale con RAG, Milvus e Ollama
In questo post del blog, vedremo come possiamo applicare RAG ai dati legali.
La ricerca legale può richiedere molto tempo. Di solito è necessario esaminare un gran numero di documenti per trovare le risposte di cui hai bisogno. Retrieval-Augmented Generation (RAG) può aiutare a semplificare il tuo processo di ricerca.
Che cos'è RAG?
Retrieval Augmented Generation (RAG) è una tecnica che potenzia gli LLM integrando fonti di dati aggiuntive. Una tipica applicazione RAG prevede:
Indicizzazione - una pipeline per acquisire dati da una fonte e indicizzarli, che di solito consiste nel caricare, suddividere e ordinare i dati in Milvus.
Recupero e generazione - In fase di esecuzione, RAG elabora la query dell'utente, recupera i dati pertinenti dall'indice archiviato in Milvus e l'LLM genera una risposta basata su questo contesto arricchito.
In questa guida pratica esploreremo come configurare un sistema Retrieval Augmented Generation (RAG) utilizzando Ollama, concentrandoci sui dati legali e sfruttando Milvus come nostro database vettoriale.
Gli strumenti:
Ollama: Porta la potenza degli LLM sul tuo laptop, semplificando l'esecuzione locale.
Milvus: Il database vettoriale che utilizziamo per archiviare e recuperare i tuoi dati in modo efficiente.
Llama 3: L'ultima iterazione di Meta di una serie di modelli linguistici di grandi dimensioni.
Voyage AI - Fornisce modelli di embedding specializzati in domini specifici. Stiamo utilizzando il loro embedding specializzato per il diritto, ottimizzato per il recupero legale e a lungo contesto.
Preparazione
Dipendenze e dati
Per prima cosa, installa le dipendenze necessarie:
! pip install --upgrade pymilvus ollama tqdm pypdf voyageai openai wget
Importa le chiavi API
Se hai impostato la tua chiave API in un file .env, puoi caricarla utilizzando dotenv per evitare di esporre la chiave quando carichi il tuo notebook.
import os
from dotenv import load_dotenv
load_dotenv()
VOYAGE_API_KEY = os.getenv('VOYAGE_API_KEY')
Se non hai un file .env, salta semplicemente l'importazione di dotenv.
Prepara i dati
Per questo tutorial, useremo dati della Royal Courts of Justice di Londra. Scaricali utilizzando wget e salvali localmente:
! wget https://www.judiciary.uk/wp-content/uploads/2024/07/Final-Judgment-CA-2023-001978-BBC-v-BBC-Pension-Trust-another.pdf
Successivamente, leggi il file PDF ed estrai il suo contenuto per utilizzarlo nella nostra applicazione 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])
Questo dovrebbe darti il seguente output:
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
Incorpora i tuoi documenti
Useremo voyage-law-2, un modello di embedding specializzato per il dominio legale.
Per prima cosa, definisci una funzione per generare embedding di testo utilizzando l'API 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 di test e stampa la sua dimensione e i primi elementi.
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]
Caricare i dati in Milvus
Creare la collection in Milvus
from pymilvus import MilvusClient
milvus_client = MilvusClient(uri="./milvus_legal.db")
collection_name = "my_rag_collection"
Impostare l'URI come file locale, ad esempio ./milvus_legal.db, è comodo perché utilizza automaticamente Milvus Lite per archiviare tutti i dati in questo file. Per dati su larga scala, puoi configurare un server Milvus più performante su Docker o Kubernetes.
Elimina la collection se esiste già, quindi creane una nuova:
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
)
Se non specifichiamo alcuna informazione sui campi, Milvus creerà automaticamente un campo id predefinito per la chiave primaria e un campo vettoriale per archiviare i dati vettoriali. Un campo JSON riservato viene utilizzato per archiviare campi non definiti nello schema e i relativi valori.
Inserire i dati
Itera attraverso le pagine del nostro documento, crea gli embeddings e poi inserisci i dati in Milvus.
Introduciamo un nuovo campo chiamato text, un campo non definito nello schema della collection. Verrà aggiunto automaticamente al campo dinamico JSON riservato, che può essere trattato come un campo normale a livello alto.
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}
Costruire il sistema RAG di base
Successivamente, definiamo una query sul contenuto dell'udienza in tribunale:
question = "who are the lawyers?"
Useremo Milvus per cercare nei nostri dati indicizzati. Più avanti, lo integreremo 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
)
Stampa le righe recuperate con le relative distanze:
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))
```
Il testo associato ai nostri embeddings è piuttosto lungo, ma ecco un esempio di ciò che Milvus restituisce
[" n nNumero di citazione neutrale [2024] EWCA Civ 767 n nN. caso: CA-2023 -001978 nNELLA CORTE D'APPELLO ( DIVISIONE CIVILE) nIN APPELLO DALLA ALTA CORTE DI GIUSTIZIA nTRIBUNALI PER LE IMPRESE E LA PROPRIETÀ DI INGHILTERRA E GALLES nELENCO COMMERCIALE : PENSIONI (ChD) nL'On. Mr Justice Adam Johnson n[2023] EWHC 1965 (Ch) nRoyal Courts of Justice nStrand, London, WC2A 2LL n nData: 09/07 /2024 nDavanti a : n nLORD JUSTICE LEWISON nLADY JUSTICE FALK ne nSIR CHRISTOPHER FLOYD n n- - - - - - - - - - - - - - - - - - - - - n nTra : n n BRITISH BROADCASTING CORPORATION Appellante n - e - n (1) BBC P ENSION TRUST LIMITED n(2) CHRISTINA BURNS nResistent i n n- - - - - - - - - - - - - - - - - - - - - n n Michael Tennet KC e Edward Sawyer (incaricati da Linklaters LLP ) nper l'Appellante n Brian Green KC e Joseph Steadman (incaricati da Slaughter and May Solicitors ) nper il Primo Resistente nAndrew Spink KC e Saul Margo (incaricati da Stephenson Harwood LLP ) nper il Secondo Resistente n nDate dell'udienza: 25, 26 & 27/06/2024 n- - - - - - - - - - - - - - - - - - - - - n nSentenza approvata n nQuesta sentenza è stata pronunciata da remoto alle 11.00 del 09/07/2024 mediante trasmissione alle nparti o ai loro rappresentanti via e -mail e mediante pubblicazione presso i Nat ional Archives. n n............................. n",
0.1101425364613533
],
Utilizzare un LLM per ottenere una risposta RAG
Combina i documenti recuperati in un contesto e definisci i prompt di sistema e utente per il modello linguistico:
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 ha un'API OpenAI pienamente compatibile, il che significa che possiamo usare l'SDK Python di OpenAI per chiamare 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)
Secondo il testo, gli avvocati coinvolti in questo caso sono:
* Andrew Spink KC (incaricato da Stephenson Harwood LLP) per il Primo Resistente
* Saul Margo (anch'egli incaricato da Stephenson Harwood LLP) per il Primo Resistente
* Mr. Tennet (che rappresenta il Secondo Resistente)
* Mr. Spink KC (che rappresenta anch'egli il Secondo Resistente)
* Arden LJ (menzionata come autrice di una precedente sentenza in Stena Line)
Si noti che "KC" sta per King's Counsel, che è un titolo di distinzione conferito ad alcuni barrister senior in Inghilterra e Galles.
Conclusione
Configurare RAG con Milvus e Ollama per dati legali può rendere la ricerca giuridica molto più semplice ed efficiente.
Sentiti libero di consultare Milvus, il codice su Github, e di condividere le tue esperienze con la community unendoti al nostro Discord.
Altre risorse su Milvus e Ollama:
Continua a leggere

Introducing Zilliz CLI and Agent Skills for Zilliz Cloud
Manage your vector database from your terminal or AI coding agent. Zilliz CLI and Agent Skills work with Claude Code, Cursor, Codex, and Copilot.

Zilliz Cloud Update: Smarter Autoscaling for Cost Savings, Stronger Compliance with Audit Logs, and More
What's new in Zilliz Cloud? Smarter autoscaling with scale-down, audit logs GA, enhanced SSO, and Milvus 2.6 in Private Preview.

Why Not All VectorDBs Are Agent-Ready
Explore why choosing the right vector database is critical for scaling AI agents, and why traditional solutions fall short in production.



