LangChain Expression Language (LCEL)
LangChainのチェーン記法がリニューアルされていたので試してみた。
これまではLLMChainを作成してプロンプト、モデルを渡す書き方だったが、
from langchain import LLMChain
llm_chain = LLMChain( prompt=prompt, llm=model)
llm_chain("ice cream")
LCELでは ”|” で連結してChainを実装できる。(直感的にわかりやすくなっている)
またoutput_parserを繋げてレスポンスの後処理もできる。
chain = prompt | model | output_parser
chain.invoke({"topic": "ice cream"})
JSON Mode
ChatGPTからの応答がJSONで返ってくるのを保証するモード。2023/11/6に本家でリリース、11/17にAzure OpenAIでリリースされた模様。
LLM応答でJSON”だけ”返して欲しいのに、余計な文言がついてしまうようなケースを回避できるらしい。
LCELコード例
まず通常の利用。こちらはこれまでのgpt-35-turbo, gpt-4 (0613)、APIバージョン2023-07-01-previewで動く。
from langchain.chat_models import AzureChatOpenAI
from langchain.prompts import PromptTemplate
prompt = PromptTemplate.from_template("""ショートジョークを言ってください。 お題: {topic}""")
model = AzureChatOpenAI(
openai_api_base=BASE_URL,
openai_api_version="2023-07-01-preview",
deployment_name=DEPLOYMENT_NAME,
openai_api_key=API_KEY,
openai_api_type="azure",
temperature=0)
LCELでのチェーン定義部とチェーンの実行。
chain = prompt | model
result = chain.invoke({"topic": "カレー"})
print(result.content)
実行結果 (面白いかは別。。)
なぜカレーがパーティーに行きたがらなかったの?
だって、いつもスパイスが多すぎて汗ばんでしまうからさ!
output_parser
次にoutput parserを使ってみる。こちらはJSON Modeを使う必要がある。
JSON Modeを使用するにはgpt-35-turbo-1106とgpt-4-1106-previewのデプロイが必要で、2023/12/1時点では、オーストラリア東部、インド南部、アメリカ東部のリージョンに限定されるので注意。
output parserで扱うオブジェクトをBaseModelを継承して作成する。出力項目(例の場合は材料と手順)をフィールド定義する。
from langchain.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field
class Recipe(BaseModel):
ingredients: list[str] = Field(description="ingredients of the dish")
steps: list[str] = Field(description="steps to make the dish")
output_parser = PydanticOutputParser(pydantic_object=Recipe)
テンプレート設定。(ここらは参考サイトのコードを拝借させていただいた)
AOAIモデルはJSON Modeを利用するため、上記のリージョン作成のgpt-35-turbo、バージョン1106を使用。APIバージョンは2023-10-01-preview。
.bindとしてresponse_formatを指定してJSON Modeを有効化する。
prompt = PromptTemplate.from_template(
"""料理のレシピを考えてください。
{format_instructions}
料理名: {dish}""",
partial_variables={"format_instructions": output_parser.get_format_instructions()},
)
model = AzureChatOpenAI(
openai_api_base=BASE_URL,
openai_api_version="2023-10-01-preview",
deployment_name=DEPLOYMENT_NAME,
openai_api_key=API_KEY,
openai_api_type="azure",
temperature=0).bind(
response_format={"type": "json_object"}
)
チェーンの作成と実行。output parserをパイプする。
chain = prompt | model | output_parser
result = chain.invoke({"dish": "肉じゃが"})
print(type(result))
print(result)
実行結果。Recipeクラスで定義した、ingredients, stepsのリストとして応答を取得することができる。応答のJSONをパースしているのがわかる。
<class '__main__.Recipe'>
ingredients=['牛肉', 'じゃがいも', 'にんじん', '玉ねぎ', 'しょうが', 'にんにく', '醤油', 'みりん', '砂糖', '水'] steps=['1. 牛肉を食べやすい大きさに切る。', '2. じゃがいも、にんじん、玉ねぎを食べやすい大きさに切る。', '3. 鍋に油を熱し、しょうがとにんにくを炒める。', '4. 牛肉を加えて炒める。', '5. じゃがいも、にんじん、玉ねぎを加えて炒める。', '6. 醤油、みりん、砂糖、水を加えて煮る。', '7. 全体に味がなじんだら完成。']
参考