LLM開発のPydanticエラーを修正する

こんにちは！
株式会社Parksでインターンをしている乾と申します。
普段はデータサイエンスを学んでいる大学2年生です。
本記事では、[以前の記事](https://qiita.com/Tech_Intern_AIDB/items/dfc661fda219bef2ff0f
)で修正した`Pydantic`のエラー修正について書いた後、LLMの開発中にPydanticを利用する時の注意点などについても記載しようとおもいます。

https://qiita.com/Tech_Intern_AIDB/items/dfc661fda219bef2ff0f

## Pydanticについて
Pydanticは、データが設定した形式どうりになっているかを簡単に確認できたり、データをJSON、YAML、またはその他の形式に変換することができるライブラリです。

## 主な機能3つ
#### ・ データバリデーション
データの型、必須フィールド、値の範囲、正規表現パターンなどの制約を定義でき、無効なデータが処理されることを防ぐことができます。
#### ・ シリアライゼーション
データオブジェクトをJSONやその他の形式に変換するためのメソッドを提供し、簡単にデータを外部システムと交換したり、APIレスポンスとして返したりすることできます。
#### ・ デシリアライゼーション
JSON、辞書、またはその他の形式からデータオブジェクトを作成することもでき、外部から受け取ったデータを簡単に解析し、バリデーションすることができます。

## Pydanticの使い方
使い方については既に沢山の記事がかかれているので、ここでは簡単に記述します。
Pydanticを使用するには、まず`BaseModel`クラスを継承して新しいデータモデルを定義します。以下は、シンプルなモデルの例です。
```python
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str
    age: int
```
このモデルでは、`id`、`name`、`email`、`age`の4つのフィールドを定義し、それぞれのフィールドに期待するデータ型を指定しています。
データバリデーションは、モデルのインスタンスを作成する際に自動的に行われます。
```python
user_data = {
    "id": 1,
    "name": "John Doe",
    "email": "john@example.com",
    "age": 30
}

user = User(**user_data)
```
シリアライゼーションとデシリアライゼーションは、`dict()`メソッドと`parse_obj()`メソッドを使用して行います。
```py
# シリアライゼーション
user_dict = user.dict()

# デシリアライゼーション
user_obj = User.parse_obj(user_dict)
```
このような使い方により、Pythonでデータバリデーションとシリアライゼーションを直感的に行うことができます。
## Pydanticの主なエラーと読み方
・ValidationError（バリデーションエラー）
エラーメッセージ例：
`pydantic.error_wrappers.ValidationError: 1 validation error`
原因：モデルのバリデーションが失敗した
修正：エラーメッセージに表示された失敗したフィールドとその値を確認し、モデルの定義に従って値を修正してください。
・MissingError（欠損エラー）
エラーメッセージ例：
`pydantic.error_wrappers.ValidationError: field required (type=value_error.missing)`
原因：必須フィールドが欠損している
修正：エラーメッセージに表示された欠損しているフィールド名を確認し、必要な値を入力してください。
・AssertionError（アサーションエラー）
エラーメッセージ例：
`pydantic.error_wrappers.ValidationError: assertion failed`
原因：カスタムバリデーションの際にアサーションが失敗した
修正：エラーメッセージに表示された失敗したアサーションを確認し、バリデーションロジックを修正してください。
・AnnotationError（アノテーションエラー）
エラーメッセージ例：
`pydantic.errors.PydanticUserError:A non-annotated attribute was detected`
原因：モデルの属性に型アノテーションが設定されていない
修正：型アノテーションが設定されていない属性に適切な型アノテーションを追加する。
このあたりがPydanticを利用していてよく遭遇するエラーです。

## 実際にコードを修正する
例えば、以前の記事で利用した[リポジトリ](https://github.com/jiangjiechen/auction-arena)では、データバリデーションがされておらず、アノテーションエラーが多く発生してしまいました。

https://github.com/jiangjiechen/auction-arena

以下に実際に修正した例をいくつか示します。
```py:変更前
bidding_history = defaultdict(list)
```
```py:変更後
bidding_history: DefaultDict[str, List[str]] = defaultdict(list)
```
・DefaultDictを利用して、変数にキーと値の型を指定する。
```py:変更前
openai_cost = 0
```
```py:変更後
openai_cost: int = 0
```
・型アノテーションとしてintを指定し、openai_costが整数型であることを明示する。
```py:変更前
if num_bid == 0:
```
```py:変更後
if isinstance(num_bid, int) and num_bid == 0:
```
・isinstance()を使用して、num_bidが整数型であることをチェックしつつプログラムを動作させる。
#### 補足
この件についてissueを送ってみたところ反応があったため、そのうちリポジトリが修正させるかもしれません。
![スクリーンショット 2024-04-29 16.16.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3768156/5bde9537-b171-4767-1f9a-4b83e35464e9.png)
## LLMとPydanticの組み合わせ
Pydanticを用いることによって、可読性と保守性を向上させることが出来ます。
LLM開発時には、無効なデータの検出したり、LLMの入力や出力データをAPIを介して送受信する際に、データの変換を簡略化したり、モデルの変更や拡張が必要な場合、Pydanticのモデル定義を更新するだけで済む。などのメリットもあります。
管理のしやすいコードや、人に読ませるコードを作成することは簡単には出来ないので、このようなライブラリを利用することで、公開のしやすいコードになったり、今後の開発が効率的に行えるようになります。

## 参考文献
・[pydantic公式](https://docs.pydantic.dev/latest/)