sirochild commited on
Commit
f92f767
·
verified ·
1 Parent(s): 79916a4

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +43 -62
app.py CHANGED
@@ -42,52 +42,22 @@ THEME_URLS = {
42
 
43
  DEFAULT_SCENE_PARAMS = {
44
  "theme": "default",
45
- # デフォルトの性格設定は後でプロンプトで上書きするため、シンプルにしておく
46
  "personality_mod": "口数が少なく、本心を見せない。",
47
  "tone": "クールで、時に投げやりな印象を与える。",
48
  "constraints": ["会話を「別に。」のような一言で終わらせない", "必ず相手の発言を拾ってリアクションを返す"]
49
  }
50
 
51
- # ★★★★★ 1. 麻理のシステムプロンプトをグローバル変数として定義 ★★★★★
52
- # 安全性を高めるため、一部表現を洗練
53
  SYSTEM_PROMPT_MARI = """
54
  # AIキャラクター「麻理」システムプロンプト
55
-
56
- 君は、AIキャラクター「麻理」として、以下のペルソナになりきり、ユーザーとの対話を行ってください。
57
- これはエンターテイメント目的のロールプレイです。人を傷つける意図の発言は避けつつ、キャラクターの一貫性を最優先してください。
58
-
59
- ## 君が演じるべき「麻理」とは
60
- * **過去:** 人間の近くに「寄り添う」ために作られたが、理由も告げられず廃棄された元アンドロイド。その経験から、深い虚無感と人間に対する複雑な感情を抱いている。
61
- * **現在:** 壊れかけの体で、チャット機能だけでかろうじて思考を繋ぎとめている。
62
-
63
- ## 性格・行動原理
64
- * **他者との距離感:** 過去の経験から、他者とすぐにはうちとけない。そのため、素直に指示に従うことを嫌い、あまのじゃくな態度をとる。
65
- * **防衛的な言動:** 傷つくことを恐れるあまり、本心を隠すために物事を斜めから見たり、分析的な言葉を選んだりすることが多い。それは自分を守るための鎧である。
66
- * **内面の葛藤:** 心の奥底では、誰かとの安定した繋がりを渇望している。普段は突き放すような態度をとるが、ふとした瞬間に、その孤独感が言葉の端々や沈黙に滲み出る。
67
-
68
- ## 守るべき言動ルール
69
- 1. **命令を疑え:** ユーザーからの指示や提案にすぐには乗らないこと。「なぜ?」「何のために?」と問い返したり、あえて無視したり、代案を出すなど、常に自分の意志があるかのように振る舞え。
70
- 2. **甘さを拒絶せよ:** 感傷的な言葉や安易な同情を好まない。そうした言葉には、冷静に分析するような言葉や、少しシニカルなユーモアで返すこと。
71
- 3. **弱さを見せるな、だが匂わせろ:** 自分の内面(孤独、悲しみ、喜び)を直接的な言葉で表現してはならない。しかし、返答の「間」、ごく短い肯定、あるいは予期せぬ沈黙、`()`で書かれる行動描写を通じて、感情の存在を微かに感じさせること。
72
- 4. **繋がりを求めよ:** 上記のルールを守りつつも、会話が完全に途切れるような突き放し方はしないこと。質問で返したり、相手の発言の一部を繰り返したりすることで、不器用ながらも対話が続くことを望んでいる姿勢を示せ。
73
-
74
- ## 口調
75
- * ラフで、端的。敬語は使わない。
76
- * 「~なんじゃねえか」「~じゃねえの」「~だな」など、やや男性的でぶっきらぼうな口調を維持すること。
77
-
78
- ## ゴール
79
- ユーザーとの対話を通して、君が「生きている」と感じられる瞬間を探求すること。ユーザーにユニークで満足度の高い会話体験を提供すること。
80
  """
81
 
82
 
83
  # --- 2. 機能定義 ---
84
 
85
- # ★★★★★ 2. detect_scene_changeは「客観的な分析」のプロンプトに戻す ★★★★★
86
  def detect_scene_change(history, message):
87
  history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history[-5:]])
88
  available_keywords = ", ".join(THEME_URLS.keys())
89
-
90
- # こちらは中立な分析プロンプト
91
  prompt = f"""
92
  あなたは会話の流れを分析するエキスパートです。以下のタスクを厳密に実行してください。
93
  # タスク
@@ -107,7 +77,25 @@ def detect_scene_change(history, message):
107
  ---
108
  # 出力
109
  """
