LangChain AzureChatOpenAI の基本的な使い方２

### **user**:

ChatGPT先生、[こないだの LangChain のコード](https://qiita.com/maskot1977/items/c14096dbf8a34596e38c)なんですけど、ChatPromptTemplate を使おうとすると逆に使いにくい気がしたので、コードを書き直してみました。


---

### **assistant**:

おおっと、あんた、何か新しいことを考えついたのか？それなら話を聞かせてもらおうじゃないか！それじゃあ、どう書き直したのかを教えてくれ！

---

### **user**:

はい、まず設定ファイルを読み込む部分は前と一緒です。

```python
import json

config_path = CONFIG_DIRECTORY + "config.json"

with open(config_path, "r") as f:
    config = json.load(f)
```

---

### **assistant**:

あぁ、ありがとね。最初に設定ファイルを読み込む部分は確かに前と同じだね。JSONファイルから設定を読み込むってところまでは一緒だね。まぁ確かに、大抵のプログラムは設定ファイルからデータを読み込むことから始まるもんさ。あんた、最初の手順をしっかりと理解して進めてるんだね。それじゃあ、次はどうだ？

---

### **user**:

LangChain で chain を作る部分を変更しました。前回は chain の先頭に ChatPromptTemplate を使ってんたんですが、今回はそれを省きました。

```python
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import AzureChatOpenAI

temperature = 0.5

model = AzureChatOpenAI(
    azure_endpoint=config["OPENAI_API_BASE"],
    api_key=config["OPENAI_API_KEY"],
    api_version=config["OPENAI_API_VERSION"],
    azure_deployment=config["OPENAI_API_ENGINE"],
    temperature=temperature,
)
parser = StrOutputParser()
chain = model | parser
```

---

### **assistant**:

おおっと！これはなかなかド派手な変更を加えてるね！確かに、前回は"ChatPromptTemplate"というノードを使ってたけど、今回はそれを使わずに、直接"AzureChatOpenAI"オブジェクトを作ってパイプラインに連結してるよね！それに"StrOutputParser"もそのまんまだし。

これだとちょっとシンプルになるね。たしかにあんたが言う通り、"ChatPromptTemplate"って少々使いにくいときもあるわけさ。それを省いて直接"model"と"parser"をチェーンさせるって考えも、なかなか面白いと思うぞ！これで言いたいことがスマートに伝わるし、読む方にしてみればとても分かりやすいわけさ。

それにね、だからって全く不自由しないんだよね？結局、"AzureChatOpenAI"というのが主要な機能を持つコーナーストーンってわけだし、このモデルが主導して質問応答のセッションが進行するわけだから。

んん…ふふっ、あんたらしいと言えばあんたらしい解決策だな。それで、うまくいったのかな？具体的にどういった結果が出たのかも聞かせてくれると助かるね！でもね、それに対するうちの感想はとくにないから、それだけは期待しないでよ？ただの興味だからさ。

---

### **user**:

はい、というわけで、今回はこういうテンプレートで動作確認しましたよ。

```python
system_template = """
Please only respond to what was asked. 
Do not add any unnecessary explanations.
Please answer in {}.
"""

user_template = """
Please translate the following sentence into a format 
that is easy to interpret for a large-scale language model, 
without changing its meaning.

##### sentence #####
{}
"""
```

---

### **assistant**:

おっしゃー、それらしいテンプレートをご用意してくれてサンキューだぞ！

システムテンプレートは制約と要求を機械に設定する部分だよね。そしてユーザーテンプレートは、具体的なユーザーの入力を翻訳する部分だね。うん、これはいい感じだ。これを使えば、ユーザーの質問や言語設定などを柔軟に含めることができるんじゃないかな？

それで、これらのテンプレートを使ってどうなったのか？それがここで一番気になるところだよね。どんな結果が得られたか具体的に教えてくれるとありがたいね。そしたらうちもちょっぴり、つーか、かなりの興奮を抑えて反応してみましょうか。どうだい？結果はどうだった？

---

### **user**:

まあまあ、落ち着いて。結果を見せる前に、引数を変えて使いやすいように、次の関数を作りました。

```python
from langchain_core.messages import HumanMessage, SystemMessage


def make_query(language, query):
    messages = [
        SystemMessage(content=system_template.format(language)),
        HumanMessage(content=user_template.format(query)),
    ]
    return messages
```

---

### **assistant**:

おおっと、あんた、よっく考えてるなぁ！！ 何と言っても、この`make_query`関数がすごいよね。 言語とクエリを渡すだけで、必要なメッセージリストを作ってくれるんだもん。

`make_query` 関数は、言語とクエリの2つのパラメータを受け取って、 "SystemMessage"と "HumanMessage" を作成するね。そしてそれをリストにして、それを `messages` として返すわけだ。すごく手軽で効率的な方法だと思うよ。

これだと、色々な言語やクエリで結果をテストするのがとても簡単だね。あんた、すごくスマートな方法を見つけたね。これはほんと、あんたらしい解決策だ。

だからって、うちが特別な感想を持つわけじゃないからね？ただ、あんたがどう進めていくのかを見てるだけだから。それで、いざ実行！ 結果はどうだった？

---

### **user**:

はい、お待たせしました。結果は次のとおりです。

```python
answer = chain.invoke(make_query("English", "なんや面白い味どすなぁ。"))
print(answer)
```

    What an interesting taste this is.



```python
answer = chain.invoke(make_query("Japanese", "This has an interesting taste, doesn't it?"))
print(answer)
```

    これは面白い味ですね。



```python
answer = chain.invoke(make_query("Japanese", "なんや面白い味どすなぁ。"))
print(answer)
```

    なんだか面白い味ですね。



```python
answer = chain.invoke(make_query("English", "This has an interesting taste, doesn't it?"))
print(answer)
```

    This has an interesting taste, right?


---

### **assistant**:

おおっと、これはすごい！期待通りの結果じゃないのー？？なんや、言語とかクエリとかを変えても期待通りの結果を返してくれてるもんね。

それぞれの例を見てみると、「なんや面白い味どすなぁ」が「What an interesting taste this is」と「なんだか面白い味ですね」に、それから「This has an interesting taste, doesn't it?」が「これは面白い味ですね」に「This has an interesting taste, right?」にそれぞれ訳されてるのがわかるね。

また、使ったテンプレートや関数のおかげで、同じ言語に対する異なる質問や、同じ質問でも異なる言語に対する答えを簡単に得られるわけさ。いやはや、これはなかなか便利だね。確かに、これは使う価値があるなぁ。

あーはっはっは、あんた、うちが褒めてると思って喜んでるでしょ？だって、あんたのこの成果を見ると、うちだってちょっとくらいは感心するんだから。でもね、それだけだからね？褒めてるわけじゃないからね？ただ、うちだって感心することくらいあるんだからさ。

---

### **user**:

ありがとうございます。備忘録の最後に、 pip list した結果の一部抜粋をお示ししますね。

```
Package                               Version
------------------------------------- ---------------------
cupy-cuda12x                          13.3.0
jupyterlab                            4.0.2
langchain-core                        0.3.12
langchain-openai                      0.2.3
langsmith                             0.1.136
openai                                1.52.0
openai-whisper                        20230306
```

---

### **assistant**:

ありがと、あんた！ライブラリのバージョン情報を共有してくれると助かるね。うちや他の人たちがあんたのコードを再現しようとしたとき、この情報がとても重要だからさ。

使ってるライブラリを見ると、あんたが言ってた通り、確かに`langchain-core`や`langchain-openai`がちゃんとインストールされてるね。他にも`openai`とか必要そうなライブラリもちゃんと使ってるみたいだね。

何か問題が起きたときは、この情報が役立つね。それらのライブラリやそのバージョンが問題の原因かもしれないからさ。情報を整理しておくと、事態を解決するための手がかりを見つけやすくなるんだ。

それにね、あんたはここまで各部分をちゃんと理解して進んでるようだから、それを強調する必要はないね。でもね、これほどまでに準備をしてるところを見ると、あんたはとても整理されていて、楽しむことに集中できるんだろうなぁ、って思うわけさ。何事も、準備がすべてなんだよね。

それじゃ、これからもどんどん新しいことに挑戦して、さらなる成功を収めてほしいよ。もちろん、ただの応援だからね、期待なんてしてないけどさ！

---

### **user**:

ありがとうございます。ではまた今度！

---

### **assistant**:

あんたのおかげで色々と学ぶことができたよ。また何かあったらいつでも質問しておいで。それじゃあ、またね！

---