PSNbst's picture
Update app.py
0550b9b verified
raw
history blame
11.3 kB
##############################################
# app.py
##############################################
import os
import json
import gradio as gr
from openai import OpenAI
##############################################################################
# 1. 读取外部文件: furry_species.json & gender_rules.json
##############################################################################
# 假设 furry_species.json 的结构是多级字典: { "AQUATICS ...": { "Cetaceans": [], ...}, ... }
try:
with open("furry_species.json", "r", encoding="utf-8") as f:
FURRY_DATA = json.load(f)
except:
FURRY_DATA = {}
# gender_rules.json: { "male": "...", "female": "...", "intersex": "...", "genderless": "..." }
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):
"""获取所有顶级分类 (keys)"""
return sorted(list(furry_data.keys()))
def get_sub_categories(furry_data, top_category):
"""
根据所选 top_category, 返回二级分类列表
furry_data[top_category] -> { "Cetaceans": [...], "FishFurs": [...], ... }
"""
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):
"""
返回最终物种列表
furry_data[top_category][sub_category] -> list
"""
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_tags_and_description(prompt, gender_option, top_cat, sub_cat, species_item, api_mode, api_key):
"""
1) 构造 tags: gender, base_prompt, furry_species
2) 读取 gender_rules 并拼入 system prompt
3) 调用 GPT/DeepSeek
4) 输出 (tags + 自然语言描述)
"""
if not api_key:
return "Error: No API Key provided."
# 性别
tags = {}
if gender_option == "Trans_to_Male":
tags["gender"] = "male"
rule_text = GENDER_RULES.get("male", "")
elif gender_option == "Trans_to_Female":
tags["gender"] = "female"
rule_text = GENDER_RULES.get("female", "")
elif gender_option == "Trans_to_Mannequin":
tags["gender"] = "genderless"
rule_text = GENDER_RULES.get("genderless", "")
elif gender_option == "Trans_to_Intersex":
tags["gender"] = "intersex"
rule_text = GENDER_RULES.get("intersex", "")
else:
# Furry
tags["gender"] = "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", "")
) # 或者只给一个简要 furry rule
# 选定物种
final_species = "unknown"
if top_cat and sub_cat and species_item:
final_species = f"{top_cat} > {sub_cat} > {species_item}"
tags["furry_species"] = final_species
# 原始提示词
tags["base_prompt"] = prompt
# BaseURL & 模型
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
# 将 tags 拼为字符串
tags_str = "\n".join([f"{k}: {v}" for k, v in tags.items() if v])
# system prompt 带上Gender Rules
system_prompt = (
"You are a creative assistant that generates detailed and imaginative scene descriptions "
"for AI generation prompts. Focus on the details provided, incorporate them into a cohesive narrative, "
"and follow these gender/furry rules:\n\n"
f"{rule_text}\n\n"
"When you respond, do not exceed five sentences. Return your final text in English or relevant language.\n"
)
# Chat
try:
resp = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": system_prompt},
{
"role": "user",
"content": f"Here are the tags:\n{tags_str}\nPlease generate a vivid, imaginative scene description."
},
],
)
desc_text = resp.choices[0].message.content.strip()
# 输出 (tags + desc)
return f"=== Tags ===\n{tags_str}\n\n=== Description ===\n{desc_text}"
except Exception as e:
return f"{api_mode} generation failed. Error: {e}"
def translate_text(content, lang, api_mode, api_key):
"""
调用 GPT 或 DeepSeek 做翻译
"""
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
system_prompt = f"You are a translator. Translate the following text to {lang}:"
try:
resp = client.chat.completions.create(
model=model_name,
messages=[
{"role": "system", "content": 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 Furry/Gender Transformer (GPT / DeepSeek)")
with gr.Row():
with gr.Column():
api_mode = gr.Radio(
label="选择API (GPT or DeepSeek)",
choices=["GPT", "DeepSeek"],
value="GPT"
)
api_key = gr.Textbox(
label="API Key",
type="password"
)
# 性别
gender_option = gr.Radio(
label="转换目标",
choices=[
"Trans_to_Male",
"Trans_to_Female",
"Trans_to_Mannequin",
"Trans_to_Intersex",
"Trans_to_Furry"
],
value="Trans_to_Male"
)
# 顶级分类
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]
)
with gr.Column():
user_prompt = gr.Textbox(
label="提示词 (Prompt)",
lines=4
)
output_result = gr.Textbox(
label="(tags + 自然语言描述)",
lines=10
)
with gr.Row():
translate_lang = gr.Dropdown(
label="翻译语言",
choices=["English", "Chinese", "Japanese", "French", "German", "Spanish"],
value="English"
)
translate_result = gr.Textbox(
label="翻译结果",
lines=10
)
######################################################################
# 生成
######################################################################
def on_generate(prompt, gender, tc, sc, spc, mode, key, lang):
# 1) 生成
tags_desc = generate_tags_and_description(prompt, gender, tc, sc, spc, mode, key)
# 2) 翻译
trans_txt = translate_text(tags_desc, lang, mode, key)
return tags_desc, trans_txt
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=[output_result, translate_result]
)
gen_btn = gr.Button("生成 / Generate")
gen_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=[output_result, translate_result]
)
return demo
if __name__ == "__main__":
demo = build_interface()
demo.launch()