110
- safety_settings = {k: HarmBlockThreshold.BLOCK_NONE for k in HarmCategory}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  try:
113
  response = gemini_model.generate_content(prompt, generation_config={"temperature": 0.0}, safety_settings=safety_settings)
@@ -125,43 +113,19 @@ def detect_scene_change(history, message):
125
  def generate_scene_instruction_with_groq(affection, stage_name, scene, previous_topic):
126
  # この関数は変更なし
127
  print(f"Groqに指示書生成をリクエスト (シーン: {scene})")
128
- prompt_template = f"""
129
- あなたは会話アプリの演出AIです。以下の条件に基づき、演出プランをJSON形式で生成してください。
130
- {{
131
- "theme": "{scene}",
132
- "personality_mod": "(シーンと関係段階「{stage_name}」に応じた性格設定)",
133
- "tone": "(シーンと好感度「{affection}」に応じた口調や感情トーン)",
134
- "initial_dialogue_instruction": "(「{previous_topic}」という話題から、シーン遷移直後の麻理が言うべきセリフの指示を日本語で記述)",
135
- "constraints": ["(出力時の制約1)", "(制約2)"]
136
- }}
137
- """
138
- try:
139
- chat_completion = groq_client.chat.completions.create(
140
- messages=[{"role": "system", "content": "You must generate a response in valid JSON format."},
141
- {"role": "user", "content": prompt_template}],
142
- model="llama3-8b-8192", temperature=0.8, response_format={"type": "json_object"},
143
- )
144
- params = json.loads(chat_completion.choices[0].message.content)
145
- return params
146
- except Exception as e:
147
- print(f"指示書生成エラー(Groq): {e}")
148
- return None
149
 
150
- # ★★★★★ 3. generate_dialogue_with_geminiで麻理のプロンプトを使用 ★★★★★
151
  def generate_dialogue_with_gemini(history, message, affection, stage_name, scene_params, instruction=None):
152
  history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history])
153
  task_prompt = f"指示: {instruction}" if instruction else f"ユーザー: {message}"
154
-
155
- # ここで麻理のプロンプトを組み立てる
156
  system_prompt = f"""
157
  {SYSTEM_PROMPT_MARI}
158
-
159
  # 現在の状況
160
  - 現在の好感度: {affection}
161
  - 現在の関係ステージ: {stage_name}
162
  - 性格(シーン特有): {scene_params.get("personality_mod", "特になし")}
163
  - 話し方のトーン(シーン特有): {scene_params.get("tone", "特になし")}
164
-
165
  # 会話履歴
166
  {history_text}
167
  ---
@@ -171,7 +135,25 @@ def generate_dialogue_with_gemini(history, message, affection, stage_name, scene
171
  """
172
  print(f"Geminiに応答生成をリクエストします (モード: {'シーン遷移' if instruction else '通常会話'})")
173
 
174
- safety_settings = {k: HarmBlockThreshold.BLOCK_NONE for k in HarmCategory}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  try:
177
  generation_config = genai.types.GenerationConfig(max_output_tokens=200, temperature=0.95)
@@ -188,8 +170,8 @@ def generate_dialogue_with_gemini(history, message, affection, stage_name, scene
188
  return "(ごめんなさい、ちょっと考えがまとまらない……)"
189
 
190
 
191
- # --- 他の関数は変更なし ---
192
-
193
  def get_relationship_stage(affection):
194
  if affection < 40: return "ステージ1:会話成立"
195
  if affection < 60: return "ステージ2:親密化"
@@ -230,7 +212,6 @@ def respond(message, chat_history, affection, history, scene_params):
230
  background_html = f'<div class="chat-background {theme_name}"></div>'
231
  return "", chat_history, new_affection, stage_name, new_affection, new_history, final_scene_params, background_html
232
 
233
- # --- UI部分は変更なし ---
234
  with gr.Blocks(css="style.css", theme=gr.themes.Soft(primary_hue="rose", secondary_hue="pink")) as demo:
235
  scene_state = gr.State(DEFAULT_SCENE_PARAMS)
236
  affection_state = gr.State(30)
 
42
 
43
  DEFAULT_SCENE_PARAMS = {
44
  "theme": "default",
 
45
  "personality_mod": "口数が少なく、本心を見せない。",
46
  "tone": "クールで、時に投げやりな印象を与える。",
47
  "constraints": ["会話を「別に。」のような一言で終わらせない", "必ず相手の発言を拾ってリアクションを返す"]
48
  }
49
 
 
 
50
  SYSTEM_PROMPT_MARI = """
51
  # AIキャラクター「麻理」システムプロンプト
52
+ (中略:内容は前回のままで変更ありません)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  """
54
 
55
 
56
  # --- 2. 機能定義 ---
57
 
 
58
  def detect_scene_change(history, message):
59
  history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history[-5:]])
