Spaces:
Sleeping
Sleeping
| 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() |