PSNbst's picture
Update app.py
21bc132 verified
raw
history blame
11.5 kB
import os
import json
import gradio as gr
from openai import OpenAI
##############################################################################
# 1. 读取外部文件: furry_species.json & gender_rules.json
##############################################################################
try:
with open("furry_species.json", "r", encoding="utf-8") as f:
FURRY_DATA = json.load(f)
except:
FURRY_DATA = {}
try:
with open("gender_rules.json", "r", encoding="utf-8") as f:
GENDER_RULES = json.load(f)
except:
GENDER_RULES = {}
##############################################################################
# 2. 多级菜单构造函数
##############################################################################
def get_top_categories(furry_data):
return sorted(list(furry_data.keys()))
def get_sub_categories(furry_data, top_category):
if top_category in furry_data:
return sorted(list(furry_data[top_category].keys()))
return []
def get_species_list(furry_data, top_category, sub_category):
if top_category in furry_data and sub_category in furry_data[top_category]:
return sorted(furry_data[top_category][sub_category])
return []
##############################################################################
# 3. 核心调用:GPT 或 DeepSeek
##############################################################################
def generate_transformed_output(
prompt, # 原始 Prompt,如 "1girl, butterfly, solo..."
gender_option, # 转换目标
top_cat, sub_cat, species_item,
api_mode, api_key
):
"""
根据指定的性别/物种等规则,让 GPT/DeepSeek 输出仅两段内容:
(转化后tags)
转化后描述 (3~6句)
不展示原始 prompt/base_prompt/gender: ... 等信息。
"""
if not api_key:
return "Error: No API Key provided."
# 根据 gender_option 选对应的 rule
if gender_option == "Trans_to_Male":
rule_text = GENDER_RULES.get("male", "")
elif gender_option == "Trans_to_Female":
rule_text = GENDER_RULES.get("female", "")
elif gender_option == "Trans_to_Mannequin":
rule_text = GENDER_RULES.get("genderless", "")
elif gender_option == "Trans_to_Intersex":
rule_text = GENDER_RULES.get("intersex", "")
else:
# Furry
# 你可以综合 male/female/intersex/genderless,也可以有专门 furry 的说明
rule_text = (
GENDER_RULES.get("male", "") + "\n\n"
+ GENDER_RULES.get("female", "") + "\n\n"
+ GENDER_RULES.get("intersex", "") + "\n\n"
+ GENDER_RULES.get("genderless", "")
)
# 如果想在规则中附加选定的物种信息:
if top_cat and sub_cat and species_item:
rule_text += f"\nFurry species: {top_cat} > {sub_cat} > {species_item}\n"
# 选定 GPT or DeepSeek
if api_mode == "GPT":
base_url = None
model_name = "gpt-3.5-turbo" # 可改成 "gpt-4"
else:
base_url = "https://api.deepseek.com"
model_name = "deepseek-chat"
client = OpenAI(api_key=api_key)
if base_url:
client.base_url = base_url
# 构造 System Prompt:要求只输出两段;第一行(转化后tags),空行,随后3~6句描述
# 让它把 prompt 中的 tags 进行「合并、替换、去重、增加」等处理
system_prompt = f"""
You are a creative assistant that modifies the user's base prompt tags
to reflect the correct gender/furry transformations, following these rules:
{rule_text}
Steps:
1) The original prompt tags are: {prompt}
2) Convert them into NEW combined tags that reflect the requested transformation.
(Remove or replace conflicting tags, unify synonyms, add any essential tags
for {gender_option} or for the selected furry species.)
3) Output EXACTLY two parts:
- First line: the final, consolidated tags in parentheses (e.g. (male, solo, ...)).
- Then a blank line.
- Then a short imaginative scene description (3 to 6 sentences).
4) Do NOT include 'gender:' or 'base_prompt:' or any headings or extra lines.
5) Output everything in English.
6) Do not reference these steps in the final answer.
""".strip()
try:
resp = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": "Generate the final tags and description now."},
],
)
# 结果中仅包含 (tags)\n\n(description)
result = resp.choices[0].message.content.strip()
return result
except Exception as e:
return f"{api_mode} generation failed. Error: {e}"
def translate_text(content, lang, api_mode, api_key):
"""
对上一步的 (tags)\n\n(description) 做翻译,保持格式
"""
if not api_key:
return "Error: No API Key provided."
if not content.strip():
return ""
if api_mode == "GPT":
base_url = None
model_name = "gpt-3.5-turbo"
else:
base_url = "https://api.deepseek.com"
model_name = "deepseek-chat"
client = OpenAI(api_key=api_key)
if base_url:
client.base_url = base_url
translate_system_prompt = f"""
You are a translator. Translate the following text to {lang},
preserving the parentheses line and blank lines if present.
Do not add extra headings.
""".strip()
try:
resp = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": translate_system_prompt},
{"role": "user", "content": content},
],
)
return resp.choices[0].message.content.strip()
except Exception as e:
return f"{api_mode} translation failed. Error: {e}"
##############################################################################
# 4. Gradio 前端
##############################################################################
def build_interface():
with gr.Blocks() as demo:
gr.Markdown("## Prompt Transformer Tool- 提示词物种性别转化器(GPT/DeepSeek)")
with gr.Row():
with gr.Column():
# 选择 GPT/DeepSeek
api_mode = gr.Radio(
label="Choose API (GPT or DeepSeek)",
choices=["GPT", "DeepSeek"],
value="GPT"
)
# 输入 API Key
api_key = gr.Textbox(
label="API Key-API密匙",
type="password",
placeholder="Enter your GPT or DeepSeek Key here"
)
# 性别/Furry
gender_option = gr.Radio(
label="Gender / Furry Conversion 选择物种性别",
choices=[
"Trans_to_Male",
"Trans_to_Female",
"Trans_to_Mannequin",
"Trans_to_Intersex",
"Trans_to_Furry"
],
value="Trans_to_Male"
)
# 若选 Furry -> 多级菜单
top_cat_dd = gr.Dropdown(
label="Furry: Top Category",
choices=get_top_categories(FURRY_DATA),
value=None,
visible=False
)
sub_cat_dd = gr.Dropdown(
label="Furry: Sub Category",
choices=[],
value=None,
visible=False
)
species_dd = gr.Dropdown(
label="Furry: Species",
choices=[],
value=None,
visible=False
)
# 当性别选项切到 Furry 时,显示下拉,否则隐藏
def show_furry_options(chosen):
if chosen == "Trans_to_Furry":
return (gr.update(visible=True),
gr.update(visible=True),
gr.update(visible=True))
else:
return (gr.update(visible=False),
gr.update(visible=False),
gr.update(visible=False))
gender_option.change(
fn=show_furry_options,
inputs=[gender_option],
outputs=[top_cat_dd, sub_cat_dd, species_dd]
)
# 主分类 -> 子分类
def on_top_cat_select(selected):
subs = get_sub_categories(FURRY_DATA, selected)
return gr.update(choices=subs, value=None)
top_cat_dd.change(
fn=on_top_cat_select,
inputs=[top_cat_dd],
outputs=[sub_cat_dd]
)
# 子分类 -> 物种
def on_sub_cat_select(top_c, sub_c):
sp = get_species_list(FURRY_DATA, top_c, sub_c)
return gr.update(choices=sp, value=None)
sub_cat_dd.change(
fn=on_sub_cat_select,
inputs=[top_cat_dd, sub_cat_dd],
outputs=[species_dd]
)
# 输入 prompt & 输出
with gr.Column():
user_prompt = gr.Textbox(
label="原始 Prompt (Base Tags)",
lines=5,
placeholder="Your Prompts"
)
final_output = gr.Textbox(
label="(转化后Tags)\n\n(转化后描述)",
lines=10
)
# 翻译
with gr.Row():
translate_lang = gr.Dropdown(
label="翻译语言 Translater",
choices=["English", "Chinese", "Japanese", "French", "German", "Spanish"],
value="English"
)
translated_result = gr.Textbox(
label="翻译后的结果 Trans-Language Result",
lines=10
)
######################################################################
# 事件
######################################################################
def on_generate(prompt, gender, tc, sc, sp, mode, key, lang):
# 1) 生成新的 (tags) + 描述
merged = generate_transformed_output(prompt, gender, tc, sc, sp, mode, key)
# 2) 翻译
trans = translate_text(merged, lang, mode, key)
return merged, trans
# 回车提交
user_prompt.submit(
fn=on_generate,
inputs=[user_prompt, gender_option, top_cat_dd, sub_cat_dd, species_dd, api_mode, api_key, translate_lang],
outputs=[final_output, translated_result]
)
# 点击按钮
btn = gr.Button("生成 / Generate")
btn.click(
fn=on_generate,
inputs=[user_prompt, gender_option, top_cat_dd, sub_cat_dd, species_dd, api_mode, api_key, translate_lang],
outputs=[final_output, translated_result]
)
return demo
if __name__ == "__main__":
demo = build_interface()
demo.launch()