この記事は、6/26開催のAIねじ伏せプロンプト選手権で発表したLT資料を技術記事化したものになります。
はじめに
テキストを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️⃣ ログやテストで改善
最後に
今回の内容は実案件で実施した内容になっています。LTでの登壇や今回の技術記事化に快く承諾していただいたフォワード様ありがとうございました。
フォワード社はかなり最先端なChatGPT APIを活用してプロダクトを作っていますので、副業等興味ある方はぜひTwitterから連絡してください!