LlamIndex+Azure OpenAI ServiceをServiceContextをカスタマイズして実現してみた

カスタマイズしたLlamIndexのServiceContextとAzure OpenAI Serviceのモデルから、文脈を踏まえた回答を得てみました。
2023.06.23

データアナリティクス事業本部 インテグレーション部 機械学習チームの鈴木です。

LlamaIndexのドキュメントで、Azure OpenAI Serviceにデプロイしたモデルを利用するサンプルがあり、自分でも試してみたのでご共有です。

試したサンプル

以下のLlamaIndexライブラリの、Azure OpenAI向けのサンプルをやってみました。

前回はLangChainでAzure OpenAI Serviceにデプロイしたモデルを利用するサンプルの記事を公開しましたが、一部内容を踏まえているので、よければご確認ください。

クライアント実行環境

実行環境はGoogle Colaboratoryを使いました。ハードウェアアクセラレータ無し、ランタイム仕様は標準としました。

Pythonのバージョンは以下でした。

!python --version
# Python 3.10.12

また、ライブラリは以下のようにインストールしました。

!pip install llama-index
!pip install python-dotenv

インストールされたライブラリのバージョンは以下でした。

pip freeze | grep -e "openai" -e "llama" -e "langchain"
# langchain==0.0.209
# langchainplus-sdk==0.0.16
# llama-index==0.6.31
# openai==0.27.8

環境変数の設定

まず、必要な値を.envファイルに書き込みます。

# openaiパッケージの設定
!echo 'OPENAI_API_TYPE="azure"' >.env
!echo 'OPENAI_API_BASE="<エンドポイント>"' >>.env
!echo 'OPENAI_API_VERSION="2023-05-15"' >>.env
!echo 'OPENAI_API_KEY="<トークン>"' >>.env

# 環境変数としてコードで別途利用するもの 
!echo 'LLM_DEPLOYMENT_NAME="<回答生成用のモデルのデプロイ名>"' >>.env
!echo 'LLM_MODEL_NAME="<回答生成用のモデル名>"' >>.env
!echo 'EMBEDDING_LLM_DEPLOYMENT_NAME="<Embedding生成用のモデルのデプロイ名>"' >>.env
!echo 'EMBEDDING_LLM_MODEL_NAME="<Embedding生成用のモデル名>"' >>.env

上の4つは、openaiパッケージの設定になります。langchain.llms.AzureOpenAIで環境変数から読み込むことを想定しています。langchain.embeddings.OpenAIEmbeddingsには、サンプルを参考に、一度環境変数から変数に読み込んで渡しています。

下の4つは、langchain.llms.AzureOpenAIおよびlangchain.embeddings.OpenAIEmbeddingsに明示的に渡す、モデルに関する指定で、単純に環境変数にて切り替えられるように意図しました。

今回、OPENAI_API_VERSION2023-05-15としました。APIのバージョンについては、以下のドキュメントを参考にしました。

LLM_MODEL_NAMEEMBEDDING_LLM_MODEL_NAMEはそれぞれ、gpt-35-turbotext-embedding-ada-002としました。モデルについては、以下のドキュメントを参考にしました。

load_dotenv()で環境変数を読み込みました。

from dotenv import load_dotenv
load_dotenv()

データのアップロード

データを格納するディレクトリを作成します。

# データ用のディレクトリの作成
!mkdir /content/data/

ディレクトリを右クリックしてローカルにあるテキストデータをアップロードしました。

データのアップロード

以下のようにアップロードしたことを確認できました。

# アップロード結果の確認
!ls /content/data
# sample.txt

データは、機械学習チームで提供しているサービスの紹介ページのテキスト部分を使いました。

内容を踏まえて上手く回答を生成してくれるようになれば、お問い合わせ窓口として機能するアプリになったりするといいなというような想定です。

実行してみる

まず、必要なライブラリを読み込みました。

import os
import json
import openai
from langchain.llms import AzureOpenAI
from langchain.embeddings import OpenAIEmbeddings
from llama_index import LangchainEmbedding
from llama_index import (
    VectorStoreIndex,
    SimpleDirectoryReader,
    LLMPredictor,
    ServiceContext
)
import logging
import sys

logging.basicConfig(stream=sys.stdout, level=logging.INFO) # logging.DEBUG for more verbose output
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

