【Ollama】【LangChain】RAG (Retrieval-Augmented Generation)を実行する

この書籍を購入しました。
gihyo.jp
第4章でRAG (Retrieval-Augmented Generation)がでてきます。

Ollamaを使って実行してみました。

GitHubリポジトリのクローン

git clone -b master --depth 1 https://github.com/langchain-ai/langchain

「mdx」ファイルを抽出

from langchain_community.document_loaders import GitLoader

loader = GitLoader(
    repo_path="./langchain",
    branch="master",
    file_filter=lambda file_path: file_path.endswith(".mdx")
)

raw_docs = loader.load()

print(len(raw_docs))
print(type(raw_docs))
print(type(raw_docs[0]))

結果

389
<class 'list'>
<class 'langchain_core.documents.base.Document'>

チャンクに分ける

from langchain_community.document_loaders import GitLoader
from langchain_text_splitters import CharacterTextSplitter

loader = GitLoader(
    repo_path="./langchain",
    branch="master",
    file_filter=lambda file_path: file_path.endswith(".mdx")
)

raw_docs = loader.load()

text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

docs = text_splitter.split_documents(raw_docs)

print(len(docs))
print(type(docs))
print(type(docs[0]))
1365
<class 'list'>
<class 'langchain_core.documents.base.Document'>

ベクトル化してローカルに保存

from langchain_community.document_loaders import GitLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_ollama import OllamaEmbeddings
from langchain_chroma import Chroma

loader = GitLoader(
    repo_path="./langchain",
    branch="master",
    file_filter=lambda file_path: file_path.endswith(".mdx")
)

raw_docs = loader.load()

text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)

docs = text_splitter.split_documents(raw_docs)

embed_model_id = "mxbai-embed-large:latest"
embeddings = OllamaEmbeddings(model=embed_model_id)

index = Chroma.from_documents(
    documents=docs,
    embedding=embeddings,
    persist_directory = "./vectorstore"
)

保存したデータからクエリに近いものを探す

from langchain_chroma import Chroma
from langchain_ollama import OllamaEmbeddings

embed_model_id = "mxbai-embed-large:latest"
embeddings = OllamaEmbeddings(model=embed_model_id)

vectorstore = Chroma(
    persist_directory="./vectorstore",
    embedding_function=embeddings
)

retriever = vectorstore.as_retriever()

query = "AWSのS3からデータを読み込むためのDocument loaderはありますか?"

context_docs = retriever.invoke(query)
print(f"len = {len(context_docs)}")
print()

first_doc = context_docs[0]
print(f"metadata = {first_doc.metadata}")
print()
print(first_doc.page_content)

結果

len = 4

metadata = {'file_name': 'aws.mdx', 'file_path': 'docs\\docs\\integrations\\providers\\aws.mdx', 'file_type': '.mdx', 'source': 'docs\\docs\\integrations\\providers\\aws.mdx'}

## Document loaders

### AWS S3 Directory and File

>[Amazon Simple Storage Service (Amazon S3)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html)
> is an object storage service.
>[AWS S3 Directory](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-folders.html)
>[AWS S3 Buckets](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)

See a [usage example for S3DirectoryLoader](/docs/integrations/document_loaders/aws_s3_directory).

See a [usage example for S3FileLoader](/docs/integrations/document_loaders/aws_s3_file).

```python
from langchain_community.document_loaders import S3DirectoryLoader, S3FileLoader
```

### Amazon Textract

>[Amazon Textract](https://docs.aws.amazon.com/managedservices/latest/userguide/textract.html) is a machine
> learning (ML) service that automatically extracts text, handwriting, and data from scanned documents.

See a [usage example](/docs/integrations/document_loaders/amazon_textract).

検索結果はデフォルトで4になっています。
変更する場合は以下のようにします。

retriever = vectorstore.as_retriever(
    search_kwargs={"k": 5}
)

RAGの実行

from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

embed_model_id = "mxbai-embed-large:latest"
embeddings = OllamaEmbeddings(model=embed_model_id)

model = ChatOllama(model="phi4", temperature=0)

prompt = ChatPromptTemplate.from_template('''\
以下の文脈だけを踏まえて質問に回答してください。

文脈: """
{context}
"""

質問: {question}
''')

vectorstore = Chroma(
    persist_directory="./vectorstore",
    embedding_function=embeddings
)

retriever = vectorstore.as_retriever()

query = "AWSのS3からデータを読み込むためのDocument loaderはありますか?"

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | model
    | StrOutputParser()
)

output = chain.invoke(query)
print(output)

結果

はい、AWS S3からデータを読み込むために使用できるDocument loaderがあります。提供された文脈によれば、`S3DirectoryLoader`と`S3FileLoader`の2つのオプションがあります。

  • `S3DirectoryLoader`: これはAWS S3ディレクトリからドキュメントを読み込むために使用されます。詳細な使用例は以下のリンク で確認できます: `/docs/integrations/document_loaders/aws_s3_directory`。
  • `S3FileLoader`: これはAWS S3ファイルからドキュメントを読み込むために使用されます。詳細な使用例は以下のリンクで確認できます: `/docs/integrations/document_loaders/aws_s3_file`。
どちらのloaderも、Pythonコード内で次のようにインポートして使用することができます: ```python from langchain_community.document_loaders import S3DirectoryLoader, S3FileLoader ```

使用したライブラリ

chromadb==0.5.23
GitPython==3.1.44
langchain==0.3.14
langchain-chroma==0.2.0
langchain-community==0.3.14
langchain-core==0.3.29
langchain-ollama==0.2.2
langchain-text-splitters==0.3.5
ollama==0.4.5