├── .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 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/src/components/iconSvg.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/src/components/selectLanguage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 | {{ item.code }} - {{ item.name }}
13 |
14 |
15 |
16 |
17 |
18 |
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 |
--------------------------------------------------------------------------------
/styles/icons/api.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/blacklist.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/chatgpt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/clear.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/copy.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/disabled.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/enable.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/english.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/favorite-no.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/favorite-yes.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/favorite.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/format.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/github.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/history.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/hotkey.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/i18n.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/input.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/load.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/load2.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/loading.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/moon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/move-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/move-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/refresh.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/remove-space.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/remove.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/reset.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/setting.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/sun.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/theme.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/tooltip.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/translate.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/unfold.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/use.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/styles/icons/weight-braces-dec.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/weight-braces-inc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/weight-brackets-dec.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/weight-brackets-inc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/weight-parentheses-dec.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/weight-parentheses-inc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/styles/icons/wrap.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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'))
--------------------------------------------------------------------------------