はじめにテキストをJSON化させるのは、データ分析の前処理などで利用できます。例えば、自由記述の文章から分析で使いたいデータをJSONで抽出して、分析可能な表形式データにしたいなどのケースがあります。例題1月収: 20万円 ~ 30万円 というテキストから、以下のような形式でJSONデータを抽出しようと思います。{ "minimum_monthly_salary": 200000, "maximum_monthly_salary": 300000}Function CallingでJSONにするFunction Callingを利用することで、JSON形式のデータ抽出が容易に可能です。functions = [ { "name": "extract", "description": "テキストからJSONを抽出する", "parameters": { "type": "object", "properties": { "minimum_monthly_salary": { "type": "number", "description": "", }, "maximum_monthly_salary": { "type": "number", "description": "", }, }, "required": ["minimum_monthly_salary", "maximum_monthly_salary"], }, }]function_call = {"name": "extract"}response = openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=[ { "role": "user", "content": text }, ], functions=functions, function_call=function_call )単純にカラム名を指定しているだけですが、ChatGPTが勝手に解釈をしてその形式でJSONを返してくれました。例題2続いて年収: 500万円 というテキストから、月収に計算してJSON化させます。先ほどのFunction Callingをすると・・・特に何も変更せず、先ほどのFunction CallingでJSON化させると、以下のように、よく分からない結果が返ってきました。Chain Of Thoughtを入れてみるプロンプトエンジニアリングのテクニックに、Chain Of Thoughtと呼ばれるものがあります。これはただ単純に答えを出力させるのではなく、計算過程や思考過程を出力させることで計算精度が上がるというものです。シンプルにJSONにthought_proess(思考回路)というカラムを追加してあげます。functions = [ { "name": "extract", "description": "テキストからJSONを抽出する", "parameters": { "type": "object", "properties": { "thought_process": { "type": "string", "description": "", }, "minimum_monthly_salary": { "type": "number", "description": "", }, "maximum_monthly_salary": { "type": "number", "description": "", }, }, "required": ["minimum_monthly_salary", "maximum_monthly_salary", "thought_process"], }, }]その結果、きちんと12で割った計算結果が入ってきました。FewShotをさせるもう一つ有効なプロンプトエンジニアリングにFew Shotを使いましょう。具体例をChatGPTに与えると、それに沿ってその後の回答をしてくれます。以下のように、年収400万円というテキストが入ってきた時に、どのようなJSONを返して欲しいのかを具体例で渡してあげます。examples = [ {"role": "user", "content": "年収400万"}, { "role": "assistant", "content": None, "function_call": { "name": "extract", "arguments": ''' { "minimum_monthly_salary": 333333.33, "maximum_monthly_salary": 333333.33, "thought_process": " We can calculate the minimum and maximum monthly salary by dividing the annual salary by 12. We need to convert the amount from Japanese characters to a number." }''' } }]function_call = {"name": "extract"}response = openai.ChatCompletion.create( model="gpt-3.5-turbo-0613", messages=[ *examples, { "role": "user", "content": text }, ], functions=functions, function_call=function_call例で与えたように小数第2位まで計算してくれ、thought_processもこちらの意図通りの思考回路で計算してくれたことが記述されています。更なる改善ログを残すAIあるあるですが、精度100%にはなりません。全く想定外のアウトプットを返すことがあるので、きちんとログをとって改善に繋げましょう。リグレッションテストをする自由記述な文章はいろいろなパターンがあるため、うまくいかなかったものはFunctionsの定義を詳細に書いたりFew Shotの追加で対応していきます。 (このあと完全歩合制など書いてある求人が出てきたりします・・・)このようにプロンプトを改善していると、デグレしていないか気になってきますよね。そこで対応したいケースをカバーしたリグレッションテストを記述することをお勧めします。自動テスト化させると、毎回OpenAIとのAPIが発生してコストがかかるので、全く同じリクエストであれば同じレスポンスを返すキャッシュサーバを配置することでAPIコストを削減できます。この辺は弊社プロダクトのLangCoreを活用していただくと、ログやキャッシュを行ってくれます(宣伝)結論1️⃣ Function CallingでJSONにする2️⃣ Chain Of Thoughtで思考回路を出力させる3️⃣ Few Shotで具体例を与えてこちらの意図を伝える4️⃣ ログやテストで改善