次に、先に設定した環境変数を読み込みました。

# LangchainEmbeddingで使うもの
openai.api_type = os.getenv("OPENAI_API_TYPE")
openai.api_base = os.getenv("OPENAI_API_BASE")
openai.api_version = os.getenv("OPENAI_API_VERSION")
openai.api_key = os.getenv("OPENAI_API_KEY")

# デプロイ名・モデル名
llm_deployment_name = os.environ['LLM_DEPLOYMENT_NAME']
llm_model_name = os.environ['LLM_MODEL_NAME']
embedding_llm_deployment_name = os.environ['EMBEDDING_LLM_DEPLOYMENT_NAME']
embedding_llm_model_name = os.environ['EMBEDDING_LLM_MODEL_NAME']

llama_index.ServiceContextに設定するLLMPredictorLangchainEmbeddingを作成しました。

今回はLLMPredictorgpt-35-turboLangchainEmbeddingtext-embedding-ada-002を、環境変数から設定しています。

以下のコードでは、langchain.llms.AzureOpenAIの引数は、『PythonのLangChainでAzure OpenAI Serviceにデプロイしたモデルを利用するサンプルをやってみた』を踏まえて、LangChainのサンプルに沿ったものに直してみました。

# LLMPredictorの宣言については、2023/06/22に以下のドキュメントも参考にしました。
# https://python.langchain.com/docs/modules/model_io/models/llms/integrations/azure_openai_example
llm = AzureOpenAI(
    deployment_name=llm_deployment_name,
    model_name=llm_model_name
      )
llm_predictor = LLMPredictor(llm=llm)

# You need to deploy your own embedding model as well as your own chat completion model
embedding_llm = LangchainEmbedding(
    OpenAIEmbeddings(
        model=embedding_llm_model_name,
        deployment=embedding_llm_deployment_name,
        openai_api_key= openai.api_key,
        openai_api_base=openai.api_base,
        openai_api_type=openai.api_type,
        openai_api_version=openai.api_version,
    ),
    embed_batch_size=1,
)

アップロードしたデータを元に、インデックスを作成しました。

# Google Colabの/content/のdataディレクトリにデータをアップロードしておいたとする。
documents = SimpleDirectoryReader('/content/data/').load_data()

service_context = ServiceContext.from_defaults(
    llm_predictor=llm_predictor,
    embed_model=embedding_llm,
)

index = VectorStoreIndex.from_documents(documents, service_context=service_context)

準備ができたので、質問を投げてみました。

今回は、機械学習システム導入支援を検討しているのですが、コンサルティングとしてはどのような内容を提供頂けますか?というクエリを投げてみました。

query = '機械学習システム導入支援を検討しているのですが、コンサルティングとしてはどのような内容を提供頂けますか?'

query_engine = index.as_query_engine()
answer = query_engine.query(query)

print('answer was:\n', answer)

以下のように回答が出力されました!アップロードしたデータの内容を踏まえて回答してくれていていいですね!

answer was:

  • 機械学習システムの構築・導入を支援

  • ECサイトのレコメンドシステム構築支援

  • SNSや問い合わせのログなどからのテキストマイニングを活用したインサイトの発見

  • 工場における不良品検出や農業・畜産業分野での生育管理など、幅広い分野で活用できる画像解析

  • 売上や消費者の行動などから、将来の需要の予測を立てることができる時系列データに基づく将来予測

  • 既存環境への組み込みやモデルの定期更新、オンライン評価の仕組みなどを考慮したシステム

回答はちょっとさっぱりしているのですが、例えば以下のブログを参考にすると回答内容を改善できそうです。

最後に

今回はPythonのLangChainで、Azure OpenAI Serviceを利用してみました。

LlamaIndexを使って、アップロードしたデータの内容を踏まえて回答を生成できました。

また、Azure OpenAI Serviceへの接続設定も、環境変数と簡単な実装で実現できたのでとても使いやすかったです。

参考になりましたら幸いです。

修正履歴

  • 実行してみる』記載のPythonスクリプトのOpenAIEmbeddingsの引数について、embedding_llm_deployment_nameembedding_llm_model_nameの記載箇所が誤っていたので修正しました。(2023/08/02)