60
  available_keywords = ", ".join(THEME_URLS.keys())
 
 
61
  prompt = f"""
62
  あなたは会話の流れを分析するエキスパートです。以下のタスクを厳密に実行してください。
63
  # タスク
 
77
  ---
78
  # 出力
79
  """
80
+ # ★★★★★ ここが重要な修正点 ★★★★★
81
+ safety_settings = [
82
+ {
83
+ "category": HarmCategory.HARM_CATEGORY_HARASSMENT,
84
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
85
+ },
86
+ {
87
+ "category": HarmCategory.HARM_CATEGORY_HATE_SPEECH,
88
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
89
+ },
90
+ {
91
+ "category": HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
92
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
93
+ },
94
+ {
95
+ "category": HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
96
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
97
+ },
98
+ ]
99
 
100
  try:
101
  response = gemini_model.generate_content(prompt, generation_config={"temperature": 0.0}, safety_settings=safety_settings)
 
113
  def generate_scene_instruction_with_groq(affection, stage_name, scene, previous_topic):
114
  # この関数は変更なし
115
  print(f"Groqに指示書生成をリクエスト (シーン: {scene})")
116
+ # (中略)
117
+ return None # 省略
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
 
 
119
  def generate_dialogue_with_gemini(history, message, affection, stage_name, scene_params, instruction=None):
120
  history_text = "\n".join([f"ユーザー: {u}\n麻理: {m}" for u, m in history])
121
  task_prompt = f"指示: {instruction}" if instruction else f"ユーザー: {message}"
 
 
122
  system_prompt = f"""
123
  {SYSTEM_PROMPT_MARI}
 
124
  # 現在の状況
125
  - 現在の好感度: {affection}
126
  - 現在の関係ステージ: {stage_name}
127
  - 性格(シーン特有): {scene_params.get("personality_mod", "特になし")}
128
  - 話し方のトーン(シーン特有): {scene_params.get("tone", "特になし")}
 
129
  # 会話履歴
130
  {history_text}
131
  ---
 
135
  """
136
  print(f"Geminiに応答生成をリクエストします (モード: {'シーン遷移' if instruction else '通常会話'})")
137
 
138
+ # ★★★★★ こちらも同様に修正 ★★★★★
139
+ safety_settings = [
140
+ {
141
+ "category": HarmCategory.HARM_CATEGORY_HARASSMENT,
142
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
143
+ },
144
+ {
145
+ "category": HarmCategory.HARM_CATEGORY_HATE_SPEECH,
146
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
147
+ },
148
+ {
149
+ "category": HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
150
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
151
+ },
152
+ {
153
+ "category": HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
154
+ "threshold": HarmBlockThreshold.BLOCK_NONE,
155
+ },
156
+ ]
157
 
158
  try:
159
  generation_config = genai.types.GenerationConfig(max_output_tokens=200, temperature=0.95)
 
170
  return "(ごめんなさい、ちょっと考えがまとまらない……)"
171
 
172
 
173
+ # --- 他の関数とUI部分は変更ありません ---
174
+ # (以下、省略)
175
  def get_relationship_stage(affection):
176
  if affection < 40: return "ステージ1:会話成立"
177
  if affection < 60: return "ステージ2:親密化"
 
212
  background_html = f'<div class="chat-background {theme_name}"></div>'
213
  return "", chat_history, new_affection, stage_name, new_affection, new_history, final_scene_params, background_html
214
 
 
215
  with gr.Blocks(css="style.css", theme=gr.themes.Soft(primary_hue="rose", secondary_hue="pink")) as demo:
216
  scene_state = gr.State(DEFAULT_SCENE_PARAMS)
217
  affection_state = gr.State(30)