TAKEO

TAKEO

OpenAIEmbeddingsを使ってみた

OpenAIEmbeddingsは、テキストをベクトル形式に変換するための埋め込み(Embedding)モデルの一種で、特に自然言語処理(NLP)での検索、分類、クラスタリングなどに役立ちます。この埋め込みモデルは、言語の意味や関係をベクトル空間に表現することで、文書や単語の意味を比較したり、類似性を評価したりするのに使われます。

OpenAIEmbeddingsの特徴

  1. 高次元ベクトルへの変換 OpenAIEmbeddingsは、テキストを固定の次元数(例えば、1536次元など)のベクトルに変換します。このベクトルは、テキストの意味や文脈を表現した数値データであり、類似性比較や距離計算に使用されます。

  2. 意味の保持 同じ意味や関連性を持つテキストは、ベクトル空間上で近くに配置されます。これにより、意味検索や関連文書の検索が容易になります。例えば、「犬」と「猫」のベクトルは、「犬」と「テーブル」のベクトルよりも近くに配置される傾向があります。

  3. 応用例

    • 意味検索: 特定のクエリに対して、類似の文書やフレーズをベクトル距離を使って検索します。
    • 分類・クラスタリング: テキストのクラス分けや、類似性に基づいたクラスタリング。
    • 質問応答システム: 質問と回答の意味的な一致を判断して関連情報を提供します。
  4. トレーニングと精度 OpenAIEmbeddingsは、大規模なデータセットでトレーニングされており、高度な意味理解能力を備えています。そのため、さまざまな業界のアプリケーションで正確な結果が期待できます。

OpenAIEmbeddingsは、情報検索、類似性検索、レコメンデーションエンジンなどの構築に便利で、言語理解が必要な幅広い用途で利用されています。

実際に使ってみよう!

実際にOpenAIEmbeddingsを使ってみました。筆者のブログ内容を知識のベースとし、質問応答システムを作ってみます!以下3つのブログが知識のベースとなります。

準備

  • OpenAIのAPIキーが必要です。OpenAIプラットフォームで取得できます。

  • 今回必要なライブラリです。各パッケージの詳細なversionはブログの末尾に記載しています。

    Copied!!
    $ pip install -U langchain
    $ pip install -U langchain-openai
    $ pip install -U langchain-community
    $ pip install -U langchain-core
    

実装

sample.py
Copied!!
import os
from langchain_openai import OpenAIEmbeddings
from langchain_community.document_loaders import WebBaseLoader, TextLoader
from langchain_core.vectorstores import InMemoryVectorStore
from langchain.text_splitter import RecursiveCharacterTextSplitter

# OpenAI APIキーの設定
os.environ["OPENAI_API_KEY"] = (
    "OpenAIのAPIキーに置き換えてください"
)

# Webページの読み込み:これが今回モデルで使用する知識のベースになります。
web_loader = WebBaseLoader(
    [
        "https://www.takeo-blog.jp/posts/tech/java-jit-sample",  # JavaのJITについてのブログ
        "https://www.takeo-blog.jp/posts/tech/python-pickle",  # Pyhtonのpickleについてのブログ
        "https://www.takeo-blog.jp/posts/tech/process-thread-relation",  # プロセスとスレッドの関係についてのブログ
    ]
)
web_docs = web_loader.load()
print(f"web_docs num: {len(web_docs)}")  # 3

# web_docsのままだと知識数が3つです。
# このまま「JITとは何の略ですか?」のように検索すると、検索結果が3通りになってしまいます。(いずれかのブログのページの内容を丸ごと返してしまう)
# そのため、150文字ずつにブログの内容を分割します。(chunk_size=150)
# chunk_overlap=100 は、チャンク同士が重なる文字数が100文字であることを示します。
# chunk分割のイメージ
# チャンク1:最初の150文字
# チャンク2:1チャンク目の最後の100文字と、次の50文字(合計150文字)
# チャンク3:2チャンク目の最後の100文字と、次の50文字
text_splitter = RecursiveCharacterTextSplitter(chunk_size=150, chunk_overlap=100)
splits = text_splitter.split_documents(web_docs)
print(f"splits num: {len(splits)}")  # 63: 3個のブログの内容を63個の知識に分割しました

# Embeddingsモデルの初期化
embeddings = OpenAIEmbeddings()

# RAM上にベクトルストアを作成します
vectorstore = InMemoryVectorStore.from_documents(
    documents=splits,      # 63個のドキュメントを知識として使います
    embedding=embeddings,  # OpenAIEmbeddingモデル
)

# ベクトルストアから取り出し専用のインスタンスを作ります
retriever = vectorstore.as_retriever()

# 質問に対して関連するドキュメントを探します。
query = "JITとは何の略ですか?"
retrieved_documents = retriever.invoke(query)
print(f"== {query} ==")
# 0番目に最も関連するドキュメントが格納されています。
print(retrieved_documents[0].page_content)

query = "pickleとは何ですか?"
retrieved_documents = retriever.invoke(query)
print(f"== {query} ==")
# 0番目に最も関連するドキュメントが格納されています。
print(retrieved_documents[0].page_content)

query = "プロセスの定義を教えて"
retrieved_documents = retriever.invoke(query)
print(f"== {query} ==")
# 0番目に最も関連するドキュメントが格納されています。
print(retrieved_documents[0].page_content)

実行結果

以下は筆者の環境での出力例です。それぞれの質問について、関連するドキュメントを取り出すことができていますね!すごい!

