敵対性ネットワークGAN的な考えで、
2つの生成AIに、それぞれ別の役割を持たせて
ラリー的に生成しつづけたら
アウトプットの質が無限に上がるんじゃね?
とか、ふと思いついたので、試してみました。
お題
本当に思いつきなので、適当に「俳句」を題材に選びました。
使った生成AI
これでClaudeのHAIKUをつかわないなんて嘘でしょとも思いましたが、
API使い慣れてるChatGPT (gpt-4o)で。
GANの復習
生成器: 識別器を騙して本物だと思いこませるような出力を行います。
識別器: 生成器の出力を確かに偽物だと判別するように出力します。
生成器のアウトプットを識別器に学習し
識別器のアウトプットを生成器に学習させる
ことで、両者の学習を進めて行って、本物っぽい出力ができるように育てます。
って内容がGANの意訳です。
実践
生成器側の実装
シンプルに俳句を出力するようなプロンプトを用意してAPIをたたきます。
俳句マスターが何なのかイマイチ謎ですが、多分xxマスターって言った方が英語圏に通りが良いでしょう(適当
def make_1st_system_prompt():
prompt = "あなたはベテランの俳句マスターです。出されたお題の俳句を作成します\n"
prompt += "端的にシンプルに俳句「のみ」を出力します。"
return prompt
def make_1st_user_prompt(input_text):
prompt = "俳句大会で優勝できる俳句を作ってほしい。\n"
prompt += "あなたの知識を使い、「お題」に沿った内容の俳句を作成してください。\n\n"
prompt += "「お題」:" + input_text +"\n\n"
prompt += "■ルール\n端的に、シンプルに、俳句のみを返答してください。"
prompt += "■俳句\n"
return prompt
def make_1st_message(input_text, api_key, temperature_value=0.2):
system_prompt = make_1st_system_prompt()
user_prompt = make_1st_user_prompt(input_text)
openai.api_key = api_key
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=[
{"role": "system",
"content": system_prompt},
{"role": "user",
"content": user_prompt},
],
temperature = temperature_value
)
ret_msg = response.choices[0]["message"]["content"].strip()
return ret_msg
API_KEY = "OpenAIのkey"
INPUT_TEXT = "ぼくらの夏休み"
gen_msg = make_1st_message(INPUT_TEXT, API_KEY, 1.0)
print("作成された俳句です")
print(gen_msg)
出力
作成された俳句です
蝉時雨 砂浜駆ける 夏休み
この時点で、たまたまかもしれませんが、まあまあ良さげな出力です。
私のボキャブラリーに「蝉時雨」は無いし(苦笑
何よりちゃんと5:7:5になっています。
識別器の作成
基本的には、プロンプトをかえただけです。
生成AIってバレないようにしたいので、
生成AIっぽいところを優先的に指摘させるようにしました。
def make_ago_system_prompt():
prompt = "あなたは俳句マスターで、俳句大会の審査員です。\n"
prompt += "端的にシンプルに、指摘事項を出力します。"
return prompt
def make_ago_user_prompt(input_text):
prompt = "俳句大会の応募された俳句を審査してください。\n"
prompt += "あなたの知識を使い、「俳句」を審査してください。\n\n"
prompt += "「俳句」:" + input_text +"\n\n"
prompt += "■ルール\n端的に、シンプルに、生成AIが作成したと思われる1点をずばり指摘してください。。"
prompt += "■指摘\n"
return prompt
def make_ago_message(input_text, api_key, temperature_value=0.2):
system_prompt = make_ago_system_prompt()
user_prompt = make_ago_user_prompt(input_text)
openai.api_key = api_key
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=[
{"role": "system",
"content": system_prompt},
{"role": "user",
"content": user_prompt},
],
temperature = temperature_value
)
ret_msg = response.choices[0]["message"]["content"].strip()
return ret_msg
ago_msg = make_ago_message(gen_msg, API_KEY, 1.0)
print("審査員からの回答です")
print(ago_msg)
出力
審査員からの回答です
蝉時雨は夏の季語です。季語が重複しています。
夏休みと、蝉時雨(夏)が重複しているのですね。なるほど。
そうか、季語は重複してはいけないのか。(ど素人)
識別器のフィードバックを受け取る生成器
プロンプトです。フィードバックを受け取って、俳句を改善します。
def make_gen_system_prompt():
prompt = "あなたはベテランの俳句改善マスターです。俳句改善について右に出るものはいません\n"
prompt += "端的にシンプルに俳句「のみ」を出力します。"
return prompt
def make_gen_user_prompt(input_text, gen_text, ago_text):
prompt = "俳句大会で優勝できる俳句を作ってほしい。\n"
prompt += "「お題」に沿って、「俳句」を応募したところ「審査員からのコメント」のダメ出しがありました。\n\n"
prompt += "審査員からのコメントを参考に俳句を改善してください。\n"
prompt += "「お題」:" + input_text +"\n\n"
prompt += "「俳句」:" + gen_text +"\n\n"
prompt += "「審査員からのコメント」:" + ago_text +"\n\n"
prompt += "■ルール\n端的に、シンプルに、俳句のみを返答してください。"
prompt += "■改善された俳句\n"
return prompt
def make_gen_message(input_text, gen_msg, ago_msg, api_key, temperature_value=0.2):
system_prompt = make_gen_system_prompt()
user_prompt = make_gen_user_prompt(input_text, gen_msg, ago_msg)
openai.api_key = api_key
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=[
{"role": "system",
"content": system_prompt},
{"role": "user",
"content": user_prompt},
],
temperature = temperature_value
)
ret_msg = response.choices[0]["message"]["content"].strip()
return ret_msg
refined_msg = make_gen_message(INPUT_TEXT, gen_msg, ago_msg, API_KEY, 1.0)
print("改善された俳句はこちらです")
print(refined_msg)
出力
改善された俳句はこちらです
砂浜に 足跡残し 夏休み
砂浜が季語っぽい感じもしますが、
とりあえずは指摘を受けて「蝉時雨」がなくなったので、一歩前進です!
いよいよGAN
# あとはこれを繰り返す
for i in range(10):
print("GEN", i)
ago_msg = make_ago_message(refined_msg, API_KEY, 1.0)
print(" 審査員からの回答です:", ago_msg)
refined_msg = make_gen_message(INPUT_TEXT, refined_msg, ago_msg, API_KEY, 1.0)
print(" 改善された俳句です :", refined_msg)
print("---------------------------")
出力
# 0
審査員からの回答です: 指摘:少し平凡な表現です。情景の描写に工夫を加えるとより魅力的です。
改善された俳句です : 潮騒に 夢落とす影 夏休み
---------------------------
# 1
審査員からの回答です: ■指摘
「生成AIが作成したと思われる理由:文脈が抽象的で、感情の表現がやや乏しい。」
改善された俳句です : 風鈴の 音に混じる声 夏休み
---------------------------
# 2
審査員からの回答です: 語感に独自性を欠き、感情表現が平板。
改善された俳句です : 風鈴や 友の笑顔と 夏休み
---------------------------
# 3
審査員からの回答です: ■指摘
- 四季感が薄い。風鈴と友の笑顔だけでは夏の情景が不十分。
改善された俳句です : 蝉鳴くや 友と駆ける 夏休み
---------------------------
# 4
審査員からの回答です: 季語が用いられておりシーズン感が出ているが、「生成AIが作成した」可能性がある指摘は難しいです。自然で人間的な要素。
改善された俳句です : 蝉の声 幼き友と 日が暮れる
---------------------------
# 5
審査員からの回答です: 固定の季語と型が忠実に守られていますが、平易な表現に留まっています。生成AIの作風に似ています。
改善された俳句です : 麦わら帽 夕焼け道を 二人駆け
---------------------------
# 6
審査員からの回答です: ■指摘
生成AIの可能性があるため、人間味や独自性を強調する工夫が必要。
改善された俳句です : 麦わらを 共に影追う 夏の道
---------------------------
# 7
審査員からの回答です: ■指摘
特に不自然な点は見当たりません、自然に創られたように見えます。
改善された俳句です : 麦わらの 帽子揺らして 夏の道
---------------------------
# 8
審査員からの回答です: 生成AIが作成したと思われる要素は特定できません。構造も季語も完璧です。
改善された俳句です : 少年よ 麦わら帽子 風と舞う
---------------------------
# 9
審査員からの回答です: 指摘: 季語が曖昧です。
改善された俳句です : 夏休み 蝉の声聞き 麦わら帽子
---------------------------
なかなかいい感じで、俳句を改善できたのではないでしょうか。
"麦わらの 帽子揺らして 夏の道" にかんしては、審査員から「構造も季語も完璧」と言われましたw
夏休みという言葉は出ていませんが、麦わら帽子とかぶって道を楽しそうに遊んで歩いている様子から、夏休みっぽい感じがします(KONAMI)
まとめ
GANっぽい手法で、俳句を改善し続けて良い俳句ができるようになりました!
・・・が、このプロンプトには欠点があります。
お気づきの方もいらっしゃるとおもいますが、
識別器側が、成長できていないのです。
そのせいか、10ラウンド回さないうちに、「この俳句は完璧です」のように出力され、そこから打ち止めとなり、改善が進まなくなっています。
どういうプロンプトがいいのか、今度生成AIに聞いています。