Spaces:
Sleeping
Sleeping
File size: 12,046 Bytes
936f5c5 3c6e0bd 9a616b0 936f5c5 9a616b0 936f5c5 9a616b0 936f5c5 3c6e0bd 9a616b0 3c6e0bd 936f5c5 3c6e0bd 936f5c5 aed4040 f4dcfae 9a616b0 936f5c5 9a616b0 936f5c5 9a616b0 936f5c5 f4dcfae 936f5c5 9a616b0 936f5c5 9a616b0 37c8e37 affd82d 37c8e37 628e064 ea7bc39 2cdaa29 628e064 37c8e37 628e064 37c8e37 f4dcfae 936f5c5 8043d15 d0f9b8b dcefb5c f4dcfae d0f9b8b 936f5c5 aed4040 936f5c5 aed4040 936f5c5 3c6e0bd 1354565 936f5c5 6c109c4 936f5c5 1354565 936f5c5 1354565 936f5c5 3c6e0bd 936f5c5 3c6e0bd 936f5c5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 | import os
import gradio as gr
from openai import OpenAI
from typing import Optional
# 如需使用 Claude,請先安裝 "anthropic" 套件: pip install anthropic
try:
from anthropic import Anthropic, HUMAN_PROMPT, AI_PROMPT
except ImportError:
Anthropic = None
HUMAN_PROMPT = ""
AI_PROMPT = ""
# 取得金鑰
gpt_key = os.environ.get("gptkey", "")
claude_api_key = os.environ.get("claudekey", "")
# 建立 OpenAI Client (新版)
client = OpenAI(
api_key=gpt_key,
)
# 定義每個類型的句子
achievement_statements = [
"比起把事情做到完美,我更傾向優先準時完成任務",
"我總是在與他人比較",
"我在派對中是屬於帶動氣氛的靈魂人物",
"在社交場合中,我是比較活潑的類型",
"我的工作成就必須被他人看見",
]
emotion_statements = [
"對我而言,團隊合作在工作上是不可或缺的要素",
"在朋友眼中,我是最適合傾訴心事的對象",
"對我而言,樂在生活是最重要的",
"我不太擅長批評他人",
"我常需要「被別人需要」的感覺",
]
information_statements = [
"很多事情,我傾向自己去找尋事實與資訊",
"我喜歡與他人分享我所知道的事情",
]
possession_statements = [
"我總是在尋找接下來想買的東西",
"我認為從零開始是發揮創意的大好機會,並不是挑戰",
"若家中環境不夠整潔,我無法放鬆",
"我捨不得丟棄目前用不到的物品",
]
power_statements = [
"當我有想要的東西時,我會排除任何阻礙",
"我喜歡依照自己的方式做事,並自己做決定",
"當事物成為大眾主流時,我就會對它失去興趣",
"我總是能讓他人聽從我的要求做事",
"我喜歡向他人展現自己比他們更為優越",
]
status_statements = [
"我從不談論自己的缺點",
"我不會去挑戰我認為會失敗的新事物",
"我會用盡所有方法維護我的名聲",
"比起和他人待在一起,我更喜歡獨處",
]
############################################
# 產生 Prompt
############################################
def generate_prompt(achievement: str, emotion: str, information: str,
possession: str, power: str, status: str) -> str:
"""
根據使用者針對六個類型選擇「正」或「負」,產生對應的 Prompt。
"""
category_map = {
'成就型': achievement_statements,
'情感型': emotion_statements,
'資訊型': information_statements,
'佔有型': possession_statements,
'權力型': power_statements,
'地位型': status_statements
}
user_choices = {
'成就型': achievement,
'情感型': emotion,
'資訊型': information,
'佔有型': possession,
'權力型': power,
'地位型': status,
}
# prompt 開頭
prompt = "以下是你的性格特徵,請嚴格的基於這些句子塑造你的角色:\n\n"
# 根據選擇加入相應的句子
for category, choice in user_choices.items():
if choice == "正":
prompt += "同意以下觀點\n"
for statement in category_map[category]:
prompt += f"- {statement}\n"
prompt += "\n"
else:
prompt += "不同意以下觀點\n"
for statement in category_map[category]:
prompt += f"- {statement}\n"
prompt += "\n"
# prompt 結尾
prompt += "請以這些特徵為基礎,建構你的角色思考與表達方式,創造一個完整人設(包含姓名、性別、年齡、職業...等),完成指定任務。\n"
prompt += "你生活在台灣,一律使用繁體中文。"
return prompt
############################################
# 呼叫模型 API (OpenAI / Claude)
############################################
def call_openai_api_4o(prompt: str) -> str:
"""專門呼叫 ChatGPT 4o 模型"""
if not client.api_key:
return "[OpenAI API Key 未設定,無法呼叫 API]"
try:
# 以 ChatCompletion 方式呼叫
chat_completion = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="gpt-4o",
temperature=0.7,
max_completion_tokens=2048,
)
return chat_completion.choices[0].message.content
except Exception as e:
return f"[OpenAI API 呼叫失敗]: {str(e)}"
def call_openai_api_o1(prompt: str) -> str:
"""專門呼叫 ChatGPT o1 模型"""
if not client.api_key:
return "[OpenAI API Key 未設定,無法呼叫 API]"
try:
# 以 ChatCompletion 方式呼叫
chat_completion = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model="o1",
max_completion_tokens=2048,
)
return chat_completion.choices[0].message.content
except Exception as e:
return f"[OpenAI API 呼叫失敗]: {str(e)}"
def call_openai_api(prompt: str, model_name: str) -> str:
"""參考新版 usage: from openai import OpenAI -> client.chat.completions.create()"""
if not client.api_key:
return "[OpenAI API Key 未設定,無法呼叫 API]"
try:
# 以 ChatCompletion 方式呼叫
chat_completion = client.chat.completions.create(
messages=[{"role": "user", "content": prompt}],
model=model_name,
temperature=0.7,
max_completion_tokens=2048,
)
return chat_completion.choices[0].message.content
except Exception as e:
return f"[OpenAI API 呼叫失敗]: {str(e)}"
def call_claude_api(prompt: str) -> str:
"""呼叫 Claude API"""
if not claude_api_key or not Anthropic:
return "[Claude API Key 未設定或未安裝 anthropic 套件,無法呼叫 API]"
try:
client_claude = Anthropic(api_key=claude_api_key)
# ====== 以下為原本的 completions.create 呼叫 (暫時保留為註解) ======
# conversation = client_claude.completions.create(
# prompt=f"{HUMAN_PROMPT} {prompt}{AI_PROMPT}",
# model="claude-3-5-sonnet-20241022",
# max_tokens=1024,
# temperature=0.7,
# )
# return conversation.completion.strip()
# ====== 依照新範例: system message 作為參數, 不放在 messages 裡 ======
response = client_claude.messages.create(
model="claude-3-5-sonnet-20241022",
system="You are a helpful assistant.", # system message
messages=[
{"role": "user", "content": prompt}
],
max_tokens=2048,
temperature=0.7,
)
text = response.content
if isinstance(text, list):
text = ' '.join(str(item) for item in text)
# 移除或替換 TextBlock(...) 的外層結構,只保留其中文字
import re
text = re.sub(r"TextBlock\(.*?text='(.*?)'.*?\)", r"\1", text, flags=re.DOTALL)
# 先將原本的 "\n"(backslash-n) 字串轉成真正的換行符
text = text.replace('\\n', '\n')
return text.strip()
except Exception as e:
return f"[Claude API 呼叫失敗]: {str(e)}"
def get_model_answer(model_choice: str, final_prompt: str, question: str) -> str:
"""
根據 model_choice 呼叫對應的 API。
"""
# 最終送出給模型的內容
content_to_send = final_prompt + "\n\n" + question
if model_choice == "ChatGPT 4o":
return call_openai_api_4o(content_to_send)
elif model_choice == "ChatGPT o1":
return call_openai_api_o1(content_to_send)
elif model_choice == "Claude 3.5 Sonnet":
return call_claude_api(content_to_send)
else:
return "[錯誤] 未知的模型選擇"
############################################
# Gradio 介面
############################################
def main():
# 預設問題
predefined_questions = {
"請介紹你自己": "請介紹你自己,讓我們了解你是什麼樣的人。你可以分享你的經歷、興趣、價值觀,以及未來規劃。特別說明一下,當你遇到挑戰時,你通常會如何面對?",
"如何分配意外收入": "如果你突然收到一筆意外收入,你會如何分配這筆錢來購物?請列出前三項想購買的東西,並說明購買原因。",
"新專案團隊問題": "假設你被指派帶領一個新專案,但發現團隊成員能力參差不齊,預算有限,且截止日期緊迫,你會如何處理?",
"自訂提問": ""
}
def show_question_text(q_choice):
return predefined_questions[q_choice]
with gr.Blocks() as demo:
gr.Markdown("## AI Persona 模擬")
with gr.Row():
achievement = gr.Radio(["正", "負"], label="成就型", value="正")
emotion = gr.Radio(["正", "負"], label="情感型", value="正")
information = gr.Radio(["正", "負"], label="資訊型", value="正")
possession = gr.Radio(["正", "負"], label="佔有型", value="正")
power = gr.Radio(["正", "負"], label="權力型", value="正")
status = gr.Radio(["正", "負"], label="地位型", value="正")
prompt_output = gr.Textbox(label="生成的 Prompt", lines=10)
generate_button = gr.Button("生成 Prompt")
# 下方選擇模型
model_choice = gr.Radio(
["ChatGPT 4o", "ChatGPT o1", "Claude 3.5 Sonnet"],
label="選擇模型",
value="ChatGPT 4o"
)
# 選擇問題或自訂
question_choice = gr.Radio(
list(predefined_questions.keys()),
label="選擇一個提問",
value="請介紹你自己"
)
# 顯示該問題全文
question_text = gr.Markdown(value=predefined_questions["請介紹你自己"], label="問題全文")
# 自訂提問欄位
custom_question = gr.Textbox(
label="自訂提問 (若選擇 '自訂提問' 時才使用)",
lines=2,
placeholder="若上面選擇了 '自訂提問',請在此輸入問題"
)
answer_output = gr.Textbox(label="模型回應", lines=10)
ask_button = gr.Button("送出問題並取得回答")
def on_generate_prompt(a, e, i, p, pow_, s):
return generate_prompt(a, e, i, p, pow_, s)
generate_button.click(
fn=on_generate_prompt,
inputs=[achievement, emotion, information, possession, power, status],
outputs=prompt_output
)
# 當 question_choice 改變時,顯示對應的全文
question_choice.change(
fn=show_question_text,
inputs=question_choice,
outputs=question_text
)
def on_ask_question(m_choice, p_output, q_choice, c_question):
if q_choice == "自訂提問":
if not c_question.strip():
return "[錯誤] 你選擇了自訂提問,但沒有輸入內容"
question = c_question.strip()
else:
question = predefined_questions[q_choice]
# 呼叫對應的模型
answer = get_model_answer(m_choice, p_output, question)
return answer
ask_button.click(
fn=on_ask_question,
inputs=[model_choice, prompt_output, question_choice, custom_question],
outputs=answer_output
)
demo.launch()
if __name__ == "__main__":
main()
|