├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── bug_report_cn.yml │ ├── feature_request.yml │ └── feature_request_cn.yml └── workflows │ ├── build.yml │ └── issue-translator.yml ├── .gitignore ├── LICENSE ├── Leticia service ├── README.MD ├── README_CN.MD ├── README_JP.MD ├── README_KR.MD ├── README_RU.MD ├── README_TW.MD ├── group_tags ├── .gitignore ├── de_DE.yaml ├── default.yaml ├── es_ES.yaml ├── fr_FR.yaml ├── it_IT.yaml ├── ja_JP.yaml ├── ko_KR.yaml ├── pt_PT.yaml ├── ru_RU.yaml ├── zh_CN.yaml ├── zh_HK.yaml └── zh_TW.yaml ├── i18n.json ├── install.py ├── javascript ├── .gitignore ├── main.entry.js └── main.entry.js.map ├── models └── .gitignore ├── scripts ├── on_app_started.py └── physton_prompt │ ├── csv.py │ ├── gen_openai.py │ ├── get_extensions.py │ ├── get_extra_networks.py │ ├── get_group_tags.py │ ├── get_i18n.py │ ├── get_lang.py │ ├── get_token_counter.py │ ├── get_translate_apis.py │ ├── get_version.py │ ├── history.py │ ├── mbart50.py │ ├── packages.py │ ├── storage.py │ ├── styles.py │ ├── translate.py │ ├── translator │ ├── alibaba_translator.py │ ├── amazon_translator.py │ ├── baidu_translator.py │ ├── base_tanslator.py │ ├── caiyun_translator.py │ ├── deepl_translator.py │ ├── google_tanslator.py │ ├── iflytekV1_translator.py │ ├── iflytekV2_translator.py │ ├── mbart50_translator.py │ ├── microsoft_translator.py │ ├── mymemory_translator.py │ ├── niutrans_translator.py │ ├── openai_translator.py │ ├── tencent_translator.py │ ├── translators_translator.py │ ├── volcengine_translator.py │ ├── yandex_translator.py │ └── youdao_translator.py │ └── translators │ ├── README.md │ ├── requirements.txt │ └── server.py ├── src ├── .gitignore ├── README.md ├── globals.js ├── index.html ├── package.json ├── src │ ├── App.vue │ ├── components │ │ ├── about.vue │ │ ├── blacklist.vue │ │ ├── chatgptPrompt.vue │ │ ├── extensionCss.vue │ │ ├── extraNetworksPopup.vue │ │ ├── favorite.vue │ │ ├── highlightPrompt.vue │ │ ├── history.vue │ │ ├── hotkey.vue │ │ ├── iconSvg.vue │ │ ├── packagesState.vue │ │ ├── phystonPrompt.vue │ │ ├── promptFormat.vue │ │ ├── selectLanguage.vue │ │ ├── translateSetting.vue │ │ └── vue-number-input.vue │ ├── main.js │ ├── mixins │ │ ├── commonMixin.js │ │ ├── languageMixin.js │ │ └── phystonPrompt │ │ │ ├── dropMixin.js │ │ │ ├── groupTagsMixin.js │ │ │ ├── headerMixin.js │ │ │ └── tagMixin.js │ └── utils │ │ ├── common.js │ │ ├── favorite.js │ │ ├── favoriteItem.js │ │ ├── gradioAPI.js │ │ ├── history.js │ │ ├── historyItem.js │ │ ├── splitTags.js │ │ └── waitTick.js └── vite.config.js ├── storage └── .gitignore ├── style.css ├── styles ├── animate.less ├── animate.min.css ├── extensions │ ├── MyStyle-shuai │ │ ├── manifest.json │ │ └── style.min.css │ ├── README.MD │ ├── Webui │ │ ├── images │ │ │ ├── code.svg │ │ │ ├── d.svg │ │ │ ├── favorite.svg │ │ │ ├── favorite_l.svg │ │ │ ├── lan.svg │ │ │ ├── updown.svg │ │ │ ├── 人物.svg │ │ │ ├── 其它.svg │ │ │ ├── 反向提示词.svg │ │ │ ├── 场景.svg │ │ │ ├── 开始.svg │ │ │ ├── 服饰.svg │ │ │ ├── 汉服.svg │ │ │ ├── 物品.svg │ │ │ ├── 环境.svg │ │ │ ├── 画面.svg │ │ │ ├── 表情动作.svg │ │ │ ├── 镜头.svg │ │ │ └── 魔法系.svg │ │ ├── manifest.json │ │ └── style.min.css │ ├── demo.zip │ ├── firefox-fix │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── full-input │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-group-tags-en-text │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-input-dropdown │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-btns-blacklist │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-btns-weight-brackets │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-btns-weight │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-btns │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-extra-network-popup │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── hide-tag-local │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── left-input │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── line-breaks-new-line │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── minimalist │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── remove-hide-default-input │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── setting-btns-top │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── tag-btns-right │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── tag-group-tweak │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ ├── tag-weight-character │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css │ └── weaken-keywords │ │ ├── manifest.json │ │ ├── style.less │ │ └── style.min.css ├── icons │ ├── about.svg │ ├── api.svg │ ├── blacklist.svg │ ├── chatgpt.svg │ ├── clear.svg │ ├── close.svg │ ├── copy.svg │ ├── disabled.svg │ ├── enable.svg │ ├── english.svg │ ├── favorite-no.svg │ ├── favorite-yes.svg │ ├── favorite.svg │ ├── format.svg │ ├── github.svg │ ├── history.svg │ ├── hotkey.svg │ ├── i18n.svg │ ├── input.svg │ ├── load.svg │ ├── load2.svg │ ├── loading.svg │ ├── moon.svg │ ├── move-down.svg │ ├── move-up.svg │ ├── refresh.svg │ ├── remove-space.svg │ ├── remove.svg │ ├── reset.svg │ ├── setting.svg │ ├── sun.svg │ ├── theme.svg │ ├── tooltip.svg │ ├── translate.svg │ ├── unfold.svg │ ├── use.svg │ ├── weight-braces-dec.svg │ ├── weight-braces-inc.svg │ ├── weight-brackets-dec.svg │ ├── weight-brackets-inc.svg │ ├── weight-parentheses-dec.svg │ ├── weight-parentheses-inc.svg │ └── wrap.svg ├── main.less ├── main.min.css ├── tippy.css ├── toastr.min.css └── vue3-colorpicker.css ├── tags └── .gitignore ├── tests ├── .gitignore ├── get_lang.py ├── get_version.py ├── privacy_api_config.py ├── translate.py ├── translator.py └── translators.py ├── translate_apis.backup.json └── translate_apis.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: physton 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry 13 | custom: ['https://paypal.me/physton', 'https://aiodoc.physton.com/Donate.html'] 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: 'Bug report' 2 | description: "❗️❗️❗️If you don't use this template to provide bug feedback, I won't address your issue." 3 | title: '[Bug] ' 4 | body: 5 | - type: checkboxes 6 | attributes: 7 | label: 'Issue Feedback' 8 | description: Please check the box below to indicate that you are aware of the relevant information. 9 | options: 10 | - label: I confirm that I have searched for a solution to this issue in the [FAQ](https://aiodoc.physton.com/FAQ.html) and couldn't find a solution. 11 | required: true 12 | - label: I confirm that I have searched for this issue in the [Issues](https://github.com/Physton/sd-webui-prompt-all-in-one/issues) list (including closed ones) and couldn't find a solution. 13 | required: true 14 | - label: I confirm that I have read the [Wiki](https://aiodoc.physton.com/) and couldn't find a solution. 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: 'Describe the Issue' 19 | description: Please describe the problem you encountered here. 20 | validations: 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: 'Steps to Reproduce' 25 | description: Please let me know the steps you took to trigger the issue. 26 | - type: textarea 27 | attributes: 28 | label: 'Screenshot or log' 29 | description: Please provide console screenshots or screenshots of the issue if possible. 30 | - type: dropdown 31 | attributes: 32 | label: 'OS' 33 | options: 34 | - Windows 35 | - macOS 36 | - Ubuntu 37 | - Other Linux 38 | - Other 39 | validations: 40 | required: true 41 | - type: dropdown 42 | attributes: 43 | label: 'Browser' 44 | options: 45 | - Chrome 46 | - Edge 47 | - Safari 48 | - Firefox 49 | - Other 50 | validations: 51 | required: true 52 | - type: input 53 | attributes: 54 | label: Stable Diffusion WebUI version 55 | placeholder: e.g. b6af0a3, 1.3.1 56 | validations: 57 | required: false 58 | - type: input 59 | attributes: 60 | label: Extension version 61 | placeholder: e.g. e0498a1 62 | validations: 63 | required: false 64 | - type: input 65 | attributes: 66 | label: Python version 67 | placeholder: e.g. 3.10.11 68 | validations: 69 | required: false 70 | - type: input 71 | attributes: 72 | label: Gradio version 73 | placeholder: e.g. 3.31.0 74 | validations: 75 | required: false 76 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report_cn.yml: -------------------------------------------------------------------------------- 1 | name: '反馈问题' 2 | description: '❗️❗️❗️如果不使用此模板反馈bug,我不会去解决你的问题' 3 | title: '[Bug] ' 4 | body: 5 | - type: checkboxes 6 | attributes: 7 | label: '反馈须知' 8 | description: 请在下方勾选表示你已经知晓相关内容。 9 | options: 10 | - label: 我确认已经在 [常见问题](https://aiodoc.physton.com/zh-CN/FAQ.html) 中搜索了此次反馈的问题,没有找到解决方法。 11 | required: true 12 | - label: 我确认已经在 [Issues](https://github.com/Physton/sd-webui-prompt-all-in-one/issues) 列表(包括已经 Close 的)中搜索了此次反馈的问题,没有找到解决方法。 13 | required: true 14 | - label: 我确认阅读了 [文档](https://aiodoc.physton.com/zh-CN/),没有找到解决方法。 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: '描述问题' 19 | description: 请在此描述你遇到了什么问题。 20 | validations: 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: '如何复现' 25 | description: 请告诉我你是通过什么操作触发的该问题。 26 | - type: textarea 27 | attributes: 28 | label: '截图或日志' 29 | description: 请在此提供控制台截图、屏幕截图。 30 | - type: dropdown 31 | attributes: 32 | label: '操作系统' 33 | options: 34 | - Windows 35 | - macOS 36 | - Ubuntu 37 | - Other Linux 38 | - Other 39 | validations: 40 | required: true 41 | - type: dropdown 42 | attributes: 43 | label: '浏览器' 44 | options: 45 | - Chrome 46 | - Edge 47 | - Safari 48 | - Firefox 49 | - Other 50 | validations: 51 | required: true 52 | - type: input 53 | attributes: 54 | label: Stable Diffusion WebUI 版本 55 | placeholder: e.g. b6af0a3, 1.3.1 56 | validations: 57 | required: false 58 | - type: input 59 | attributes: 60 | label: 扩展版本 61 | placeholder: e.g. e0498a1 62 | validations: 63 | required: false 64 | - type: input 65 | attributes: 66 | label: Python 版本 67 | placeholder: e.g. 3.10.11 68 | validations: 69 | required: false 70 | - type: input 71 | attributes: 72 | label: Gradio 版本 73 | placeholder: e.g. 3.31.0 74 | validations: 75 | required: false 76 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 'Feature request' 2 | description: 'Feature request' 3 | title: '[Feature] ' 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: 'Is this feature related to existing issues?' 8 | description: If it is, please list the links or describe the issues here. 9 | - type: textarea 10 | attributes: 11 | label: 'What feature do you want or what suggestions do you have?' 12 | description: Please let me know. 13 | validations: 14 | required: true 15 | - type: textarea 16 | attributes: 17 | label: 'Are there any similar competitors that can be referenced?' 18 | description: You can provide links or screenshots of reference products. 19 | - type: textarea 20 | attributes: 21 | label: 'Additional information' 22 | description: Feel free to share any other considerations you have. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request_cn.yml: -------------------------------------------------------------------------------- 1 | name: '功能建议' 2 | description: '功能建议' 3 | title: '[Feature] ' 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: '这个功能与现有的问题有关吗?' 8 | description: 如果有关,请在此列出链接或者描述问题。 9 | - type: textarea 10 | attributes: 11 | label: '你想要什么功能或者有什么建议?' 12 | description: 尽管告诉我。 13 | validations: 14 | required: true 15 | - type: textarea 16 | attributes: 17 | label: '有没有可以参考的同类竞品?' 18 | description: 可以给出参考产品的链接或者截图。 19 | - type: textarea 20 | attributes: 21 | label: '其他信息' 22 | description: 可以说说你的其他考虑。 -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | # push: 6 | # branches: 7 | # - main 8 | # paths: 9 | # - 'src/**' 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | 19 | - name: Set up Node.js 20 | uses: actions/setup-node@v2 21 | with: 22 | node-version: '18' 23 | 24 | - name: Install dependencies 25 | run: npm install 26 | working-directory: ./src 27 | 28 | - name: Build 29 | run: npm run build 30 | working-directory: ./src 31 | 32 | - name: Configure Git 33 | run: | 34 | git config --global user.name "GitHub Actions" 35 | git config --global user.email "actions@github.com" 36 | 37 | - name: Push javascript 38 | if: success() 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | run: | 42 | git add -f ./javascript/* 43 | git commit -m "Build" 44 | git push origin main 45 | -------------------------------------------------------------------------------- /.github/workflows/issue-translator.yml: -------------------------------------------------------------------------------- 1 | name: 'issue-translator' 2 | on: 3 | issue_comment: 4 | types: [created] 5 | issues: 6 | types: [opened] 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: usthe/issues-translate-action@v2.7 13 | with: 14 | IS_MODIFY_TITLE: false 15 | # not require, default false, . Decide whether to modify the issue title 16 | # if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot. 17 | CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿 18 | # not require. Customize the translation robot prefix message. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /development_styles 3 | /index.php 4 | /src/node_modules 5 | /src/package-lock.json 6 | /styles/extensions/demo 7 | __pycache__ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Physton 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Leticia service: -------------------------------------------------------------------------------- 1 | from together import Together 2 | 3 | image = client.images.generate( 4 | prompt="MJ v6, A sensual, full-body anime elf girl with long, flowing silver hair and sparkling highlights, deep red eyes, and a seductive, lustful expression, posing with both hands grasping a green wine bottle, wearing an Egyptian-inspired sheer black skirt with intricate golden embroidery, split front and back panels, and a delicate black silk veil draped over her head, paired with black elbow-length fingerless gloves, elegant golden jewelry, and ornate bracelets, set against a dark fantasy blur background with soft body lighting, detailed anime shading, and line art, strong contrast with dramatic shadows, cinematic lighting, and a Goblin Slayer-inspired aesthetic, rendered in a highly detailed, ultra-sharp, and masterful style, with a focus on photorealistic textures and a close-up composition that emphasizes the subject's intricate features and sensual presence.", 5 | model="black-forest-labs/FLUX.1-dev-lora", 6 | height=768, 7 | width=1024, 8 | seed=8910047, 9 | steps=28, 10 | image_loras=[ 11 | { 12 | "path": "https://huggingface.co/strangerzonehf/Flux-Midjourney-Mix2-LoRA", 13 | "scale": 1, 14 | }, 15 | ], 16 | ) 17 | 18 | print(image.data[0].url) 19 | -------------------------------------------------------------------------------- /group_tags/.gitignore: -------------------------------------------------------------------------------- 1 | custom.yaml 2 | prepend.yaml 3 | append.yaml -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | import launch 2 | 3 | packages = { 4 | "chardet": "chardet", 5 | "fastapi": "fastapi", 6 | "execjs": "PyExecJS", 7 | "lxml": "lxml", 8 | "tqdm": "tqdm", 9 | "pathos": "pathos", 10 | "cryptography": "cryptography", 11 | 12 | # The following packages are required for translation service. If you do not need translation service, you can remove them. 13 | # 以下是翻译所需的包,如果不需要翻译服务,可以删除掉它们。 14 | "openai": "openai", 15 | "boto3": "boto3", 16 | "aliyunsdkcore": "aliyun-python-sdk-core", 17 | "aliyunsdkalimt": "aliyun-python-sdk-alimt", 18 | } 19 | 20 | if __name__ == "__main__": 21 | for package_name in packages: 22 | package = packages[package_name] 23 | try: 24 | if not launch.is_installed(package_name): 25 | launch.run_pip(f"install {package}", f"sd-webui-prompt-all-in-one: {package_name}") 26 | except Exception as e: 27 | print(e) 28 | print(f'Warning: Failed to install {package}, some preprocessors may not work.') -------------------------------------------------------------------------------- /javascript/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /models/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /scripts/physton_prompt/csv.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | base_dir = str(Path().absolute()) 5 | self_base_dir = os.path.abspath(os.path.join(os.path.join(os.path.dirname(__file__)), '../', '../')) 6 | self_tags_dir = os.path.join(self_base_dir, 'tags') 7 | dirs = [ 8 | self_tags_dir, 9 | # os.path.join(base_dir, 'extensions', 'sd-webui-prompt-all-in-one', 'tags'), 10 | os.path.join(base_dir, 'extensions', 'a1111-sd-webui-tagcomplete', 'tags'), 11 | ] 12 | 13 | 14 | def get_csvs(): 15 | global base_dir 16 | global self_base_dir 17 | global self_tags_dir 18 | csvs = [] 19 | for dir in dirs: 20 | if not os.path.exists(dir): 21 | continue 22 | for file in os.listdir(dir): 23 | if file.endswith('.csv'): 24 | path = os.path.join(dir, file) 25 | name = os.path.basename(file) 26 | size = os.path.getsize(path) 27 | if dir == self_tags_dir: 28 | # 去除 self_tags_dir 后的路径 29 | key = path.replace(self_tags_dir, '') 30 | key = '\\extensions\\sd-webui-prompt-all-in-one\\tags\\' + name 31 | else: 32 | # 去除 base_dir 后的路径 33 | key = path.replace(base_dir, '') 34 | csvs.append({ 35 | 'key': key, 36 | 'name': name, 37 | 'size': size, 38 | 'path': path 39 | }) 40 | return csvs 41 | 42 | 43 | def get_csv(key): 44 | global base_dir 45 | global self_base_dir 46 | global self_tags_dir 47 | path = base_dir + key 48 | if not os.path.exists(path): 49 | path = os.path.join(self_tags_dir, key.replace('\\extensions\\sd-webui-prompt-all-in-one\\tags\\', '')) 50 | if not os.path.exists(path): 51 | return None 52 | return path 53 | -------------------------------------------------------------------------------- /scripts/physton_prompt/gen_openai.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.get_lang import get_lang 2 | from scripts.physton_prompt.get_translate_apis import unprotected_translate_api_config 3 | 4 | 5 | def gen_openai(messages, api_config): 6 | import openai 7 | from distutils.version import LooseVersion 8 | api_config = unprotected_translate_api_config('chatgpt_key', api_config) 9 | openai.api_base = api_config.get('api_base', 'https://api.openai.com/v1') 10 | openai.api_key = api_config.get('api_key', '') 11 | model = api_config.get('model', 'gpt-3.5-turbo') 12 | if not openai.api_key: 13 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 14 | if not messages or len(messages) == 0: 15 | raise Exception(get_lang('is_required', {'0': 'messages'})) 16 | if LooseVersion(openai.__version__) < LooseVersion('1.0.0'): 17 | completion = openai.ChatCompletion.create(model=model, messages=messages, timeout=60) 18 | else: 19 | from openai import OpenAI 20 | client = OpenAI( 21 | base_url=openai.api_base, 22 | api_key=openai.api_key, 23 | ) 24 | completion = client.chat.completions.create(model=model, messages=messages, timeout=60) 25 | if len(completion.choices) == 0: 26 | raise Exception(get_lang('no_response_from', {'0': 'OpenAI'})) 27 | content = completion.choices[0].message.content 28 | return content 29 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_extensions.py: -------------------------------------------------------------------------------- 1 | import os 2 | from pathlib import Path 3 | 4 | 5 | def get_extensions(): 6 | extends_dir = os.path.join(Path().absolute(), 'extensions') 7 | extends = [] 8 | for name in os.listdir(extends_dir): 9 | path = os.path.join(extends_dir, name) 10 | if os.path.isdir(path): 11 | extends.append(name) 12 | return extends 13 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_extra_networks.py: -------------------------------------------------------------------------------- 1 | # -*- coding: UTF-8 -*- 2 | 3 | from modules import script_callbacks, extra_networks, prompt_parser, shared, ui_extra_networks 4 | import json 5 | import os 6 | import copy 7 | 8 | filters = [ 9 | # 'filename', 10 | # 'description', 11 | 'search_term', 12 | 'local_preview', 13 | 'metadata', 14 | ] 15 | 16 | 17 | def get_extra_networks(): 18 | result = [] 19 | try: 20 | for extra_page in ui_extra_networks.extra_pages: 21 | result_item = { 22 | 'name': extra_page.name, 23 | 'title': extra_page.title, 24 | 'items': [] 25 | } 26 | for oriItem in extra_page.list_items(): 27 | item = copy.deepcopy(oriItem) 28 | # 解析metadata 29 | output_name = None 30 | try: 31 | if 'metadata' in item and item['metadata']: 32 | metadata = json.loads(item['metadata']) 33 | if metadata and 'ss_output_name' in metadata: 34 | output_name = metadata['ss_output_name'] 35 | except Exception as e: 36 | pass 37 | item['output_name'] = output_name 38 | 39 | # 获取civitai.info 40 | item['civitai_info'] = {} 41 | try: 42 | if 'filename' in item and item['filename']: 43 | item['basename'] = os.path.basename(item['filename']) 44 | item['dirname'] = os.path.dirname(item['filename']) 45 | base, ext = os.path.splitext(item['filename']) 46 | info_file = base + '.civitai.info' 47 | if not os.path.isfile(info_file): 48 | info_file = item['filename'] + '.civitai.info' 49 | if os.path.isfile(info_file): 50 | with open(info_file, 'r') as f: 51 | info = json.load(f) 52 | images = info.get('images', []) 53 | info = { 54 | 'modelId': info.get('modelId', ''), 55 | 'name': info.get('name', ''), 56 | 'description': info.get('description', ''), 57 | 'baseModel': info.get('baseModel', ''), 58 | 'model': info.get('model', {}), 59 | 'trainedWords': info.get('trainedWords', []), 60 | 'images': [], 61 | } 62 | if images and len(images) > 0: 63 | for image in images: 64 | info['images'].append(image['url']) 65 | item['civitai_info'] = info 66 | except Exception as e: 67 | pass 68 | 69 | # 过滤掉不需要的字段 70 | newItem = {} 71 | for key in item: 72 | if key not in filters: 73 | newItem[key] = item[key] 74 | 75 | result_item['items'].append(newItem) 76 | 77 | result.append(result_item) 78 | except Exception as e: 79 | print(f'[sd-webui-prompt-all-in-one] get_extra_networks error: {e}') 80 | pass 81 | return result 82 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_group_tags.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | current_dir = os.path.dirname(os.path.abspath(__file__)) 4 | 5 | def _get_tags_filename(name): 6 | file = os.path.join(current_dir, '../../group_tags/', name + '.yaml') 7 | return file 8 | 9 | def get_group_tags(lang): 10 | tags_file = _get_tags_filename('custom') 11 | is_exists = os.path.exists(tags_file) 12 | if is_exists: 13 | try: 14 | with open(tags_file, 'r', encoding='utf8') as f: 15 | data = f.read() 16 | is_exists = len(data.strip()) > 0 17 | except: 18 | is_exists = False 19 | 20 | if not is_exists: 21 | tags_file = _get_tags_filename(lang) 22 | if not os.path.exists(tags_file): 23 | tags_file = _get_tags_filename('default') 24 | if not os.path.exists(tags_file): 25 | return '' 26 | 27 | tags = '' 28 | 29 | try: 30 | prepend_file = _get_tags_filename('prepend') 31 | with open(prepend_file, 'r', encoding='utf8') as f: 32 | prepend = f.read() 33 | tags += prepend + "\n\n" 34 | except: 35 | pass 36 | 37 | try: 38 | with open(tags_file, 'r', encoding='utf8') as f: 39 | data = f.read() 40 | tags += data + "\n\n" 41 | except: 42 | pass 43 | 44 | try: 45 | append_file = _get_tags_filename('append') 46 | with open(append_file, 'r', encoding='utf8') as f: 47 | append = f.read() 48 | tags += append + "\n\n" 49 | except: 50 | pass 51 | 52 | return tags -------------------------------------------------------------------------------- /scripts/physton_prompt/get_i18n.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | i18n = {} 5 | 6 | 7 | def get_i18n(reload=False): 8 | global i18n 9 | if reload or not i18n: 10 | i18n = {} 11 | current_dir = os.path.dirname(os.path.abspath(__file__)) 12 | config_file = os.path.join(current_dir, '../../i18n.json') 13 | config_file = os.path.normpath(config_file) 14 | with open(config_file, 'r', encoding='utf8') as f: 15 | i18n = json.load(f) 16 | return i18n 17 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_lang.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.storage import Storage 2 | from scripts.physton_prompt.get_i18n import get_i18n 3 | 4 | 5 | def replace_vars(text, vars): 6 | for key, value in vars.items(): 7 | text = text.replace("{" + key + "}", value) 8 | return text 9 | 10 | 11 | def get_lang(key, vars={}): 12 | i18n = get_i18n() 13 | code = Storage.get('languageCode') 14 | 15 | def find_lang(code): 16 | for item in i18n['languages']: 17 | if item['code'] == code: 18 | return True 19 | return False 20 | 21 | if not find_lang(code): 22 | code = i18n['default'] 23 | 24 | if not find_lang(code): 25 | code = 'en_US' 26 | 27 | def find_key(key, code): 28 | for item in i18n['languages']: 29 | if item['code'] == code: 30 | if key in item['lang']: 31 | if vars == {}: 32 | return item['lang'][key] 33 | else: 34 | return replace_vars(item['lang'][key], vars) 35 | return False 36 | 37 | find = find_key(key, code) 38 | if find: 39 | return find 40 | 41 | find = find_key(key, 'en_US') 42 | if find: 43 | return find 44 | 45 | return replace_vars(key, vars) 46 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_token_counter.py: -------------------------------------------------------------------------------- 1 | from modules import script_callbacks, extra_networks, prompt_parser, sd_models 2 | from modules.sd_hijack import model_hijack 3 | from functools import partial, reduce 4 | 5 | 6 | def get_token_counter(text, steps): 7 | # copy from modules.ui.py 8 | try: 9 | text, _ = extra_networks.parse_prompt(text) 10 | 11 | _, prompt_flat_list, _ = prompt_parser.get_multicond_prompt_list([text]) 12 | prompt_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(prompt_flat_list, steps) 13 | 14 | except Exception: 15 | # a parsing error can happen here during typing, and we don't want to bother the user with 16 | # messages related to it in console 17 | prompt_schedules = [[[steps, text]]] 18 | 19 | try: 20 | from modules_forge import forge_version 21 | forge = True 22 | 23 | except: 24 | forge = False 25 | 26 | flat_prompts = reduce(lambda list1, list2: list1 + list2, prompt_schedules) 27 | prompts = [prompt_text for step, prompt_text in flat_prompts] 28 | 29 | if forge: 30 | cond_stage_model = sd_models.model_data.sd_model.cond_stage_model 31 | token_count, max_length = max([model_hijack.get_prompt_lengths(prompt,cond_stage_model) for prompt in prompts], 32 | key=lambda args: args[0]) 33 | else: 34 | token_count, max_length = max([model_hijack.get_prompt_lengths(prompt) for prompt in prompts], 35 | key=lambda args: args[0]) 36 | 37 | return {"token_count": token_count, "max_length": max_length} 38 | -------------------------------------------------------------------------------- /scripts/physton_prompt/get_version.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import requests 4 | import subprocess 5 | import hashlib 6 | 7 | 8 | def get_git_commit_version(): 9 | extension_dir = os.path.dirname(os.path.abspath(__file__)) + '/../../' 10 | extension_dir = os.path.normpath(extension_dir) 11 | git_path = os.path.join(extension_dir, '.git') 12 | if os.path.exists(git_path): 13 | try: 14 | git = os.environ.get('GIT', "git") 15 | if not git: 16 | git = "git" 17 | cmd = [git, 'rev-parse', 'HEAD'] 18 | commit_version = subprocess.check_output(cmd, cwd=extension_dir).decode('utf-8').strip() 19 | if re.match(r'^[0-9a-f]{40}$', commit_version): 20 | return commit_version 21 | except Exception as e: 22 | pass 23 | 24 | try: 25 | ref_path = os.path.join(git_path, 'refs', 'heads', 'main') 26 | with open(ref_path, 'r') as f: 27 | commit_version = f.read().strip() 28 | if re.match(r'^[0-9a-f]{40}$', commit_version): 29 | return commit_version 30 | except Exception as e: 31 | pass 32 | 33 | return '' 34 | 35 | 36 | def _handle_versions(response, filter_update_readme=False): 37 | try: 38 | if response.status_code != 200: 39 | return [] 40 | result = response.json() 41 | if not result: 42 | return [] 43 | versions = [] 44 | for item in result: 45 | message = item['commit']['message'] 46 | is_update_readme = False 47 | if message.lower().strip() == 'update readme.md': 48 | if filter_update_readme: 49 | continue 50 | is_update_readme = True 51 | versions.append({ 52 | 'version': item['sha'], 53 | 'message': message, 54 | 'date': item['commit']['committer']['date'], 55 | 'is_update_readme': is_update_readme 56 | }) 57 | return versions 58 | except Exception as e: 59 | return [] 60 | 61 | 62 | def get_git_remote_versions(page=1, per_page=100, filter_update_readme=False): 63 | api_urls = [ 64 | 'https://api.github.com/repos/physton/sd-webui-prompt-all-in-one/commits', 65 | 'https://gitee.com/api/v5/repos/physton/sd-webui-prompt-all-in-one/commits' 66 | ] 67 | 68 | for api_url in api_urls: 69 | try: 70 | api_url += f'?page={page}&per_page={per_page}' 71 | key = hashlib.md5(api_url.encode('utf-8')).hexdigest() 72 | response = requests.get(api_url) 73 | versions = _handle_versions(response, filter_update_readme) 74 | return versions 75 | except Exception as e: 76 | pass 77 | 78 | return [] 79 | 80 | 81 | def get_latest_version(): 82 | current_version = get_git_commit_version() 83 | # if not current_version: 84 | # return current_version 85 | versions = get_git_remote_versions(1, 10, False) 86 | if len(versions) < 1: 87 | return current_version 88 | return versions[0]['version'] 89 | -------------------------------------------------------------------------------- /scripts/physton_prompt/mbart50.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | from scripts.physton_prompt.get_lang import get_lang 4 | 5 | model = None 6 | tokenizer = None 7 | model_name = "facebook/mbart-large-50-many-to-many-mmt" 8 | cache_dir = os.path.normpath(os.path.dirname(os.path.abspath(__file__)) + '/../../models') 9 | loading = False 10 | 11 | def initialize(reload=False): 12 | global model, tokenizer, model_name, cache_dir, loading 13 | if loading: 14 | while not loading: 15 | time.sleep(0.1) 16 | pass 17 | if model is None or tokenizer is None: 18 | raise Exception('error') 19 | # raise Exception(get_lang('model_is_loading')) 20 | return 21 | if not reload and model is not None: 22 | return 23 | loading = True 24 | model = None 25 | tokenizer = None 26 | 27 | model_path = os.path.join(cache_dir, "mbart-large-50-many-to-many-mmt") 28 | model_file = os.path.join(model_path, "pytorch_model.bin") 29 | if os.path.exists(model_path) and os.path.exists(model_file): 30 | model_name = model_path 31 | 32 | try: 33 | from transformers import MBart50TokenizerFast, MBartForConditionalGeneration 34 | print(f'[sd-webui-prompt-all-in-one] Loading model {model_name} from {cache_dir}...') 35 | model = MBartForConditionalGeneration.from_pretrained(model_name, cache_dir=cache_dir) 36 | tokenizer = MBart50TokenizerFast.from_pretrained(model_name, cache_dir=cache_dir) 37 | print(f'[sd-webui-prompt-all-in-one] Model {model_name} loaded.') 38 | loading = False 39 | except Exception as e: 40 | loading = False 41 | raise e 42 | 43 | def translate(text, src_lang, target_lang): 44 | global model, tokenizer 45 | 46 | if not text: 47 | if isinstance(text, list): 48 | return [] 49 | else: 50 | return '' 51 | 52 | if model is None: 53 | raise Exception(get_lang('model_not_initialized')) 54 | 55 | if tokenizer is None: 56 | raise Exception(get_lang('model_not_initialized')) 57 | 58 | if src_lang == target_lang: 59 | return text 60 | 61 | tokenizer.src_lang = src_lang 62 | encoded_input = tokenizer(text, return_tensors="pt", padding=True) 63 | generated_tokens = model.generate( 64 | **encoded_input, forced_bos_token_id=tokenizer.lang_code_to_id[target_lang], 65 | max_new_tokens=500 66 | ) 67 | return tokenizer.batch_decode(generated_tokens, skip_special_tokens=True) 68 | -------------------------------------------------------------------------------- /scripts/physton_prompt/packages.py: -------------------------------------------------------------------------------- 1 | import launch 2 | from scripts.physton_prompt.get_lang import get_lang 3 | 4 | packages = { 5 | "chardet": "chardet", 6 | "fastapi": "fastapi", 7 | "execjs": "PyExecJS", 8 | "lxml": "lxml", 9 | "tqdm": "tqdm", 10 | "pathos": "pathos", 11 | "cryptography": "cryptography", 12 | 13 | # The following packages are required for translation service. If you do not need translation service, you can remove them. 14 | # 以下是翻译所需的包,如果不需要翻译服务,可以删除掉它们。 15 | "openai": "openai", 16 | "boto3": "boto3", 17 | "aliyunsdkcore": "aliyun-python-sdk-core", 18 | "aliyunsdkalimt": "aliyun-python-sdk-alimt", 19 | } 20 | 21 | 22 | def get_packages_state(): 23 | states = [] 24 | for package_name in packages: 25 | package = packages[package_name] 26 | item = { 27 | 'name': package_name, 28 | 'package': package, 29 | 'state': False 30 | } 31 | if launch.is_installed(package) or launch.is_installed(package_name): 32 | item['state'] = True 33 | 34 | states.append(item) 35 | 36 | return states 37 | 38 | 39 | def install_package(name, package): 40 | result = {'state': False, 'message': ''} 41 | try: 42 | launch.run_pip(f"install {package}", f"sd-webui-prompt-all-in-one: {name}") 43 | result['state'] = True 44 | result['message'] = get_lang('install_success', {'0': package}) 45 | except Exception as e: 46 | print(e) 47 | print(f'Warning: Failed to install {package}, some preprocessors may not work.') 48 | result['message'] = get_lang('install_failed', {'0': package}) + '\n' + str(e) 49 | return result 50 | -------------------------------------------------------------------------------- /scripts/physton_prompt/styles.py: -------------------------------------------------------------------------------- 1 | import os 2 | from scripts.physton_prompt.storage import Storage 3 | 4 | 5 | styles_path = os.path.dirname(os.path.abspath(__file__)) + '/../../styles' 6 | styles_path = os.path.normpath(styles_path) 7 | 8 | 9 | def get_style_full_path(file): 10 | global styles_path 11 | path = os.path.join(styles_path, file) 12 | path = os.path.abspath(path) 13 | path = os.path.normpath(path) 14 | if not os.path.exists(path): 15 | return None 16 | if styles_path not in path: 17 | return None 18 | return path 19 | 20 | 21 | def get_extension_css_list(): 22 | global styles_path 23 | extension_path = os.path.join(styles_path, 'extensions') 24 | if not os.path.exists(extension_path): 25 | return [] 26 | css_list = [] 27 | # 扫描下面的每个文件夹 28 | for dir in os.listdir(extension_path): 29 | dir_path = os.path.join(extension_path, dir) 30 | if not os.path.isdir(dir_path): 31 | continue 32 | 33 | # 是否有 manifest.json 文件 34 | manifest_path = os.path.join(dir_path, 'manifest.json') 35 | if not os.path.exists(manifest_path): 36 | continue 37 | 38 | # 是否有 style.min.css 文件 39 | style_path = os.path.join(dir_path, 'style.min.css') 40 | if not os.path.exists(style_path): 41 | continue 42 | 43 | manifest = None 44 | try: 45 | with open(manifest_path, 'r', encoding='utf8', errors='ignore') as f: 46 | manifest = f.read() 47 | except Exception as e: 48 | print(f'读取 {manifest_path} 失败:{e}') 49 | pass 50 | if not manifest: 51 | continue 52 | 53 | css_item = { 54 | 'dir': dir, 55 | 'dataName': 'extensionSelect.' + dir, 56 | 'selected': False, 57 | 'manifest': manifest, 58 | 'style': f'extensions/{dir}/style.min.css', 59 | } 60 | css_item['selected'] = Storage.get(css_item['dataName']) 61 | css_list.append(css_item) 62 | 63 | return css_list 64 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/alibaba_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import json 3 | from math import ceil 4 | from scripts.physton_prompt.get_lang import get_lang 5 | 6 | 7 | class AlibabaTranslator(BaseTranslator): 8 | def __init__(self): 9 | super().__init__('alibaba') 10 | 11 | def _get_config(self): 12 | access_key_id = self.api_config.get('access_key_id', '') 13 | access_key_secret = self.api_config.get('access_key_secret', '') 14 | region = self.api_config.get('region', 'cn-shanghai') 15 | if not access_key_id: 16 | raise Exception(get_lang('is_required', {'0': 'Access Key ID'})) 17 | if not access_key_secret: 18 | raise Exception(get_lang('is_required', {'0': 'Access Key Secret'})) 19 | if not region: 20 | raise Exception(get_lang('is_required', {'0': 'Region ID'})) 21 | return access_key_id, access_key_secret, region 22 | 23 | def translate(self, text): 24 | if not text: 25 | return '' 26 | access_key_id, access_key_secret, region = self._get_config() 27 | from aliyunsdkcore.client import AcsClient 28 | from aliyunsdkalimt.request.v20181012 import TranslateRequest 29 | 30 | client = AcsClient(access_key_id, access_key_secret, region) 31 | request = TranslateRequest.TranslateRequest() 32 | request.set_SourceLanguage(self.from_lang) 33 | request.set_Scene("general") 34 | request.set_SourceText(text) 35 | request.set_FormatType("text") # 翻译文本的格式 36 | request.set_TargetLanguage(self.to_lang) 37 | request.set_method("POST") 38 | response = client.do_action_with_exception(request) 39 | result = json.loads(response) 40 | if 'Code' not in result: 41 | raise Exception(get_lang('no_response_from', {'0': 'Alibaba'})) 42 | if result['Code'] != '200': 43 | raise Exception(result['Message']) 44 | if 'Translated' not in result['Data']: 45 | raise Exception(get_lang('no_response_from', {'0': 'Alibaba'})) 46 | return result['Data']['Translated'] 47 | 48 | def translate_batch(self, texts): 49 | if not texts: 50 | return [] 51 | access_key_id, access_key_secret, region = self._get_config() 52 | from aliyunsdkcore.client import AcsClient 53 | from aliyunsdkalimt.request.v20181012 import GetBatchTranslateRequest 54 | 55 | results = [] 56 | 57 | concurrent = self.get_concurrent() 58 | texts_len = len(texts) 59 | group_num = ceil(texts_len / concurrent) 60 | for i in range(group_num): 61 | start = i * concurrent 62 | end = (i + 1) * concurrent 63 | if end > texts_len: 64 | end = texts_len 65 | group_texts = texts[start:end] 66 | source_texts = {} 67 | dist_texts = {} 68 | for i in range(len(group_texts)): 69 | source_texts[str(i)] = group_texts[i] 70 | dist_texts[str(i)] = '' 71 | 72 | client = AcsClient(access_key_id, access_key_secret, region) 73 | request = GetBatchTranslateRequest.GetBatchTranslateRequest() 74 | request.set_SourceLanguage(self.from_lang) 75 | request.set_Scene("general") 76 | request.set_SourceText(source_texts) 77 | request.set_FormatType("text") 78 | request.set_TargetLanguage(self.to_lang) 79 | request.set_ApiType("translate_standard") 80 | request.set_method("POST") 81 | response = client.do_action_with_exception(request) 82 | result = json.loads(response) 83 | if 'Code' not in result: 84 | raise Exception(get_lang('no_response_from', {'0': 'Alibaba'})) 85 | if result['Code'] != '200': 86 | raise Exception(result['Message']) 87 | for item in result['TranslatedList']: 88 | index = item['index'] 89 | if item['code'] == '200': 90 | dist_texts[index] = item['translated'] 91 | 92 | for i in range(len(group_texts)): 93 | results.append(dist_texts[str(i)]) 94 | 95 | return results 96 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/amazon_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | from scripts.physton_prompt.get_lang import get_lang 3 | 4 | 5 | class AmazonTranslator(BaseTranslator): 6 | def __init__(self): 7 | super().__init__('amazon') 8 | 9 | def translate(self, text): 10 | if not text: 11 | return '' 12 | api_key_id = self.api_config.get('api_key_id', '') 13 | api_key_secret = self.api_config.get('api_key_secret', '') 14 | region = self.api_config.get('region', '') 15 | if not api_key_id: 16 | raise Exception(get_lang('is_required', {'0': 'API Key ID'})) 17 | if not api_key_secret: 18 | raise Exception(get_lang('is_required', {'0': 'API Key Secret'})) 19 | if not region: 20 | raise Exception(get_lang('is_required', {'0': 'Region'})) 21 | 22 | import boto3 23 | translate = boto3.client(service_name='translate', region_name=region, use_ssl=True, 24 | aws_access_key_id=api_key_id, aws_secret_access_key=api_key_secret) 25 | result = translate.translate_text(Text=text, SourceLanguageCode=self.from_lang, TargetLanguageCode=self.to_lang) 26 | if 'TranslatedText' not in result: 27 | raise Exception(get_lang('no_response_from', {'0': 'Amazon'})) 28 | return result['TranslatedText'] 29 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/baidu_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import requests 3 | import hashlib 4 | import random 5 | from scripts.physton_prompt.get_lang import get_lang 6 | 7 | 8 | class BaiduTranslator(BaseTranslator): 9 | def __init__(self): 10 | super().__init__('baidu') 11 | 12 | def translate(self, text): 13 | if not text: 14 | return '' 15 | url = "https://fanyi-api.baidu.com/api/trans/vip/translate" 16 | app_id = self.api_config.get('app_id', '') 17 | app_secret = self.api_config.get('app_secret', '') 18 | if not app_id: 19 | raise Exception(get_lang('is_required', {'0': 'APP ID'})) 20 | if not app_secret: 21 | raise Exception(get_lang('is_required', {'0': 'APP Secret'})) 22 | salt = random.randint(32768, 65536) 23 | send_text = text 24 | if isinstance(text, list): 25 | send_text = '\n'.join(send_text) 26 | sign = app_id + send_text + str(salt) + app_secret 27 | sign = hashlib.md5(sign.encode()).hexdigest() 28 | params = { 29 | 'q': send_text, 30 | 'from': self.from_lang, 31 | 'to': self.to_lang, 32 | 'appid': app_id, 33 | 'salt': salt, 34 | 'sign': sign 35 | } 36 | response = requests.get(url, params=params, timeout=10) 37 | result = response.json() 38 | if 'error_code' in result: 39 | raise Exception(result['error_msg']) 40 | if 'trans_result' not in result: 41 | raise Exception(get_lang('no_response_from', {'0': 'Baidu'})) 42 | translated_text = [] 43 | for item in result['trans_result']: 44 | translated_text.append(item['dst']) 45 | if isinstance(text, list): 46 | return translated_text 47 | else: 48 | return '\n'.join(translated_text) 49 | 50 | def translate_batch(self, texts): 51 | if not texts: 52 | return [] 53 | for text in texts: 54 | text = text.replace('\n', ' ') 55 | return self.translate(texts) 56 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/base_tanslator.py: -------------------------------------------------------------------------------- 1 | import time 2 | from abc import ABC, abstractmethod 3 | from concurrent.futures import ThreadPoolExecutor 4 | from math import ceil 5 | 6 | from scripts.physton_prompt.get_lang import get_lang 7 | from scripts.physton_prompt.get_translate_apis import get_translate_apis 8 | 9 | 10 | class BaseTranslator(ABC): 11 | from_lang = None 12 | to_lang = None 13 | api = None 14 | api_config = {} 15 | api_item = {} 16 | 17 | def __init__(self, api): 18 | self.api = api 19 | apis = get_translate_apis() 20 | find = False 21 | for group in apis['apis']: 22 | for item in group['children']: 23 | if item['key'] == api: 24 | find = item 25 | break 26 | if not find: 27 | raise Exception(get_lang('translate_api_not_support')) 28 | self.api_item = find 29 | 30 | def set_from_lang(self, from_lang): 31 | from_lang = self.api_item['support'].get(from_lang, False) 32 | if not from_lang: 33 | raise Exception(get_lang('translate_language_not_support')) 34 | self.from_lang = from_lang 35 | return self 36 | 37 | def set_to_lang(self, to_lang): 38 | to_lang = self.api_item['support'].get(to_lang, False) 39 | if not to_lang: 40 | raise Exception(get_lang('translate_language_not_support')) 41 | self.to_lang = to_lang 42 | return self 43 | 44 | def set_api_config(self, api_config): 45 | self.api_config = api_config 46 | return self 47 | 48 | def get_concurrent(self): 49 | concurrent = 1 50 | if self.api_item.get('concurrent', False): 51 | concurrent = self.api_item['concurrent'] 52 | return concurrent 53 | 54 | @abstractmethod 55 | def translate(self, text): 56 | pass 57 | 58 | def translate_batch(self, texts): 59 | concurrent = self.get_concurrent() 60 | texts_len = len(texts) 61 | group_num = ceil(texts_len / concurrent) 62 | 63 | # 分组并发翻译,每组完成后等待1秒,然后再进行下一组 64 | results = [] 65 | with ThreadPoolExecutor(max_workers=concurrent) as executor: 66 | for i in range(group_num): 67 | group_texts = texts[i * concurrent: (i + 1) * concurrent] 68 | texts_dict = {} 69 | futures = [] 70 | for i in range(len(group_texts)): 71 | text = group_texts[i] 72 | texts_dict[str(i)] = '' 73 | future = executor.submit(self.translate, text) 74 | futures.append(future) 75 | 76 | for i in range(len(futures)): 77 | future = futures[i] 78 | text_dict = texts_dict 79 | future.result() 80 | text_dict[str(i)] = future.result() 81 | 82 | for i in range(len(texts_dict)): 83 | results.append(texts_dict[str(i)]) 84 | 85 | time.sleep(1) 86 | 87 | return results 88 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/caiyun_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import uuid 3 | import requests 4 | import json 5 | from scripts.physton_prompt.get_lang import get_lang 6 | 7 | 8 | class CaiyunTranslator(BaseTranslator): 9 | def __init__(self): 10 | super().__init__('caiyun') 11 | 12 | def translate(self, text): 13 | if not text: 14 | return '' 15 | url = 'http://api.interpreter.caiyunai.com/v1/translator' 16 | token = self.api_config.get('token', '') 17 | if not token: 18 | raise Exception(get_lang('is_required', {'0': 'Token'})) 19 | 20 | payload = { 21 | "source": text, 22 | "trans_type": f'{self.from_lang}2{self.to_lang}', 23 | "request_id": str(uuid.uuid4()), 24 | "detect": True, 25 | } 26 | 27 | headers = { 28 | "content-type": "application/json", 29 | "x-authorization": "token " + token, 30 | } 31 | 32 | response = requests.post(url, data=json.dumps(payload), headers=headers) 33 | if not response.text: 34 | raise Exception(get_lang('response_is_empty', {'0': 'caiyun'})) 35 | result = response.json() 36 | if 'message' in result: 37 | raise Exception(result['message']) 38 | if 'target' not in result: 39 | raise Exception(get_lang('no_response_from', {'0': 'caiyun'})) 40 | return result['target'] 41 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/deepl_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import requests 3 | from scripts.physton_prompt.get_lang import get_lang 4 | 5 | 6 | class DeeplTranslator(BaseTranslator): 7 | def __init__(self): 8 | super().__init__('deepl') 9 | 10 | def translate(self, text): 11 | if not text: 12 | if isinstance(text, list): 13 | return [] 14 | else: 15 | return '' 16 | url = 'https://api-free.deepl.com/v2/translate' 17 | api_key = self.api_config.get('api_key', '') 18 | if not api_key: 19 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 20 | headers = {"Authorization": f"DeepL-Auth-Key {api_key}"} 21 | data = { 22 | 'text': text, 23 | 'source_lang': self.from_lang, 24 | 'target_lang': self.to_lang 25 | } 26 | 27 | response = requests.post(url, headers=headers, data=data, timeout=10) 28 | if response.status_code != 200: 29 | raise Exception(get_lang('request_error', {'0': 'DeepL'})) 30 | if not response.text: 31 | raise Exception(get_lang('response_is_empty', {'0': 'DeepL'})) 32 | result = response.json() 33 | if 'message' in result: 34 | raise Exception(result['message']) 35 | if 'translations' not in result: 36 | raise Exception(get_lang('no_response_from', {'0': 'DeepL'})) 37 | if isinstance(text, list): 38 | results = [] 39 | for item in result['translations']: 40 | results.append(item['text']) 41 | return results 42 | else: 43 | return result['translations'][0]['text'] 44 | 45 | def translate_batch(self, texts): 46 | return self.translate(texts) 47 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/google_tanslator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import requests 3 | from scripts.physton_prompt.get_lang import get_lang 4 | 5 | 6 | class GoogleTranslator(BaseTranslator): 7 | def __init__(self): 8 | super().__init__('google') 9 | 10 | def translate(self, text): 11 | if not text: 12 | return '' 13 | url = 'https://translation.googleapis.com/language/translate/v2/' 14 | api_key = self.api_config.get('api_key', '') 15 | if not api_key: 16 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 17 | params = { 18 | 'key': api_key, 19 | 'q': text, 20 | 'source': self.from_lang, 21 | 'target': self.to_lang, 22 | 'format': 'text' 23 | } 24 | response = requests.get(url, params=params, timeout=10) 25 | result = response.json() 26 | if 'error' in result: 27 | raise Exception(result['error']['message']) 28 | if 'data' not in result: 29 | raise Exception(get_lang('no_response_from', {'0': 'Google'})) 30 | if 'translations' not in result['data']: 31 | raise Exception(get_lang('no_response_from', {'0': 'Google'})) 32 | return result['data']['translations'][0]['translatedText'] 33 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/mbart50_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | from scripts.physton_prompt.get_lang import get_lang 3 | from scripts.physton_prompt.mbart50 import initialize as mbart50_initialize, translate as mbart50_translate 4 | 5 | 6 | class MBart50Translator(BaseTranslator): 7 | def __init__(self): 8 | super().__init__('mbart50') 9 | 10 | def translate(self, text): 11 | if not text: 12 | if isinstance(text, list): 13 | return [] 14 | else: 15 | return '' 16 | 17 | result = mbart50_translate(text=text, src_lang=self.from_lang, target_lang=self.to_lang) 18 | if not result: 19 | raise Exception(get_lang('response_is_empty', {'0': 'mbart50'})) 20 | 21 | if isinstance(text, list): 22 | return result 23 | else: 24 | return result[0] 25 | 26 | def translate_batch(self, texts): 27 | return self.translate(texts) 28 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/microsoft_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import uuid 3 | import requests 4 | from scripts.physton_prompt.get_lang import get_lang 5 | 6 | 7 | class MicrosoftTranslator(BaseTranslator): 8 | def __init__(self): 9 | super().__init__('microsoft') 10 | 11 | def translate(self, text): 12 | if not text: 13 | if isinstance(text, list): 14 | return [] 15 | else: 16 | return '' 17 | url = 'https://api.cognitive.microsofttranslator.com/translate' 18 | api_key = self.api_config.get('api_key', '') 19 | region = self.api_config.get('region', '') 20 | if not api_key: 21 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 22 | if not region: 23 | raise Exception(get_lang('is_required', {'0': 'Region'})) 24 | params = { 25 | 'api-version': '3.0', 26 | 'from': self.from_lang, 27 | 'to': self.to_lang 28 | } 29 | headers = { 30 | 'Ocp-Apim-Subscription-Key': api_key, 31 | 'Ocp-Apim-Subscription-Region': region, 32 | 'Content-type': 'application/json', 33 | 'X-ClientTraceId': str(uuid.uuid4()) 34 | } 35 | 36 | body = [] 37 | if isinstance(text, list): 38 | for item in text: 39 | body.append({'text': item}) 40 | else: 41 | body.append({'text': text}) 42 | 43 | response = requests.post(url, params=params, headers=headers, json=body, timeout=10) 44 | result = response.json() 45 | if 'error' in result: 46 | raise Exception(result['error']['message']) 47 | if len(result) == 0: 48 | raise Exception(get_lang('no_response_from', {'0': 'Microsoft'})) 49 | 50 | if isinstance(text, list): 51 | return [item['translations'][0]['text'] for item in result] 52 | else: 53 | return result[0]['translations'][0]['text'] 54 | 55 | def translate_batch(self, texts): 56 | return self.translate(texts) 57 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/mymemory_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import uuid 3 | import requests 4 | from scripts.physton_prompt.get_lang import get_lang 5 | 6 | 7 | class MyMemoryTranslator(BaseTranslator): 8 | def __init__(self): 9 | super().__init__('myMemory_free') 10 | 11 | def translate(self, text): 12 | if not text: 13 | return '' 14 | url = 'https://api.mymemory.translated.net/get' 15 | api_key = self.api_config.get('api_key', '') 16 | params = { 17 | 'q': text, 18 | 'langpair': f'{self.from_lang}|{self.to_lang}', 19 | } 20 | if api_key: 21 | params['key'] = api_key 22 | 23 | response = requests.get(url, params=params) 24 | if response.status_code != 200: 25 | raise Exception(get_lang('request_error', {'0': 'myMemory'})) 26 | if not response.text: 27 | raise Exception(get_lang('response_is_empty', {'0': 'myMemory'})) 28 | result = response.json() 29 | if 'responseStatus' not in result: 30 | raise Exception(get_lang('no_response_from', {'0': 'myMemory'})) 31 | if result['responseStatus'] != 200: 32 | raise Exception(result['responseDetails']) 33 | if 'responseData' not in result: 34 | raise Exception(get_lang('no_response_from', {'0': 'myMemory'})) 35 | if 'translatedText' not in result['responseData']: 36 | raise Exception(get_lang('no_response_from', {'0': 'myMemory'})) 37 | return result['responseData']['translatedText'] 38 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/niutrans_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import uuid 3 | import requests 4 | from scripts.physton_prompt.get_lang import get_lang 5 | 6 | 7 | class NiutransTranslator(BaseTranslator): 8 | def __init__(self): 9 | super().__init__('niutrans') 10 | 11 | def translate(self, text): 12 | if not text: 13 | return '' 14 | url = 'https://api.niutrans.com/NiuTransServer/translation' 15 | api_key = self.api_config.get('api_key', '') 16 | if not api_key: 17 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 18 | data = { 19 | 'from': self.from_lang, 20 | 'to': self.to_lang, 21 | 'apikey': api_key, 22 | 'src_text': text, 23 | } 24 | 25 | response = requests.post(url, data=data) 26 | if response.status_code != 200: 27 | raise Exception(get_lang('request_error', {'0': 'niutrans'})) 28 | if not response.text: 29 | raise Exception(get_lang('response_is_empty', {'0': 'niutrans'})) 30 | result = response.json() 31 | if 'error_msg' in result: 32 | raise Exception(result['error_msg']) 33 | if 'tgt_text' not in result: 34 | raise Exception(get_lang('no_response_from', {'0': 'niutrans'})) 35 | return result['tgt_text'] 36 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/openai_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import json 3 | from scripts.physton_prompt.get_lang import get_lang 4 | 5 | 6 | class OpenaiTranslator(BaseTranslator): 7 | def __init__(self): 8 | super().__init__('openai') 9 | 10 | def translate(self, text): 11 | if not text: 12 | if isinstance(text, list): 13 | return [] 14 | else: 15 | return '' 16 | import openai 17 | from distutils.version import LooseVersion 18 | openai.api_base = self.api_config.get('api_base', 'https://api.openai.com/v1') 19 | openai.api_key = self.api_config.get('api_key', '') 20 | model = self.api_config.get('model', 'gpt-3.5-turbo') 21 | if not openai.api_key: 22 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 23 | 24 | body = [] 25 | if isinstance(text, list): 26 | for item in text: 27 | body.append({'text': item}) 28 | else: 29 | body.append({'text': text}) 30 | 31 | body_str = json.dumps(body, ensure_ascii=False) 32 | 33 | messages = [ 34 | {"role": "system", "content": "You are a translator assistant."}, 35 | { 36 | "role": "user", 37 | "content": f"You are a translator assistant. Please translate the following JSON data {self.to_lang}. Preserve the original format. Only return the translation result, without any additional content or annotations. If the prompt word is in the target language, please send it to me unchanged:\n{body_str}" 38 | }, 39 | ] 40 | if LooseVersion(openai.__version__) < LooseVersion('1.0.0'): 41 | completion = openai.ChatCompletion.create(model=model, messages=messages, timeout=60) 42 | else: 43 | from openai import OpenAI 44 | client = OpenAI( 45 | base_url=openai.api_base, 46 | api_key=openai.api_key, 47 | ) 48 | completion = client.chat.completions.create(model=model, messages=messages, timeout=60) 49 | if len(completion.choices) == 0: 50 | raise Exception(get_lang('no_response_from', {'0': 'OpenAI'})) 51 | content = completion.choices[0].message.content 52 | try: 53 | # 找到第一个[,然后找到最后一个],截取中间的内容 54 | start = content.index('[') 55 | end = content.rindex(']') 56 | if start == -1 or end == -1: 57 | raise Exception(get_lang('response_error', {'0': 'OpenAI'})) 58 | result_json = '[' + content[start + 1:end] + ']' 59 | # 解析json 60 | result = json.loads(result_json) 61 | if isinstance(text, list): 62 | return [item['text'] for item in result] 63 | else: 64 | return result[0]['text'] 65 | except Exception as e: 66 | raise Exception(get_lang('response_error', {'0': 'OpenAI'})) 67 | 68 | def translate_batch(self, texts): 69 | return self.translate(texts) 70 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/translators_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import os 3 | 4 | 5 | class TranslatorsTranslator(BaseTranslator): 6 | translator = None 7 | 8 | def set_translator(self, translator): 9 | self.translator = translator 10 | return self 11 | 12 | def translate(self, text): 13 | region = self.api_config.get('region', 'CN') 14 | host = self.api_config.get('host', '') 15 | os.environ['translators_default_region'] = region 16 | from scripts.physton_prompt.translators.server import translate_text, tss, AlibabaV1 17 | tss.server_region = region 18 | tss._bing.server_region = region 19 | tss._google.server_region = region 20 | 21 | params = { 22 | 'from_language': self.from_lang, 23 | 'to_language': self.to_lang, 24 | 'translator': self.translator, 25 | 'reset_host_url': host, 26 | 'if_check_reset_host_url': False, 27 | 'timeout': 30 28 | } 29 | return translate_text(text, **params) 30 | # return translate_text(text, from_language=self.from_lang, to_language=self.to_lang, translator=self.translator, timeout=30) 31 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/yandex_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import requests 3 | from scripts.physton_prompt.get_lang import get_lang 4 | 5 | 6 | class YandexTranslator(BaseTranslator): 7 | def __init__(self): 8 | super().__init__('yandex') 9 | 10 | def translate(self, text): 11 | if not text: 12 | if isinstance(text, list): 13 | return [] 14 | else: 15 | return '' 16 | api_key = self.api_config.get('api_key', '') 17 | if not api_key: 18 | raise Exception(get_lang('is_required', {'0': 'API Key'})) 19 | 20 | if isinstance(text, list): 21 | texts = text 22 | else: 23 | texts = [text] 24 | body = { 25 | "sourceLanguageCode": self.from_lang, 26 | "targetLanguageCode": self.to_lang, 27 | "format": "PLAIN_TEXT", 28 | "texts": texts, 29 | "folderId": '', 30 | } 31 | headers = { 32 | "Content-Type": "application/json", 33 | "Authorization": f"Api-Key {api_key}" 34 | } 35 | response = requests.post('https://translate.api.cloud.yandex.net/translate/v2/translate', 36 | json=body, 37 | headers=headers 38 | ) 39 | result = response.json() 40 | if not result: 41 | raise Exception(get_lang('no_response_from', {'0': 'Yandex'})) 42 | if response.status_code != 200: 43 | if 'code' in result: 44 | raise Exception(result["message"]) 45 | else: 46 | raise Exception(response.text) 47 | 48 | if 'translations' not in result: 49 | raise Exception(get_lang('no_response_from', {'0': 'Yandex'})) 50 | 51 | if len(result['translations']) != len(texts): 52 | raise Exception(get_lang('no_response_from', {'0': 'Yandex'})) 53 | 54 | if isinstance(text, list): 55 | return [item['text'] for item in result['translations']] 56 | else: 57 | return result['translations'][0]['text'] 58 | 59 | def translate_batch(self, texts): 60 | return self.translate(texts) 61 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translator/youdao_translator.py: -------------------------------------------------------------------------------- 1 | from scripts.physton_prompt.translator.base_tanslator import BaseTranslator 2 | import requests 3 | import hashlib 4 | import random 5 | import time 6 | from scripts.physton_prompt.get_lang import get_lang 7 | 8 | 9 | class YoudaoTranslator(BaseTranslator): 10 | def __init__(self): 11 | super().__init__('youdao') 12 | 13 | def translate(self, text): 14 | if not text: 15 | if isinstance(text, list): 16 | return [] 17 | else: 18 | return '' 19 | if isinstance(text, list): 20 | url = "https://openapi.youdao.com/v2/api" 21 | else: 22 | url = "https://openapi.youdao.com/api" 23 | app_id = self.api_config.get('app_id', '') 24 | app_secret = self.api_config.get('app_secret', '') 25 | if not app_id: 26 | raise Exception(get_lang('is_required', {'0': 'App ID'})) 27 | if not app_secret: 28 | raise Exception(get_lang('is_required', {'0': 'App Secret'})) 29 | curtime = str(int(time.time())) 30 | salt = random.randint(32768, 65536) 31 | if isinstance(text, list): 32 | sign_text = "".join(text) 33 | else: 34 | sign_text = text 35 | input = '' 36 | if len(sign_text) <= 20: 37 | input = sign_text 38 | elif len(sign_text) > 20: 39 | input = sign_text[:10] + str(len(sign_text)) + sign_text[-10:] 40 | sign = app_id + input + str(salt) + curtime + app_secret 41 | sign = hashlib.sha256(sign.encode()).hexdigest() 42 | params = { 43 | 'q': text, 44 | 'from': self.from_lang, 45 | 'to': self.to_lang, 46 | 'appKey': app_id, 47 | 'salt': salt, 48 | 'signType': 'v3', 49 | 'curtime': curtime, 50 | 'sign': sign 51 | } 52 | headers = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"} 53 | response = requests.post(url, params=params, timeout=10, headers=headers) 54 | result = response.json() 55 | if 'errorCode' not in result: 56 | raise Exception(get_lang('no_response_from', {'0': 'Youdao'})) 57 | if result['errorCode'] != '0': 58 | raise Exception(f'errorCode: {result["errorCode"]}') 59 | if isinstance(text, list): 60 | if 'translateResults' not in result: 61 | raise Exception(get_lang('no_response_from', {'0': 'Youdao'})) 62 | results = [] 63 | for item in result['translateResults']: 64 | if 'translation' not in item: 65 | raise Exception(get_lang('no_response_from', {'0': 'Youdao'})) 66 | results.append(item['translation']) 67 | return results 68 | else: 69 | if 'translation' not in result: 70 | raise Exception(get_lang('no_response_from', {'0': 'Youdao'})) 71 | return result['translation'][0] 72 | 73 | def translate_batch(self, texts): 74 | return self.translate(texts) 75 | -------------------------------------------------------------------------------- /scripts/physton_prompt/translators/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | PyExecJS 3 | lxml 4 | tqdm 5 | pathos 6 | cryptography 7 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | dist-ssr 14 | coverage 15 | *.local 16 | 17 | /cypress/videos/ 18 | /cypress/screenshots/ 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | *.suo 25 | *.ntvs* 26 | *.njsproj 27 | *.sln 28 | *.sw? 29 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # sd-webui-prompt-all-in-one 2 | 3 | This template should help get you started developing with Vue 3 in Vite. 4 | 5 | ## Recommended IDE Setup 6 | 7 | [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). 8 | 9 | ## Customize configuration 10 | 11 | See [Vite Configuration Reference](https://vitejs.dev/config/). 12 | 13 | ## Project Setup 14 | 15 | ```sh 16 | npm install 17 | ``` 18 | 19 | ### Compile and Hot-Reload for Development 20 | 21 | ```sh 22 | npm run dev 23 | ``` 24 | 25 | ### Compile and Minify for Production 26 | 27 | ```sh 28 | npm run build 29 | ``` 30 | -------------------------------------------------------------------------------- /src/globals.js: -------------------------------------------------------------------------------- 1 | export default { 2 | name: 'Physton/sd-webui-prompt-all-in-one', 3 | shortName: 'sd-webui-prompt-all-in-one', 4 | github: 'https://github.com/Physton/sd-webui-prompt-all-in-one', 5 | nameAssets: 'Physton/sd-webui-prompt-all-in-one-assets', 6 | shortNameAssets: 'sd-webui-prompt-all-in-one-assets', 7 | githubAssets: 'https://github.com/Physton/sd-webui-prompt-all-in-one-assets', 8 | gitee: 'https://gitee.com/Physton/sd-webui-prompt-all-in-one', 9 | docs: 'https://aiodoc.physton.com', 10 | nameTagComplete: 'DominikDoom/a1111-sd-webui-tagcomplete', 11 | shortNameTagComplete: 'a1111-sd-webui-tagcomplete', 12 | githubTagComplete: 'https://github.com/DominikDoom/a1111-sd-webui-tagcomplete', 13 | civitaiUrl: 'https://civitai.com', 14 | } -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sd-webui-prompt-all-in-one", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "dev": "vite", 7 | "build": "vite build", 8 | "build:watch": "vite build --watch", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "autosize-input": "^1.0.2", 13 | "axios": "^1.4.0", 14 | "js-yaml": "^4.1.0", 15 | "papaparse": "^5.4.1", 16 | "sortablejs": "^1.15.0", 17 | "tinycolor2": "^1.6.0", 18 | "tippy.js": "^6.3.7", 19 | "toastr": "^2.1.4", 20 | "vue": "^3.2.47", 21 | "vue-clipboard3": "^2.0.0", 22 | "vue3-colorpicker": "^2.2.2" 23 | }, 24 | "devDependencies": { 25 | "@vitejs/plugin-vue": "^4.0.0", 26 | "less": "^4.1.3", 27 | "less-loader": "^11.1.0", 28 | "sass": "^1.65.1", 29 | "vite": "^4.1.4" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/src/components/highlightPrompt.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/src/components/iconSvg.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/src/components/selectLanguage.vue: -------------------------------------------------------------------------------- 1 | 19 | -------------------------------------------------------------------------------- /src/src/main.js: -------------------------------------------------------------------------------- 1 | import * as Vue from 'vue' 2 | import App from './App.vue' 3 | import toastr from 'toastr' 4 | import VueClipboard from 'vue-clipboard3' 5 | const {toClipboard} = VueClipboard() 6 | import CommonMixin from "@/mixins/commonMixin" 7 | import common from "@/utils/common" 8 | import tippy from "tippy.js" 9 | 10 | onUiLoaded(async () => { 11 | const div = document.createElement('div') 12 | div.id = 'physton-prompt-all-in-one' 13 | common.gradioApp().appendChild(div) 14 | const app = Vue.createApp(App) 15 | 16 | app.config.globalProperties.$appMode = typeof APP_MODE !== 'undefined' && APP_MODE 17 | app.config.globalProperties.$toastr = toastr 18 | app.config.globalProperties.$copyText = toClipboard 19 | app.config.globalProperties.$tippyList = [] 20 | app.mixin(CommonMixin) 21 | app.directive('animate', { 22 | mounted(el, binding) { 23 | el.classList.add('animate__animated', `animate__${binding.value}`, 'animate__faster') 24 | }, 25 | updated(el, binding) { 26 | el.classList.remove(`animate__${binding.oldValue}`) 27 | el.classList.add(`animate__${binding.value}`) 28 | } 29 | }) 30 | app.directive('tooltip', { 31 | mounted(el, binding) { 32 | // data-tippy-content 33 | el.setAttribute('data-tippy-content', binding.value) 34 | // 如果有 unaffected 属性,则不受 localStorage 控制 35 | let unaffected = el.getAttribute('unaffected') 36 | unaffected = unaffected === null ? false : unaffected === 'true' 37 | const instance = tippy(el, { 38 | placement: 'bottom', 39 | theme: 'light', 40 | allowHTML: true, 41 | onCreate(instance, partialProps) { 42 | if (!binding.value) return 43 | if (unaffected) return 44 | instance.enable() 45 | const enable = localStorage.getItem('phystonPromptEnableTooltip') === 'true' 46 | if (!enable) { 47 | instance.disable() 48 | } 49 | }, 50 | }) 51 | el.$tippyInstance = instance 52 | if (!unaffected) app.config.globalProperties.$tippyList.push(instance) 53 | }, 54 | updated(el, binding) { 55 | if (!binding.value) { 56 | el.$tippyInstance.disable() 57 | } else { 58 | el.setAttribute('data-tippy-content', binding.value) 59 | el.$tippyInstance.setContent(binding.value) 60 | } 61 | } 62 | }) 63 | 64 | app.mount(div) 65 | }) 66 | 67 | -------------------------------------------------------------------------------- /src/src/mixins/commonMixin.js: -------------------------------------------------------------------------------- 1 | import common from "@/utils/common"; 2 | import GradioAPI from "@/utils/gradioAPI"; 3 | 4 | export default { 5 | data() { 6 | return { 7 | /** 8 | * @type {GradioAPI} 9 | */ 10 | gradioAPI: null, 11 | } 12 | }, 13 | beforeMount() { 14 | this.gradioAPI = new GradioAPI() 15 | }, 16 | methods: { 17 | loadExtraNetworks(loadI = 0) { 18 | if (common.gradioApp().querySelectorAll("#txt2img_checkpoints_cards .card").length) { 19 | // console.log('系统ExtraNetworks已加载,开始加载ExtraNetworks') 20 | return this._loadExtraNetworks() 21 | } 22 | if (loadI > 10) { 23 | // console.log('超时10秒,开始加载ExtraNetworks') 24 | return this._loadExtraNetworks() 25 | } 26 | setTimeout(this.loadExtraNetworks, 1000, loadI + 1) 27 | }, 28 | _loadExtraNetworks() { 29 | this.gradioAPI.getExtraNetworks().then(res => { 30 | if (!res) return 31 | this.extraNetworks = res 32 | res.forEach(extraNetwork => { 33 | if (extraNetwork.name === 'textual inversion') { 34 | let list = {} 35 | extraNetwork.items.forEach(item => { 36 | list[item.name.toLowerCase()] = item.name 37 | }) 38 | this.embeddings = list 39 | } else if (extraNetwork.name === 'lora' || extraNetwork.name === 'lycoris') { 40 | let list = {} 41 | extraNetwork.items.forEach(item => { 42 | list[item.name.toLowerCase()] = item.name 43 | if (item.output_name) { 44 | list[item.output_name.toLowerCase()] = item.name 45 | } 46 | }) 47 | if (extraNetwork.name === 'lora') { 48 | this.loras = list 49 | } else { 50 | this.lycos = list 51 | } 52 | } 53 | }) 54 | }) 55 | }, 56 | getExtraNetworkFullName(name, type = 'lora') { 57 | if (typeof this.extraNetworks !== 'object') return name 58 | for (let extraNetwork of this.extraNetworks) { 59 | if (extraNetwork.name !== type) continue 60 | const nameLowerCase = name.toLowerCase() 61 | for (let item of extraNetwork.items) { 62 | if (item.name.toLowerCase() === nameLowerCase || item.output_name?.toLowerCase() === nameLowerCase) { 63 | if (!item.civitai_info?.name) return name 64 | if (item.civitai_info.model?.name && item.civitai_info.model.name !== item.civitai_info.name) { 65 | return '[' + item.civitai_info.name + '] ' + item.civitai_info.model.name 66 | } else { 67 | return item.civitai_info.name 68 | } 69 | } 70 | } 71 | } 72 | return name 73 | }, 74 | loraExists(name) { 75 | if (typeof this.loras !== 'object') return name 76 | return this.loras[name.toLowerCase()] ?? false 77 | }, 78 | lycoExists(name) { 79 | if (typeof this.lycos !== 'object') return name 80 | return this.lycos[name.toLowerCase()] ?? false 81 | }, 82 | embeddingExists(name) { 83 | if (typeof this.embeddings !== 'object') return name 84 | return this.embeddings[name.toLowerCase()] ?? false 85 | }, 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/src/utils/favorite.js: -------------------------------------------------------------------------------- 1 | import FavoriteItem from "./favoriteItem"; 2 | 3 | // not use,废弃 4 | // not use,废弃 5 | // not use,废弃 6 | class Favorite { 7 | /** 8 | * 列表 9 | * @type {Array.} 10 | */ 11 | favorites = [] 12 | 13 | /** 14 | * 构造函数 15 | */ 16 | constructor() { 17 | } 18 | 19 | /** 20 | * 添加收藏 21 | * @param favoriteItem {FavoriteItem} 22 | * @returns {number} 23 | */ 24 | push(favoriteItem) { 25 | this.favorites.push(favoriteItem) 26 | return this.favorites.length - 1 27 | } 28 | 29 | /** 30 | * 添加收藏 31 | * @param favoriteItem {Object} 32 | * @returns {number} 33 | */ 34 | pushObject(favoriteItem) { 35 | return this.push(FavoriteItem.fromObject(favoriteItem)) 36 | } 37 | 38 | /** 39 | * 添加收藏 40 | * @param favoriteItem {string} 41 | * @returns {number} 42 | */ 43 | pushString(favoriteItem) { 44 | return this.push(FavoriteItem.fromString(favoriteItem)) 45 | } 46 | 47 | /** 48 | * 设置收藏 49 | * @param index {number} 50 | * @param favoriteItem {FavoriteItem} 51 | */ 52 | setItemByIndex(index, favoriteItem) { 53 | this.favorites[index] = favoriteItem 54 | } 55 | 56 | /** 57 | * 设置收藏 58 | * @param id {string} 59 | * @param favoriteItem {FavoriteItem} 60 | */ 61 | setItemById(id, favoriteItem) { 62 | this.setItemByIndex(this.getFavoriteIndexById(id), favoriteItem) 63 | } 64 | 65 | /** 66 | * 删除收藏 67 | * @param index {number} 68 | */ 69 | removeItem(index) { 70 | this.favorites.splice(index, 1) 71 | } 72 | 73 | /** 74 | * 删除收藏 75 | * @param id {string} 76 | */ 77 | removeItemById(id) { 78 | this.removeItem(this.getFavoriteIndexById(id)) 79 | } 80 | 81 | /** 82 | * 获取最后一条收藏 83 | * @returns {FavoriteItem} 84 | */ 85 | getLatest() { 86 | return this.favorites[this.favorites.length - 1] 87 | } 88 | 89 | /** 90 | * 获取收藏 91 | * @param id {string} 92 | * @returns {FavoriteItem} 93 | */ 94 | getFavoriteById(id) { 95 | return this.favorites.find(item => item.id === id) 96 | } 97 | 98 | /** 99 | * 获取收藏 100 | * @param index {number} 101 | * @returns {FavoriteItem} 102 | */ 103 | getFavoriteByIndex(index) { 104 | return this.favorites[index] 105 | } 106 | 107 | /** 108 | * 获取收藏 109 | * @param id {string} 110 | * @returns {number} 111 | */ 112 | getFavoriteIndexById(id) { 113 | return this.favorites.findIndex(item => item.id === id) 114 | } 115 | 116 | /** 117 | * 获取所有收藏 118 | * @returns {Array} 119 | */ 120 | getFavorites() { 121 | return this.favorites 122 | } 123 | 124 | /** 125 | * 获取收藏数量 126 | * @returns {number} 127 | */ 128 | getFavoritesLength() { 129 | return this.favorites.length 130 | } 131 | 132 | /** 133 | * 转换为收藏 134 | * @returns {{name: string, id: number, time: number, prompt: string, tags: *[]}[]} 135 | */ 136 | toObject() { 137 | return this.favorites.map(item => item.toObject()) 138 | } 139 | 140 | /** 141 | * 转换为字符串 142 | * @returns {string} 143 | */ 144 | toString() { 145 | return JSON.stringify(this.toObject()) 146 | } 147 | } 148 | 149 | export default Favorite -------------------------------------------------------------------------------- /src/src/utils/favoriteItem.js: -------------------------------------------------------------------------------- 1 | // not use,废弃 2 | // not use,废弃 3 | // not use,废弃 4 | 5 | class FavoriteItem { 6 | /** 7 | * id 8 | * @type {string} 9 | */ 10 | id = '' 11 | /** 12 | * 名称 13 | * @type {string} 14 | */ 15 | name = '' 16 | /** 17 | * 标签 18 | * @type {[]} 19 | */ 20 | tags = [] 21 | /** 22 | * 提示词 23 | * @type {string} 24 | */ 25 | prompt = '' 26 | /** 27 | * 时间 28 | * @type {number} 29 | */ 30 | time = 0 31 | 32 | constructor(id = '') { 33 | this.id = id ? id : Math.random().toString(36).slice(2) 34 | } 35 | 36 | /** 37 | * 设置名称 38 | * @param name {string} 39 | * @returns {FavoriteItem} 40 | */ 41 | setName(name) { 42 | this.name = name 43 | return this 44 | } 45 | 46 | /** 47 | * 设置标签 48 | * @param tags {Array} 49 | * @returns {FavoriteItem} 50 | */ 51 | setTags(tags) { 52 | this.tags = tags 53 | return this 54 | } 55 | 56 | /** 57 | * 设置提示 58 | * @param prompt {string} 59 | * @returns {FavoriteItem} 60 | */ 61 | setPrompt(prompt) { 62 | this.prompt = prompt 63 | return this 64 | } 65 | 66 | /** 67 | * 设置时间 68 | * @param time {number} 69 | * @returns {FavoriteItem} 70 | */ 71 | setTime(time = 0) { 72 | this.time = time || Date.now() 73 | return this 74 | } 75 | 76 | /** 77 | * 判断标签是否相等 78 | * @param tags {Array} 79 | * @param ignoreId {boolean} 80 | * @returns {boolean} 81 | */ 82 | isEqualTags(tags, ignoreId = false) { 83 | if (this.tags.length !== tags.length) return false 84 | for (let i = 0; i < tags.length; i++) { 85 | for (let key in tags[i]) { 86 | if (ignoreId && key === 'id') continue 87 | if (this.tags[i][key] !== tags[i][key]) return false 88 | } 89 | for (let key in this.tags[i]) { 90 | if (ignoreId && key === 'id') continue 91 | if (this.tags[i][key] !== tags[i][key]) return false 92 | } 93 | } 94 | return true 95 | } 96 | 97 | /** 98 | * 转换为对象 99 | * @returns {{name: string, id: number, time: number, prompt: string, tags: *[]}} 100 | */ 101 | toObject() { 102 | return { 103 | id: this.id, 104 | name: this.name, 105 | tags: this.tags, 106 | prompt: this.prompt, 107 | time: this.time, 108 | } 109 | } 110 | 111 | /** 112 | * 转换为字符串 113 | * @returns {string} 114 | */ 115 | toString() { 116 | return JSON.stringify(this.toObject()) 117 | } 118 | 119 | /** 120 | * 从对象创建 121 | * @param obj {Object} 122 | * @returns {FavoriteItem} 123 | */ 124 | static fromObject(obj) { 125 | return new FavoriteItem(obj.id || '').setName(obj.name || '').setTags(obj.tags || []).setPrompt(obj.prompt || '').setTime(obj.time || 0) 126 | } 127 | 128 | /** 129 | * 从字符串创建 130 | * @param str {string} 131 | * @returns {FavoriteItem} 132 | */ 133 | static fromString(str) { 134 | return FavoriteItem.fromObject(JSON.parse(str)) 135 | } 136 | } 137 | 138 | export default FavoriteItem -------------------------------------------------------------------------------- /src/src/utils/history.js: -------------------------------------------------------------------------------- 1 | import HistoryItem from './historyItem' 2 | 3 | // not use,废弃 4 | // not use,废弃 5 | // not use,废弃 6 | export class History { 7 | /** 8 | * 最大历史记录数 9 | * @type {number} 10 | */ 11 | max = 100 12 | /** 13 | * 列表 14 | * @type {Array.} 15 | */ 16 | histories = [] 17 | 18 | /** 19 | * 构造函数 20 | * @param max {number} 21 | */ 22 | constructor(max = 100) { 23 | this.max = max 24 | } 25 | 26 | /** 27 | * 添加历史记录 28 | * @param historyItem {HistoryItem} 29 | * @returns {number} 30 | */ 31 | push(historyItem) { 32 | this.histories.push(historyItem) 33 | if (this.histories.length > this.max) { 34 | this.histories.shift() 35 | } 36 | return this.histories.length - 1 37 | } 38 | 39 | /** 40 | * 添加历史记录 41 | * @param historyItem {Object} 42 | * @returns {number} 43 | */ 44 | pushObject(historyItem) { 45 | return this.push(HistoryItem.fromObject(historyItem)) 46 | } 47 | 48 | /** 49 | * 添加历史记录 50 | * @param historyItem {string} 51 | * @returns {number} 52 | */ 53 | pushString(historyItem) { 54 | return this.push(HistoryItem.fromString(historyItem)) 55 | } 56 | 57 | /** 58 | * 设置历史记录 59 | * @param index {number} 60 | * @param historyItem {HistoryItem} 61 | */ 62 | setItemByIndex(index, historyItem) { 63 | this.histories[index] = historyItem 64 | } 65 | 66 | /** 67 | * 设置历史记录 68 | * @param id {string} 69 | * @param historyItem {HistoryItem} 70 | */ 71 | setItemById(id, historyItem) { 72 | this.setItemByIndex(this.getHistoryIndexById(id), historyItem) 73 | } 74 | 75 | /** 76 | * 删除历史记录 77 | * @param index {number} 78 | */ 79 | removeItem(index) { 80 | this.histories.splice(index, 1) 81 | } 82 | 83 | /** 84 | * 删除历史记录 85 | * @param id {string} 86 | */ 87 | removeItemById(id) { 88 | this.removeItem(this.getHistoryIndexById(id)) 89 | } 90 | 91 | /** 92 | * 设置最大历史记录数 93 | * @param max {number} 94 | * @returns {History} 95 | */ 96 | setMax(max) { 97 | this.max = max 98 | return this 99 | } 100 | 101 | /** 102 | * 获取最大历史记录数 103 | * @returns {number} 104 | */ 105 | getMax() { 106 | return this.max 107 | } 108 | 109 | /** 110 | * 获取最后一条历史记录 111 | * @returns {FavoriteItem} 112 | */ 113 | getLatest() { 114 | return this.histories[this.histories.length - 1] 115 | } 116 | 117 | /** 118 | * 获取历史记录 119 | * @param id {string} 120 | * @returns {FavoriteItem} 121 | */ 122 | getHistoryById(id) { 123 | return this.histories.find(item => item.id === id) 124 | } 125 | 126 | /** 127 | * 获取历史记录 128 | * @param index {number} 129 | * @returns {FavoriteItem} 130 | */ 131 | getHistoryByIndex(index) { 132 | return this.histories[index] 133 | } 134 | 135 | /** 136 | * 获取历史记录 137 | * @param id {string} 138 | * @returns {number} 139 | */ 140 | getHistoryIndexById(id) { 141 | return this.histories.findIndex(item => item.id === id) 142 | } 143 | 144 | /** 145 | * 获取所有历史记录 146 | * @returns {Array} 147 | */ 148 | getHistories() { 149 | return this.histories 150 | } 151 | 152 | /** 153 | * 获取历史记录数 154 | * @returns {number} 155 | */ 156 | getHistoriesLength() { 157 | return this.histories.length 158 | } 159 | 160 | /** 161 | * 转换为对象 162 | * @returns {{name: string, id: number, time: number, prompt: string, tags: *[]}[]} 163 | */ 164 | toObject() { 165 | return this.histories.map(item => item.toObject()) 166 | } 167 | 168 | /** 169 | * 转换为字符串 170 | * @returns {string} 171 | */ 172 | toString() { 173 | return JSON.stringify(this.toObject()) 174 | } 175 | } 176 | 177 | export default History -------------------------------------------------------------------------------- /src/src/utils/historyItem.js: -------------------------------------------------------------------------------- 1 | // not use,废弃 2 | // not use,废弃 3 | // not use,废弃 4 | 5 | class HistoryItem { 6 | /** 7 | * id 8 | * @type {string} 9 | */ 10 | id = '' 11 | /** 12 | * 名称 13 | * @type {string} 14 | */ 15 | name = '' 16 | /** 17 | * 标签 18 | * @type {[]} 19 | */ 20 | tags = [] 21 | /** 22 | * 提示词 23 | * @type {string} 24 | */ 25 | prompt = '' 26 | /** 27 | * 时间 28 | * @type {number} 29 | */ 30 | time = 0 31 | 32 | constructor(id = '') { 33 | this.id = id ? id : Math.random().toString(36).slice(2) 34 | } 35 | 36 | /** 37 | * 设置名称 38 | * @param name {string} 39 | * @returns {HistoryItem} 40 | */ 41 | setName(name) { 42 | this.name = name 43 | return this 44 | } 45 | 46 | /** 47 | * 设置标签 48 | * @param tags {Array} 49 | * @returns {HistoryItem} 50 | */ 51 | setTags(tags) { 52 | this.tags = tags 53 | return this 54 | } 55 | 56 | /** 57 | * 设置提示 58 | * @param prompt {string} 59 | * @returns {HistoryItem} 60 | */ 61 | setPrompt(prompt) { 62 | this.prompt = prompt 63 | return this 64 | } 65 | 66 | /** 67 | * 设置时间 68 | * @param time {number} 69 | * @returns {HistoryItem} 70 | */ 71 | setTime(time=0) { 72 | this.time = time || Date.now() 73 | return this 74 | } 75 | 76 | /** 77 | * 判断标签是否相等 78 | * @param tags {Array} 79 | * @param ignoreId {boolean} 80 | * @returns {boolean} 81 | */ 82 | isEqualTags(tags, ignoreId = false) { 83 | if (this.tags.length !== tags.length) return false 84 | for (let i = 0; i < tags.length; i++) { 85 | for (let key in tags[i]) { 86 | if (ignoreId && key === 'id') continue 87 | if (this.tags[i][key] !== tags[i][key]) return false 88 | } 89 | for (let key in this.tags[i]) { 90 | if (ignoreId && key === 'id') continue 91 | if (this.tags[i][key] !== tags[i][key]) return false 92 | } 93 | } 94 | return true 95 | } 96 | 97 | /** 98 | * 转换为对象 99 | * @returns {{name: string, id: number, time: number, prompt: string, tags: *[]}} 100 | */ 101 | toObject() { 102 | return { 103 | id: this.id, 104 | name: this.name, 105 | tags: this.tags, 106 | prompt: this.prompt, 107 | time: this.time, 108 | } 109 | } 110 | 111 | /** 112 | * 转换为字符串 113 | * @returns {string} 114 | */ 115 | toString() { 116 | return JSON.stringify(this.toObject()) 117 | } 118 | 119 | /** 120 | * 从对象创建 121 | * @param obj {Object} 122 | * @returns {HistoryItem} 123 | */ 124 | static fromObject(obj) { 125 | return new HistoryItem(obj.id || '').setName(obj.name || '').setTags(obj.tags || []).setPrompt(obj.prompt || '').setTime(obj.time || 0) 126 | } 127 | 128 | /** 129 | * 从字符串创建 130 | * @param str {string} 131 | * @returns {HistoryItem} 132 | */ 133 | static fromString(str) { 134 | return HistoryItem.fromObject(JSON.parse(str)) 135 | } 136 | } 137 | 138 | export default HistoryItem -------------------------------------------------------------------------------- /src/src/utils/waitTick.js: -------------------------------------------------------------------------------- 1 | import { nextTick } from 'vue' 2 | 3 | export default { 4 | /** 5 | * @types Function[] 6 | */ 7 | waitTickList: [], 8 | startingTick: false, 9 | /** 10 | * 11 | * @param cb Function 12 | */ 13 | addWaitTick(cb) { 14 | this.waitTickList.push(cb) 15 | return this.startWaitTick() 16 | }, 17 | 18 | async execatueWaitTick() 19 | { 20 | if (this.startingTick) return 21 | 22 | this.startingTick = true 23 | 24 | while (this.waitTickList.length) { 25 | const cb = this.waitTickList.shift() 26 | await nextTick().then(cb) 27 | } 28 | 29 | this.startingTick = false 30 | }, 31 | 32 | async startWaitTick() { 33 | if (!this.startingTick) 34 | { 35 | return nextTick(() => this.execatueWaitTick().catch(e => { 36 | this.startingTick = false 37 | return this.startWaitTick() 38 | })) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/vite.config.js: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | import { resolve } from 'path' 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | /** @type {import('vite').UserConfig} */ 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | define: { 10 | 'process.env.NODE_ENV': '"production"', 11 | }, 12 | plugins: [vue()], 13 | resolve: { 14 | alias: { 15 | '@': fileURLToPath(new URL('./src', import.meta.url)) 16 | } 17 | }, 18 | build: { 19 | // outDir: '../javascript', 20 | // assetsDir: '../', 21 | minify: true, 22 | sourcemap: true, 23 | // watch: { 24 | // https://rollupjs.org/configuration-options/#watch 25 | // }, 26 | lib: { 27 | entry: resolve(__dirname, 'src/main.js'), 28 | name: 'sd-webui-prompt-all-in-one', 29 | formats: ['umd'], 30 | }, 31 | rollupOptions: { 32 | plugins: [ 33 | ], 34 | output: { 35 | globals: { 36 | }, 37 | name: "sdWebuiPromptAllInOne", 38 | dir: '../', // 对于多文件构建,指定文件夹输出路径 39 | format: 'umd', 40 | chunkFileNames: 'javascript/[name].chunk.js', // 指定 chunk 文件名称 41 | entryFileNames: 'javascript/[name].entry.js', // 指定入口文件名称 42 | assetFileNames: 'style.[ext]' 43 | }, 44 | }, 45 | } 46 | }) 47 | -------------------------------------------------------------------------------- /storage/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /styles/extensions/MyStyle-shuai/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MyStyle-shuaiqiang", 3 | "i18n": { 4 | "zh_CN": "《我的风格》" 5 | }, 6 | "author": "帅强", 7 | "type": "theme" 8 | } -------------------------------------------------------------------------------- /styles/extensions/README.MD: -------------------------------------------------------------------------------- 1 | # English: 2 | 3 | ## Guide to Developing Extension Styles 4 | 5 | - Each extension style is a separate folder. 6 | - The extension style folder must contain a `manifest.json` file, which provides basic information about the extension style. 7 | - The extension style folder must contain a `style.min.css` file. The `style.min.css` file is the main file of the extension style, and other `*.css` files will be ignored. 8 | - If you need to load images in CSS files, you can use the `/physton_prompt/styles?file=extensions/扩展文件夹名/图片文件名` URL format to load them. 9 | - There is a `demo.zip` file in the current directory that you can refer to. 10 | 11 | ## `manifest.json` Format 12 | 13 | ```json 14 | { 15 | "name": "Move the keyword input box to the left", 16 | "i18n": { 17 | "zh_CN": "移动关键词输入框到左侧", 18 | "zh_HK": "移動關鍵字輸入框到左側", 19 | "zh_TW": "移動關鍵字輸入框到左側" 20 | }, 21 | "author": "Physton", 22 | "type": "enhance" 23 | } 24 | ``` 25 | 26 | - `name` The English name of the extension style, which must be included. 27 | - `i18n` The multilingual name(s) of the extension style, which can be absent or multiple. The language codes are available in the `i18n.json` file in the root directory of the extension. 28 | - `author` The author of the extension style, which can be absent. 29 | - `type` The type of the extension style. The value can be `enhance` or `theme`. 30 | 31 | --- 32 | 33 | # 简体中文: 34 | 35 | ## 扩展样式开发说明 36 | - 每个扩展样式都是一个独立的文件夹。 37 | - 扩展样式文件夹下必须包含一个`manifest.json`文件,用于说明扩展样式的基本信息。 38 | - 扩展样式文件夹下必须包含一个`style.min.css`文件。`style.min.css`文件是扩展样式的主文件,其他`*.css`文件都将被忽略。 39 | - 在css文件中如果需要加载图片,可以使用`/physton_prompt/styles?file=extensions/扩展文件夹名/图片文件名`的URL方式加载。 40 | - 在当前文件中有一份`demo.zip`文件,可以用于参考。 41 | 42 | ## `manifest.json` 格式 43 | 44 | ```json 45 | { 46 | "name": "Move the keyword input box to the left", 47 | "i18n": { 48 | "zh_CN": "移动关键词输入框到左侧", 49 | "zh_HK": "移動關鍵字輸入框到左側", 50 | "zh_TW": "移動關鍵字輸入框到左側" 51 | }, 52 | "author": "Physton", 53 | "type": "enhance" 54 | } 55 | ``` 56 | - `name` 扩展样式的英文名称,必须包含。 57 | - `i18n` 扩展样式的多语言名称,可以没有,可以为多个。国家语言代码见扩展根目录的 `i18n.json` 文件。 58 | - `author` 扩展样式的作者,可以没有。 59 | - `type` 扩展样式的类型。值可以为 `enhance`:增强 或 `theme`:主题。 -------------------------------------------------------------------------------- /styles/extensions/Webui/images/code.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/d.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/favorite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/favorite_l.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/lan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/updown.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/人物.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/其它.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/反向提示词.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/场景.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/开始.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/服饰.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/汉服.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/物品.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/环境.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/画面.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/表情动作.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/镜头.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/images/魔法系.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /styles/extensions/Webui/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hellostyle", 3 | "i18n": { 4 | "zh_CN": "\u6839\u636eWebUI\u81ea\u5e26\u6837\u5f0f\u4fee\u6539", 5 | "zh_HK": "\u6839\u64daWebUI\u81ea\u5e36\u6a23\u5f0f\u4fee\u6539", 6 | "zh_TW": "\u6839\u64daWebUI\u81ea\u5e36\u6a23\u5f0f\u4fee\u6539" 7 | }, 8 | "author": "laohe", 9 | "type": "theme" 10 | } -------------------------------------------------------------------------------- /styles/extensions/demo.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Physton/sd-webui-prompt-all-in-one/b00149b4c7fbfc9e4b8dcd02125f157b1d105dde/styles/extensions/demo.zip -------------------------------------------------------------------------------- /styles/extensions/firefox-fix/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Temporary fix for issues caused by css in Firefox.", 3 | "i18n": { 4 | "zh_CN": "临时修复Firefox中css导致的问题" 5 | }, 6 | "author": "PTCMode", 7 | "type": "enhance" 8 | } -------------------------------------------------------------------------------- /styles/extensions/firefox-fix/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | .prompt-tags { 3 | .prompt-tags-list { 4 | .prompt-tag { 5 | .prompt-tag-main { 6 | --pp-pt-dsb-ptl-pt-promptTagMain-width: calc(100% + 4px); 7 | .prompt-tag-edit { 8 | --pp-pt-dsb-ptl-pt-ptm-promptTagEdit-width: calc(100% + 8px); 9 | .prompt-tag-value { 10 | --pp-pt-dsb-ptl-pt-ptm-pte-promptTagValue-width: calc(100% - 8px); 11 | .character { 12 | --pp-pt-dsb-ptl-pt-ptm-pte-ptv-character-white-space: nowrap; 13 | } 14 | } 15 | .input-tag-edit { 16 | --pp-pt-dsb-ptl-pt-ptm-pte-inputTagEdit-max-width: calc(100% - 8px); 17 | } 18 | .btn-tag-delete { 19 | --pp-pt-dsb-ptl-pt-ptm-pte-btnTagDelete-width: 100%; 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /styles/extensions/firefox-fix/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt{.prompt-tags{.prompt-tags-list{.prompt-tag{.prompt-tag-main{--pp-pt-dsb-ptl-pt-promptTagMain-width:calc(100%+4px);.prompt-tag-edit{--pp-pt-dsb-ptl-pt-ptm-promptTagEdit-width:calc(100%+8px);.prompt-tag-value{--pp-pt-dsb-ptl-pt-ptm-pte-promptTagValue-width:calc(100%-8px);.character{--pp-pt-dsb-ptl-pt-ptm-pte-ptv-character-white-space:nowrap;}}.input-tag-edit{--pp-pt-dsb-ptl-pt-ptm-pte-inputTagEdit-max-width:calc(100%-8px);}.btn-tag-delete{--pp-pt-dsb-ptl-pt-ptm-pte-btnTagDelete-width:100%;}}}}}}} -------------------------------------------------------------------------------- /styles/extensions/full-input/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "The keyword input box is 100% width", 3 | "i18n": { 4 | "zh_CN": "\u5173\u952e\u8bcd\u8f93\u5165\u6846100%\u5bbd\u5ea6", 5 | "zh_HK": "\u95dc\u9375\u8a5e\u8f38\u5165\u6846\u64c1\u6709100%\u5bec\u5ea6", 6 | "zh_TW": "\u95dc\u9375\u5b57\u8f38\u5165\u6846\u4f54\u64da100%\u5bec\u5ea6" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/full-input/style.less: -------------------------------------------------------------------------------- 1 | .physton-gradio-container { 2 | --pp-ph-phe-ec-inputTagAppend-width: calc(100% - 42px - 10px); 3 | } -------------------------------------------------------------------------------- /styles/extensions/full-input/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-gradio-container{--pp-ph-phe-ec-inputTagAppend-width:calc(100% - 42px - 10px)} -------------------------------------------------------------------------------- /styles/extensions/hide-group-tags-en-text/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the English label text in the keyword group", 3 | "i18n": { 4 | "zh_CN": "隐藏关键词组中的英语标签文本", 5 | "zh_HK": "隱藏關鍵詞組中的英語標籤文本", 6 | "zh_TW": "隱藏關鍵詞組中的英語標籤文本" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-group-tags-en-text/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .group-tabs .group-body .group-main .sub-group-main .group-tags .tag-item .tag-en { 2 | display: none; 3 | } -------------------------------------------------------------------------------- /styles/extensions/hide-group-tags-en-text/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .group-tabs .group-body .group-main .sub-group-main .group-tags .tag-item .tag-en{display:none} -------------------------------------------------------------------------------- /styles/extensions/hide-input-dropdown/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the dropdown menu of the keyword input box", 3 | "i18n": { 4 | "zh_CN": "\u9690\u85cf\u5173\u952e\u8bcd\u8f93\u5165\u6846\u4e0b\u62c9\u83dc\u5355", 5 | "zh_HK": "\u96b1\u85cf\u95dc\u9375\u8a5e\u8f38\u5165\u6846\u4e0b\u62c9\u9078\u55ae", 6 | "zh_TW": "\u96b1\u85cf\u95dc\u9375\u5b57\u8f38\u5165\u6846\u4e0b\u62c9\u5f0f\u9078\u55ae" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-input-dropdown/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-append-list { 2 | display: none !important; 3 | } -------------------------------------------------------------------------------- /styles/extensions/hide-input-dropdown/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-append-list{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-blacklist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the extension button for tags - blacklist", 3 | "i18n": { 4 | "zh_CN": "隐藏标籤的扩展按钮-黑名单", 5 | "zh_HK": "隱藏標籤的擴展按鈕-黑名單", 6 | "zh_TW": "隱藏標籤的擴展按鈕-黑名單" 7 | }, 8 | "author": "bluelovers", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-blacklist/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend 2 | { 3 | button[name="blacklist"] { 4 | display: none !important; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-blacklist/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=blacklist]{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight-brackets/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the extension button for tags - weight brackets", 3 | "i18n": { 4 | "zh_CN": "隐藏标籤的扩展按钮-权重符號", 5 | "zh_HK": "隱藏標籤的擴展按鈕-權重符號", 6 | "zh_TW": "隱藏標籤的擴展按鈕-權重符號" 7 | }, 8 | "author": "bluelovers", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight-brackets/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend 2 | { 3 | button[name="weight-parentheses-inc"], button[name="weight-parentheses-dec"], button[name="weight-braces-inc"], button[name="weight-braces-dec"], button[name="weight-brackets-inc"], button[name="weight-brackets-dec"] { 4 | display: none !important; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight-brackets/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-parentheses-inc],.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-parentheses-dec],.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-braces-inc],.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-braces-dec],.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-brackets-inc],.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend button[name=weight-brackets-dec]{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the extension button for tags - weight input", 3 | "i18n": { 4 | "zh_CN": "隐藏标籤的扩展按钮-权重", 5 | "zh_HK": "隱藏標籤的擴展按鈕-權重", 6 | "zh_TW": "隱藏標籤的擴展按鈕-權重" 7 | }, 8 | "author": "bluelovers", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend 2 | { 3 | .input-number { 4 | display: none !important; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns-weight/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend .input-number{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the extension button for tags", 3 | "i18n": { 4 | "zh_CN": "隐藏标签的扩展按钮", 5 | "zh_HK": "隱藏標籤的擴展按鈕", 6 | "zh_TW": "隱藏標籤的擴展按鈕" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend { 2 | display: none !important; 3 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-btns/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .btn-tag-extend{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-extra-network-popup/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide the ExtraNetworks popup for tags", 3 | "i18n": { 4 | "zh_CN": "隐藏标签的ExtraNetworks弹窗", 5 | "zh_HK": "隱藏標籤的ExtraNetworks彈窗", 6 | "zh_TW": "隱藏標籤的ExtraNetworks彈窗" 7 | }, 8 | "author": "physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-extra-network-popup/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt-extra-networks-popup[data-from="tags"] { 2 | display: none !important; 3 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-extra-network-popup/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt-extra-networks-popup[data-from=tags]{display:none!important} -------------------------------------------------------------------------------- /styles/extensions/hide-tag-local/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hide local language under the tag", 3 | "i18n": { 4 | "zh_CN": "\u9690\u85cf\u6807\u7b7e\u4e0b\u65b9\u672c\u5730\u8bed\u8a00", 5 | "zh_HK": "\u96b1\u85cf\u6a19\u7c64\u4e0b\u65b9\u672c\u5730\u8a9e\u8a00", 6 | "zh_TW": "\u96b1\u85cf\u6a19\u7c64\u4e0b\u65b9\u672c\u5730\u8a9e\u8a00" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-local/style.less: -------------------------------------------------------------------------------- 1 | .physton-gradio-container { 2 | --pp-pt-dsb-ptl-pt-promptLocalLanguage-display: none; 3 | } -------------------------------------------------------------------------------- /styles/extensions/hide-tag-local/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-gradio-container{--pp-pt-dsb-ptl-pt-promptLocalLanguage-display:none} -------------------------------------------------------------------------------- /styles/extensions/left-input/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Move the keyword input box to the left", 3 | "i18n": { 4 | "zh_CN": "\u79fb\u52a8\u5173\u952e\u8bcd\u8f93\u5165\u6846\u5230\u5de6\u4fa7", 5 | "zh_HK": "\u79fb\u52d5\u95dc\u9375\u5b57\u8f38\u5165\u6846\u5230\u5de6\u5074", 6 | "zh_TW": "\u79fb\u52d5\u95dc\u9375\u5b57\u8f38\u5165\u6846\u5230\u5de6\u5074" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/left-input/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-header { 2 | .prompt-unfold { 3 | order: 1; 4 | } 5 | 6 | .prompt-header-title { 7 | order: 2; 8 | } 9 | 10 | .prompt-header-counter { 11 | order: 3; 12 | } 13 | 14 | .prompt-header-extend { 15 | order: 5; 16 | 17 | &:nth-last-child(2) { 18 | margin-right: 0; 19 | } 20 | 21 | &.prompt-append { 22 | order: 4; 23 | margin-right: 10px; 24 | 25 | .extend-content { 26 | justify-content: flex-start; 27 | 28 | .input-tag-append { 29 | order: -1; 30 | margin-right: 10px; 31 | } 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /styles/extensions/left-input/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-header .prompt-unfold{order:1}.physton-prompt .prompt-header .prompt-header-title{order:2}.physton-prompt .prompt-header .prompt-header-counter{order:3}.physton-prompt .prompt-header .prompt-header-extend{order:5}.physton-prompt .prompt-header .prompt-header-extend:nth-last-child(2){margin-right:0}.physton-prompt .prompt-header .prompt-header-extend.prompt-append{order:4;margin-right:10px}.physton-prompt .prompt-header .prompt-header-extend.prompt-append .extend-content{justify-content:flex-start}.physton-prompt .prompt-header .prompt-header-extend.prompt-append .extend-content .input-tag-append{order:-1;margin-right:10px} -------------------------------------------------------------------------------- /styles/extensions/line-breaks-new-line/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "The interface displays line breaks as a new line", 3 | "i18n": { 4 | "zh_CN": "\u754C\u9762\u4E2D\u201C\u6362\u884C\u7B26\u53F7\u201D\u6362\u884C\u663E\u793A", 5 | "zh_HK": "\u754C\u9762\u4E2D\u300C\u63DB\u884C\u7B26\u865F\u300D\u63DB\u884C\u986F\u793A", 6 | "zh_TW": "\u4ECB\u9762\u4E2D\u300C\u63DB\u884C\u7B26\u865F\u300D\u63DB\u884C\u986F\u793A" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/line-breaks-new-line/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | .prompt-wrap.wrap-tag { 3 | display: block !important; 4 | } 5 | } -------------------------------------------------------------------------------- /styles/extensions/line-breaks-new-line/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-wrap.wrap-tag{display:block!important} -------------------------------------------------------------------------------- /styles/extensions/minimalist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Minimalist", 3 | "i18n": { 4 | "zh_CN": "简约", 5 | "zh_HK": "簡約", 6 | "zh_TW": "簡約" 7 | }, 8 | "author": "Physton", 9 | "type": "theme" 10 | } -------------------------------------------------------------------------------- /styles/extensions/remove-hide-default-input/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Remove the \"Show/Hide default input box\" checkbox", 3 | "i18n": { 4 | "zh_CN": "去除“显示/隐藏默认输入框”勾选框", 5 | "zh_HK": "去除“顯示/隱藏預設輸入框”勾選框", 6 | "zh_TW": "去除“顯示/隱藏預設輸入框”勾選框" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/remove-hide-default-input/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-header .prompt-header-extend.prompt-append .extend-content .gradio-checkbox { 2 | display: none !important; 3 | } 4 | .physton-gradio-container { 5 | --pp-ph-phe-ec-inputTagAppend-width: calc(100%) !important; 6 | } -------------------------------------------------------------------------------- /styles/extensions/remove-hide-default-input/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-header .prompt-header-extend.prompt-append .extend-content .gradio-checkbox{display:none!important}.physton-gradio-container{--pp-ph-phe-ec-inputTagAppend-width:calc(100%)!important} -------------------------------------------------------------------------------- /styles/extensions/setting-btns-top/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Move the settings button popup to the top", 3 | "i18n": { 4 | "zh_CN": "移动设置按钮弹窗到上方", 5 | "zh_HK": "移動設置按鈕彈窗到上方", 6 | "zh_TW": "移動設置按鈕彈窗到上方" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/setting-btns-top/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | --pp-ph-phe-ec-ebg-ebi-settingBox-top: -35px; 3 | --pp-ph-phe-ec-ebg-ebi-settingBox-left: 0; 4 | } -------------------------------------------------------------------------------- /styles/extensions/setting-btns-top/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt{--pp-ph-phe-ec-ebg-ebi-settingBox-top:-35px;--pp-ph-phe-ec-ebg-ebi-settingBox-left:0} -------------------------------------------------------------------------------- /styles/extensions/tag-btns-right/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Move the expansion button of the keyword tag to the right", 3 | "i18n": { 4 | "zh_CN": "将关键词标签的扩展按钮移到到右侧", 5 | "zh_HK": "將關鍵詞標籤的擴展按鈕移動到右側", 6 | "zh_TW": "將關鍵詞標籤的擴展按鈕移動到右側" 7 | }, 8 | "author": "Physton", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/tag-btns-right/style.less: -------------------------------------------------------------------------------- 1 | .physton-gradio-container { 2 | --pp-pt-dsb-ptl-pt-ptm-btnTagExtend-top: -4px; 3 | --pp-pt-dsb-ptl-pt-ptm-btnTagExtend-left: calc(100% - 2px); 4 | } -------------------------------------------------------------------------------- /styles/extensions/tag-btns-right/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-gradio-container{--pp-pt-dsb-ptl-pt-ptm-btnTagExtend-top:-4px;--pp-pt-dsb-ptl-pt-ptm-btnTagExtend-left:calc(100% - 2px)} -------------------------------------------------------------------------------- /styles/extensions/tag-group-tweak/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tag Group Style Tweak", 3 | "i18n": { 4 | "zh_CN": "调整关键词组样式", 5 | "zh_HK": "調整關鍵詞群組樣式", 6 | "zh_TW": "調整關鍵詞群組樣式" 7 | }, 8 | "author": "bluelovers", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/tag-group-tweak/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | .group-tabs { 3 | .group-body { 4 | .group-main { 5 | .sub-group-body { 6 | .group-tags { 7 | max-height: 250px; 8 | overflow: visible; 9 | overflow-y: scroll; 10 | .tag-item { 11 | max-width: 32%; 12 | } 13 | } 14 | } 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /styles/extensions/tag-group-tweak/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .group-tabs .group-body .group-main .sub-group-body .group-tags{max-height:250px;overflow:visible;overflow-y:scroll}.physton-prompt .group-tabs .group-body .group-main .sub-group-body .group-tags .tag-item{max-width:32%} -------------------------------------------------------------------------------- /styles/extensions/tag-weight-character/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Emphasize Tag Weight Character", 3 | "i18n": { 4 | "zh_CN": "强调关键词权重标签", 5 | "zh_HK": "強調關鍵詞權重標籤", 6 | "zh_TW": "強調關鍵詞權重標籤" 7 | }, 8 | "author": "bluelovers", 9 | "type": "enhance" 10 | } -------------------------------------------------------------------------------- /styles/extensions/tag-weight-character/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | .prompt-tags { 3 | .prompt-tags-list { 4 | .prompt-tag { 5 | .prompt-tag-main { 6 | .prompt-tag-edit { 7 | .prompt-tag-value { 8 | .weight-character { 9 | font-weight: bold; 10 | padding: 0 1px; 11 | &:first-of-type { 12 | padding-right: 3px; 13 | } 14 | &:last-of-type { 15 | padding-left: 3px; 16 | } 17 | } 18 | } 19 | } 20 | } 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /styles/extensions/tag-weight-character/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value .weight-character{font-weight:700;padding:0 1px}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value .weight-character:first-of-type{padding-right:3px}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value .weight-character:last-of-type{padding-left:3px} -------------------------------------------------------------------------------- /styles/extensions/weaken-keywords/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Weaken the keyword list", 3 | "i18n": { 4 | "zh_CN": "弱化关键词列表", 5 | "zh_HK": "弱化關鍵詞列表", 6 | "zh_TW": "弱化關鍵詞列表" 7 | }, 8 | "author": "Physton", 9 | "type": "theme" 10 | } -------------------------------------------------------------------------------- /styles/extensions/weaken-keywords/style.less: -------------------------------------------------------------------------------- 1 | .physton-prompt { 2 | .prompt-tags { 3 | .prompt-tags-list { 4 | .prompt-tag { 5 | margin-bottom: 4px; 6 | margin-right: 6px; 7 | 8 | .prompt-tag-main { 9 | .prompt-tag-edit { 10 | min-height: 22px; 11 | 12 | .prompt-tag-value, .btn-tag-delete { 13 | background: transparent; 14 | padding: 2px; 15 | } 16 | } 17 | } 18 | 19 | .prompt-local-language { 20 | margin-top: 0; 21 | 22 | svg { 23 | width: 12px; 24 | height: 12px; 25 | } 26 | } 27 | } 28 | } 29 | } 30 | } 31 | 32 | /* 33 | 浅色主题 34 | Light theme 35 | */ 36 | .physton-gradio-container.light .physton-prompt { 37 | .prompt-tags { 38 | .prompt-tags-list { 39 | .prompt-tag { 40 | .prompt-tag-main { 41 | .prompt-tag-edit { 42 | .prompt-tag-value, .btn-tag-delete { 43 | border-color: #e9e9e9 !important; 44 | } 45 | } 46 | } 47 | 48 | .prompt-local-language { 49 | svg path { 50 | fill: var(--block-info-text-color); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | /** 59 | 深色主题 60 | Dark theme 61 | */ 62 | .physton-gradio-container.dark .physton-prompt { 63 | .prompt-tags { 64 | .prompt-tags-list { 65 | .prompt-tag { 66 | .prompt-tag-main { 67 | .prompt-tag-edit { 68 | .prompt-tag-value, .btn-tag-delete { 69 | border-color: #222222; 70 | } 71 | 72 | .btn-tag-delete { 73 | svg path { 74 | fill: #505050; 75 | } 76 | } 77 | } 78 | } 79 | 80 | .prompt-local-language { 81 | .local-language { 82 | //color: #5a5a5a; 83 | } 84 | 85 | svg path { 86 | fill: #5a5a5a; 87 | } 88 | } 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /styles/extensions/weaken-keywords/style.min.css: -------------------------------------------------------------------------------- 1 | .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag{margin-bottom:4px;margin-right:6px}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit{min-height:22px}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .btn-tag-delete,.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value{background:0 0;padding:2px}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-local-language{margin-top:0}.physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-local-language svg{width:12px;height:12px}.physton-gradio-container.light .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .btn-tag-delete,.physton-gradio-container.light .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value{border-color:#e9e9e9!important}.physton-gradio-container.light .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-local-language svg path{fill:var(--block-info-text-color)}.physton-gradio-container.dark .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .btn-tag-delete,.physton-gradio-container.dark .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .prompt-tag-value{border-color:#222}.physton-gradio-container.dark .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-tag-main .prompt-tag-edit .btn-tag-delete svg path{fill:#505050}.physton-gradio-container.dark .physton-prompt .prompt-tags .prompt-tags-list .prompt-tag .prompt-local-language svg path{fill:#5a5a5a} -------------------------------------------------------------------------------- /styles/icons/about.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/api.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/blacklist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/chatgpt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/copy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/disabled.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/enable.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/english.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/favorite-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/favorite-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/favorite.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/format.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/github.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/history.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/hotkey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/i18n.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/input.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/load.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/load2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/loading.svg: -------------------------------------------------------------------------------- 1 | 4 | 6 | 9 | 12 | 13 | 15 | 18 | 21 | 22 | -------------------------------------------------------------------------------- /styles/icons/moon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/move-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/move-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/refresh.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/remove-space.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/remove.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/reset.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/setting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/sun.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/theme.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/tooltip.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/translate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/unfold.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/icons/use.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /styles/icons/weight-braces-dec.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 8 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /styles/icons/weight-braces-inc.svg: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 8 | 10 | 11 | 13 | 14 | -------------------------------------------------------------------------------- /styles/icons/weight-brackets-dec.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /styles/icons/weight-brackets-inc.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 7 | 8 | -------------------------------------------------------------------------------- /styles/icons/weight-parentheses-dec.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | -------------------------------------------------------------------------------- /styles/icons/weight-parentheses-inc.svg: -------------------------------------------------------------------------------- 1 | 3 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /styles/icons/wrap.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /styles/tippy.css: -------------------------------------------------------------------------------- 1 | .tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{position:relative;background-color:#333;color:#fff;border-radius:4px;font-size:14px;line-height:1.4;white-space:normal;outline:0;transition-property:transform,visibility,opacity}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{bottom:-7px;left:0;border-width:8px 8px 0;border-top-color:initial;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{top:-7px;left:0;border-width:0 8px 8px;border-bottom-color:initial;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-width:8px 0 8px 8px;border-left-color:initial;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{left:-7px;border-width:8px 8px 8px 0;border-right-color:initial;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{width:16px;height:16px;color:#333}.tippy-arrow:before{content:"";position:absolute;border-color:transparent;border-style:solid}.tippy-content{position:relative;padding:5px 9px;z-index:1} -------------------------------------------------------------------------------- /tags/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | tested.json 2 | .env -------------------------------------------------------------------------------- /tests/get_lang.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 4 | 5 | from scripts.physton_prompt.get_lang import get_lang 6 | 7 | print(get_lang('is_required', {'0': '11'})) 8 | print(get_lang('is_required1')) -------------------------------------------------------------------------------- /tests/get_version.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 4 | 5 | from scripts.physton_prompt.get_version import get_git_commit_version, get_git_remote_versions, get_latest_version 6 | 7 | print(get_git_remote_versions()) 8 | print(get_git_commit_version()) 9 | print(get_latest_version()) -------------------------------------------------------------------------------- /tests/privacy_api_config.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 4 | from scripts.physton_prompt.storage import Storage 5 | from scripts.physton_prompt.get_translate_apis import privacy_translate_api_config, unprotected_translate_api_config 6 | key = 'translate_api.volcengine' 7 | data = Storage.get(key) 8 | data = privacy_translate_api_config(key, data) 9 | print(data) 10 | data = unprotected_translate_api_config(key, data) 11 | print(data) 12 | 13 | data = { 14 | 'key': 'translate_api.volcengine', 15 | 'data': { 16 | 'access_key_id': 'AKLTYz*****************************************', 17 | 'access_key_secret': 'TWpVNV******************************************************', 18 | 'region': 'cn-north-1', 19 | } 20 | } 21 | data['data'] = unprotected_translate_api_config(data['key'], data['data']) 22 | print(data) -------------------------------------------------------------------------------- /tests/translate.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 4 | import time 5 | import json 6 | from scripts.physton_prompt.translate import translate 7 | from scripts.physton_prompt.get_i18n import get_i18n 8 | from scripts.physton_prompt.get_translate_apis import get_translate_apis 9 | from scripts.physton_prompt.storage import Storage 10 | 11 | i18n = get_i18n() 12 | text = 'Hello World, I am a boy' 13 | 14 | tested_file = os.path.join(os.path.dirname(__file__), 'tested.json') 15 | tested = [] 16 | if os.path.exists(tested_file): 17 | with open(tested_file, 'r') as f: 18 | tested = json.load(f) 19 | 20 | def is_tested(api_key, from_lang, to_lang): 21 | for item in tested: 22 | if item['api'] == api_key and item['from'] == from_lang and item['to'] == to_lang: 23 | return item['translated_text'] 24 | return False 25 | 26 | def add_tested(api_key, from_lang, to_lang, translated_text): 27 | tested.append({ 28 | 'api': api_key, 29 | 'from': from_lang, 30 | 'to': to_lang, 31 | 'translated_text': translated_text 32 | }) 33 | with open(tested_file, 'w') as f: 34 | json.dump(tested, f, indent=4, ensure_ascii=False) 35 | 36 | def test_api(api): 37 | print(f"开始测试 {api['name']}") 38 | config_name = 'translate_api.' + api['key'] 39 | config = Storage.get(config_name) 40 | if not config: 41 | config = {} 42 | for lang_code in api['support']: 43 | if lang_code == 'en_US' or lang_code == 'en_GB': 44 | continue 45 | if not api['support'][lang_code]: 46 | continue 47 | if api['key'] == 'openai' or api['key'] == 'deepl': 48 | continue 49 | 50 | translated_text = is_tested(api['key'], 'en_US', lang_code) 51 | if not translated_text: 52 | print(f" 测试 en_US -> {lang_code}", end=' ') 53 | result = translate(text, from_lang='en_US', to_lang=lang_code, api=api['key'],api_config=config) 54 | if not result['success']: 55 | print(f"失败: {result['message']}") 56 | time.sleep(0.5) 57 | # raise Exception(f"测试 {api['name']} 失败:{result['message']}") 58 | continue 59 | add_tested(api['key'], 'en_US', lang_code, result['translated_text']) 60 | translated_text = result['translated_text'] 61 | print(f" 结果: {translated_text}") 62 | time.sleep(0.5) 63 | 64 | if not is_tested(api['key'], lang_code, 'en_US'): 65 | print(f" 测试 {lang_code} -> en_US", end=' ') 66 | result = translate(translated_text, from_lang=lang_code, to_lang='en_US', api=api['key'],api_config=config) 67 | if not result['success']: 68 | print(f"失败: {result['message']}") 69 | time.sleep(0.5) 70 | # raise Exception(f"测试 {api['name']} 失败:{result['message']}") 71 | continue 72 | translated_text = result['translated_text'] 73 | add_tested(api['key'], lang_code, 'en_US', translated_text) 74 | print(f" 结果: {translated_text}") 75 | time.sleep(0.5) 76 | 77 | apis = get_translate_apis() 78 | for group in apis['apis']: 79 | for api in group['children']: 80 | test_api(api) 81 | 82 | -------------------------------------------------------------------------------- /tests/translators.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | sys.path.append(os.path.join(os.path.dirname(__file__), "..")) 4 | 5 | region = 'CN' 6 | os.environ['translators_default_region'] = region 7 | from scripts.physton_prompt.translators.server import translate_text, tss 8 | tss.server_region = region 9 | tss._bing.server_region = region 10 | tss._google.server_region = region 11 | 12 | text = ''' 13 | Hi, this extension is developed by Physton. Welcome to use it! 14 | If you have any suggestions or opinions, please feel free to raise an issue or PR on Github. 15 | If you find this extension helpful, please give me a star on Github! 16 | 17 | Developed by: Physton 18 | Github: Physton/sd-webui-prompt-all-in-one 19 | ''' 20 | translator = 'alibaba' 21 | print("--------------------------------------") 22 | print(translate_text(text, translator, 'zh', 'en')) 23 | 24 | print("--------------------------------------") 25 | print(translate_text('你好', translator, 'zh', 'en')) 26 | 27 | print("--------------------------------------") 28 | print(translate_text('女孩', translator, 'zh', 'en')) 29 | 30 | print("--------------------------------------") 31 | print(translate_text('美女', translator, 'zh', 'en')) --------------------------------------------------------------------------------