はじめに
langchainが安定版であるバージョン0.1Xをリリースしたようなので、以前書いたコードをリファクタしようとしました。
すると非推奨の警告メッセージがたくさん出てきたり、どのドキュメントが最新なのか非常に分かりづらかったので、備忘録として書き残します。
事前準備
ライブラリ
pip install
してください
pip install langchain, langchain-openai
langchain==0.1.3
langchain-openai==0.0.3
langchain-community==0.0.15
langchain-core==0.1.15
langsmith==0.0.83
環境変数
Azure側で準備してから、以下の環境変数を入れてください。
AZURE_OPENAI_API_KEY = "APIキー"
AZURE_OPENAI_ENDPOINT = "エンドポイント"
書く
インポート
AzureChatOpenAI
はlangchain_openai
からインポートしてください。
langchain.chat_models
は非推奨になっています。
from langchain.schema import HumanMessage
from langchain_openai import AzureChatOpenAI
モデル用意
AzureChatOpenAI
でLLMを用意します。
2024年1月現在、APIのバージョン名は2023-12-01-preview
が最新みたいです。
APIのバージョン名はここに載っているようです。
model = AzureChatOpenAI(
openai_api_version="APIのバージョン名",
azure_deployment="デプロイ名",
)
呼び出し
invoke
で呼び出します。
run
は非推奨になっています。そのままinvoke
に書き換えればOKです。
message = "こんにちは"
res = model.invoke(message)
print(res)
結果
ちゃんと帰ってきました。
content='こんにちは!お元気ですか?何かお手伝いできることはありますか?'
Chainを使う
langchainと言えば!の機能、Chainも使ってみます。
基本的に以前と書き方は変わりません。LCEL使ってないのは許してください…
from os.path import join, dirname
from dotenv import load_dotenv
import langchain
from langchain_openai import AzureChatOpenAI
from langchain.chains import LLMChain
from langchain.output_parsers import PydanticOutputParser
from langchain.prompts import PromptTemplate
from langchain.chains import SequentialChain
from pydantic import BaseModel, Field
from typing import List
langchain.verbose = True
# フォーマット
## 食材と数
class Foods(BaseModel):
name: str = Field(description="食材の名前")
count: str = Field(description="量")
## 買い物リスト
class BuyList(BaseModel):
buyList: List[Foods]
# ローカル用環境変数呼び出し
dotenv_path = join(dirname(__file__), ".env")
load_dotenv(dotenv_path)
# LLM用意
model = AzureChatOpenAI(
openai_api_version="2023-12-01-preview",
azure_deployment="デプロイ名",
)
template1 = """
{recipe}のレシピを簡潔に教えてください。
食材とその個数は必ず教えてください。
"""
template2 = """
以下のレシピに必要な食材とその個数をまとめて教えてください。
### レシピ
{res1}
{format_instructions}
"""
# 実行関数
def generate_questions(recipe: str):
# 命令1: 1回目
## プロンプト作成
prompt1 = PromptTemplate(
template=template1,
input_variables=["recipe"],
)
## chain作成
chain1 = LLMChain(llm=model, prompt=prompt1, output_key="res1")
# 命令1: 2回目
## Parser作成
parser = PydanticOutputParser(pydantic_object=BuyList)
## プロンプト作成
prompt2 = PromptTemplate(
template=template2,
input_variables=["res1"],
partial_variables={"format_instructions": parser.get_format_instructions()},
)
## chain作成
chain2 = LLMChain(llm=model, prompt=prompt2)
# chains作成
chains = SequentialChain(
chains=[chain1, chain2],
input_variables=["recipe"],
)
# chains実行
answer = chains.invoke({"recipe":recipe})
# JSON整形
s = "```json\n"
answer = answer['text'].strip(s)
# 表示
print(answer)
print(type(answer))
return answer
if __name__ == "__main__":
recipe = "カレー"
output = generate_questions(recipe)
結果
> Entering new SequentialChain chain...
> Entering new LLMChain chain...
Prompt after formatting:
カレーのレシピを簡潔に教えてください。
食材とその個数は必ず教えてください。
> Finished chain.
> Entering new LLMChain chain...
Prompt after formatting:
以下のレシピに必要な食材とその個数をまとめて教えてください。
### レシピ
材料:
- 玉ねぎ: 1個
- にんじん: 1本
- じゃがいも: 2個
- 鶏肉or牛肉: 300g
- カレールー: 1箱
- 水: 500ml
- サラダ油: 大さじ1
- 塩: 小さじ1/2
作り方:
1. 食材を準備する。玉ねぎ、にんじん、じゃがいもをそれぞれみじん切りにする。肉は食べやすい大き
さに切る。
2. 鍋にサラダ油を熱し、玉ねぎを炒める。
3. 玉ねぎが透明になったら肉を加えて炒める。
4. にんじん、じゃがいもを加えて炒め、水を加えて煮る。
5. カレールーを加え、溶かしてから塩で味を調える。
6. 全体が煮えたら完成です。ご飯と一緒にお召し上がりください。
# Parser用プロンプトのため割愛
The output should be formatted as a JSON instance that conforms to the JSON schema below.
> Finished chain.
> Finished chain.
{
"buyList": [
{"name": "玉ねぎ", "count": "1個"},
{"name": "にんじん", "count": "1本"},
{"name": "じゃがいも", "count": "2個"},
{"name": "鶏肉or牛肉", "count": "300g"},
{"name": "カレールー", "count": "1箱"},
{"name": "水", "count": "500ml"},
{"name": "サラダ油", "count": "大さじ1"},
{"name": "塩", "count": "小さじ1/2"}
]
}
<class 'str'>
しっかりChain出来ていることが確認できます。
Parserも効いており、指定したJSON形式に変換されています。
おわりに
langchainは便利ですが、更新が非常に速いので追いつくのが大変でした。
公式ドキュメントすら最新化が追い付いてないので、恐ろしいですね…
また、AzureChatOpenAI
のパラメータであるopenai_api_version
の参照先が本当に分からなくて調べるのに時間がかかりました。
Azureの画面上か、モデル詳細に記載しておいてほしいです、切実に