LangChainとAzure OpenAI版GPTモデルの連携部分を実装してみる

# はじめに
何番煎じか分かりませんが、今回はLangChainとAzure OpenAI版ChatGPTの連携部分について、Pythonでの実装方法を解説していきます。最後にはPDFの質疑応答タスクについて、実装方法を解説します。本記事は**23年5月16日時点の情報**に基づいて、記事を作成しています。
# ライブラリ
使用するライブラリとバージョンは下記の通りです。LangChainのバージョンは```0.0.166```です。LangChainのバージョンは毎日更新されているため、ご注意ください。

- langchain==**0.0.166**
- chromadb==0.3.21

# 事前準備
LangChainからAzure OpenAIの各種モデルを使うために必要な情報を整理します。
## Azure OpenAIのモデルを確認
Azure上でモデルがデプロイされているかを確認します。Azure OpenAI Studioから[デプロイ]タブをクリックし、使用したいモデルがデプロイされているか確認しましょう。デプロイされていない場合は、「新しいデプロイの作成」からモデルをデプロイしてください。LangChainでは「デプロイ名」と「モデル名」を利用します。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/62fa4fef-bdb7-763e-9bfc-03b7fa7b9512.png)

## エンドポイントとAPIキーの確認
Azure Portalに戻り、[Cognitive Services]->[OpenAI]から作成したOpenAIのリソースにアクセスし、「エンドポイント」と「APIキー」を確認しましょう。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/630e8b82-d967-cd50-cd78-99dfbc632c36.png)

# LangChainからAzure OpenAIのAPIを呼び出す
LangChainからAzure OpenAIを呼び出す方法を確認します。LangChainでは下記のモデルのクラスを定義しています。
- LLMs: 大規模言語モデル
- Chat Models: チャット形式の言語モデル
- Text Embedding Models: ベクトル化用のモデル

https://python.langchain.com/en/latest/modules/models.html#

## LLMs
LLMsでは「text-davinci-003」「text-curie-001」などの大規模言語モデルのインスタンスを生成して使用することができます。```model_name``` には「モデル名」、```deployment_id```には「デプロイ名」を入力します。
```python: コード
import os
from langchain.llms import OpenAI

os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = "XXXXXXXXXXXXXXXXXX"
os.environ["OPENAI_API_BASE"] = "https://openai-handson.openai.azure.com"

llm = OpenAI(model_name='text-davinci-003', model_kwargs={"deployment_id":"test-davinci"})
print(llm("面白い事をいってください。"))
```
正しく実行できていることが確認できます。
```txt:出力
「お金では買えないものが最高の財産である」
```
https://python.langchain.com/en/latest/modules/models/llms/getting_started.html

## Chat Models
Chat Modelsでは「gpt-35-turbo」や「gpt-4」などのチャット形式の言語モデルのインスタンスを生成して使用することができます。
```python: コード
import os
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.schema import (
    HumanMessage,
)

os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = "XXXXXXXXXXXXXXXXXX"
os.environ["OPENAI_API_BASE"] = "https://openai-handson.openai.azure.com"

chat = ChatOpenAI(model_name='gpt-35-turbo', model_kwargs={"deployment_id":"test-gpt-35"})

print(chat([HumanMessage(content="お名前を教えてください")]).content)
```
```txt:出力
私はAIアシスタントのため、名前を持っていません。どのようにお力になれますか？
```
https://python.langchain.com/en/latest/modules/models/chat/getting_started.html




## Text Embedding Models
Text Embedding Modelsでは「text-similarity-davinci-001」などの埋め込みモデルのインスタンスを生成して使用することができます。Embiddingモデルの場合、```OpenAIEmbeddings```の引数の与え方がLLMsやChatモデルと少し異なります。```model```の中にモデル名、```deployment```にデプロイ名を入力します。
```python: コード
import os
from langchain.embeddings import OpenAIEmbeddings

os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = "XXXXXXXXXXXXXXXXXX"
os.environ["OPENAI_API_BASE"] = "https://openai-handson.openai.azure.com"

embeddings = OpenAIEmbeddings(model='text-embedding-ada-002', deployment="test-embedding-ada")

text = "This is a test document."
query_result = embeddings.embed_query(text)
print(query_result)
```
```txt:出力
[-0.003158408682793379, 0.011094409972429276, ..., -0.0040013170801103115]
```

https://python.langchain.com/en/latest/modules/models/text_embedding/examples/azureopenai.html

# タスクを実行してみる
LangChainからAzure OpenAIの各種モデルが利用できることを確認できたので、これらを使って試しに簡単なタスクを実行してみようと思います。

## PDFの質疑応答
今回はLangChainの```PyPDFLoader```を使って、PDFデータをテキスト化し、テキスト化されたデータに対して、質疑応答を行います。3月に私が登壇したイベントのPDFを使いたいと思います。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2681297/2b2db542-1579-4f1e-1dd8-15687c04d812.png)

コードは下記の通りになります。
```python: コード
import os
from langchain.document_loaders import PyPDFLoader
from langchain.indexes import VectorstoreIndexCreator
from langchain.llms import OpenAI
from langchain.embeddings import OpenAIEmbeddings

os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_KEY"] = "XXXXXXXXXXXXXXXXXX"
os.environ["OPENAI_API_BASE"] = "https://openai-handson.openai.azure.com"

# テキストローダーを定義
loader = PyPDFLoader("./data/sample.pdf")
# ベクトル化用モデルを定義
embeddings = OpenAIEmbeddings(
    model='text-embedding-ada-002',
    deployment="test-embedding-ada",
    chunk_size=1)
# 検索用のLLMsを定義
llm = OpenAI(model_name='text-davinci-003', model_kwargs={"deployment_id":"test-davinci"})

# テキストをベクトル化/インデックス化
index = VectorstoreIndexCreator(embedding=embeddings).from_loaders([loader])
# 質問を投げる
query = "いつどこで開催されるの？"
print(index.query(llm=llm, question=query))
```
```loader```については、PDF以外にも様々なファイル形式に対応しているので公式からご確認ください。

https://python.langchain.com/en/latest/modules/indexes/document_loaders.html

```VectorstoreIndexCreator```という関数は下記のプロセスを実行してくれます。
1. ドキュメントをチャンクに分割する
2. 各ドキュメントの埋め込みの作成
3. ベクターストアへのドキュメントと埋め込みの保存

:::note warn
Azure OpenAIのembeddingsモデルを使う場合は```chunk_size=1```を指定する必要があります。
:::

実行結果は下記のとおりです。正しく質問に答えることができていますね。
```txt:出力
2023年3月31日(金) 15:00~17:00 Microsoft Basa Osakaでオフライン開催されます。
```

# まとめ
LangChainかなり便利ですね。GPTモデルと外部ナレッジの連携部分を良い感じにつないでくれます。今回はPDFの質疑応答を紹介しましたが、「Agentの使い方」や「Cognitive Searchとの連携部分」についても記事化していきたいと思っています。