OpenAIのFunction callingで小説の解析をしてみる

ローカルLLMのチューニングに奮闘されているsaldraさんが、ご自身が運営されているDiscordコミュニティに、Function callingのアイデアを募る投稿をされていました。サンプルコードも貼ってくださったので、早速試してみることにしました。

様々な使い方が考えられる夢の機能であるFunction callingですが、趣味で小説を書く私としては、小説の分析に使えないかなと思いました。例えば、もうパブリックドメインになった古典小説を解析して要素を分解し、自分なりに現代劇として再構成する、なんて使い方は楽しそうです。GPT-3.5、GPT-4は外国語を読み込んで解析して日本語で返すということもできますから、外国の古典小説の分析もできそうです。

とりあえずはFunction callingの威力を確かめるべく、自分の書いた原稿で試してみました。ブルーアーカイブというゲームの二次創作小説です(二次創作ガイドラインが整備されていて安心して二次創作を楽しめる作品です)

文字数はだいた3800文字。トークン数から考えてもテストには最適でしょう。

試してみたソースコードはこちら。Discordコミュニティに貼られたサンプルコードをほとんどそのまま拝借しています。

import openai
import json
from dotenv import load_dotenv
load_dotenv()
import os

model_name = "gpt-4-0613"

openai.api_key = os.getenv("OPENAI_API_KEY")

functions=[
    {
        "name":"whoisheroine",
        "description":"",
        "parameters":{
            "type":"object",
            "properties":{
                "heroine":{
                    "type":"string",
                    "description":"与えられた小説を解析し、主人公の名前を返します。"
                },
                "appearance":{
                    "type":"string",
                    "description":"与えられた小説を解析し、主人公の外見を返します。"
                },
                "personality":{
                    "type":"string",
                    "description":"与えられた小説を解析し、主人公の性格を返します。"
                },
                "other":{
                    "type":"string",
                    "description":"与えられた小説を解析し、主人公のその他の情報を返します。"
                }
                }
        },
        "type":"object",
    }
]

arg = """
(※小説の本文を貼る)
"""
question = f'「{arg}」について、この小説の登場人物を判定し、名前をheroineに、外見をappearance' \
           f'に、性格をpersonarityに、その他の情報をotherに入れてください。' \
           f'複数人の登場人物がいます。全ての人物について同様の内容をリストアップして返してください。'

print(question)
res = openai.ChatCompletion.create(
    model=model_name,
    messages=[{
        "role":"user",
        "content":question
        }],
    functions=functions,
    function_call = "auto"
)
res_json = json.loads(res["choices"][0]["message"]["function_call"]["arguments"])
print(res_json)

すると、以下の様なJSONが返ってきました(改行はこちらで入れています)

{'heroine': ['下江コハル',
'ミカ',
'ヒフミ',
'ハナコ',
'アズサ',
'ハスミ先輩',
'シャーレの先生'],

'appearance': ['下江コハル: 黒い羽が生えている',
'ミカ: 本物のお嬢様スタイル',
'ヒフミ: 形状は特に記述なし',
'ハナコ: 形状は特に記述なし',
'アズサ: 形状は特に記述なし',
'ハスミ先輩: 形状は特に記述なし',
'シャーレの先生: 形状は特に記述なし'],

'personality': ['下江コハル: 4月が苦手で、人のことをよく気にする性格',
'ミカ: 強いが優しく、コハルのことを思いやっている',
'ヒフミ: 親切で、コハルの誕生日パーティを企画する',
'ハナコ: エッチなことに興味がある',
'アズサ: 爆発物が好きで、コハルのために爆発物を考えている',
'ハスミ先輩: コハルを正義実現員会に戻ってこられるよう願っている',
'シャーレの先生: 大人であり、コハルのことを思いやっている'],

'other': ['下江コハル: 正義実現員会の一員で、ミカに感謝される',
'ミカ: ティーパーティーのメンバーで、コハルのことを好き',
'ヒフミ: 補習授業部のメンバーで、パーティを提案する',
'ハナコ: 補習授業部のメンバーで、エッチなネタが好き',
'アズサ: 補習授業部のメンバーで、爆発物を使う',
'ハスミ先輩: 正義実現員会の一員で、コハルに助けられる',
'シャーレの先生: 教師で、コハルにメッセージを送る']}

返ってきたJSON

細かいところを言うと、ハスミ先輩はコハルに助けられてはいないのですが(私が書いた原稿の中ではコハルが助けたのはミカ)、他の部分は書いた内容の通りで、かなり良い感じに抽出できています。

同じ内容は、ChatGPTでも得ることができます。ですが、このFunction callingを使うと夢が広がるのが、複数の小説を同じ視点で、同じフォーマットで大量に解析できることでしょう。

古典小説は、現代の小説にも受け継がれるフォーマットがたくさんあります。登場人物やシーンを抽出し、プロットを取り出しておけば、後から自分なりにアイデアを作るのに役立つでしょう。また、たとえば主人公の社会的地位を同じフォーマットで抽出し、小説の年代別に整理することで、歴史の中で移りゆく主人公像の変遷なども分析出来そうです。

というわけで、ちょっと興奮したので、深夜の走り書きとしてまとめてみました。Function calling、色んなアイデアを見てみたいです。

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