Simplifier la recherche juridique avec RAG, Milvus et Ollama
Dans cet article de blog, nous verrons comment appliquer RAG aux données juridiques.
La recherche juridique peut prendre beaucoup de temps. Vous devez généralement examiner un grand nombre de documents pour trouver les réponses dont vous avez besoin. La génération augmentée par récupération (Retrieval-Augmented Generation, RAG) peut vous aider à rationaliser votre processus de recherche.
Qu’est-ce que RAG ?
Retrieval Augmented Generation (RAG) est une technique qui améliore les LLM en intégrant des sources de données supplémentaires. Une application RAG typique implique :
Indexation - un pipeline pour ingérer des données depuis une source et les indexer, ce qui consiste généralement à charger, diviser et trier les données dans Milvus.
Récupération et génération - À l’exécution, RAG traite la requête de l’utilisateur, récupère les données pertinentes depuis l’index stocké dans Milvus, et le LLM génère une réponse basée sur ce contexte enrichi.
Dans ce guide pratique, nous explorerons comment configurer un système de génération augmentée par récupération (RAG) à l’aide d’Ollama, en nous concentrant sur les données juridiques et en tirant parti de Milvus comme base de données vectorielle.
Les outils :
Ollama : Apporte la puissance des LLM à votre ordinateur portable, simplifiant l’exécution locale.
Milvus : La base de données vectorielle que nous utilisons pour stocker et récupérer efficacement vos données.
Llama 3 : La dernière itération de Meta dans une gamme de grands modèles de langage.
Voyage AI - Fournit des modèles d’embedding spécialisés dans des domaines spécifiques. Nous utilisons leur embedding juridique spécialisé, optimisé pour la récupération juridique et à long contexte.
Préparation
Dépendances et données
Tout d’abord, installez les dépendances nécessaires :
! pip install --upgrade pymilvus ollama tqdm pypdf voyageai openai wget
Importer les clés API
Si votre clé API est définie dans un fichier .env, vous pouvez la charger avec dotenv afin d’éviter de divulguer la clé lorsque vous publiez votre notebook.
import os
from dotenv import load_dotenv
load_dotenv()
VOYAGE_API_KEY = os.getenv('VOYAGE_API_KEY')
Si vous n’avez pas de fichier .env, ignorez simplement l’importation de dotenv.
Préparer les données
Pour ce tutoriel, nous utiliserons des données provenant des Royal Courts of Justice à Londres. Téléchargez-les avec wget et enregistrez-les localement :
! wget https://www.judiciary.uk/wp-content/uploads/2024/07/Final-Judgment-CA-2023-001978-BBC-v-BBC-Pension-Trust-another.pdf
Ensuite, lisez le fichier PDF et extrayez son contenu pour l’utiliser dans notre application 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])
Cela devrait vous donner la sortie suivante :
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
Générer les embeddings de vos documents
Nous utiliserons voyage-law-2, un modèle d’embedding spécialisé pour le domaine juridique.
Tout d’abord, définissez une fonction pour générer des embeddings de texte à l’aide de 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]
Générez un embedding de test et affichez sa dimension ainsi que ses premiers éléments.
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]
Charger les données dans Milvus
Créer la collection dans Milvus
from pymilvus import MilvusClient
milvus_client = MilvusClient(uri="./milvus_legal.db")
collection_name = "my_rag_collection"
Définir l’URI comme un fichier local, par exemple ./milvus_legal.db, est pratique, car cela utilise automatiquement Milvus Lite pour stocker toutes les données dans ce fichier. Pour des données à grande échelle, vous pouvez mettre en place un serveur Milvus plus performant sur Docker ou Kubernetes.
Supprimez la collection si elle existe déjà, puis créez-en une nouvelle :
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 nous ne spécifions aucune information de champ, Milvus créera automatiquement un champ id par défaut pour la clé primaire, ainsi qu’un champ vectoriel pour stocker les données vectorielles. Un champ JSON réservé est utilisé pour stocker les champs non définis par le schéma et leurs valeurs.
Insérer les données
Parcourez les pages de notre document, créez les embeddings, puis insérez les données dans Milvus.
Nous introduisons un nouveau champ appelé text, un champ non défini dans le schéma de la collection. Il sera automatiquement ajouté au champ dynamique JSON réservé, qui peut être traité comme un champ normal à haut niveau.
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}
Construire le système RAG de base
Ensuite, définissons une question sur le contenu de l’audience :
question = "who are the lawyers?"
Nous utiliserons Milvus pour rechercher nos données indexées. Plus tard, nous intégrerons cela avec 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
)
Affichez les lignes récupérées avec leurs distances :
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))
```
Le texte associé à nos embeddings est assez long, mais voici un exemple de ce que Milvus renvoie
[" n nNuméro de référence neutre [2024] EWCA Civ 767 n nAffaire n° : CA-2023 -001978 nDEVANT LA COUR D’APPEL ( DIVISION CIVILE) nEN APPEL DEPUIS LA HAUTE COUR DE JUSTICE nTRIBUNAUX DES AFFAIRES COMMERCIALES ET DE LA PROPRIÉTÉ D’ANGLETERRE ET DU PAYS DE GALLES nLISTE COMMERCIALE : PENSIONS (ChD) nL’Honorable juge Adam Johnson n[2023] EWHC 1965 (Ch) nRoyal Courts of Justice nStrand, London, WC2A 2LL n nDate : 09/07 /2024 nDevant : n nLORD JUSTICE LEWISON nLADY JUSTICE FALK net nSIR CHRISTOPHER FLOYD n n- - - - - - - - - - - - - - - - - - - - - n nEntre : n n BRITISH BROADCASTING CORPORATION Appelante n - et - n (1) BBC P ENSION TRUST LIMITED n(2) CHRISTINA BURNS nIntimé s n n- - - - - - - - - - - - - - - - - - - - - n n Michael Tennet KC et Edward Sawyer (mandatés par Linklaters LLP ) npour l’Appelante n Brian Green KC et Joseph Steadman (mandatés par Slaughter and May Solicitors ) npour la Première Intimée nAndrew Spink KC et Saul Margo (mandatés par Stephenson Harwood LLP ) npour la Deuxième Intimée n nDates d’audience : 25, 26 & 27/06/2024 n- - - - - - - - - - - - - - - - - - - - - n nJugement approuvé n nCe jugement a été rendu à distance à 11h00 le 09/07/2024 par diffusion aux nparties ou à leurs représentants par e -mail et par transmission aux Archives nationales. n n............................. n",
0.1101425364613533
],
Utiliser un LLM pour obtenir une réponse RAG
Combinez les documents récupérés dans un contexte et définissez les prompts système et utilisateur pour le modèle de langage :
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 dispose d’une API OpenAI entièrement compatible, ce qui signifie que nous pouvons utiliser le SDK Python OpenAI pour appeler 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)
Selon le texte, les avocats impliqués dans cette affaire sont :
* Andrew Spink KC (mandaté par Stephenson Harwood LLP) pour la Première Intimée
* Saul Margo (également mandaté par Stephenson Harwood LLP) pour la Première Intimée
* M. Tennet (représentant la Deuxième Intimée)
* M. Spink KC (représentant également la Deuxième Intimée)
* Arden LJ (mentionnée comme ayant rendu un jugement antérieur dans Stena Line)
Notez que « KC » signifie King's Counsel, un titre de distinction conféré à certains avocats plaidants seniors en Angleterre et au pays de Galles.
Conclusion
La mise en place d’un RAG avec Milvus et Ollama pour les données juridiques peut rendre la recherche juridique beaucoup plus facile et plus efficace.
N’hésitez pas à consulter Milvus, le code sur Github, et à partager vos expériences avec la communauté en rejoignant notre Discord.
Plus de ressources sur Milvus et Ollama :
Continuer à lire

Zilliz Cloud Update: Tiered Storage, Business Critical Plan, Cross-Region Backup, and Pricing Changes
This release offers a rebuilt tiered storage with lower costs, a new Business Critical plan for enhanced security, and pricing updates, among other features.

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.

Announcing the General Availability of Zilliz Cloud BYOC on Google Cloud Platform
Zilliz Cloud BYOC on GCP offers enterprise vector search with full data sovereignty and seamless integration.



