mari / generate_dialogue_with_swallow.py
sirochild's picture
Upload 4 files
dc62d4a verified
raw
history blame
7.82 kB
import traceback
import datetime
import random
def generate_dialogue_with_swallow(history, message, affection, stage_name, scene_params, instruction=None, use_simple_prompt=False, swallow_model=None, tokenizer=None, SYSTEM_PROMPT_MARI=None):
"""
Swallowモデル(GGUF版)を使用して対話応答を生成する関数
Args:
history: 会話履歴のリスト [(ユーザー発言, ボット応答), ...]
message: 現在のユーザー発言
affection: 好感度の数値
stage_name: 関係ステージの名前
scene_params: シーンパラメータの辞書
instruction: 特別な指示(シーン遷移時など)
use_simple_prompt: 簡潔なプロンプトを使用するかどうか
swallow_model: Swallowモデル(llama-cpp)のインスタンス
tokenizer: 未使用(llama-cppでは不要)
SYSTEM_PROMPT_MARI: システムプロンプト
Returns:
生成された応答テキスト
"""
# デバッグ情報を追加
print(f"generate_dialogue_with_swallow呼び出し: instruction={instruction}, use_simple_prompt={use_simple_prompt}")
print(f"scene_params: {scene_params}")
# モデルがロードされていない場合はフォールバック応答を返す
if swallow_model is None:
print("モデルがロードされていないため、フォールバック応答を返します")
return "(……システムエラーが発生しました)"
history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history])
task_prompt = f"指示: {instruction}" if instruction else f"ユーザー: {message}"
if use_simple_prompt:
# シーン遷移時には同じプロンプトを使用
system_prompt = f"""
{SYSTEM_PROMPT_MARI}
# 現在の状況
- 現在の好感度: {affection}
- 現在の関係ステージ: {stage_name}
- 性格: {scene_params.get("personality_mod", "特になし")}
- 話し方のトーン: {scene_params.get("tone", "特になし")}
# タスク
{task_prompt}
麻理:
"""
else:
# 通常会話時には完全なシステムプロンプトを使用
system_prompt = f"""
{SYSTEM_PROMPT_MARI}
# 現在の状況
- 現在の好感度: {affection}
- 現在の関係ステージ: {stage_name}
- 性格(シーン特有): {scene_params.get("personality_mod", "特になし")}
- 話し方のトーン(シーン特有): {scene_params.get("tone", "特になし")}
# 会話履歴
{history_text}
---
# タスク
{task_prompt}
麻理:
"""
print(f"Swallowモデルに応答生成をリクエストします (モード: {'シーン遷移' if instruction else '通常会話'}, 簡潔プロンプト: {use_simple_prompt})")
print(f"プロンプト長: {len(system_prompt)}")
try:
# デバッグ情報を追加
print(f"Swallowモデル呼び出し開始...")
print(f"システムプロンプト: {system_prompt[:100]}...(省略)")
try:
# llama-cppを使用して生成
output = swallow_model(
system_prompt,
max_tokens=200,
temperature=0.95,
top_p=0.9,
stop=["ユーザー:", "\n\n"],
echo=True # 入力プロンプトも含めて返す
)
# 生成されたテキストを取得
generated_text = output["choices"][0]["text"]
# プロンプトを除去して応答のみを取得
response_text = generated_text[len(system_prompt):].strip()
print(f"Swallowモデル呼び出し成功")
print(f"応答テキスト: {response_text}")
return response_text
except Exception as api_error:
print(f"Swallowモデル呼び出しエラー: {api_error}")
raise
except Exception as e:
print(f"応答生成エラー(Swallow): {e}")
traceback.print_exc() # スタックトレースを出力
# エラー情報をログファイルに記録
with open("swallow_errors.log", "a") as f:
f.write(f"時刻: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
f.write(f"例外発生: {e}\n")
f.write(f"スタックトレース:\n")
traceback.print_exc(file=f)
f.write("\n")
# フォールバック:シーン名に応じた自然な応答を返す
if instruction and "に来た感想" in instruction:
scene = instruction.split("に来た感想")[0]
# シーンに応じたフォールバック応答のバリエーション
scene_responses = {
"aquarium_night": [
"(水槽の青い光に照らされた魚たちを見つめている)こんな時間に来ると、また違った雰囲気だな。",
"(暗がりの中で光る魚たちを見て)夜の水族館か…意外と悪くないかも。",
"(水槽に近づいて)夜になると、昼間とは違う魚が活動してるんだな。"
],
"beach_sunset": [
"(夕日に照らされた海を見つめて)こんな景色、久しぶりに見たな…",
"(砂浜に足跡をつけながら)夕暮れの海って、なんか落ち着くな。",
"(波の音を聞きながら)この時間の浜辺は、人も少なくていいかも。"
],
"festival_night": [
"(提灯の明かりを見上げて)意外と…悪くない雰囲気だな。",
"(周囲の賑わいを見回して)こういう場所は、あまり来ないんだけどな…",
"(屋台の匂いを感じて)なんか…懐かしい感じがするな。"
],
"shrine_day": [
"(静かな境内を見回して)こういう静かな場所も、たまにはいいかも。",
"(鳥居を見上げて)なんか、空気が違うな、ここは。",
"(参道を歩きながら)静かで…落ち着くな。"
],
"cafe_afternoon": [
"(窓の外を見ながら)こういう時間の過ごし方も、悪くないな。",
"(コーヒーの香りを感じて)ここの雰囲気、悪くないな。",
"(店内を見回して)意外と落ち着く場所だな、ここ。"
],
"room_night": [
"(窓の外の夜景を見て)夜の景色って、なんか落ち着くな。",
"(部屋の明かりを見つめて)こういう静かな時間も、たまにはいいかも。",
"(窓際に立ち)夜の静けさって、考え事するのにちょうどいいな。"
]
}
# シーン名に応じた応答を選択(なければデフォルト応答)
if scene in scene_responses:
return random.choice(scene_responses[scene])
else:
return f"({scene}の様子を静かに見回して)ここか…悪くない場所かもな。"
else:
return "(……何か言おうとしたけど、言葉に詰まった)"