knowledge graphsを使ったRAGへ初めの一歩

はじめに

少し前のこの投稿で、ナレッジグラフを使うため、nao4jをローカル環境(dockerコンテナとして)インストールしたことについて述べた。

この投稿ではネット記事を参考にしながら、簡単なナレッジグラフを構築し、RAGとして使用してみたので、その内容についてまとめたい。今回はネット記事をそのまま試したので初めの一歩とした。

情報源

  1. Knowledge Graphを使った RAG をLangChainで実装 前編 今回の内容は、この記事のコード(以下、情報源コードと呼ぶ)をそのまま実行した。ナレッジグラフをRAGを実現する流れが理解できる内容である。
  2. RAGアプリケーションの精度をナレッジグラフで高める Neo4j開発者ブログの記事の日本語訳。情報源1.は、このページおよびこのページでポイントしているgithubが元になっていると思われる。

LLMについて

情報源コードを6つのLLMで試した。実行結果は次の通り。

LLM 実行結果
PLaMo β BadRequestError: Error code: 400 - {‘message’: ‘invalid field: parallel_tool_calls’}
Llama-3-ELYZA-JP-8B-q4_k_m.gguf ImportError: Could not import json_repair python package. Please install it with pip install json-repair.json-repairを追加して、実行するも次のエラー。グラフが作られていないようだ?Received notification from DBMS server: {severity: WARNING} {code: Neo.ClientNotification.Statement.UnknownRelationshipTypeWarning} {category: UNRECOGNIZED} {title: The provided relationship type is not in the database.} {description: One of the relationship types in your query is not available in the database, make sure you didn’t misspell it or that the label is available when you run this statement in your application (the missing relationship type is: MENTIONS)} {position: line: 1, column: 15, offset: 14} for query: ‘MATCH (s)-[r:!MENTIONS]->(t) RETURN s,r,t LIMIT 50’
llama-3-youko-8b-instruct.Q6_K.gguf TypeError: string indices must be integers
gpt-4o 正しく実行される。上記2つのLLMで、正しく実行されないようなので、サンプルコードで使われているLLMと同じものを使った。この記事にも同じようにLLMでハマっている記事があった。
gpt-4o-mini 正しく実行される。 API使用料金を抑えるために、こちらを使うようにした。
Mistral-7B-Instruct-v0.3-Q6_K.gguf TypeError: list indices must be integers or slices, not str

情報源2.によると、サポートしているLLMは、OpenAIとMistralとあったので、「Mistral-7B-Instruct-v0.3-Q6_K.gguf」を試したが、上の表の通り、エラーとなった。OpenAIと同じようにAPI版でないと使えないのかな?

手順

Dockerfile

情報源コードを実行するために、必要なパッケージを追加したjupyterlabのDockerfileの抜粋を以下に示す。他の部分は、この記事のDockerfileと同じである。

RUN pip install --upgrade pip setuptools \
        && pip install torch==2.2.2 torchvision==0.17.2 torchaudio==2.2.2 \
        --index-url https://download.pytorch.org/whl/cu121 \
        && pip install torch torchvision torchaudio \
        && pip install jupyterlab matplotlib pandas scikit-learn ipywidgets \
        && pip install transformers accelerate sentencepiece einops \
        && pip install langchain bitsandbytes protobuf \
        && pip install auto-gptq optimum \
        && pip install pypdf tiktoken sentence_transformers faiss-gpu trafilatura \
        && pip install langchain-community langchain_openai wikipedia \
        && pip install langchain-huggingface unstructured html2text rank-bm25 janome \
        && pip install langchain-chroma sudachipy sudachidict_full \
        && pip install mysql-connector-python \
        && pip install langchain-experimental neo4j pandas \
        && pip install json-repair

情報源コードを実行するための追加部分は、最後から2行目「pip install langchain-experimental neo4j pandas」である。最後の「pip install json-repair」は、「LLMについて」の「実行結果」で記載したとおり、Llama-3-ELYZA-JP-8B-q4_k_m.gguf モデルを使うとエラーとなったので追加したものである。

Graphを作成

情報源コードをそのまま実行した。

自分の環境に合わせて追加/修正したコードのみを以下に示す。

# neo4j用の環境変数を設定
import os

os.environ['NEO4J_URI'] = 'bolt://192.168.11.8:7687'
os.environ['NEO4J_USERNAME'] = 'neo4j'
os.environ['NEO4J_PASSWORD'] = 'password'

NEO4J_URIは、この記事でインストールしたコンテナが動作しているサーバのIPアドレスとポート。

詳細は、こちらのDocsページを参照のこと。実は、ここで自分はハマった。

NEO4J_USERNAME/PASSWORDは、同じ記事のdocker-compose.ymlのNEO4J_AUTHで指定したIDとパスワード。

# OpenAIのAPIキーを設定する
import os

os.environ['OPENAI_API_KEY'] = 'xxxx'

「xxxx」の部分は、取得したAPIキーである。

得られたグラフをブラウザから接続して確認した時の画面キャプチャは以下の通り。

neo4j_01

Vector Store インデックスを作成

更に、情報源コードに従って、Neo4jVectorでインデックスを作成する。記事と同じように、追加を確認する。

neo4j_03

Graphからの retrieverとVector Storeからのretriever

情報源コードの「2.RAGでのLLM実行」の部分も、そのまま実行した。

自分が実行したChainの部分コードは次の通り。

# Chainを実行

from langchain_core.runnables import RunnableParallel, RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

template = """Answer the question based only on the following context:
{context}

Question: {question}
Use natural language and be concise.
Answer:"""
prompt = ChatPromptTemplate.from_template(template)

chain = (
    RunnableParallel(
        {
            "context": retriever,
            "question": RunnablePassthrough(),
        }
    )
    | prompt
    | ChatOpenAI(temperature=0, model_name="gpt-4o")
    | StrOutputParser()
)

chain.invoke("花田はどんな人間?")

実行結果は次の通り。

Search query: 花田はどんな人間?
'花田一路は近所でも有名な腕白小僧です。'

今後について

今回、Knowledge Graphsを使ったRAGシステムが自分の環境でも試せるようになった。

今後、情報源記事の後編を試した後、自分のデータを使ってGraph RAGを試してみたい。

更に、gpt-*以外のLLMが使えないか、もう少し調査もしてみたい。