🐍
LLM から出力した JSON が Pydantic のバリデーションに引っかかるときに上手いことフォールバックする方法
背景
システムに LLM を組み込む際に、所望の JSON の書式に従わせるために Pydantic を使って JSON Schema を作成して、それを記載したプロンプトを LLM へ与えることがあるかと思います。例えば以下のような Pydantic モデルを考えます。
class Table(BaseModel):
foo: int
このときに LLM が以下のような JSON を出力してきて、型が異なるためバリデーションエラーが起こってしまうとき、あると思います。本記事ではその対処法を GitHub Gist に書き留めました。
{
"foo": "123"
}
対処例
以下の Gist に記載の通り、WrapValidator
を使って handler
から ValueError
が送出された際にあらかじめ指定したフォールバック値を返すような振る舞いを登録することで、ValidationError が送出されることなく、代わりにアトリビュートに指定したフォールバック値がデータに書き込まれるといった仕組みです。
def Fallback(fallback_value: Any):
def use_fallback(
v: Any,
handler: ValidatorFunctionWrapHandler,
info: ValidationInfo,
) -> Any:
try:
return handler(v)
except ValueError:
return fallback_value
return WrapValidator(use_fallback)
class Hoge(BaseModel):
...
hoge_str: Annotated[str, Field(default="hoge"), Fallback("fallback-str")]
はじめからこの問題が起こらないようにするには
OpenAI/ChatGPT と Google/Gemini の場合は Structured Outputs という機能があり、これを使えばそもそもこのような問題は起こらない。しかし、DeepseekV3 や Gemini だと対応していなかったり、対応状況が実用に耐えるレベルでなかったりするので、そのときは本記事の方法でフォールバックさせると良いかも。
参考
Discussion