46.4kデモを予約するログイン無料で始める

RAG、Milvus、Ollamaによるリーガル・リサーチの簡素化

Jul 12, 20242 min read

このブログでは、リーガル・データにRAGを適用する方法を紹介する。

法務調査は時間がかかるものです。必要な答えを見つけるためには、通常、大量の文書をレビューする必要があります。Retrieval-Augmented Generation (RAG)はリサーチプロセスの効率化に役立ちます。

RAGとは?

Retrieval Augmented Generation(RAG)は、追加のデータソースを統合することによってLLMを強化する技術です。典型的なRAGアプリケーションには以下が含まれる:

  • インデックス作成** - データソースからデータを取り込み、インデックスを作成するパイプライン。

  • 検索と生成** - 実行時に、RAGはユーザーのクエリを処理し、Milvusに格納されたインデックスから関連データをフェッチし、LLMはこのエンリッチされたコンテキストに基づいてレスポンスを生成する。

このハンズオンガイドでは、Ollamaを使用したRAG(Retrieval Augmented Generation)システムのセットアップ方法を、法律データに焦点を当て、ベクターデータベースとしてMilvusを活用しながらご紹介します。

**ツール

  • Ollama](https://ollama.com/):LLMのパワーをラップトップにもたらし、ローカル操作を簡素化する。

  • Milvus](https://github.com/milvus-io/milvus):データを効率的に保存・検索するために使用するベクトルデータベース。

  • Llama 3](https://llama.meta.com/llama-downloads):Metaの大規模言語モデルの最新版。

  • Voyage AI](https://www.voyageai.com/) - 特定のドメインに特化した埋め込みモデルを提供。法律や長い文脈の検索に最適化されている。

準備

依存関係とデータ

まず、必要な依存関係をインストールします:


    pip install --upgrade pymilvus ollama tqdm pypdf voyageai openai wget

API キーのインポート

API キーが .env ファイルに設定されている場合、dotenv を使用してそれを読み込むことで、ノートブックをプッシュする際にキーが漏れるのを防ぐことができる。


    import os
    from dotenv import load_dotenv

    load_dotenv()

    VOYAGE_API_KEY = os.getenv('VOYAGE_API_KEY')

.envファイルがない場合は、dotenv` インポートをスキップしてください。

データの準備

このチュートリアルでは、ロンドンのRoyal Courts of Justiceのデータを使います。wget`を使ってダウンロードし、ローカルに保存する:


    wget https://www.judiciary.uk/wp-content/uploads/2024/07/Final-Judgment-CA-2023-001978-BBC-v-BBC-Pension-Trust-another.pdf

次に、PDFファイルを読み込み、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])

これで次のような出力が得られるはずだ:


    中立引用番号 [2024] EWCA Civ 767
     
    事件番号  CA-2023 -001978
    控訴裁判所(民事部)
    高等法院からの控訴
    イングランドおよびウェールズのビジネスおよび財産裁判所
    企業リスト:年金(ChD)
    アダム・ジョンソン裁判官
    [2023] EWHC 1965 (Ch)
    王立裁判所
    ロンドン、ストランド、WC2A 2LL
     
    日付: 2024年7月9日
    前
     
    ルウィソン判事
    フォーク判事
    そして
    クリストファー・フロイド判事

ドキュメントを埋め込む

法律領域に特化した埋め込みモデルである voyage-law-2 を使用します。

まず、Voyage AI APIを使って埋め込みテキストを生成する関数を定義します:


    インポート voyageai

    voyage_client = voyageai.Client()

    def embed_text(text: str) -> str:
        return voyage_client.embed([text], model="voyage-law-2").embeddings[0].

テスト埋め込みを生成し、その次元と最初のいくつかの要素を表示します。


    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]

データをMilvusにロードする

Milvusでコレクションを作成する


    from pymilvus import MilvusClient

    milvus_client = MilvusClient(uri="./milvus_legal.db")

    コレクション名 = "my_rag_collection"

URIをローカルファイル、例えば./milvus_legal.dbに設定すると、自動的にMilvus Liteを使用してこのファイルにすべてのデータを保存するので便利である。大規模なデータについては、DockerやKubernetes上でよりパフォーマンスの高いMilvusサーバを立ち上げることができる。

コレクションが既に存在する場合は削除し、新しいコレクションを作成する:


    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", # 内積距離
        consistency_level="Strong", # 強い一貫性レベル
    )

フィールド情報を指定しない場合、Milvusは自動的にプライマリキー用のデフォルトidフィールドと、ベクトルデータを格納するためのベクトルフィールドを作成します。予約されたJSONフィールドはスキーマで定義されていないフィールドとその値を格納するために使用されます。

データの挿入

ドキュメントのページを繰り返し、埋め込みを作成し、Milvusにデータを挿入します。

コレクションスキーマの非定義フィールドである text という新しいフィールドを導入する。これは予約されたJSON動的フィールドに自動的に追加され、高レベルでは通常のフィールドとして扱うことができる。


    from tqdm import tqdm

    data = [] (データ)

    for i, page in enumerate(tqdm(pages, desc="埋め込みを作成する")):
        data.append({"id": i, "vector": embed_text(page), "text": page})

    milvus_client.insert(collection_name=collection_name, data=data)


    エンベッディングの作成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}

基本的なRAGシステムを構築する

次に、裁判の審理内容に関するクエリを定義してみよう:


    question = "弁護士は誰ですか?"

インデックスされたデータを検索するためにMilvusを使う。後で、これをLLMと統合する。


    search_res = milvus_client.search(
        コレクション名=コレクション名、
        data=[
            embed_text(question)
        ], # `embed_text`関数を使って質問を埋め込みベクトルに変換する
        limit=3, # 上位3つの結果を返す
        search_params={"metric_type":"IP", "params":{}}, # 内積距離
        output_fields=["text"], # テキストフィールドを返す
    )

検索された行とその距離を表示する:


    インポート 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))
    ```

埋め込みに関連するテキストはかなり長いですが、Milvusが返すものの例を示します。

[中立引用番号 [2024] EWCA Civ 767 n 事件番号  CA-2023 -001978 nIN THE COURT OF APPEAL ( CIVIL DIVISION) nNON APPEAL FROM THE HIGH COURT OF JUSTICE nBUSINESS AND PROPERTY COURTS OF ENGLAND AND WALES nBUSINESS LIST :  n n Michael Tennet KC および Edward Sawyer(Linklaters LLP が代理) n n 控訴人の代理人 n Brian Green KC および Joseph Steadman(Slaughter and May Solicitors が代理) n 第1被控訴人の代理人 n Andrew Spink KC および Saul Margo(Stephenson Harwood LLP が代理) n 第2被控訴人の代理人 n 審問日
        0.1101425364613533
    ],

LLMを使ってRAGレスポンスを取得する

検索された文書をコンテキストに結合し、言語モデルに対するシステムとユーザーのプロンプトを定義する:

    コンテキスト = "n".join(
        [line_with_distance[0]、line_with_distance in retrieved_lines_with_distances)
    )

    system_prompt = """
    Human: あなたはAIアシスタントです。あなたは提供された文脈に沿った文章の断片から質問の答えを見つけることができます。
    """

    USER_PROMPT = f""
        <question>タグで囲まれた質問に対する答えを提供するために、<context>タグで囲まれた以下の情報の断片を使ってください。
        <context>
        {コンテキスト}
        </context>
        <question>
        質問
        </question>
    """

Ollamaは完全に互換性のあるOpenAI APIを持っています。つまり、OpenAI Python SDKを使ってOllamaを呼び出すことができます:

from openai import OpenAI

client = OpenAI(
    base_url = 'http://localhost:11434/v1'、
    api_key='ollama', # 必須だが未使用
)

response = client.chat.completions.create(
    model="llama3"、
    messages=[
        {"role":"system", "content":system_prompt}、
        {"role":"user", "content":USER_PROMPT}、
    ],
)
print(response.choices[0].message.content)
    本文によると、この件に関与した弁護士は以下の通り:

    * アンドリュー・スピンクKC(Stephenson Harwood LLPの代理人)が一審被告を担当。
    * ソール・マーゴ(同じくStephenson Harwood LLPの代理人
    * テネット氏(第二被申立人の代理人)
    * スピンクKC(同じく二審被告代理人)
    * アーデン法務大臣(Stena Line事件で判決を下したことがある。)

    KC」はKing's Counselの略であり、イングランドおよびウェールズの特定の上級法廷弁護士に与えられる称号である。

結論

MilvusとOllamaで法律データのRAGをセットアップすることにより、法律調査がより簡単で効率的になる。

Milvus](https://github.com/milvus-io/milvus)やGithubにあるコードを自由にチェックし、私たちのDiscordに参加してコミュニティと経験を共有してください。

MilvusとOllamaに関するその他のリソース:

  • Kickstart Your Local RAG Setup:Ollama、Milvus、LangChainでLlama 3を使うための初心者ガイド](https://zilliz.com/blog/a-beginners-guide-to-using-llama-3-with-ollama-milvus-langchain)

  • Llama3、Ollama、DSPy、Milvusを使った検索支援生成(RAG)システムの構築方法](https://zilliz.com/learn/how-to-build-rag-system-using-llama3-ollama-dspy-milvus)

  • Milvus、Ollama、LangGraphを使ったエージェント型RAGの構築](https://www.youtube.com/watch?v=GMWEdjsgM6A)

Updated on Jul 09, 2026