Copied!!
$ python3 embeddings-sample.py
USER_AGENT environment variable not set, consider setting it to identify your requests.
web_docs num: 3
splits num: 63
== JITとは何の略ですか? ==
JITとは
JIT(Just-in-Time)コンパイルとは、Javaなどの一部のプログラミング言語における実行時の最適化技術の一つです。JITは、プログラムを実行するタイミングでコードを機械語にコンパイルすることで、実行パフォーマンスを向上させる役割を果たします。
JITコンパイルの仕組み
== pickleとは何ですか? ==
pickleはPythonオブジェクトをバイナリ化することができるツールです。また、バイナリ化したものをPythonオブジェクトに復元することができます。基本的な使い方は次の通りです。
ファイル書き込み・読み込み
== プロセスの定義を教えて ==
プロセスの定義
「プロセスは独立したメモリ空間を持つプログラムの実行単位で、プロセス間でメモリを共有しません。」
この定義についてマクドナルドの注文処理を例に説明します。
プロセスと並列処理の例 - マクドナルドの注文処理編


1プロセスの例:店員が1人の場合

まとめ・所感・日記

今日はOpenAIEmbeddingsについて調べてみました。今回これを調べるに至った経緯ですが、

という記事を見つつ、手を動かして実装していたところ、こやつは何ぞと思いこのページを書くまでに至りました。今朝初めてOpenAI Platformに課金して、ChatGPTをAPI経由で叩けるようになったばかりで、言語モデル系に関する知識が全くない状態だったんですが、なんか一気に理解がすすんだような気がしました。これでRAGの理解を進められそうです!

最後に、OpenAIEmbeddingsのテストケースとして、いくつかの実用例を紹介します。これらは、特に自然言語検索やレコメンデーションに役立つシナリオです。

テストケース1: 類似文検索(意味検索)

シナリオ: 英単語学習ゲームや用語辞典のようなシステムで、ユーザーが単語やフレーズを検索するとき、意味が似ているフレーズを引き出す。

  • テストケース:
    • ユーザーが「キャンセル」というキーワードを検索したとします。OpenAIEmbeddingsを使って、類似する「取り消し」「中止」などの関連する単語やフレーズを返すように設計します。
    • assert文を用いて、期待した結果に類似度が高い結果が得られているかを確認します。
  • 成功基準: キーワードと関連の高い語句が表示され、検索結果が意味的に一致する。

テストケース2: Q&Aシステムでの最適回答検索

シナリオ: Q&Aシステムにおいて、ユーザーからの質問に関連する回答をOpenAIEmbeddingsで探し出し、適切な返答を提供する。

  • テストケース:
    • 質問例: 「TOEIC学習に役立つ勉強方法は?」。この質問をベクトル化し、知識ベースに保存されているベクトルと比較して最も類似度の高い回答を取得。
    • 質問と回答をペアにしてテストし、関連性の高い回答が適切に返されるかを確認します。
  • 成功基準: 質問に合致した回答がトップに表示されること。

テストケース3: 類似製品の推薦(レコメンデーション)

シナリオ: ユーザーが閲覧した製品やアイテムに類似するものを推薦する。

  • テストケース:
    • ユーザーが「ノートパソコン」を検索した場合、関連する「タブレット」「デスクトップPC」など、埋め込みベクトルが近いアイテムを推奨リストに表示。
    • 類似度の高い製品が推薦されているかを確認し、適切に並んでいるかをテストします。
  • 成功基準: ユーザーの検索意図に近い製品が上位に並び、レコメンデーションとして機能していること。

テストケース4: TOEIC頻出単語学習での類似単語の提供

シナリオ: 英単語学習ゲーム内で、ユーザーが特定の単語を検索したときに、類似単語を埋め込みを使用して提示する。

  • テストケース:
    • ユーザーが「vacation」を検索すると、関連する「休暇」「休み」などの日本語訳や類似する英単語「holiday」などが表示される。
    • 結果がTOEIC頻出の単語として適切か、意味が通るかを確認。
  • 成功基準: 検索単語と関連性のある単語やフレーズが上位に表示され、学習効果が高まる。

付録 - 環境情報

Copied!!
$ python3 --version
Python 3.10.12
Copied!!
$ pip show langchain
Name: langchain
Version: 0.3.7
Summary: Building applications with LLMs through composability
Home-page: https://github.com/langchain-ai/langchain
Author:
Author-email:
License: MIT
Location: /home/hoge/lib/python3.10/site-packages
Requires: aiohttp, async-timeout, langchain-core, langchain-text-splitters, langsmith, numpy, pydantic, PyYAML, requests, SQLAlchemy, tenacity
Required-by: langchain-community
$ pip show langchain-core
Name: langchain-core
Version: 0.3.15
Summary: Building applications with LLMs through composability
Home-page: https://github.com/langchain-ai/langchain
Author:
Author-email:
License: MIT
Location: /home/hoge/lib/python3.10/site-packages
Requires: jsonpatch, langsmith, packaging, pydantic, PyYAML, tenacity, typing-extensions
Required-by: langchain, langchain-community, langchain-openai, langchain-text-splitters
$ pip show langchain-community
Name: langchain-community
Version: 0.3.5
Summary: Community contributed LangChain integrations.
Home-page: https://github.com/langchain-ai/langchain
Author:
Author-email:
License: MIT
Location: /home/hoge/lib/python3.10/site-packages
Requires: aiohttp, dataclasses-json, httpx-sse, langchain, langchain-core, langsmith, numpy, pydantic-settings, PyYAML, requests, SQLAlchemy, tenacity
Required-by:
$ pip show langchain-openai
Name: langchain-openai
Version: 0.2.6
Summary: An integration package connecting OpenAI and LangChain
Home-page: https://github.com/langchain-ai/langchain
Author:
Author-email:
License: MIT
Location: /home/hoge/lib/python3.10/site-packages
Requires: langchain-core, openai, tiktoken
Required-by: