見出し画像

LangChainのJSON出力パーサー

  • LLMからの出力形式は、プロンプトで直接指定する方法がシンプルですが、LLMの出力が安定しない場合がままあると思うので、LangChainには、構造化した出力形式を指定できるパーサー機能があります。

  • LangChainには、いくつか出力パーサーがありますが、汎用的に使い道がありそうな、Pydantic/JSON 出力パーサーを試してみました。

1.ライブラリほか準備

from langchain.llms import OpenAI
from langchain.output_parsers import PydanticOutputParser

from pydantic import BaseModel, Field, validator
from typing import List
  • 今回の主役は、「PydanticOutputParser」です。

model = OpenAI(model_name="gpt-3.5-turbo", temperature=0)
  • モデルはgpt-3.5-turboを使いました。

  • ChatOpenAIを使えと諭されますが、あくまで試食なので…。😓
    もちろん公式のサンプルの通り、'text-davinci-003'でよいです。

出力データ構造・バリデーションの定義


# 出力データ構造の定義
SHIKOKU = ('香川県','愛媛県','徳島県','高知県')

class SouvenirInShikoku(BaseModel):
    name: str = Field(description="県名")
    specialty: List[str] = Field(description="その県の特産品")
    
    # 出力時のデータのバリデーション
    @validator('name')
    def include_in_shikoku(cls, field):
        if field not in SHIKOKU:
            raise ValueError("I can only answer for the souvenirs from Shikoku!")
        return field
  • Pydanticの機能を活用するため、BaseModelを継承して、Fieldに必要なJSON形式の変数名と型を定義します。

  • 出力データのバリデーションは@validator以下で適宜行えます。厳密なバリデーションのロジックを書いてもいいし、LLMにふんわりチェックさせるのも面白いかも。

出力パーサー・プロンプトの設定

parser = PydanticOutputParser(pydantic_object=SouvenirInShikoku)

prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()}
)
  • PydanticOutputParserに作成したpydanticの型を指定します。

実行!

ask_query = "高知の特産品を教えて"

_input = prompt.format_prompt(query=ask_query)
output = model(_input.to_string())

parser.parse(output)

SouvenirInShikoku(name='高知県', specialty=['かつお節', 'ゆず胡椒', '土佐和紙', '土佐銘茶', '桂浜の砂'])

みごと利用しやすそうな感じに成形されて出力できました。😀

エラー処理

実際使うときは、モデルを呼ぶところにエラー処理時の例外処理を書いておくと、バリデーション時のエラーを捕まえられると思います。

OutputParserException: Failed to parse SouvenirInShikoku from completion { "name": "宮崎県", "specialty": ["マンゴー", "チキン南蛮", "日南鶏", "宮崎牛", "たかなわんこ"] }. Got: 1 validation error for SouvenirInShikoku name I can only answer for the souvenirs from Shikoku! (type=value_error)

そのほかの出力パーサー

Enum Output Parser

  • 指定した列挙型(Enum)で出力

  • シンプルなので、逆にこれを一番使うのかもしれないです。

DatetimeOutputParser()

  • datetime型に変換して出力

CommaSeparatedListOutputParser

  • コンマ区切りのリストで出力

感想

  • Agent周りなどはLangChainが強い印象ですが、好みの問題だと思いますが、出力関係はマイクロソフトの{{guidance}} とかのほうが使いやすいのかも。場面に応じて複数のフレームワークを使っても良い気がします。

おしまい。ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?