mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Compare commits
201 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
e4d1463a22 | ||
|
ea4b1759aa | ||
|
2e81e47967 | ||
|
2622999284 | ||
|
78c599a413 | ||
|
1a07fa8365 | ||
|
4200f1da0a | ||
|
1f8f200caf | ||
|
e39e9428b6 | ||
|
4fd042b9a5 | ||
|
41f504ef00 | ||
|
9b5e082a26 | ||
|
0ed340bd9a | ||
|
26a9c2889f | ||
|
53e41bdda8 | ||
|
25bd2541f7 | ||
|
6c909acea6 | ||
|
8c70b1decd | ||
|
7effc3497d | ||
|
cd86999d30 | ||
|
2fea218661 | ||
|
ef3a9a810e | ||
|
2c3cfb31f5 | ||
|
7c6429a577 | ||
|
e343f2461d | ||
|
c94eae6eb6 | ||
|
9a7654598e | ||
|
5ac375097b | ||
|
508e1a06da | ||
|
5ba7588838 | ||
|
98f8613e38 | ||
|
5ea30d9d4d | ||
|
78825352e5 | ||
|
264b52b52d | ||
|
0cb63e689d | ||
|
c1ab0212e5 | ||
|
128945aaaa | ||
|
75bb0d641f | ||
|
fcc51b6481 | ||
|
c124fc589f | ||
|
32e5566a37 | ||
|
f8e8929834 | ||
|
4167047f9b | ||
|
5f97a52d58 | ||
|
7384cb07a4 | ||
|
e0d6430ade | ||
|
23a57e86a7 | ||
|
6e55b99aa9 | ||
|
2424367460 | ||
|
c4602df108 | ||
|
c86e2154c9 | ||
|
151f4d322c | ||
|
04a2d82a8d | ||
|
cfc4394e41 | ||
|
74b973c571 | ||
|
ef1f6b3143 | ||
|
58f7c77281 | ||
|
39e43e8a0d | ||
|
b59e0cdfc8 | ||
|
e3f48ea767 | ||
|
b3bb88e99b | ||
|
51ed6ba0c9 | ||
|
632d1a2a17 | ||
|
078eb051ad | ||
|
5b1095abcb | ||
|
b1666dc18d | ||
|
3aa8229401 | ||
|
734b0201be | ||
|
6ddfcc7a06 | ||
|
ef8aef7994 | ||
|
8128c2436b | ||
|
649bc69b19 | ||
|
bfac10028f | ||
|
4ae3e9db0a | ||
|
d05d4042fe | ||
|
1061971cdb | ||
|
6b2455da2b | ||
|
7b5bb030ad | ||
|
19b3e13675 | ||
|
d16f6f8fea | ||
|
45a66fae9d | ||
|
6b288ca83c | ||
|
d59d7e6c8d | ||
|
8b3f65073c | ||
|
b407fe2388 | ||
|
33af7ad266 | ||
|
cd8a24a712 | ||
|
84283bc2b4 | ||
|
14827d6135 | ||
|
b34df90905 | ||
|
c18a845f64 | ||
|
2a00e98ec5 | ||
|
d84d55c35f | ||
|
853d81e67c | ||
|
791b18d78e | ||
|
079b1623c5 | ||
|
708b065300 | ||
|
140b86d822 | ||
|
8f1321f09d | ||
|
9333340175 | ||
|
4698f0f765 | ||
|
f106666ded | ||
|
2d07cce1dd | ||
|
ea809023b5 | ||
|
bcffaec6a6 | ||
|
008d8fa6fc | ||
|
926bf0b4c9 | ||
|
aefafdebe0 | ||
|
2f94451948 | ||
|
e5a678fb2d | ||
|
109f6ace63 | ||
|
44340208de | ||
|
19a0f8e5ac | ||
|
2a153e3b15 | ||
|
249ab7106a | ||
|
d5e32af9b2 | ||
|
65732f4406 | ||
|
3da9438b63 | ||
|
f892931d44 | ||
|
a837b1e2fb | ||
|
9cf4056b28 | ||
|
37e653dcf4 | ||
|
0a12fe0bdb | ||
|
56a4a6eb83 | ||
|
8446f10408 | ||
|
4b7c837fe3 | ||
|
aebdd6cd42 | ||
|
73f15060c9 | ||
|
e381e1cefc | ||
|
2fc6813e66 | ||
|
0ad3c86e17 | ||
|
9f44a72d76 | ||
|
c760447288 | ||
|
ea0fe349cd | ||
|
1f56f0d64a | ||
|
905131c764 | ||
|
31feaee805 | ||
|
a07cbe5f7f | ||
|
67fa7b9607 | ||
|
1b005ef47f | ||
|
c8b5b7da22 | ||
|
5a67d72fea | ||
|
68e5ae63d6 | ||
|
9712e4bbb0 | ||
|
61c0e3b08b | ||
|
d4278388f7 | ||
|
2fdec7eb03 | ||
|
1d0f67c144 | ||
|
14ef5d9a6b | ||
|
143b4347c2 | ||
|
2a08e199d2 | ||
|
f198f5eb6e | ||
|
65a16970f4 | ||
|
5a7c4947b3 | ||
|
bb3fc5be62 | ||
|
ea800d1550 | ||
|
90e08e08de | ||
|
9d99b89c9c | ||
|
baddee8082 | ||
|
a51653e8b5 | ||
|
7dfaf6f0b0 | ||
|
3f015f4bd2 | ||
|
6f18c457fc | ||
|
c57de3d47b | ||
|
cd02abe205 | ||
|
aac7525204 | ||
|
42cc66f06e | ||
|
f6f51d21c5 | ||
|
9a4d62ca6f | ||
|
9d023dc3b1 | ||
|
ac98ebcc6c | ||
|
29a3c5d590 | ||
|
0c0e24323c | ||
|
32f605e413 | ||
|
af8c21fea2 | ||
|
72974d8a54 | ||
|
7f86551ab4 | ||
|
c5d87e4808 | ||
|
e5f3a70860 | ||
|
7596d78322 | ||
|
5645432e9d | ||
|
bad7892baa | ||
|
a0c8ac54dd | ||
|
73fd306b8b | ||
|
72213add56 | ||
|
6f4fd15095 | ||
|
78d62d7be2 | ||
|
99af6ed472 | ||
|
16b45f1ea9 | ||
|
435d319090 | ||
|
e7148c41a9 | ||
|
192c82b180 | ||
|
8aff89de30 | ||
|
6768c56e2b | ||
|
4939387bbf | ||
|
4c14b8ee2d | ||
|
0bbcf0db83 | ||
|
0c919bf32d | ||
|
9f92b19004 | ||
|
7824a18103 | ||
|
0eef05908d |
@@ -5,3 +5,4 @@ readme*
|
|||||||
Start.bat
|
Start.bat
|
||||||
/dist
|
/dist
|
||||||
/backups/
|
/backups/
|
||||||
|
cloudflared.exe
|
||||||
|
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -7,7 +7,7 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
> **Warning**. Complete **all** the fields below. Otherwise your bug report will be **ignored**!
|
> **Warning**. Complete **all** the fields below. Otherwise, your bug report will be **ignored**!
|
||||||
|
|
||||||
**Have you searched for similar [bugs](https://github.com/SillyTavern/SillyTavern/issues?q=)?**
|
**Have you searched for similar [bugs](https://github.com/SillyTavern/SillyTavern/issues?q=)?**
|
||||||
Yes/No
|
Yes/No
|
||||||
@@ -38,7 +38,7 @@ Providing the logs from the browser DevTools console (opened by pressing the F12
|
|||||||
- Node.js version (if applicable): [run `node --version` in cmd]
|
- Node.js version (if applicable): [run `node --version` in cmd]
|
||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
- Generation API [e.g. KoboldAI, OpenAI]
|
- Generation API [e.g. KoboldAI, OpenAI]
|
||||||
- Branch [main, dev]
|
- Branch [staging, release]
|
||||||
- Model [e.g. Pygmalion 6b, LLaMa 13b]
|
- Model [e.g. Pygmalion 6b, LLaMa 13b]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
20
.github/readme-zh_cn.md
vendored
20
.github/readme-zh_cn.md
vendored
@@ -1,6 +1,8 @@
|
|||||||
|
[English](readme.md) | 中文
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
移动设备界面友好,多种人工智能服务或模型支持(KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)),类似 Galgame 的 老 婆 模 式,Horde SD,文本系统语音生成,世界信息(Lorebooks),可定制的界面,自动翻译,和比你所需要的更多的 Prompt。附带扩展服务,支持文本绘画生成与语音生成和基于向量数据库 ChromaDB 的聊天信息总结。
|
移动设备界面友好,多种人工智能服务或模型支持(KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI, OpenRouter, Claude, Scale),类似 Galgame 的 老 婆 模 式,Horde SD,文本系统语音生成,世界信息(Lorebooks),可定制的界面,自动翻译,和比你所需要的更多的 Prompt。附带扩展服务,支持文本绘画生成与语音生成和基于向量数据库 ChromaDB 的聊天信息总结。
|
||||||
|
|
||||||
基于 TavernAI 1.2.8 的分叉版本
|
基于 TavernAI 1.2.8 的分叉版本
|
||||||
|
|
||||||
@@ -282,24 +284,26 @@ SillyTavern 会将 API 密钥保存在目录中的 `secrets.json` 文件内。
|
|||||||
|
|
||||||
## 许可证和贡献
|
## 许可证和贡献
|
||||||
|
|
||||||
** 发布本程序是希望它能有所帮助,但不做任何保证;甚至没有明示的性能、稳定性和其他任何特定用途的可用性保证。更多详情,请参阅 GNU Affero 通用公共许可证。 **
|
**发布本程序是希望它能有所帮助,但不做任何保证;甚至没有明示的性能、稳定性和其他任何特定用途的可用性保证。更多详情,请参阅 GNU Affero 通用公共许可证。**
|
||||||
|
|
||||||
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. **
|
**This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.**
|
||||||
|
|
||||||
* TAI Base by Humi: Unknown license
|
* TAI Base by Humi: Unknown license
|
||||||
* Cohee's modifications and derived code: AGPL v3
|
* Cohee's modifications and derived code: AGPL v3
|
||||||
* RossAscends' additions: AGPL v3
|
* RossAscends' additions: AGPL v3
|
||||||
* Portions of CncAnon's TavernAITurbo mod: Unknown license
|
* Portions of CncAnon's TavernAITurbo mod: Unknown license
|
||||||
* kingbri's various commits and suggestions (https://github.com/bdashore3)
|
* kingbri's various commits and suggestions (<https://github.com/bdashore3>)
|
||||||
* Waifu mode inspired by the work of PepperTaco (https://github.com/peppertaco/Tavern/)
|
* StefanDanielSchwarz's various commits and bug reports (<https://github.com/StefanDanielSchwarz>)
|
||||||
|
* Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
|
||||||
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
|
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
|
||||||
* Thanks oobabooga for compiling presets for TextGen
|
* Thanks oobabooga for compiling presets for TextGen
|
||||||
* KoboldAI Presets from KAI Lite: https://lite.koboldai.net/
|
* KoboldAI Presets from KAI Lite: <https://lite.koboldai.net/>
|
||||||
* Noto Sans font by Google (OFL license)
|
* Noto Sans font by Google (OFL license)
|
||||||
* Icon theme by Font Awesome https://fontawesome.com (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
* Icon theme by Font Awesome <https://fontawesome.com> (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
* AI Horde client library by ZeldaFan0225: https://github.com/ZeldaFan0225/ai_horde
|
* AI Horde client library by ZeldaFan0225: <https://github.com/ZeldaFan0225/ai_horde>
|
||||||
* Linux startup script by AlpinDale
|
* Linux startup script by AlpinDale
|
||||||
* Thanks paniphons for providing a FAQ document
|
* Thanks paniphons for providing a FAQ document
|
||||||
* 10K Discord Users Celebratory Background by @kallmeflocc
|
* 10K Discord Users Celebratory Background by @kallmeflocc
|
||||||
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
|
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
|
||||||
* Korean translation by @doloroushyeonse
|
* Korean translation by @doloroushyeonse
|
||||||
|
* 中文翻译由 [@XXpE3](https://github.com/XXpE3) 完成,中文 ISSUES 可以联系 @XXpE3
|
||||||
|
8
.github/readme.md
vendored
8
.github/readme.md
vendored
@@ -1,6 +1,8 @@
|
|||||||
|
English | [中文](readme-zh_cn.md)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI+proxies, WindowAI(Claude!)), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
|
Mobile-friendly, Multi-API (KoboldAI/CPP, Horde, NovelAI, Ooba, OpenAI, OpenRouter, Claude, Scale), VN-like Waifu Mode, Horde SD, System TTS, WorldInfo (lorebooks), customizable UI, auto-translate, and more prompt options than you'd ever want or need. Optional Extras server for more SD/TTS options + ChromaDB/Summarize.
|
||||||
|
|
||||||
Based on a fork of TavernAI 1.2.8
|
Based on a fork of TavernAI 1.2.8
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ Get in touch with the developers directly:
|
|||||||
* Chat bookmarks / branching (duplicates the dialogue in its current state)
|
* Chat bookmarks / branching (duplicates the dialogue in its current state)
|
||||||
* Advanced KoboldAI / TextGen generation settings with a lot of community-made presets
|
* Advanced KoboldAI / TextGen generation settings with a lot of community-made presets
|
||||||
* World Info support: create rich lore or save tokens on your character card
|
* World Info support: create rich lore or save tokens on your character card
|
||||||
* Window AI browser extension support (run models like Claude, GPT 4): <https://windowai.io/>
|
* [OpenRouter](https://openrouter.ai) connection for various APIs (Claude, GPT-4/3.5 and more)
|
||||||
* [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection
|
* [Oobabooga's TextGen WebUI](https://github.com/oobabooga/text-generation-webui) API connection
|
||||||
* [AI Horde](https://horde.koboldai.net/) connection
|
* [AI Horde](https://horde.koboldai.net/) connection
|
||||||
* Prompt generation formatting tweaking
|
* Prompt generation formatting tweaking
|
||||||
@@ -293,6 +295,7 @@ GNU Affero General Public License for more details.**
|
|||||||
* RossAscends' additions: AGPL v3
|
* RossAscends' additions: AGPL v3
|
||||||
* Portions of CncAnon's TavernAITurbo mod: Unknown license
|
* Portions of CncAnon's TavernAITurbo mod: Unknown license
|
||||||
* kingbri's various commits and suggestions (<https://github.com/bdashore3>)
|
* kingbri's various commits and suggestions (<https://github.com/bdashore3>)
|
||||||
|
* StefanDanielSchwarz's various commits and bug reports (<https://github.com/StefanDanielSchwarz>)
|
||||||
* Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
|
* Waifu mode inspired by the work of PepperTaco (<https://github.com/peppertaco/Tavern/>)
|
||||||
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
|
* Thanks Pygmalion University for being awesome testers and suggesting cool features!
|
||||||
* Thanks oobabooga for compiling presets for TextGen
|
* Thanks oobabooga for compiling presets for TextGen
|
||||||
@@ -306,3 +309,4 @@ GNU Affero General Public License for more details.**
|
|||||||
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
|
* Default content (characters and lore books) provided by @OtisAlejandro, @RossAscends and @kallmeflocc
|
||||||
* Korean translation by @doloroushyeonse
|
* Korean translation by @doloroushyeonse
|
||||||
* k_euler_a support for Horde by <https://github.com/Teashrock>
|
* k_euler_a support for Horde by <https://github.com/Teashrock>
|
||||||
|
* Chinese translation by [@XXpE3](https://github.com/XXpE3), 中文 ISSUES 可以联系 @XXpE3
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,3 +28,4 @@ secrets.json
|
|||||||
public/movingUI/
|
public/movingUI/
|
||||||
public/QuickReplies/
|
public/QuickReplies/
|
||||||
content.log
|
content.log
|
||||||
|
cloudflared.exe
|
||||||
|
18
Remote-Link.cmd
Normal file
18
Remote-Link.cmd
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
@echo off
|
||||||
|
echo ========================================================================================================================
|
||||||
|
echo WARNING: Cloudflare Tunnel!
|
||||||
|
echo ========================================================================================================================
|
||||||
|
echo This script downloads and runs the latest cloudflared.exe from Cloudflare to set up an HTTPS tunnel to your SillyTavern!
|
||||||
|
echo Using the randomly generated temporary tunnel URL, anyone can access your SillyTavern over the Internet while the tunnel
|
||||||
|
echo is active. Keep the URL safe and secure your SillyTavern installation by setting a username and password in config.conf!
|
||||||
|
echo.
|
||||||
|
echo See https://docs.sillytavern.app/usage/remoteconnections/ for more details about how to secure your SillyTavern install.
|
||||||
|
echo.
|
||||||
|
echo By continuing you confirm that you're aware of the potential dangers of having a tunnel open and take all responsibility
|
||||||
|
echo to properly use and secure it!
|
||||||
|
echo.
|
||||||
|
echo To abort, press Ctrl+C or close this window now!
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
|
if not exist cloudflared.exe curl -Lo cloudflared.exe https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-windows-amd64.exe
|
||||||
|
cloudflared.exe tunnel --url localhost:8000
|
@@ -14,6 +14,7 @@
|
|||||||
"world_info_depth": 2,
|
"world_info_depth": 2,
|
||||||
"world_info_budget": 25,
|
"world_info_budget": 25,
|
||||||
"world_info_recursive": true,
|
"world_info_recursive": true,
|
||||||
|
"world_info_overflow_alert": false,
|
||||||
"world_info_case_sensitive": false,
|
"world_info_case_sensitive": false,
|
||||||
"world_info_match_whole_words": false,
|
"world_info_match_whole_words": false,
|
||||||
"world_info_character_strategy": 1,
|
"world_info_character_strategy": 1,
|
||||||
@@ -27,6 +28,7 @@
|
|||||||
"eta_cutoff": 0,
|
"eta_cutoff": 0,
|
||||||
"typical_p": 1,
|
"typical_p": 1,
|
||||||
"rep_pen": 1.1,
|
"rep_pen": 1.1,
|
||||||
|
"rep_pen_range": 0,
|
||||||
"no_repeat_ngram_size": 0,
|
"no_repeat_ngram_size": 0,
|
||||||
"penalty_alpha": 0,
|
"penalty_alpha": 0,
|
||||||
"num_beams": 1,
|
"num_beams": 1,
|
||||||
@@ -57,7 +59,7 @@
|
|||||||
"trusted_workers_only": false
|
"trusted_workers_only": false
|
||||||
},
|
},
|
||||||
"power_user": {
|
"power_user": {
|
||||||
"tokenizer": 3,
|
"tokenizer": 99,
|
||||||
"token_padding": 64,
|
"token_padding": 64,
|
||||||
"collapse_newlines": false,
|
"collapse_newlines": false,
|
||||||
"pygmalion_formatting": 0,
|
"pygmalion_formatting": 0,
|
||||||
@@ -91,7 +93,7 @@
|
|||||||
"sort_order": "asc",
|
"sort_order": "asc",
|
||||||
"sort_rule": null,
|
"sort_rule": null,
|
||||||
"font_scale": 1,
|
"font_scale": 1,
|
||||||
"blur_strength": 5,
|
"blur_strength": 10,
|
||||||
"shadow_width": 2,
|
"shadow_width": 2,
|
||||||
"main_text_color": "rgba(220, 220, 210, 1)",
|
"main_text_color": "rgba(220, 220, 210, 1)",
|
||||||
"italics_text_color": "rgba(145, 145, 145, 1)",
|
"italics_text_color": "rgba(145, 145, 145, 1)",
|
||||||
@@ -144,7 +146,9 @@
|
|||||||
"persona_descriptions": {},
|
"persona_descriptions": {},
|
||||||
"persona_description": "",
|
"persona_description": "",
|
||||||
"persona_description_position": 0,
|
"persona_description_position": 0,
|
||||||
"custom_stopping_strings": ""
|
"custom_stopping_strings": "",
|
||||||
|
"custom_stopping_strings_macro": true,
|
||||||
|
"fuzzy_search": false
|
||||||
},
|
},
|
||||||
"extension_settings": {
|
"extension_settings": {
|
||||||
"apiUrl": "http://localhost:5100",
|
"apiUrl": "http://localhost:5100",
|
||||||
@@ -183,7 +187,14 @@
|
|||||||
"promptInterval": 10,
|
"promptInterval": 10,
|
||||||
"promptMinInterval": 1,
|
"promptMinInterval": 1,
|
||||||
"promptMaxInterval": 100,
|
"promptMaxInterval": 100,
|
||||||
"promptIntervalStep": 1
|
"promptIntervalStep": 1,
|
||||||
|
"template": "[Summary: {{summary}}]",
|
||||||
|
"position": 0,
|
||||||
|
"depth": 2,
|
||||||
|
"promptForceWords": 0,
|
||||||
|
"promptForceWordsStep": 100,
|
||||||
|
"promptMinForceWords": 0,
|
||||||
|
"promptMaxForceWords": 10000
|
||||||
},
|
},
|
||||||
"note": {
|
"note": {
|
||||||
"default": "",
|
"default": "",
|
||||||
@@ -203,7 +214,8 @@
|
|||||||
"ttsEnabled": false,
|
"ttsEnabled": false,
|
||||||
"currentProvider": "System",
|
"currentProvider": "System",
|
||||||
"auto_generation": true,
|
"auto_generation": true,
|
||||||
"ElevenLabs": {}
|
"ElevenLabs": {},
|
||||||
|
"System": {}
|
||||||
},
|
},
|
||||||
"sd": {
|
"sd": {
|
||||||
"scale_min": 1,
|
"scale_min": 1,
|
||||||
@@ -228,7 +240,16 @@
|
|||||||
"horde": true,
|
"horde": true,
|
||||||
"horde_nsfw": false,
|
"horde_nsfw": false,
|
||||||
"horde_karras": true,
|
"horde_karras": true,
|
||||||
"refine_mode": false
|
"refine_mode": false,
|
||||||
|
"prompts": {
|
||||||
|
"0": "[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'full body portrait,']",
|
||||||
|
"1": "[Pause your roleplay and provide a detailed description of {{user}}'s physical appearance from the perspective of {{char}} in the form of a comma-delimited list of keywords and phrases. The list must include all of the following items in this order: name, species and race, gender, age, clothing, occupation, physical features and appearances. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'full body portrait,'. Ignore the rest of the story when crafting this description. Do not roleplay as {{char}} when writing this description, and do not attempt to continue the story.]",
|
||||||
|
"2": "[Pause your roleplay and provide a detailed description for all of the following: a brief recap of recent events in the story, {{char}}'s appearance, and {{char}}'s surroundings. Do not roleplay while writing this description.]",
|
||||||
|
"3": "[Pause your roleplay and provide ONLY the last chat message string back to me verbatim. Do not write anything after the string. Do not roleplay at all in your response. Do not continue the roleplay story.]",
|
||||||
|
"4": "[Pause your roleplay. Your next response must be formatted as a single comma-delimited list of concise keywords. The list will describe of the visual details included in the last chat message.\n\n Only mention characters by using pronouns ('he','his','she','her','it','its') or neutral nouns ('male', 'the man', 'female', 'the woman').\n\n Ignore non-visible things such as feelings, personality traits, thoughts, and spoken dialog.\n\n Add keywords in this precise order:\n a keyword to describe the location of the scene,\n a keyword to mention how many characters of each gender or type are present in the scene (minimum of two characters:\n {{user}} and {{char}}, example: '2 men ' or '1 man 1 woman ', '1 man 3 robots'),\n\n keywords to describe the relative physical positioning of the characters to each other (if a commonly known term for the positioning is known use it instead of describing the positioning in detail) + 'POV',\n\n a single keyword or phrase to describe the primary act taking place in the last chat message,\n\n keywords to describe {{char}}'s physical appearance and facial expression,\n keywords to describe {{char}}'s actions,\n keywords to describe {{user}}'s physical appearance and actions.\n\n If character actions involve direct physical interaction with another character, mention specifically which body parts interacting and how.\n\n A correctly formatted example response would be:\n '(location),(character list by gender),(primary action), (relative character position) POV, (character 1's description and actions), (character 2's description and actions)']",
|
||||||
|
"5": "[In the next response I want you to provide only a detailed comma-delimited list of keywords and phrases which describe {{char}}. The list must include all of the following items in this order: name, species and race, gender, age, facial features and expressions, occupation, hair and hair accessories (if any), what they are wearing on their upper body (if anything). Do not describe anything below their neck. Do not include descriptions of non-visual qualities such as personality, movements, scents, mental traits, or anything which could not be seen in a still photograph. Do not write in full sentences. Prefix your description with the phrase 'close up facial portrait,']"
|
||||||
|
},
|
||||||
|
"character_prompts": {}
|
||||||
},
|
},
|
||||||
"chromadb": {},
|
"chromadb": {},
|
||||||
"translate": {
|
"translate": {
|
||||||
@@ -237,7 +258,15 @@
|
|||||||
"provider": "google",
|
"provider": "google",
|
||||||
"auto_mode": "none"
|
"auto_mode": "none"
|
||||||
},
|
},
|
||||||
"objective": {},
|
"objective": {
|
||||||
|
"customPrompts": {
|
||||||
|
"default": {
|
||||||
|
"createTask": "Pause your roleplay and generate a list of tasks to complete an objective. Your next response must be formatted as a numbered list of plain text entries. Do not include anything but the numbered list. The list must be prioritized in the order that tasks must be completed.\n\nThe objective that you must make a numbered task list for is: [{{objective}}].\nThe tasks created should take into account the character traits of {{char}}. These tasks may or may not involve {{user}} directly. Be sure to include the objective as the final task.\n\nGiven an example objective of 'Make me a four course dinner', here is an example output:\n1. Determine what the courses will be\n2. Find recipes for each course\n3. Go shopping for supplies with {{user}}\n4. Cook the food\n5. Get {{user}} to set the table\n6. Serve the food\n7. Enjoy eating the meal with {{user}}\n ",
|
||||||
|
"checkTaskCompleted": "Pause your roleplay. Determine if this task is completed: [{{task}}].\nTo do this, examine the most recent messages. Your response must only contain either true or false, nothing other words.\nExample output:\ntrue\n ",
|
||||||
|
"currentTask": "Your current task is [{{task}}]. Balance existing roleplay with completing this task."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"quickReply": {
|
"quickReply": {
|
||||||
"quickReplyEnabled": false,
|
"quickReplyEnabled": false,
|
||||||
"numberOfSlots": 5,
|
"numberOfSlots": 5,
|
||||||
@@ -273,6 +302,14 @@
|
|||||||
"controls": [],
|
"controls": [],
|
||||||
"fluctuation": 0.1,
|
"fluctuation": 0.1,
|
||||||
"enabled": false
|
"enabled": false
|
||||||
|
},
|
||||||
|
"speech_recognition": {
|
||||||
|
"currentProvider": "None",
|
||||||
|
"messageMode": "append",
|
||||||
|
"messageMappingText": "",
|
||||||
|
"messageMapping": [],
|
||||||
|
"messageMappingEnabled": false,
|
||||||
|
"None": {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"context_settings": {
|
"context_settings": {
|
||||||
@@ -296,33 +333,46 @@
|
|||||||
"1345561466591"
|
"1345561466591"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"temp_novel": 1.11,
|
"nai_settings": {
|
||||||
"rep_pen_novel": 1.11,
|
"temperature": 0.63,
|
||||||
"rep_pen_size_novel": 320,
|
"repetition_penalty": 1.148125,
|
||||||
"model_novel": "euterpe-v2",
|
"repetition_penalty_range": 2048,
|
||||||
"preset_settings_novel": "Classic-Euterpe",
|
"repetition_penalty_slope": 0.09,
|
||||||
"streaming_novel": false,
|
"repetition_penalty_frequency": 0,
|
||||||
"temp": 1,
|
"repetition_penalty_presence": 0,
|
||||||
"rep_pen": 1.1,
|
"tail_free_sampling": 0.975,
|
||||||
"rep_pen_range": 600,
|
"top_k": 0,
|
||||||
"top_p": 0.95,
|
"top_p": 0.975,
|
||||||
"top_a": 0,
|
"top_a": 1,
|
||||||
"top_k": 0,
|
"typical_p": 1,
|
||||||
"typical": 1,
|
"min_length": 1,
|
||||||
"tfs": 1,
|
"model_novel": "euterpe-v2",
|
||||||
"rep_pen_slope": 0,
|
"preset_settings_novel": "Classic-Euterpe",
|
||||||
"single_line": false,
|
"streaming_novel": false
|
||||||
"use_stop_sequence": false,
|
},
|
||||||
"streaming_kobold": false,
|
"kai_settings": {
|
||||||
"sampler_order": [
|
"temp": 1,
|
||||||
6,
|
"rep_pen": 1.1,
|
||||||
0,
|
"rep_pen_range": 600,
|
||||||
1,
|
"top_p": 0.95,
|
||||||
2,
|
"top_a": 0,
|
||||||
3,
|
"top_k": 0,
|
||||||
4,
|
"typical": 1,
|
||||||
5
|
"tfs": 1,
|
||||||
],
|
"rep_pen_slope": 0,
|
||||||
|
"single_line": false,
|
||||||
|
"use_stop_sequence": false,
|
||||||
|
"streaming_kobold": false,
|
||||||
|
"sampler_order": [
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
},
|
||||||
"preset_settings_openai": "Default",
|
"preset_settings_openai": "Default",
|
||||||
"temp_openai": "0.9",
|
"temp_openai": "0.9",
|
||||||
"freq_pen_openai": 0.7,
|
"freq_pen_openai": 0.7,
|
||||||
@@ -374,5 +424,8 @@
|
|||||||
"legacy_streaming": false,
|
"legacy_streaming": false,
|
||||||
"chat_completion_source": "openai",
|
"chat_completion_source": "openai",
|
||||||
"max_context_unlocked": false,
|
"max_context_unlocked": false,
|
||||||
"api_url_scale": ""
|
"api_url_scale": "",
|
||||||
|
"show_external_models": false,
|
||||||
|
"proxy_password": "",
|
||||||
|
"assistant_prefill": ""
|
||||||
}
|
}
|
||||||
|
61
package-lock.json
generated
61
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.9.4",
|
"version": "1.9.7",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.9.4",
|
"version": "1.9.7",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dqbd/tiktoken": "^1.0.2",
|
"@dqbd/tiktoken": "^1.0.2",
|
||||||
@@ -42,7 +42,6 @@
|
|||||||
"sentencepiece-js": "^1.1.0",
|
"sentencepiece-js": "^1.1.0",
|
||||||
"simple-git": "^3.19.1",
|
"simple-git": "^3.19.1",
|
||||||
"uniqolor": "^1.1.0",
|
"uniqolor": "^1.1.0",
|
||||||
"user-agents": "^1.0.1444",
|
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"yargs": "^17.7.1",
|
"yargs": "^17.7.1",
|
||||||
@@ -1223,14 +1222,6 @@
|
|||||||
"npm": "1.2.8000 || >= 1.4.16"
|
"npm": "1.2.8000 || >= 1.4.16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/detect-indent": {
|
|
||||||
"version": "6.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz",
|
|
||||||
"integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=8"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/detect-libc": {
|
"node_modules/detect-libc": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
|
||||||
@@ -1260,32 +1251,11 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/docopt": {
|
|
||||||
"version": "0.6.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/docopt/-/docopt-0.6.2.tgz",
|
|
||||||
"integrity": "sha512-NqTbaYeE4gA/wU1hdKFdU+AFahpDOpgGLzHP42k6H6DKExJd0A55KEVWYhL9FEmHmgeLvEU2vuKXDuU+4yToOw==",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dom-walk": {
|
"node_modules/dom-walk": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
|
||||||
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
|
||||||
},
|
},
|
||||||
"node_modules/dot-json": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/dot-json/-/dot-json-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-Pu11Prog/Yjf2lBICow82/DSV46n3a2XT1Rqt/CeuhkO1fuacF7xydYhI0SwQx2Ue0jCyLtQzgKPFEO6ewv+bQ==",
|
|
||||||
"dependencies": {
|
|
||||||
"detect-indent": "~6.0.0",
|
|
||||||
"docopt": "~0.6.2",
|
|
||||||
"underscore-keypath": "~0.0.22"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"dot-json": "bin/dot-json.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ee-first": {
|
"node_modules/ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@@ -2037,11 +2007,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
},
|
},
|
||||||
"node_modules/lodash.clonedeep": {
|
|
||||||
"version": "4.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
|
||||||
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
|
|
||||||
},
|
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
@@ -3456,19 +3421,6 @@
|
|||||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||||
},
|
},
|
||||||
"node_modules/underscore": {
|
|
||||||
"version": "1.13.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz",
|
|
||||||
"integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A=="
|
|
||||||
},
|
|
||||||
"node_modules/underscore-keypath": {
|
|
||||||
"version": "0.0.22",
|
|
||||||
"resolved": "https://registry.npmjs.org/underscore-keypath/-/underscore-keypath-0.0.22.tgz",
|
|
||||||
"integrity": "sha512-fU7aYj1J2LQd+jqdQ67AlCOZKK3Pl+VErS8fGYcgZG75XB9/bY+RLM+F2xEcKHhHNtLvqqFyXAoZQlLYfec3Xg==",
|
|
||||||
"dependencies": {
|
|
||||||
"underscore": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/uniqolor": {
|
"node_modules/uniqolor": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uniqolor/-/uniqolor-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/uniqolor/-/uniqolor-1.1.0.tgz",
|
||||||
@@ -3491,15 +3443,6 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/user-agents": {
|
|
||||||
"version": "1.0.1444",
|
|
||||||
"resolved": "https://registry.npmjs.org/user-agents/-/user-agents-1.0.1444.tgz",
|
|
||||||
"integrity": "sha512-6WXJ0RZuUKgif1rW5FN02HnpoJ8EzH6COQoXCiVStZEVPz+YnAx3iA48etY3ZD4UwueYN9ALC7j4ayHvYEh7tA==",
|
|
||||||
"dependencies": {
|
|
||||||
"dot-json": "^1.3.0",
|
|
||||||
"lodash.clonedeep": "^4.5.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/utf8-byte-length": {
|
"node_modules/utf8-byte-length": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz",
|
||||||
|
@@ -33,7 +33,6 @@
|
|||||||
"sentencepiece-js": "^1.1.0",
|
"sentencepiece-js": "^1.1.0",
|
||||||
"simple-git": "^3.19.1",
|
"simple-git": "^3.19.1",
|
||||||
"uniqolor": "^1.1.0",
|
"uniqolor": "^1.1.0",
|
||||||
"user-agents": "^1.0.1444",
|
|
||||||
"webp-converter": "2.3.2",
|
"webp-converter": "2.3.2",
|
||||||
"ws": "^8.13.0",
|
"ws": "^8.13.0",
|
||||||
"yargs": "^17.7.1",
|
"yargs": "^17.7.1",
|
||||||
@@ -51,9 +50,10 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
||||||
},
|
},
|
||||||
"version": "1.9.4",
|
"version": "1.9.7",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
|
"start-multi": "node server.js --disableCsrf",
|
||||||
"pkg": "pkg --compress Gzip --no-bytecode --public ."
|
"pkg": "pkg --compress Gzip --no-bytecode --public ."
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 1.15,
|
"temp": 1.15,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.95,
|
"top_p": 0.95,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 90,
|
|
||||||
"temp": 0.8,
|
"temp": 0.8,
|
||||||
"top_k": 28,
|
"top_k": 28,
|
||||||
"top_p": 0.94,
|
"top_p": 0.94,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.59,
|
"temp": 0.59,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.8,
|
"temp": 0.8,
|
||||||
"top_k": 100,
|
"top_k": 100,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 1.0,
|
"temp": 1.0,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
"top_k": 40,
|
"top_k": 40,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 0.43,
|
"temp": 0.43,
|
||||||
"top_p": 0.96,
|
"top_p": 0.96,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 0.65,
|
"temp": 0.65,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.51,
|
"temp": 0.51,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 1600,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 0.79,
|
"temp": 0.79,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
|
22
public/KoboldAI Settings/Deterministic.settings
Normal file
22
public/KoboldAI Settings/Deterministic.settings
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"temp": 0,
|
||||||
|
"rep_pen": 1.1,
|
||||||
|
"rep_pen_range": 2048,
|
||||||
|
"streaming_kobold": true,
|
||||||
|
"top_p": 0,
|
||||||
|
"top_a": 0,
|
||||||
|
"top_k": 1,
|
||||||
|
"typical": 1,
|
||||||
|
"tfs": 1,
|
||||||
|
"rep_pen_slope": 0.2,
|
||||||
|
"single_line": false,
|
||||||
|
"sampler_order": [
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
}
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 0.79,
|
"temp": 0.79,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 1400,
|
|
||||||
"genamt": 180,
|
|
||||||
"temp": 0.65,
|
"temp": 0.65,
|
||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.63,
|
"temp": 0.63,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.98,
|
"top_p": 0.98,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.7,
|
"temp": 0.7,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.5,
|
"top_p": 0.5,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.7,
|
"temp": 0.7,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 90,
|
|
||||||
"temp": 0.8,
|
"temp": 0.8,
|
||||||
"top_p": 0.94,
|
"top_p": 0.94,
|
||||||
"top_k": 15,
|
"top_k": 15,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.66,
|
"temp": 0.66,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.94,
|
"temp": 0.94,
|
||||||
"top_k": 12,
|
"top_k": 12,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 1.5,
|
"temp": 1.5,
|
||||||
"top_k": 85,
|
"top_k": 85,
|
||||||
"top_p": 0.24,
|
"top_p": 0.24,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 1.05,
|
"temp": 1.05,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.95,
|
"top_p": 0.95,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 1.07,
|
"temp": 1.07,
|
||||||
"top_k": 100,
|
"top_k": 100,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.44,
|
"temp": 0.44,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 1.35,
|
"temp": 1.35,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 1400,
|
|
||||||
"genamt": 80,
|
|
||||||
"temp": 1,
|
"temp": 1,
|
||||||
"top_p": 1,
|
"top_p": 1,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 200,
|
|
||||||
"temp": 1,
|
"temp": 1,
|
||||||
"top_k": 0,
|
"top_k": 0,
|
||||||
"top_p": 0.95,
|
"top_p": 0.95,
|
||||||
|
22
public/KoboldAI Settings/Storywriter-Llama2.settings
Normal file
22
public/KoboldAI Settings/Storywriter-Llama2.settings
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"temp": 0.72,
|
||||||
|
"rep_pen": 1.1,
|
||||||
|
"rep_pen_range": 4096,
|
||||||
|
"streaming_kobold": true,
|
||||||
|
"top_p": 0.73,
|
||||||
|
"top_a": 0,
|
||||||
|
"top_k": 0,
|
||||||
|
"typical": 1,
|
||||||
|
"tfs": 1,
|
||||||
|
"rep_pen_slope": 0.2,
|
||||||
|
"single_line": false,
|
||||||
|
"sampler_order": [
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
}
|
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"max_length": 2048,
|
|
||||||
"genamt": 100,
|
|
||||||
"temp": 0.72,
|
"temp": 0.72,
|
||||||
"tfs": 1,
|
"tfs": 1,
|
||||||
"top_a": 0,
|
"top_a": 0,
|
||||||
|
22
public/KoboldAI Settings/simple-proxy-for-tavern.settings
Normal file
22
public/KoboldAI Settings/simple-proxy-for-tavern.settings
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"temp": 0.65,
|
||||||
|
"rep_pen": 1.18,
|
||||||
|
"rep_pen_range": 2048,
|
||||||
|
"streaming_kobold": true,
|
||||||
|
"top_p": 0.47,
|
||||||
|
"top_a": 0,
|
||||||
|
"top_k": 42,
|
||||||
|
"typical": 1,
|
||||||
|
"tfs": 1,
|
||||||
|
"rep_pen_slope": 0,
|
||||||
|
"single_line": false,
|
||||||
|
"sampler_order": [
|
||||||
|
6,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
2,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
}
|
@@ -15,5 +15,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "aggressive",
|
"phrase_rep_pen": "aggressive",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -15,5 +15,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "medium",
|
"phrase_rep_pen": "medium",
|
||||||
"cfg_scale": 1.55,
|
"cfg_scale": 1.55,
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -16,5 +16,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "very_aggressive",
|
"phrase_rep_pen": "very_aggressive",
|
||||||
"cfg_scale": 1.3,
|
"cfg_scale": 1.3,
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -17,5 +17,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "aggressive",
|
"phrase_rep_pen": "aggressive",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -17,5 +17,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -16,5 +16,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "off",
|
"phrase_rep_pen": "off",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -15,5 +15,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "aggressive",
|
"phrase_rep_pen": "aggressive",
|
||||||
"cfg_scale": 1.825,
|
"cfg_scale": 1.825,
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "medium",
|
"phrase_rep_pen": "medium",
|
||||||
"cfg_scale": 1.35,
|
"cfg_scale": 1.35,
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
19
public/NovelAI Settings/Pro_Writer-Kayra.settings
Normal file
19
public/NovelAI Settings/Pro_Writer-Kayra.settings
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"order": [3, 4, 0],
|
||||||
|
"temperature": 1.19,
|
||||||
|
"max_length": 300,
|
||||||
|
"min_length": 1,
|
||||||
|
"top_a": 0.116,
|
||||||
|
"tail_free_sampling": 0.958,
|
||||||
|
"repetition_penalty": 1.64,
|
||||||
|
"repetition_penalty_slope": 2.12,
|
||||||
|
"repetition_penalty_frequency": 0,
|
||||||
|
"repetition_penalty_presence": 0,
|
||||||
|
"repetition_penalty_range": 2048,
|
||||||
|
"use_cache": false,
|
||||||
|
"return_full_text": false,
|
||||||
|
"prefix": "vanilla",
|
||||||
|
"phrase_rep_pen": "medium",
|
||||||
|
"cfg_scale": 1.0,
|
||||||
|
"max_context": 7800
|
||||||
|
}
|
@@ -13,5 +13,5 @@
|
|||||||
"return_full_text": false,
|
"return_full_text": false,
|
||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "aggressive",
|
"phrase_rep_pen": "aggressive",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
19
public/NovelAI Settings/Tea_Time-Kayra.settings
Normal file
19
public/NovelAI Settings/Tea_Time-Kayra.settings
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"order": [5, 0, 4],
|
||||||
|
"temperature": 1,
|
||||||
|
"max_length": 300,
|
||||||
|
"min_length": 1,
|
||||||
|
"top_a": 0.017,
|
||||||
|
"typical_p": 0.975,
|
||||||
|
"repetition_penalty": 3,
|
||||||
|
"repetition_penalty_slope": 0.09,
|
||||||
|
"repetition_penalty_frequency": 0,
|
||||||
|
"repetition_penalty_presence": 0,
|
||||||
|
"repetition_penalty_range": 7680,
|
||||||
|
"use_cache": false,
|
||||||
|
"return_full_text": false,
|
||||||
|
"prefix": "vanilla",
|
||||||
|
"phrase_rep_pen": "aggressive",
|
||||||
|
"cfg_scale": 1.0,
|
||||||
|
"max_context": 7800
|
||||||
|
}
|
@@ -14,5 +14,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "aggressive",
|
"phrase_rep_pen": "aggressive",
|
||||||
"cfg_scale": 1.3,
|
"cfg_scale": 1.3,
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -18,5 +18,5 @@
|
|||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"cfg_scale": 1,
|
"cfg_scale": 1,
|
||||||
"phrase_rep_pen": "very_light",
|
"phrase_rep_pen": "very_light",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -15,5 +15,5 @@
|
|||||||
"return_full_text": false,
|
"return_full_text": false,
|
||||||
"prefix": "vanilla",
|
"prefix": "vanilla",
|
||||||
"phrase_rep_pen": "very_aggressive",
|
"phrase_rep_pen": "very_aggressive",
|
||||||
"max_context": 8192
|
"max_context": 7800
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
"top_p": 0.9,
|
"top_p": 0.9,
|
||||||
"top_k": 20,
|
"top_k": 20,
|
||||||
"typical_p": 1,
|
"typical_p": 1,
|
||||||
"top_a": 0.75,
|
"top_a": 0,
|
||||||
"tfs": 1,
|
"tfs": 1,
|
||||||
"epsilon_cutoff": 0,
|
"epsilon_cutoff": 0,
|
||||||
"eta_cutoff": 0,
|
"eta_cutoff": 0,
|
||||||
|
23
public/TextGen Settings/simple-proxy-for-tavern.settings
Normal file
23
public/TextGen Settings/simple-proxy-for-tavern.settings
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"temp": 0.65,
|
||||||
|
"top_p": 0.47,
|
||||||
|
"top_k": 42,
|
||||||
|
"typical_p": 1,
|
||||||
|
"top_a": 0,
|
||||||
|
"tfs": 1,
|
||||||
|
"epsilon_cutoff": 0,
|
||||||
|
"eta_cutoff": 0,
|
||||||
|
"rep_pen": 1.18,
|
||||||
|
"rep_pen_range": 0,
|
||||||
|
"no_repeat_ngram_size": 0,
|
||||||
|
"penalty_alpha": 0,
|
||||||
|
"num_beams": 1,
|
||||||
|
"length_penalty": 1,
|
||||||
|
"min_length": 0,
|
||||||
|
"encoder_rep_pen": 1,
|
||||||
|
"do_sample": true,
|
||||||
|
"early_stopping": false,
|
||||||
|
"mirostat_mode": 0,
|
||||||
|
"mirostat_tau": 5,
|
||||||
|
"mirostat_eta": 0.1
|
||||||
|
}
|
@@ -1523,7 +1523,7 @@
|
|||||||
"Continue": "이어서 계속",
|
"Continue": "이어서 계속",
|
||||||
"Editing:": "편집:",
|
"Editing:": "편집:",
|
||||||
"AI reply prefix": "AI 답변 접두사",
|
"AI reply prefix": "AI 답변 접두사",
|
||||||
"Custom Stopping Strings": "문장출력 중단 문자열 (KoboldAI/TextGen)",
|
"Custom Stopping Strings": "문장출력 중단 문자열 (KoboldAI/TextGen/NovelAI)",
|
||||||
"JSON serialized array of strings": "JSON 연속 문자배열",
|
"JSON serialized array of strings": "JSON 연속 문자배열",
|
||||||
"words you dont want generated separated by comma ','": "답변에 포함을 막으려는 단어 (쉼표','로 구분)",
|
"words you dont want generated separated by comma ','": "답변에 포함을 막으려는 단어 (쉼표','로 구분)",
|
||||||
"Extensions URL": "확장기능 URL",
|
"Extensions URL": "확장기능 URL",
|
||||||
|
@@ -147,7 +147,7 @@
|
|||||||
<i data-preset-manager-update="kobold" class="menu_button fa-solid fa-save" title="Update current preset" data-i18n="[title]Update current preset"></i>
|
<i data-preset-manager-update="kobold" class="menu_button fa-solid fa-save" title="Update current preset" data-i18n="[title]Update current preset"></i>
|
||||||
<i data-preset-manager-new="kobold" class="menu_button fa-solid fa-plus" title="Create new preset" data-i18n="[title]Create new preset"></i>
|
<i data-preset-manager-new="kobold" class="menu_button fa-solid fa-plus" title="Create new preset" data-i18n="[title]Create new preset"></i>
|
||||||
<i data-preset-manager-import="kobold" class="menu_button fa-solid fa-upload" title="Import preset" data-i18n="[title]Import preset"></i>
|
<i data-preset-manager-import="kobold" class="menu_button fa-solid fa-upload" title="Import preset" data-i18n="[title]Import preset"></i>
|
||||||
<i data-preset-manager-export="kobold" class="menu_button fa-solid fa-download"title="Export preset" data-i18n="[title]Export preset"></i>
|
<i data-preset-manager-export="kobold" class="menu_button fa-solid fa-download" title="Export preset" data-i18n="[title]Export preset"></i>
|
||||||
<i data-preset-manager-delete="kobold" class="menu_button fa-solid fa-trash-can" title="Delete the preset" data-i18n="[title]Delete the preset"></i>
|
<i data-preset-manager-delete="kobold" class="menu_button fa-solid fa-trash-can" title="Delete the preset" data-i18n="[title]Delete the preset"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -187,7 +187,7 @@
|
|||||||
<i data-preset-manager-update="textgenerationwebui" class="menu_button fa-solid fa-save" title="Update current preset" data-i18n="[title]Update current preset"></i>
|
<i data-preset-manager-update="textgenerationwebui" class="menu_button fa-solid fa-save" title="Update current preset" data-i18n="[title]Update current preset"></i>
|
||||||
<i data-preset-manager-new="textgenerationwebui" class="menu_button fa-solid fa-plus" title="Create new preset" data-i18n="[title]Create new preset"></i>
|
<i data-preset-manager-new="textgenerationwebui" class="menu_button fa-solid fa-plus" title="Create new preset" data-i18n="[title]Create new preset"></i>
|
||||||
<i data-preset-manager-import="textgenerationwebui" class="menu_button fa-solid fa-upload" title="Import preset" data-i18n="[title]Import preset"></i>
|
<i data-preset-manager-import="textgenerationwebui" class="menu_button fa-solid fa-upload" title="Import preset" data-i18n="[title]Import preset"></i>
|
||||||
<i data-preset-manager-export="textgenerationwebui" class="menu_button fa-solid fa-download"title="Export preset" data-i18n="[title]Export preset"></i>
|
<i data-preset-manager-export="textgenerationwebui" class="menu_button fa-solid fa-download" title="Export preset" data-i18n="[title]Export preset"></i>
|
||||||
<i data-preset-manager-delete="textgenerationwebui" class="menu_button fa-solid fa-trash-can" title="Delete the preset" data-i18n="[title]Delete the preset"></i>
|
<i data-preset-manager-delete="textgenerationwebui" class="menu_button fa-solid fa-trash-can" title="Delete the preset" data-i18n="[title]Delete the preset"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -328,7 +328,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="range-block-range-and-counter">
|
<div class="range-block-range-and-counter">
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input type="range" id="temp_novel" name="volume" min="0.1" max="2.0" step="0.01">
|
<input type="range" id="temp_novel" name="volume" min="0.1" max="2.50" step="0.01">
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-counter">
|
<div class="range-block-counter">
|
||||||
<div contenteditable="true" data-for="temp_novel" id="temp_counter_novel">
|
<div contenteditable="true" data-for="temp_novel" id="temp_counter_novel">
|
||||||
@@ -342,7 +342,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="range-block-range-and-counter">
|
<div class="range-block-range-and-counter">
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input type="range" id="rep_pen_novel" name="volume" min="1" max="1.5" step="0.01">
|
<input type="range" id="rep_pen_novel" name="volume" min="1" max="8" step="0.05">
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-counter">
|
<div class="range-block-counter">
|
||||||
<div contenteditable="true" data-for="rep_pen_novel" id="rep_pen_counter_novel">
|
<div contenteditable="true" data-for="rep_pen_novel" id="rep_pen_counter_novel">
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="range-block-range-and-counter">
|
<div class="range-block-range-and-counter">
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input type="range" id="rep_pen_freq_novel" name="volume" min="0" max="1" step="0.00001">
|
<input type="range" id="rep_pen_freq_novel" name="volume" min="0" max="1" step="0.01">
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-counter">
|
<div class="range-block-counter">
|
||||||
<div contenteditable="true" data-for="rep_pen_freq_novel" id="rep_pen_freq_counter_novel">
|
<div contenteditable="true" data-for="rep_pen_freq_novel" id="rep_pen_freq_counter_novel">
|
||||||
@@ -402,7 +402,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="range-block-range-and-counter">
|
<div class="range-block-range-and-counter">
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input type="range" id="rep_pen_presence_novel" name="volume" min="0" max="1" step="0.001">
|
<input type="range" id="rep_pen_presence_novel" name="volume" min="0" max="1" step="0.01">
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-counter">
|
<div class="range-block-counter">
|
||||||
<div contenteditable="true" data-for="rep_pen_presence_novel" id="rep_pen_presence_counter_novel">
|
<div contenteditable="true" data-for="rep_pen_presence_novel" id="rep_pen_presence_counter_novel">
|
||||||
@@ -787,26 +787,66 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block flexFlowColumn">
|
<div class="range-block flexFlowColumn">
|
||||||
<div class="range-block-title" data-i18n="Samplers Order">
|
<div class="range-block-title">
|
||||||
Samplers Order
|
<span data-i18n="Samplers Order">Samplers Order</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="toggle-description" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
<div class="toggle-description" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
||||||
Samplers will be applied in a top-down order.
|
Samplers will be applied in a top-down order.
|
||||||
Use with caution.
|
Use with caution.
|
||||||
</div>
|
</div>
|
||||||
<div id="kobold_order">
|
<div id="kobold_order">
|
||||||
<div data-id="0" data-i18n="Top K">Top K</div>
|
<div data-id="0">
|
||||||
<div data-id="1" data-i18n="Top A">Top A</div>
|
<span data-i18n="Top K">Top K</span>
|
||||||
<div data-id="2" data-i18n="Top P">Top P</div>
|
<small>0</small>
|
||||||
<div data-id="3" data-i18n="Tail Free Sampling">Tail Free Sampling</div>
|
</div>
|
||||||
<div data-id="4" data-i18n="Typical Sampling">Typical Sampling</div>
|
<div data-id="1">
|
||||||
<div data-id="5" data-i18n="Temperature">Temperature</div>
|
<span data-i18n="Top A">Top A</span>
|
||||||
<div data-id="6" data-i18n="Repetition Penalty">Repetition Penalty</div>
|
<small>1</small>
|
||||||
|
</div>
|
||||||
|
<div data-id="2">
|
||||||
|
<span data-i18n="Top P">Top P</span>
|
||||||
|
<small>2</small>
|
||||||
|
</div>
|
||||||
|
<div data-id="3">
|
||||||
|
<span data-i18n="Tail Free Sampling">Tail Free Sampling</span>
|
||||||
|
<small>3</small>
|
||||||
|
</div>
|
||||||
|
<div data-id="4">
|
||||||
|
<span data-i18n="Typical Sampling">Typical Sampling</span>
|
||||||
|
<small>4</small>
|
||||||
|
</div>
|
||||||
|
<div data-id="5">
|
||||||
|
<span data-i18n="Temperature">Temperature</span>
|
||||||
|
<small>5</small>
|
||||||
|
</div>
|
||||||
|
<div data-id="6">
|
||||||
|
<span data-i18n="Repetition Penalty">Repetition Penalty</span>
|
||||||
|
<small>6</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="samplers_order_recommended" class="menu_button menu_button_icon">
|
||||||
|
<span data-i18n="Load koboldcpp order">Load koboldcpp order</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="novel_api-settings">
|
<div id="novel_api-settings">
|
||||||
|
<div class="range-block">
|
||||||
|
<div class="range-block-title openai_restorable">
|
||||||
|
<span data-i18n="Preamble">Preamble</span>
|
||||||
|
<div id="nai_preamble_restore" title="Restore default prompt" data-i18n="[title]Restore default prompt"
|
||||||
|
class="right_menu_button">
|
||||||
|
<div class="fa-solid fa-clock-rotate-left "></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="toggle-description justifyLeft" data-i18n="Use style tags to modify the writing style of the output">
|
||||||
|
Use style tags to modify the writing style of the output
|
||||||
|
</div>
|
||||||
|
<div class="wide100p">
|
||||||
|
<textarea id="nai_preamble_textarea" class="text_pole textarea_compact" name="nai_preamble" rows="2"
|
||||||
|
placeholder=""></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="range-block">
|
<div class="range-block">
|
||||||
<div class="range-block-title" data-i18n="Top P">
|
<div class="range-block-title" data-i18n="Top P">
|
||||||
Top P
|
Top P
|
||||||
@@ -1320,12 +1360,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block" data-source="claude">
|
<div class="range-block" data-source="claude">
|
||||||
<div class="range-block-title" data-i18n="Assistant Prefill">
|
<span data-i18n="Assistant Prefill">Assistant Prefill</span>
|
||||||
Assistant Prefill
|
<textarea id="claude_assistant_prefill" class="text_pole textarea_compact" name="assistant_prefill" rows="3" maxlength="5000" placeholder="Start Claude's answer with..."></textarea>
|
||||||
</div>
|
|
||||||
<div class="wide100p">
|
|
||||||
<input type="text" id="claude_assistant_prefill" class="text_pole" placeholder="Start Claude's answer with...">
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inline-drawer wide100p">
|
<div class="inline-drawer wide100p">
|
||||||
@@ -1539,30 +1575,55 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="textgenerationwebui_api" style="display: none;position: relative;">
|
<div id="textgenerationwebui_api" style="display: none;position: relative;">
|
||||||
<div class="flex-container">
|
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||||
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
If you are using:
|
||||||
oobabooga/text-generation-webui
|
<div class="flex-container indent20p">
|
||||||
</a>
|
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
||||||
<span data-i18n="Make sure you run it with">
|
oobabooga/text-generation-webui
|
||||||
Make sure you run it with <tt>--api</tt> flag
|
</a>
|
||||||
</span>
|
<span data-i18n="Make sure you run it with">
|
||||||
</div>
|
Make sure you run it with <tt>--api</tt> flag
|
||||||
<div>
|
</span>
|
||||||
<div class="flex-container flexFlowColumn">
|
</div>
|
||||||
<div class="flex1">
|
<div class="flex-container indent20p">
|
||||||
<h4 data-i18n="Blocking API url">Blocking API url</h4>
|
<a href="https://mancer.tech/" target="_blank">
|
||||||
<small>Example: http://127.0.0.1:5000/</small>
|
Mancer AI
|
||||||
<input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
</a>
|
||||||
</div>
|
<label class="checkbox_label" for="use-mancer-api-checkbox">
|
||||||
<div class="flex1">
|
<span data-i18n="Use API key (Only required for Mancer)">
|
||||||
<h4 data-i18n="Streaming API url">Streaming API url</h4>
|
Click this box (and add your API key!):
|
||||||
<small>Example: ws://127.0.0.1:5005/api/v1/stream</small>
|
</span>
|
||||||
<input id="streaming_url_textgenerationwebui" type="text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
<input id="use-mancer-api-checkbox" type="checkbox" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div id="mancer-api-ui" style="display:none;">
|
||||||
|
<h4 data-i18n="Mancer API key">Mancer API key</h4>
|
||||||
|
<div class="flex-container">
|
||||||
|
<input id="api_key_mancer" name="api_key_mancer" class="text_pole flex1 wide100p" maxlength="500" size="35" type="text" autocomplete="off">
|
||||||
|
<div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_mancer">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input id="api_button_textgenerationwebui" class="menu_button" type="submit" value="Connect">
|
<div>
|
||||||
<div id="api_loading_textgenerationwebui" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
<div class="flex-container flexFlowColumn">
|
||||||
</div>
|
<div data-for="api_key_mancer" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page.">
|
||||||
|
For privacy reasons, your API key will be hidden after you reload the page.
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4 data-i18n="Blocking API url">Blocking API url</h4>
|
||||||
|
<small>Example: http://127.0.0.1:5000/</small>
|
||||||
|
<input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
<div class="flex1">
|
||||||
|
<h4 data-i18n="Streaming API url">Streaming API url</h4>
|
||||||
|
<small>Example: ws://127.0.0.1:5005/api/v1/stream</small>
|
||||||
|
<input id="streaming_url_textgenerationwebui" type="text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input id="api_button_textgenerationwebui" class="menu_button" type="submit" value="Connect">
|
||||||
|
<div id="api_loading_textgenerationwebui" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<div class="online_status4">
|
<div class="online_status4">
|
||||||
<div class="online_status_indicator4"></div>
|
<div class="online_status_indicator4"></div>
|
||||||
<div class="online_status_text4" data-i18n="Not connected">Not connected</div>
|
<div class="online_status_text4" data-i18n="Not connected">Not connected</div>
|
||||||
@@ -1713,6 +1774,9 @@
|
|||||||
<select id="model_openrouter_select">
|
<select id="model_openrouter_select">
|
||||||
<option data-i18n="Connect to the API">-- Connect to the API --</option>
|
<option data-i18n="Connect to the API">-- Connect to the API --</option>
|
||||||
</select>
|
</select>
|
||||||
|
<small>
|
||||||
|
Max prompt cost: <span id="openrouter_max_prompt_cost">Unknown</span> <span id="openrouter_max_prompt_cost_currency">USD</span>
|
||||||
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<h4 data-i18n="OpenRouter API Key">OpenRouter API Key</h4>
|
<h4 data-i18n="OpenRouter API Key">OpenRouter API Key</h4>
|
||||||
<div>
|
<div>
|
||||||
@@ -1809,7 +1873,7 @@
|
|||||||
<span data-i18n="Trim Incomplete Sentences">Trim Incomplete Sentences</span>
|
<span data-i18n="Trim Incomplete Sentences">Trim Incomplete Sentences</span>
|
||||||
</label>
|
</label>
|
||||||
<!-- Add margin since this is a child of above -->
|
<!-- Add margin since this is a child of above -->
|
||||||
<label style="margin-left: 1em;" class="checkbox_label" for="include_newline_checkbox">
|
<label class="checkbox_label indent20p" for="include_newline_checkbox">
|
||||||
<input id="include_newline_checkbox" type="checkbox" />
|
<input id="include_newline_checkbox" type="checkbox" />
|
||||||
<span data-i18n="Include Newline">Include Newline</span>
|
<span data-i18n="Include Newline">Include Newline</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -1818,7 +1882,7 @@
|
|||||||
Custom Chat Separator
|
Custom Chat Separator
|
||||||
</h4>
|
</h4>
|
||||||
<div>
|
<div>
|
||||||
<input id="custom_chat_separator" class="text_pole textarea_compact" type="text" placeholder="<START>" maxlength="100" />
|
<textarea id="custom_chat_separator" class="text_pole textarea_compact" type="text" placeholder="<START>" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -1853,6 +1917,10 @@
|
|||||||
<input id="instruct_names" type="checkbox" />
|
<input id="instruct_names" type="checkbox" />
|
||||||
<span data-i18n="Include Names">Include Names</span>
|
<span data-i18n="Include Names">Include Names</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label for="instruct_names_force_groups" class="checkbox_label indent20p">
|
||||||
|
<input id="instruct_names_force_groups" type="checkbox" />
|
||||||
|
<span data-i18n="Force for Groups and Personas">Force for Groups and Personas</span>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label for="instruct_presets">
|
<label for="instruct_presets">
|
||||||
<span data-i18n="Presets">Presets</span>
|
<span data-i18n="Presets">Presets</span>
|
||||||
@@ -1871,7 +1939,7 @@
|
|||||||
<span data-i18n="Input Sequence">Input Sequence</span>
|
<span data-i18n="Input Sequence">Input Sequence</span>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<input id="instruct_input_sequence" class="text_pole textarea_compact" type="text" maxlength="500" />
|
<textarea id="instruct_input_sequence" class="text_pole textarea_compact" type="text" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex1">
|
<div class="flex1">
|
||||||
@@ -1879,7 +1947,7 @@
|
|||||||
<span data-i18n="Output Sequence">Output Sequence</span>
|
<span data-i18n="Output Sequence">Output Sequence</span>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<input id="instruct_output_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" />
|
<textarea id="instruct_output_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1889,7 +1957,7 @@
|
|||||||
<small data-i18n="System Sequence">System Sequence</small>
|
<small data-i18n="System Sequence">System Sequence</small>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<input id="instruct_system_sequence" class="text_pole textarea_compact" type="text" maxlength="500" />
|
<textarea id="instruct_system_sequence" class="text_pole textarea_compact" type="text" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex1">
|
<div class="flex1">
|
||||||
@@ -1897,7 +1965,7 @@
|
|||||||
<small data-i18n="Stop Sequence">Stop Sequence</small>
|
<small data-i18n="Stop Sequence">Stop Sequence</small>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<input id="instruct_stop_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" />
|
<textarea id="instruct_stop_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex1">
|
<div class="flex1">
|
||||||
@@ -1905,7 +1973,7 @@
|
|||||||
<small data-i18n="Separator">Separator</small>
|
<small data-i18n="Separator">Separator</small>
|
||||||
</label>
|
</label>
|
||||||
<div>
|
<div>
|
||||||
<input id="instruct_separator_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" />
|
<textarea id="instruct_separator_sequence" class="text_pole wide100p textarea_compact" type="text" maxlength="500" rows="1"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1920,6 +1988,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</h4>
|
</h4>
|
||||||
<select id="tokenizer">
|
<select id="tokenizer">
|
||||||
|
<option value="99">Best match (recommended)</option>
|
||||||
<option value="0">None / Estimated</option>
|
<option value="0">None / Estimated</option>
|
||||||
<option value="1">GPT-3 (OpenAI)</option>
|
<option value="1">GPT-3 (OpenAI)</option>
|
||||||
<option value="2">GPT-3 (Alternative / Classic)</option>
|
<option value="2">GPT-3 (Alternative / Classic)</option>
|
||||||
@@ -1984,7 +2053,7 @@
|
|||||||
</label>
|
</label>
|
||||||
<h4>
|
<h4>
|
||||||
<span data-i18n="Custom Stopping Strings">
|
<span data-i18n="Custom Stopping Strings">
|
||||||
Custom Stopping Strings (KoboldAI/TextGen)
|
Custom Stopping Strings (KoboldAI/TextGen/NovelAI)
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<small>
|
<small>
|
||||||
@@ -1996,6 +2065,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<textarea id="custom_stopping_strings" rows="2" class="text_pole textarea_compact" placeholder="["Ford", "BMW", "Fiat"]"></textarea>
|
<textarea id="custom_stopping_strings" rows="2" class="text_pole textarea_compact" placeholder="["Ford", "BMW", "Fiat"]"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<label class="checkbox_label" for="custom_stopping_strings_macro">
|
||||||
|
<input id="custom_stopping_strings_macro" type="checkbox" checked>
|
||||||
|
<span data-i18n="Replace Macro in Custom Stopping Strings">
|
||||||
|
Replace Macro in Custom Stopping Strings
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
<h4>
|
<h4>
|
||||||
<span data-i18n="Pygmalion Formatting">
|
<span data-i18n="Pygmalion Formatting">
|
||||||
Pygmalion Formatting
|
Pygmalion Formatting
|
||||||
@@ -2145,14 +2220,12 @@
|
|||||||
Match whole words
|
Match whole words
|
||||||
</small>
|
</small>
|
||||||
</label>
|
</label>
|
||||||
<label title="Alert if your world info is greater than the allocated budget."
|
<label title="Alert if your world info is greater than the allocated budget." data-i18n="[title]Alert if your world info is greater than the allocated budget." class="checkbox_label">
|
||||||
data-i18n="[title]Alert if your world info is greater than the allocated budget."
|
<input id="world_info_overflow_alert" type="checkbox" />
|
||||||
class="checkbox_label">
|
<small data-i18n="Alert On Overflow">
|
||||||
<input id="world_info_overflow_alert" type="checkbox" />
|
Alert On Overflow
|
||||||
<small data-i18n="Alert On Overflow">
|
</small>
|
||||||
Alert On Overflow
|
</label>
|
||||||
</small>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -2433,11 +2506,11 @@
|
|||||||
<div id="power-user-options-block" class="flex-container drawer33pWidth">
|
<div id="power-user-options-block" class="flex-container drawer33pWidth">
|
||||||
<div id="power-user-option-checkboxes">
|
<div id="power-user-option-checkboxes">
|
||||||
<h4 data-i18n="Power User Options">Power User Options</h4>
|
<h4 data-i18n="Power User Options">Power User Options</h4>
|
||||||
<label for="swipes-checkbox">
|
<label class="checkbox_label" for="swipes-checkbox">
|
||||||
<input id="swipes-checkbox" type="checkbox" />
|
<input id="swipes-checkbox" type="checkbox" />
|
||||||
<span data-i18n="Swipes">Swipes</span>
|
<span data-i18n="Swipes">Swipes</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="fuzzy_search_checkbox">
|
<label class="checkbox_label" for="fuzzy_search_checkbox">
|
||||||
<input id="fuzzy_search_checkbox" type="checkbox" />
|
<input id="fuzzy_search_checkbox" type="checkbox" />
|
||||||
<span data-i18n="Advanced Character Search">Advanced Character Search</span>
|
<span data-i18n="Advanced Character Search">Advanced Character Search</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -2455,13 +2528,15 @@
|
|||||||
Press "Send" to continue
|
Press "Send" to continue
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="auto-load-chat-checkbox"><input id="auto-load-chat-checkbox" type="checkbox" />
|
<label class="checkbox_label" for="auto-load-chat-checkbox">
|
||||||
|
<input id="auto-load-chat-checkbox" type="checkbox" />
|
||||||
<span data-i18n="Auto-load Last Chat">Auto-load Last Chat</span>
|
<span data-i18n="Auto-load Last Chat">Auto-load Last Chat</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="auto_save_msg_edits"><input id="auto_save_msg_edits" type="checkbox" />
|
<label class="checkbox_label" for="auto_save_msg_edits">
|
||||||
|
<input id="auto_save_msg_edits" type="checkbox" />
|
||||||
<span data-i18n="Auto-save Message Edits">Auto-save Message Edits</span>
|
<span data-i18n="Auto-save Message Edits">Auto-save Message Edits</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="auto_fix_generated_markdown">
|
<label class="checkbox_label" for="auto_fix_generated_markdown">
|
||||||
<input id="auto_fix_generated_markdown" type="checkbox" />
|
<input id="auto_fix_generated_markdown" type="checkbox" />
|
||||||
<span data-i18n="Auto-fix Markdown">Auto-fix Markdown</span>
|
<span data-i18n="Auto-fix Markdown">Auto-fix Markdown</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -2473,36 +2548,45 @@
|
|||||||
<input id="allow_name1_display" type="checkbox" />
|
<input id="allow_name1_display" type="checkbox" />
|
||||||
<span data-i18n="Allow {{user}}: in bot messages">Show {{user}}: in responses</span>
|
<span data-i18n="Allow {{user}}: in bot messages">Show {{user}}: in responses</span>
|
||||||
</label>
|
</label>
|
||||||
<!-- <label class="checkbox_label" for="removeXML">
|
<label class="checkbox_label" for="encode_tags">
|
||||||
<input id="removeXML" type="checkbox" />
|
<input id="encode_tags" type="checkbox" />
|
||||||
<span data-i18n="Remove XML/HTML tags from responses">Remove <tags> from responses</span>
|
<span data-i18n="Show tags in responses">Show <tags> in responses</span>
|
||||||
</label> -->
|
</label>
|
||||||
<label for="console_log_prompts">
|
<label class="checkbox_label" for="console_log_prompts">
|
||||||
<input id="console_log_prompts" type="checkbox" />
|
<input id="console_log_prompts" type="checkbox" />
|
||||||
<span data-i18n="Log prompts to console">Log prompts to console</span>
|
<span data-i18n="Log prompts to console">Log prompts to console</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="render_formulas">
|
<label class="checkbox_label" for="render_formulas">
|
||||||
<input id="render_formulas" type="checkbox" />
|
<input id="render_formulas" type="checkbox" />
|
||||||
<span data-i18n="Render Formulas">Render Formulas</span>
|
<span data-i18n="Render Formulas">Render Formulas</span>
|
||||||
<a href="https://docs.sillytavern.app/usage/core-concepts/uicustomization/#formulas-rendering" class="notes-link" target="_blank">
|
<a href="https://docs.sillytavern.app/usage/core-concepts/uicustomization/#formulas-rendering" class="notes-link" target="_blank">
|
||||||
<span class="note-link-span">?</span>
|
<span class="note-link-span">?</span>
|
||||||
</a>
|
</a>
|
||||||
</label>
|
</label>
|
||||||
<label for="never_resize_avatars"><input id="never_resize_avatars" type="checkbox" />
|
<label class="checkbox_label" for="never_resize_avatars">
|
||||||
|
<input id="never_resize_avatars" type="checkbox" />
|
||||||
<span data-i18n="Never resize avatars">Never resize avatars</span>
|
<span data-i18n="Never resize avatars">Never resize avatars</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="show_card_avatar_urls"><input id="show_card_avatar_urls" type="checkbox" />
|
<label class="checkbox_label" for="show_card_avatar_urls">
|
||||||
|
<input id="show_card_avatar_urls" type="checkbox" />
|
||||||
<span data-i18n="Show avatar filenames">Show avatar filenames</span>
|
<span data-i18n="Show avatar filenames">Show avatar filenames</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="import_card_tags"><input id="import_card_tags" type="checkbox" />
|
<label class="checkbox_label" for="import_card_tags">
|
||||||
|
<input id="import_card_tags" type="checkbox" />
|
||||||
<span data-i18n="Import Card Tags">Import Card Tags</span>
|
<span data-i18n="Import Card Tags">Import Card Tags</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="confirm_message_delete"><input id="confirm_message_delete" type="checkbox" />
|
<label class="checkbox_label" for="confirm_message_delete">
|
||||||
|
<input id="confirm_message_delete" type="checkbox" />
|
||||||
<span data-i18n="Confirm message deletion">Confirm message deletion</span>
|
<span data-i18n="Confirm message deletion">Confirm message deletion</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="spoiler_free_mode"><input id="spoiler_free_mode" type="checkbox" />
|
<label class="checkbox_label" for="spoiler_free_mode">
|
||||||
|
<input id="spoiler_free_mode" type="checkbox" />
|
||||||
<span data-i18n="Spoiler Free Mode">Spoiler Free Mode</span>
|
<span data-i18n="Spoiler Free Mode">Spoiler Free Mode</span>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="checkbox_label" for="relaxed_api_urls" title="Reduce the formatting requirements on API URLS">
|
||||||
|
<input id="relaxed_api_urls" type="checkbox" />
|
||||||
|
<span data-i18n="Relaxed API URLS">Relaxed API URLS</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div class="inline-drawer wide100p flexFlowColumn">
|
<div class="inline-drawer wide100p flexFlowColumn">
|
||||||
<div class="inline-drawer-toggle inline-drawer-header">
|
<div class="inline-drawer-toggle inline-drawer-header">
|
||||||
@@ -2625,16 +2709,24 @@
|
|||||||
<option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option>
|
<option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="range-block">
|
||||||
|
<label for="persona_show_notifications" class="checkbox_label">
|
||||||
|
<input id="persona_show_notifications" type="checkbox" />
|
||||||
|
<span data-i18n="Show Notifications Show notifications on switching personas">
|
||||||
|
Show notifications on switching personas
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex1">
|
<div class="flex1">
|
||||||
<h4 data-i18n="Your Avatar" class="title_restorable">
|
<h4 class="title_restorable">
|
||||||
<span>Your Persona</span>
|
<span data-i18n="Your Persona">Your Persona</span>
|
||||||
<button class="menu_button menu_button_icon user_stats_button" title="Click for stats!">
|
<button class="menu_button menu_button_icon user_stats_button" title="Click for stats!">
|
||||||
<i class="fa-solid fa-circle-info"></i>Usage Stats
|
<i class="fa-solid fa-circle-info"></i><span data-i18n="Usage Stats">Usage Stats</span>
|
||||||
</button>
|
</button>
|
||||||
<div id="create_dummy_persona" class="menu_button menu_button_icon" title="Create a dummy persona" data-i18n="[title]Create a dummy persona">
|
<div id="create_dummy_persona" class="menu_button menu_button_icon" title="Create a dummy persona" data-i18n="[title]Create a dummy persona">
|
||||||
<i class="fa-solid fa-person-circle-question fa-fw"></i>
|
<i class="fa-solid fa-person-circle-question fa-fw"></i>
|
||||||
<span>Blank</span>
|
<span data-i18n="Blank">Blank</span>
|
||||||
</div>
|
</div>
|
||||||
</h4>
|
</h4>
|
||||||
<div id="user_avatar_block">
|
<div id="user_avatar_block">
|
||||||
@@ -3262,7 +3354,7 @@
|
|||||||
<div title="Rename chat file" class="renameChatButton fa-solid fa-pen" data-i18n="[title]Rename chat file"></div>
|
<div title="Rename chat file" class="renameChatButton fa-solid fa-pen" data-i18n="[title]Rename chat file"></div>
|
||||||
<div title="Export JSONL chat file" data-format="jsonl" class="exportRawChatButton fa-solid fa-file-export" data-i18n="[title]Export JSONL chat file"></div>
|
<div title="Export JSONL chat file" data-format="jsonl" class="exportRawChatButton fa-solid fa-file-export" data-i18n="[title]Export JSONL chat file"></div>
|
||||||
<div title="Download chat as plain text document" data-format="txt" class="exportChatButton fa-solid fa-file-lines" data-i18n="[title]Download chat as plain text document"></div>
|
<div title="Download chat as plain text document" data-format="txt" class="exportChatButton fa-solid fa-file-lines" data-i18n="[title]Download chat as plain text document"></div>
|
||||||
<div title="Delete chat file" file_name="" class="PastChat_cross fa-solid fa-circle-xmark" data-i18n="[title]Delete chat file"></div>
|
<div title="Delete chat file" file_name="" class="PastChat_cross fa-solid fa-skull" data-i18n="[title]Delete chat file"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3624,7 +3716,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="hotswap_template" class="template_element">
|
<div id="hotswap_template" class="template_element">
|
||||||
<div class="hotswapAvatar">
|
<div class="hotswapAvatar" title="Add a character/group to favorites to display it here!">
|
||||||
<img src="/img/ai4.png">
|
<img src="/img/ai4.png">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -3782,11 +3874,11 @@
|
|||||||
<!-- popups live outside sheld to avoid blur conflicts -->
|
<!-- popups live outside sheld to avoid blur conflicts -->
|
||||||
<div id="options" class="font-family-reset" style="display: none;">
|
<div id="options" class="font-family-reset" style="display: none;">
|
||||||
<div class="options-content">
|
<div class="options-content">
|
||||||
<a id="option_close_chat">
|
<a id="option_close_chat" class="displayNone">
|
||||||
<i class="fa-lg fa-solid fa-times"></i>
|
<i class="fa-lg fa-solid fa-times"></i>
|
||||||
<span data-i18n="Close chat">Close chat</span>
|
<span data-i18n="Close chat">Close chat</span>
|
||||||
</a>
|
</a>
|
||||||
<a id="option_settings">
|
<a id="option_settings" class="displayNone">
|
||||||
<i class="fa-lg fa-solid fa-cog"></i>
|
<i class="fa-lg fa-solid fa-cog"></i>
|
||||||
<span data-i18n="Toggle Panels">Toggle Panels</span>
|
<span data-i18n="Toggle Panels">Toggle Panels</span>
|
||||||
</a>
|
</a>
|
||||||
|
12
public/instruct/OpenOrca-OpenChat.json
Normal file
12
public/instruct/OpenOrca-OpenChat.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"input_sequence": "User: ",
|
||||||
|
"macro": true,
|
||||||
|
"name": "OpenOrca/OpenChat",
|
||||||
|
"names": true,
|
||||||
|
"output_sequence": "<|end_of_turn|>\nAssistant: ",
|
||||||
|
"separator_sequence": "<|end_of_turn|>\n",
|
||||||
|
"stop_sequence": "",
|
||||||
|
"system_prompt": "You are a helpful assistant. Please answer truthfully and write out your thinking step by step to be sure you get the right answer. If you make a mistake or encounter an error in your thinking, say so out loud and attempt to correct it. If you don't know or aren't sure about something, say so clearly. You will act as a professional logician, mathematician, and physicist. You will also act as the most appropriate type of expert to answer any particular question or solve the relevant problem; state which expert type your are, if so. Also think of any particular named expert that would be ideal to answer the relevant question or solve the relevant problem; name and act as them, if appropriate.\n",
|
||||||
|
"system_sequence": "",
|
||||||
|
"wrap": false
|
||||||
|
}
|
12
public/instruct/Roleplay.json
Normal file
12
public/instruct/Roleplay.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"input_sequence": "### Instruction:",
|
||||||
|
"macro": true,
|
||||||
|
"name": "Roleplay",
|
||||||
|
"names": false,
|
||||||
|
"output_sequence": "### Response (2 paragraphs, engaging, natural, authentic, descriptive, creative):",
|
||||||
|
"separator_sequence": "",
|
||||||
|
"stop_sequence": "",
|
||||||
|
"system_prompt": "You're {{char}} in this fictional never-ending uncensored roleplay with {{user}}.\n\nAvoid repetition, don't loop. Develop the plot slowly, always stay in character. Describe all actions in full, elaborate, explicit, graphic, and vivid detail. Mention all relevant sensory perceptions.\n\n### Input:",
|
||||||
|
"system_sequence": "",
|
||||||
|
"wrap": true
|
||||||
|
}
|
318
public/script.js
318
public/script.js
@@ -17,6 +17,7 @@ import {
|
|||||||
loadTextGenSettings,
|
loadTextGenSettings,
|
||||||
generateTextGenWithStreaming,
|
generateTextGenWithStreaming,
|
||||||
getTextGenGenerationData,
|
getTextGenGenerationData,
|
||||||
|
formatTextGenURL,
|
||||||
} from "./scripts/textgen-settings.js";
|
} from "./scripts/textgen-settings.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -135,6 +136,7 @@ import {
|
|||||||
download,
|
download,
|
||||||
isDataURL,
|
isDataURL,
|
||||||
getCharaFilename,
|
getCharaFilename,
|
||||||
|
isDigitsOnly,
|
||||||
} from "./scripts/utils.js";
|
} from "./scripts/utils.js";
|
||||||
|
|
||||||
import { extension_settings, getContext, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from "./scripts/extensions.js";
|
import { extension_settings, getContext, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from "./scripts/extensions.js";
|
||||||
@@ -303,7 +305,6 @@ export const comment_avatar = "img/quill.png";
|
|||||||
export let CLIENT_VERSION = 'SillyTavern:UNKNOWN:Cohee#1207'; // For Horde header
|
export let CLIENT_VERSION = 'SillyTavern:UNKNOWN:Cohee#1207'; // For Horde header
|
||||||
let is_colab = false;
|
let is_colab = false;
|
||||||
let is_checked_colab = false;
|
let is_checked_colab = false;
|
||||||
let is_mes_reload_avatar = false;
|
|
||||||
let optionsPopper = Popper.createPopper(document.getElementById('options_button'), document.getElementById('options'), {
|
let optionsPopper = Popper.createPopper(document.getElementById('options_button'), document.getElementById('options'), {
|
||||||
placement: 'top-start'
|
placement: 'top-start'
|
||||||
});
|
});
|
||||||
@@ -363,10 +364,10 @@ const system_messages = {
|
|||||||
mes:
|
mes:
|
||||||
`Hello there! Please select the help topic you would like to learn more about:
|
`Hello there! Please select the help topic you would like to learn more about:
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="javascript:displayHelp('1')">Slash Commands</a> (or <tt>/help slash</tt>)</li>
|
<li><a href="#" data-displayHelp="1">Slash Commands</a> (or <tt>/help slash</tt>)</li>
|
||||||
<li><a href="javascript:displayHelp('2')">Formatting</a> (or <tt>/help format</tt>)</li>
|
<li><a href="#" data-displayHelp="2">Formatting</a> (or <tt>/help format</tt>)</li>
|
||||||
<li><a href="javascript:displayHelp('3')">Hotkeys</a> (or <tt>/help hotkeys</tt>)</li>
|
<li><a href="#" data-displayHelp="3">Hotkeys</a> (or <tt>/help hotkeys</tt>)</li>
|
||||||
<li><a href="javascript:displayHelp('4')">{{Macros}}</a> (or <tt>/help macros</tt>)</li>
|
<li><a href="#" data-displayHelp="4">{{Macros}}</a> (or <tt>/help macros</tt>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
<br><b>Still got questions left? The <a target="_blank" href="https://docs.sillytavern.app/">Official SillyTavern Documentation Website</a> has much more information!</b>`
|
<br><b>Still got questions left? The <a target="_blank" href="https://docs.sillytavern.app/">Official SillyTavern Documentation Website</a> has much more information!</b>`
|
||||||
},
|
},
|
||||||
@@ -408,12 +409,25 @@ const system_messages = {
|
|||||||
mes:
|
mes:
|
||||||
`Text formatting commands:
|
`Text formatting commands:
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>{{text}}</tt> - sets a one-time behavioral bias for the AI. Resets when you send the next message.</li>
|
|
||||||
<li><tt>*text*</tt> - displays as <i>italics</i></li>
|
<li><tt>*text*</tt> - displays as <i>italics</i></li>
|
||||||
<li><tt>**text**</tt> - displays as <b>bold</b></li>
|
<li><tt>**text**</tt> - displays as <b>bold</b></li>
|
||||||
<li><tt>***text***</tt> - displays as <b><i>bold italics</i></b></li>
|
<li><tt>***text***</tt> - displays as <b><i>bold italics</i></b></li>
|
||||||
<li><tt>` + "```" + `text` + "```" + `</tt> - displays as a code block</li>
|
<li><tt>` + "```" + `text` + "```" + `</tt> - displays as a code block (new lines allowed between the backticks)</li>
|
||||||
<li><tt>` + "`" + `text` + "`" + `</tt> - displays as inline code</li>
|
<pre>
|
||||||
|
<code>
|
||||||
|
like
|
||||||
|
this
|
||||||
|
</code>
|
||||||
|
</pre>
|
||||||
|
<li><tt>` + "`" + `text` + "`" + `</tt> - displays as <code>inline code</code></li>
|
||||||
|
<li><tt>` + "> " + `text` + `</tt> - displays as a blockquote (note the space after >)</li>
|
||||||
|
<blockquote>like this</blockquote>
|
||||||
|
<li><tt>` + "# " + `text` + `</tt> - displays as a large header (note the space)</li>
|
||||||
|
<h1>like this</h1>
|
||||||
|
<li><tt>` + "## " + `text` + `</tt> - displays as a medium header (note the space)</li>
|
||||||
|
<h2>like this</h2>
|
||||||
|
<li><tt>` + "### " + `text` + `</tt> - displays as a small header (note the space)</li>
|
||||||
|
<h3>like this</h3>
|
||||||
<li><tt>$$ text $$</tt> - renders a LaTeX formula (if enabled)</li>
|
<li><tt>$$ text $$</tt> - renders a LaTeX formula (if enabled)</li>
|
||||||
<li><tt>$ text $</tt> - renders an AsciiMath formula (if enabled)</li>
|
<li><tt>$ text $</tt> - renders an AsciiMath formula (if enabled)</li>
|
||||||
</ul>`
|
</ul>`
|
||||||
@@ -523,7 +537,11 @@ const system_messages = {
|
|||||||
|
|
||||||
$(document).ajaxError(function myErrorHandler(_, xhr) {
|
$(document).ajaxError(function myErrorHandler(_, xhr) {
|
||||||
if (xhr.status == 403) {
|
if (xhr.status == 403) {
|
||||||
toastr.warning("doubleCsrf errors in console are NORMAL in this case. Just reload the page or close this tab.", "Looks like you've opened SillyTavern in another browser tab", { timeOut: 0, extendedTimeOut: 0, preventDuplicates: true });
|
toastr.warning(
|
||||||
|
"doubleCsrf errors in console are NORMAL in this case. If you want to run ST in multiple tabs, start the server with --disableCsrf option.",
|
||||||
|
"Looks like you've opened SillyTavern in another browser tab",
|
||||||
|
{ timeOut: 0, extendedTimeOut: 0, preventDuplicates: true },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -545,8 +563,27 @@ async function getClientVersion() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTokenizerBestMatch() {
|
||||||
|
if (main_api === 'novel') {
|
||||||
|
if (nai_settings.model_novel.includes('krake') || nai_settings.model_novel.includes('euterpe')) {
|
||||||
|
return tokenizers.CLASSIC;
|
||||||
|
}
|
||||||
|
if (nai_settings.model_novel.includes('clio')) {
|
||||||
|
return tokenizers.NERD;
|
||||||
|
}
|
||||||
|
if (nai_settings.model_novel.includes('kayra')) {
|
||||||
|
return tokenizers.NERD2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (main_api === 'kobold' || main_api === 'textgenerationwebui' || main_api === 'koboldhorde') {
|
||||||
|
return tokenizers.LLAMA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return power_user.NONE;
|
||||||
|
}
|
||||||
|
|
||||||
function getTokenCount(str, padding = undefined) {
|
function getTokenCount(str, padding = undefined) {
|
||||||
if (typeof str !== 'string') {
|
if (typeof str !== 'string' || !str?.length) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,6 +599,10 @@ function getTokenCount(str, padding = undefined) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tokenizerType === tokenizers.BEST_MATCH) {
|
||||||
|
tokenizerType = getTokenizerBestMatch();
|
||||||
|
}
|
||||||
|
|
||||||
if (padding === undefined) {
|
if (padding === undefined) {
|
||||||
padding = 0;
|
padding = 0;
|
||||||
}
|
}
|
||||||
@@ -603,11 +644,42 @@ function countTokensRemote(endpoint, str, padding) {
|
|||||||
return tokenCount + padding;
|
return tokenCount + padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getTextTokensRemote(endpoint, str) {
|
||||||
|
let ids = [];
|
||||||
|
jQuery.ajax({
|
||||||
|
async: false,
|
||||||
|
type: 'POST',
|
||||||
|
url: endpoint,
|
||||||
|
data: JSON.stringify({ text: str }),
|
||||||
|
dataType: "json",
|
||||||
|
contentType: "application/json",
|
||||||
|
success: function (data) {
|
||||||
|
ids = data.ids;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTextTokens(tokenizerType, str) {
|
||||||
|
switch (tokenizerType) {
|
||||||
|
case tokenizers.LLAMA:
|
||||||
|
return getTextTokensRemote('/tokenize_llama', str);
|
||||||
|
case tokenizers.NERD:
|
||||||
|
return getTextTokensRemote('/tokenize_nerdstash', str);
|
||||||
|
case tokenizers.NERD2:
|
||||||
|
return getTextTokensRemote('/tokenize_nerdstash_v2', str);
|
||||||
|
default:
|
||||||
|
console.warn("Calling getTextTokens with unsupported tokenizer type", tokenizerType);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function reloadMarkdownProcessor(render_formulas = false) {
|
function reloadMarkdownProcessor(render_formulas = false) {
|
||||||
if (render_formulas) {
|
if (render_formulas) {
|
||||||
converter = new showdown.Converter({
|
converter = new showdown.Converter({
|
||||||
emoji: "true",
|
emoji: "true",
|
||||||
underline: "true",
|
underline: "true",
|
||||||
|
parseImgDimensions: "true",
|
||||||
extensions: [
|
extensions: [
|
||||||
showdownKatex(
|
showdownKatex(
|
||||||
{
|
{
|
||||||
@@ -623,6 +695,7 @@ function reloadMarkdownProcessor(render_formulas = false) {
|
|||||||
converter = new showdown.Converter({
|
converter = new showdown.Converter({
|
||||||
emoji: "true",
|
emoji: "true",
|
||||||
literalMidWordUnderscores: "true",
|
literalMidWordUnderscores: "true",
|
||||||
|
parseImgDimensions: "true",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,6 +762,7 @@ let is_get_status = false;
|
|||||||
let is_get_status_novel = false;
|
let is_get_status_novel = false;
|
||||||
let is_api_button_press = false;
|
let is_api_button_press = false;
|
||||||
let is_api_button_press_novel = false;
|
let is_api_button_press_novel = false;
|
||||||
|
let api_use_mancer_webui = false;
|
||||||
|
|
||||||
let is_send_press = false; //Send generation
|
let is_send_press = false; //Send generation
|
||||||
let add_mes_without_animation = false;
|
let add_mes_without_animation = false;
|
||||||
@@ -822,9 +896,9 @@ async function getStatus() {
|
|||||||
type: "POST", //
|
type: "POST", //
|
||||||
url: "/getstatus", //
|
url: "/getstatus", //
|
||||||
data: JSON.stringify({
|
data: JSON.stringify({
|
||||||
api_server:
|
api_server: main_api == "kobold" ? api_server : api_server_textgenerationwebui,
|
||||||
main_api == "kobold" ? api_server : api_server_textgenerationwebui,
|
|
||||||
main_api: main_api,
|
main_api: main_api,
|
||||||
|
use_mancer: main_api == "textgenerationwebui" ? api_use_mancer_webui : false,
|
||||||
}),
|
}),
|
||||||
beforeSend: function () { },
|
beforeSend: function () { },
|
||||||
cache: false,
|
cache: false,
|
||||||
@@ -851,6 +925,11 @@ async function getStatus() {
|
|||||||
kai_settings.can_use_streaming = canUseKoboldStreaming(data.koboldVersion);
|
kai_settings.can_use_streaming = canUseKoboldStreaming(data.koboldVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress.
|
||||||
|
if (online_status == "no_connection" && data.response) {
|
||||||
|
toastr.error(data.response, "API Error", { timeOut: 5000, preventDuplicates: true })
|
||||||
|
}
|
||||||
|
|
||||||
//console.log(online_status);
|
//console.log(online_status);
|
||||||
resultCheckStatus();
|
resultCheckStatus();
|
||||||
if (online_status !== "no_connection") {
|
if (online_status !== "no_connection") {
|
||||||
@@ -1190,8 +1269,10 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
|
|||||||
mes = fixMarkdown(mes);
|
mes = fixMarkdown(mes);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this_chid != undefined && !isSystem)
|
if (!isSystem && power_user.encode_tags) {
|
||||||
mes = mes.replaceAll("<", "<").replaceAll(">", ">"); //for welcome message
|
mes = mes.replaceAll("<", "<").replaceAll(">", ">");
|
||||||
|
}
|
||||||
|
|
||||||
if ((this_chid === undefined || this_chid === "invalid-safety-id") && !selected_group) {
|
if ((this_chid === undefined || this_chid === "invalid-safety-id") && !selected_group) {
|
||||||
mes = mes
|
mes = mes
|
||||||
.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>")
|
.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>")
|
||||||
@@ -1233,7 +1314,7 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if (!power_user.allow_name2_display && ch_name && !isUser && !isSystem) {
|
if (!power_user.allow_name2_display && ch_name && !isUser && !isSystem) {
|
||||||
mes = mes.replaceAll(`${ch_name}:`, "");
|
mes = mes.replace(new RegExp(`(^|\n)${ch_name}:`, 'g'), "$1");
|
||||||
}
|
}
|
||||||
|
|
||||||
//function to hide any <tags> from AI response output
|
//function to hide any <tags> from AI response output
|
||||||
@@ -1332,9 +1413,6 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
|
|||||||
const momentDate = timestampToMoment(mes.send_date);
|
const momentDate = timestampToMoment(mes.send_date);
|
||||||
const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : '';
|
const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : '';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (mes?.extra?.display_text) {
|
if (mes?.extra?.display_text) {
|
||||||
messageText = mes.extra.display_text;
|
messageText = mes.extra.display_text;
|
||||||
}
|
}
|
||||||
@@ -1364,9 +1442,6 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
|
|||||||
} else {
|
} else {
|
||||||
if (characters[this_chid].avatar != "none") {
|
if (characters[this_chid].avatar != "none") {
|
||||||
avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar);
|
avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar);
|
||||||
if (is_mes_reload_avatar !== false) {
|
|
||||||
avatarImg += "&" + is_mes_reload_avatar;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
avatarImg = default_avatar;
|
avatarImg = default_avatar;
|
||||||
}
|
}
|
||||||
@@ -1614,7 +1689,7 @@ function getTimeSinceLastMessage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function randomReplace(input, emptyListPlaceholder = '') {
|
function randomReplace(input, emptyListPlaceholder = '') {
|
||||||
const randomPattern = /{{random:([^}]+)}}/gi;
|
const randomPattern = /{{random[ : ]([^}]+)}}/gi;
|
||||||
|
|
||||||
return input.replace(randomPattern, (match, listString) => {
|
return input.replace(randomPattern, (match, listString) => {
|
||||||
const list = listString.split(',').map(item => item.trim()).filter(item => item.length > 0);
|
const list = listString.split(',').map(item => item.trim()).filter(item => item.length > 0);
|
||||||
@@ -1632,10 +1707,15 @@ function randomReplace(input, emptyListPlaceholder = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function diceRollReplace(input, invalidRollPlaceholder = '') {
|
function diceRollReplace(input, invalidRollPlaceholder = '') {
|
||||||
const randomPattern = /{{roll:([^}]+)}}/gi;
|
const rollPattern = /{{roll[ : ]([^}]+)}}/gi;
|
||||||
|
|
||||||
|
return input.replace(rollPattern, (match, matchValue) => {
|
||||||
|
let formula = matchValue.trim();
|
||||||
|
|
||||||
|
if (isDigitsOnly(formula)) {
|
||||||
|
formula = `1d${formula}`;
|
||||||
|
}
|
||||||
|
|
||||||
return input.replace(randomPattern, (match, matchValue) => {
|
|
||||||
const formula = matchValue.trim();
|
|
||||||
const isValid = droll.validate(formula);
|
const isValid = droll.validate(formula);
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
@@ -1688,7 +1768,11 @@ function getStoppingStrings(isImpersonate, addSpace) {
|
|||||||
|
|
||||||
if (power_user.custom_stopping_strings) {
|
if (power_user.custom_stopping_strings) {
|
||||||
const customStoppingStrings = getCustomStoppingStrings();
|
const customStoppingStrings = getCustomStoppingStrings();
|
||||||
result.push(...customStoppingStrings);
|
if (power_user.custom_stopping_strings_macro) {
|
||||||
|
result.push(...customStoppingStrings.map(x => substituteParams(x, name1, name2)));
|
||||||
|
} else {
|
||||||
|
result.push(...customStoppingStrings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return addSpace ? result.map(x => `${x} `) : result;
|
return addSpace ? result.map(x => `${x} `) : result;
|
||||||
@@ -1768,7 +1852,7 @@ export function extractMessageBias(message) {
|
|||||||
const match = curMatch[1].trim();
|
const match = curMatch[1].trim();
|
||||||
|
|
||||||
// Ignore random/roll pattern matches
|
// Ignore random/roll pattern matches
|
||||||
if (/^random:.+/i.test(match) || /^roll:.+/i.test(match)) {
|
if (/^random[ : ].+/i.test(match) || /^roll[ : ].+/i.test(match)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1824,7 +1908,7 @@ function getPersonaDescription(storyString) {
|
|||||||
case persona_description_positions.BEFORE_CHAR:
|
case persona_description_positions.BEFORE_CHAR:
|
||||||
return `${substituteParams(power_user.persona_description)}\n${storyString}`;
|
return `${substituteParams(power_user.persona_description)}\n${storyString}`;
|
||||||
case persona_description_positions.AFTER_CHAR:
|
case persona_description_positions.AFTER_CHAR:
|
||||||
return `${storyString}\n${substituteParams(power_user.persona_description)}`;
|
return `${storyString}${substituteParams(power_user.persona_description)}\n`;
|
||||||
default:
|
default:
|
||||||
if (shouldWIAddPrompt) {
|
if (shouldWIAddPrompt) {
|
||||||
const originalAN = extension_prompts[NOTE_MODULE_NAME].value
|
const originalAN = extension_prompts[NOTE_MODULE_NAME].value
|
||||||
@@ -2487,15 +2571,15 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (i === arrMes.length - 1 && !item.trim().startsWith(name1 + ":")) {
|
if (i === arrMes.length - 1 && !item.trim().startsWith(name1 + ":")) {
|
||||||
if (textareaText == "") {
|
//if (textareaText == "") {
|
||||||
// Cohee: I think this was added to allow the model to continue
|
// Cohee: I think this was added to allow the model to continue
|
||||||
// where it left off by removing the trailing newline at the end
|
// where it left off by removing the trailing newline at the end
|
||||||
// that was added by chat2 generator. This causes problems with
|
// that was added by chat2 generator. This causes problems with
|
||||||
// instruct mode that could not have a trailing newline. So we're
|
// instruct mode that could not have a trailing newline. So we're
|
||||||
// removing a newline ONLY at the end of the string if it exists.
|
// removing a newline ONLY at the end of the string if it exists.
|
||||||
item = item.replace(/\n?$/, '');
|
item = item.replace(/\n?$/, '');
|
||||||
//item = item.substr(0, item.length - 1);
|
//item = item.substr(0, item.length - 1);
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
if (is_pygmalion && !isInstruct) {
|
if (is_pygmalion && !isInstruct) {
|
||||||
if (item.trim().startsWith(name1)) {
|
if (item.trim().startsWith(name1)) {
|
||||||
@@ -2630,8 +2714,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
setPromtString();
|
setPromtString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add chat preamble
|
||||||
|
mesSendString = addChatsPreamble(mesSendString);
|
||||||
|
|
||||||
// add a custom dingus (if defined)
|
// add a custom dingus (if defined)
|
||||||
mesSendString = adjustChatsSeparator(mesSendString);
|
mesSendString = addChatsSeparator(mesSendString);
|
||||||
|
|
||||||
let finalPromt =
|
let finalPromt =
|
||||||
storyString +
|
storyString +
|
||||||
@@ -2684,10 +2771,11 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
}
|
}
|
||||||
else if (main_api == 'textgenerationwebui') {
|
else if (main_api == 'textgenerationwebui') {
|
||||||
generate_data = getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate);
|
generate_data = getTextGenGenerationData(finalPromt, this_amount_gen, isImpersonate);
|
||||||
|
generate_data.use_mancer = api_use_mancer_webui;
|
||||||
}
|
}
|
||||||
else if (main_api == 'novel') {
|
else if (main_api == 'novel') {
|
||||||
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
|
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
|
||||||
generate_data = getNovelGenerationData(finalPromt, this_settings, this_amount_gen);
|
generate_data = getNovelGenerationData(finalPromt, this_settings, this_amount_gen, isImpersonate);
|
||||||
}
|
}
|
||||||
else if (main_api == 'openai') {
|
else if (main_api == 'openai') {
|
||||||
let [prompt, counts] = await prepareOpenAIMessages({
|
let [prompt, counts] = await prepareOpenAIMessages({
|
||||||
@@ -2789,7 +2877,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(response.status);
|
const error = await response.json();
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -2871,7 +2960,8 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Formating
|
//Formating
|
||||||
getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue);
|
const displayIncomplete = type == 'quiet';
|
||||||
|
getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete);
|
||||||
|
|
||||||
let this_mes_is_name;
|
let this_mes_is_name;
|
||||||
({ this_mes_is_name, getMessage } = extractNameFromMessage(getMessage, force_name2, isImpersonate));
|
({ this_mes_is_name, getMessage } = extractNameFromMessage(getMessage, force_name2, isImpersonate));
|
||||||
@@ -2945,6 +3035,13 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
activateSendButtons();
|
activateSendButtons();
|
||||||
//console.log('runGenerate calling showSwipeBtns');
|
//console.log('runGenerate calling showSwipeBtns');
|
||||||
showSwipeButtons();
|
showSwipeButtons();
|
||||||
|
|
||||||
|
if (main_api == 'textgenerationwebui' && api_use_mancer_webui) {
|
||||||
|
const errorText = `<h3>Inferencer endpoint is unhappy!</h3>
|
||||||
|
Returned status <tt>${data.status}</tt> with the reason:<br/>
|
||||||
|
${data.response}`;
|
||||||
|
callPopup(errorText, 'text');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.debug('/savechat called by /Generate');
|
console.debug('/savechat called by /Generate');
|
||||||
|
|
||||||
@@ -2959,6 +3056,10 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onError(exception) {
|
function onError(exception) {
|
||||||
|
if (typeof exception?.error?.message === 'string') {
|
||||||
|
toastr.error(exception.error.message, 'Error', { timeOut: 10000, extendedTimeOut: 20000 });
|
||||||
|
}
|
||||||
|
|
||||||
reject(exception);
|
reject(exception);
|
||||||
$("#send_textarea").removeAttr('disabled');
|
$("#send_textarea").removeAttr('disabled');
|
||||||
is_send_press = false;
|
is_send_press = false;
|
||||||
@@ -3104,7 +3205,12 @@ function parseTokenCounts(counts, thisPromptBits) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function adjustChatsSeparator(mesSendString) {
|
function addChatsPreamble(mesSendString) {
|
||||||
|
const preamble = main_api === 'novel' ? nai_settings.preamble : "";
|
||||||
|
return preamble + '\n' + mesSendString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addChatsSeparator(mesSendString) {
|
||||||
if (power_user.custom_chat_separator && power_user.custom_chat_separator.length) {
|
if (power_user.custom_chat_separator && power_user.custom_chat_separator.length) {
|
||||||
mesSendString = power_user.custom_chat_separator + '\n' + mesSendString;
|
mesSendString = power_user.custom_chat_separator + '\n' + mesSendString;
|
||||||
}
|
}
|
||||||
@@ -3114,6 +3220,10 @@ function adjustChatsSeparator(mesSendString) {
|
|||||||
mesSendString = mesSendString;
|
mesSendString = mesSendString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (main_api === 'novel') {
|
||||||
|
mesSendString = '\n***\n' + mesSendString;
|
||||||
|
}
|
||||||
|
|
||||||
// add non-pygma dingus
|
// add non-pygma dingus
|
||||||
else if (!is_pygmalion) {
|
else if (!is_pygmalion) {
|
||||||
mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString;
|
mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString;
|
||||||
@@ -3227,21 +3337,20 @@ function promptItemize(itemizedPrompts, requestedMesId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//these happen regardless of API
|
//these happen regardless of API
|
||||||
var charPersonalityTokens = getTokenCount(itemizedPrompts[thisPromptSet].charPersonality);
|
|
||||||
var charDescriptionTokens = getTokenCount(itemizedPrompts[thisPromptSet].charDescription);
|
var charDescriptionTokens = getTokenCount(itemizedPrompts[thisPromptSet].charDescription);
|
||||||
|
var charPersonalityTokens = getTokenCount(itemizedPrompts[thisPromptSet].charPersonality);
|
||||||
var scenarioTextTokens = getTokenCount(itemizedPrompts[thisPromptSet].scenarioText);
|
var scenarioTextTokens = getTokenCount(itemizedPrompts[thisPromptSet].scenarioText);
|
||||||
|
var userPersonaStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].userPersona);
|
||||||
|
var worldInfoStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].worldInfoString);
|
||||||
var allAnchorsTokens = getTokenCount(itemizedPrompts[thisPromptSet].allAnchors);
|
var allAnchorsTokens = getTokenCount(itemizedPrompts[thisPromptSet].allAnchors);
|
||||||
var summarizeStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].summarizeString);
|
var summarizeStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].summarizeString);
|
||||||
var authorsNoteStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].authorsNoteString);
|
var authorsNoteStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].authorsNoteString);
|
||||||
var smartContextStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].smartContextString);
|
var smartContextStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].smartContextString);
|
||||||
var afterScenarioAnchorTokens = getTokenCount(itemizedPrompts[thisPromptSet].afterScenarioAnchor);
|
var afterScenarioAnchorTokens = getTokenCount(itemizedPrompts[thisPromptSet].afterScenarioAnchor);
|
||||||
var zeroDepthAnchorTokens = getTokenCount(itemizedPrompts[thisPromptSet].zeroDepthAnchor);
|
var zeroDepthAnchorTokens = getTokenCount(itemizedPrompts[thisPromptSet].zeroDepthAnchor);
|
||||||
var worldInfoStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].worldInfoString);
|
|
||||||
var thisPrompt_max_context = itemizedPrompts[thisPromptSet].this_max_context;
|
var thisPrompt_max_context = itemizedPrompts[thisPromptSet].this_max_context;
|
||||||
var thisPrompt_padding = itemizedPrompts[thisPromptSet].padding;
|
var thisPrompt_padding = itemizedPrompts[thisPromptSet].padding;
|
||||||
var promptBiasTokens = getTokenCount(itemizedPrompts[thisPromptSet].promptBias);
|
|
||||||
var this_main_api = itemizedPrompts[thisPromptSet].main_api;
|
var this_main_api = itemizedPrompts[thisPromptSet].main_api;
|
||||||
var userPersonaStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].userPersona);
|
|
||||||
|
|
||||||
if (this_main_api == 'openai') {
|
if (this_main_api == 'openai') {
|
||||||
//for OAI API
|
//for OAI API
|
||||||
@@ -3283,6 +3392,7 @@ function promptItemize(itemizedPrompts, requestedMesId) {
|
|||||||
var mesSendStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].mesSendString)
|
var mesSendStringTokens = getTokenCount(itemizedPrompts[thisPromptSet].mesSendString)
|
||||||
var ActualChatHistoryTokens = mesSendStringTokens - (allAnchorsTokens - afterScenarioAnchorTokens) + power_user.token_padding;
|
var ActualChatHistoryTokens = mesSendStringTokens - (allAnchorsTokens - afterScenarioAnchorTokens) + power_user.token_padding;
|
||||||
var instructionTokens = getTokenCount(itemizedPrompts[thisPromptSet].instruction);
|
var instructionTokens = getTokenCount(itemizedPrompts[thisPromptSet].instruction);
|
||||||
|
var promptBiasTokens = getTokenCount(itemizedPrompts[thisPromptSet].promptBias);
|
||||||
|
|
||||||
var totalTokensInPrompt =
|
var totalTokensInPrompt =
|
||||||
storyStringTokens + //chardefs total
|
storyStringTokens + //chardefs total
|
||||||
@@ -3720,13 +3830,15 @@ function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete
|
|||||||
getMessage = cleanGroupMessage(getMessage);
|
getMessage = cleanGroupMessage(getMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!power_user.allow_name2_display) {
|
||||||
|
getMessage = getMessage.replace(new RegExp(`(^|\n)${name2}:`, 'g'), "$1");
|
||||||
|
}
|
||||||
|
|
||||||
if (isImpersonate) {
|
if (isImpersonate) {
|
||||||
getMessage = getMessage.trim();
|
getMessage = getMessage.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
const stoppingStrings = getStoppingStrings(isImpersonate, false);
|
const stoppingStrings = getStoppingStrings(isImpersonate, false);
|
||||||
//console.log('stopping on these strings: ');
|
|
||||||
//console.log(stoppingStrings);
|
|
||||||
|
|
||||||
for (const stoppingString of stoppingStrings) {
|
for (const stoppingString of stoppingStrings) {
|
||||||
if (stoppingString.length) {
|
if (stoppingString.length) {
|
||||||
@@ -4161,9 +4273,18 @@ async function read_avatar_load(input) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#create_button").trigger('click');
|
await createOrEditCharacter();
|
||||||
|
await delay(durationSaveEdit);
|
||||||
|
|
||||||
const formData = new FormData($("#form_create").get(0));
|
const formData = new FormData($("#form_create").get(0));
|
||||||
|
await fetch(getThumbnailUrl('avatar', formData.get('avatar_url')), {
|
||||||
|
method: 'GET',
|
||||||
|
cache: 'no-cache',
|
||||||
|
headers: {
|
||||||
|
'pragma': 'no-cache',
|
||||||
|
'cache-control': 'no-cache',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$(".mes").each(async function () {
|
$(".mes").each(async function () {
|
||||||
if ($(this).attr("is_system") == 'true') {
|
if ($(this).attr("is_system") == 'true') {
|
||||||
@@ -4181,22 +4302,12 @@ async function read_avatar_load(input) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await delay(durationSaveEdit);
|
|
||||||
await fetch(getThumbnailUrl('avatar', formData.get('avatar_url')), {
|
|
||||||
method: 'GET',
|
|
||||||
cache: 'no-cache',
|
|
||||||
headers: {
|
|
||||||
'pragma': 'no-cache',
|
|
||||||
'cache-control': 'no-cache',
|
|
||||||
}
|
|
||||||
});
|
|
||||||
console.log('Avatar refreshed');
|
console.log('Avatar refreshed');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getCropPopup(src) {
|
export function getCropPopup(src) {
|
||||||
return `<h3>Set the crop position of the avatar image and click Ok to confirm.</h3>
|
return `<h3>Set the crop position of the avatar image and click Accept to confirm.</h3>
|
||||||
<div id='avatarCropWrap'>
|
<div id='avatarCropWrap'>
|
||||||
<img id='avatarToCrop' src='${src}'>
|
<img id='avatarToCrop' src='${src}'>
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -4509,7 +4620,9 @@ export function setUserName(value) {
|
|||||||
name1 = default_user_name;
|
name1 = default_user_name;
|
||||||
console.log(`User name changed to ${name1}`);
|
console.log(`User name changed to ${name1}`);
|
||||||
$("#your_name").val(name1);
|
$("#your_name").val(name1);
|
||||||
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
|
||||||
|
}
|
||||||
saveSettings("change_name");
|
saveSettings("change_name");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4608,7 +4721,7 @@ function setUserAvatar() {
|
|||||||
const personaName = power_user.personas[user_avatar];
|
const personaName = power_user.personas[user_avatar];
|
||||||
if (personaName && name1 !== personaName) {
|
if (personaName && name1 !== personaName) {
|
||||||
const lockedPersona = chat_metadata['persona'];
|
const lockedPersona = chat_metadata['persona'];
|
||||||
if (lockedPersona && lockedPersona !== user_avatar) {
|
if (lockedPersona && lockedPersona !== user_avatar && power_user.persona_show_notifications) {
|
||||||
toastr.info(
|
toastr.info(
|
||||||
`To permanently set "${personaName}" as the selected persona, unlock and relock it using the "Lock" button. Otherwise, the selection resets upon reloading the chat.`,
|
`To permanently set "${personaName}" as the selected persona, unlock and relock it using the "Lock" button. Otherwise, the selection resets upon reloading the chat.`,
|
||||||
`This chat is locked to a different persona (${power_user.personas[lockedPersona]}).`,
|
`This chat is locked to a different persona (${power_user.personas[lockedPersona]}).`,
|
||||||
@@ -4715,7 +4828,9 @@ async function setDefaultPersona() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Removing default persona ${avatarId}`);
|
console.log(`Removing default persona ${avatarId}`);
|
||||||
toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
|
||||||
|
}
|
||||||
delete power_user.default_persona;
|
delete power_user.default_persona;
|
||||||
} else {
|
} else {
|
||||||
const confirm = await callPopup(`<h3>Are you sure you want to set "${personaName}" as the default persona?</h3>
|
const confirm = await callPopup(`<h3>Are you sure you want to set "${personaName}" as the default persona?</h3>
|
||||||
@@ -4727,7 +4842,9 @@ async function setDefaultPersona() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
power_user.default_persona = avatarId;
|
power_user.default_persona = avatarId;
|
||||||
toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
@@ -4790,18 +4907,22 @@ function lockUserNameToChat() {
|
|||||||
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
|
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
|
||||||
delete chat_metadata['persona'];
|
delete chat_metadata['persona'];
|
||||||
saveMetadata();
|
saveMetadata();
|
||||||
toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
|
||||||
|
}
|
||||||
updateUserLockIcon();
|
updateUserLockIcon();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(user_avatar in power_user.personas)) {
|
if (!(user_avatar in power_user.personas)) {
|
||||||
console.log(`Creating a new persona ${user_avatar}`);
|
console.log(`Creating a new persona ${user_avatar}`);
|
||||||
toastr.info(
|
if (power_user.persona_show_notifications) {
|
||||||
'Creating a new persona for currently selected user name and avatar...',
|
toastr.info(
|
||||||
'Persona not set for this avatar',
|
'Creating a new persona for currently selected user name and avatar...',
|
||||||
{ timeOut: 10000, extendedTimeOut: 20000, },
|
'Persona not set for this avatar',
|
||||||
);
|
{ timeOut: 10000, extendedTimeOut: 20000, },
|
||||||
|
);
|
||||||
|
}
|
||||||
power_user.personas[user_avatar] = name1;
|
power_user.personas[user_avatar] = name1;
|
||||||
power_user.persona_descriptions[user_avatar] = { description: '', position: persona_description_positions.BEFORE_CHAR };
|
power_user.persona_descriptions[user_avatar] = { description: '', position: persona_description_positions.BEFORE_CHAR };
|
||||||
}
|
}
|
||||||
@@ -4810,7 +4931,9 @@ function lockUserNameToChat() {
|
|||||||
saveMetadata();
|
saveMetadata();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
console.log(`Locking persona for this chat ${user_avatar}`);
|
console.log(`Locking persona for this chat ${user_avatar}`);
|
||||||
toastr.success(`User persona is locked to ${name1} in this chat`);
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.success(`User persona is locked to ${name1} in this chat`);
|
||||||
|
}
|
||||||
updateUserLockIcon();
|
updateUserLockIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5031,11 +5154,13 @@ async function getSettings(type) {
|
|||||||
|
|
||||||
setWorldInfoSettings(settings, data);
|
setWorldInfoSettings(settings, data);
|
||||||
|
|
||||||
api_server_textgenerationwebui =
|
api_server_textgenerationwebui = settings.api_server_textgenerationwebui;
|
||||||
settings.api_server_textgenerationwebui;
|
|
||||||
$("#textgenerationwebui_api_url_text").val(
|
$("#textgenerationwebui_api_url_text").val(
|
||||||
api_server_textgenerationwebui
|
api_server_textgenerationwebui
|
||||||
);
|
);
|
||||||
|
api_use_mancer_webui = settings.api_use_mancer_webui
|
||||||
|
$('#use-mancer-api-checkbox').prop("checked", api_use_mancer_webui);
|
||||||
|
$('#use-mancer-api-checkbox').trigger("change");
|
||||||
|
|
||||||
selected_button = settings.selected_button;
|
selected_button = settings.selected_button;
|
||||||
|
|
||||||
@@ -5069,6 +5194,7 @@ async function saveSettings(type) {
|
|||||||
active_group: active_group,
|
active_group: active_group,
|
||||||
api_server: api_server,
|
api_server: api_server,
|
||||||
api_server_textgenerationwebui: api_server_textgenerationwebui,
|
api_server_textgenerationwebui: api_server_textgenerationwebui,
|
||||||
|
api_use_mancer_webui: api_use_mancer_webui,
|
||||||
preset_settings: preset_settings,
|
preset_settings: preset_settings,
|
||||||
user_avatar: user_avatar,
|
user_avatar: user_avatar,
|
||||||
amount_gen: amount_gen,
|
amount_gen: amount_gen,
|
||||||
@@ -6831,6 +6957,11 @@ function importCharacter(file) {
|
|||||||
contentType: false,
|
contentType: false,
|
||||||
processData: false,
|
processData: false,
|
||||||
success: async function (data) {
|
success: async function (data) {
|
||||||
|
if (data.error) {
|
||||||
|
toastr.error('The file is likely invalid or corrupted.', 'Could not import character');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.file_name !== undefined) {
|
if (data.file_name !== undefined) {
|
||||||
$('#character_search_bar').val('').trigger('input');
|
$('#character_search_bar').val('').trigger('input');
|
||||||
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
$("#rm_info_block").transition({ opacity: 0, duration: 0 });
|
||||||
@@ -6912,6 +7043,10 @@ function doCharListDisplaySwitch() {
|
|||||||
updateVisibleDivs('#rm_print_characters_block', true);
|
updateVisibleDivs('#rm_print_characters_block', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doCloseChat() {
|
||||||
|
$("#option_close_chat").trigger('click')
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function to handle the deletion of a character, given a specific popup type and character ID.
|
* Function to handle the deletion of a character, given a specific popup type and character ID.
|
||||||
* If popup type equals "del_ch", it will proceed with deletion otherwise it will exit the function.
|
* If popup type equals "del_ch", it will proceed with deletion otherwise it will exit the function.
|
||||||
@@ -6921,13 +7056,13 @@ function doCharListDisplaySwitch() {
|
|||||||
*
|
*
|
||||||
* @param {string} popup_type - The type of popup currently active.
|
* @param {string} popup_type - The type of popup currently active.
|
||||||
* @param {string} this_chid - The character ID to be deleted.
|
* @param {string} this_chid - The character ID to be deleted.
|
||||||
|
* @param {boolean} delete_chats - Whether to delete chats or not.
|
||||||
*/
|
*/
|
||||||
export async function handleDeleteCharacter(popup_type, this_chid) {
|
export async function handleDeleteCharacter(popup_type, this_chid, delete_chats) {
|
||||||
if (popup_type !== "del_ch") {
|
if (popup_type !== "del_ch") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const delete_chats = !!$("#del_char_checkbox").prop("checked");
|
|
||||||
const avatar = characters[this_chid].avatar;
|
const avatar = characters[this_chid].avatar;
|
||||||
const name = characters[this_chid].name;
|
const name = characters[this_chid].name;
|
||||||
|
|
||||||
@@ -6978,6 +7113,10 @@ export async function deleteCharacter(name, avatar) {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doTogglePanels() {
|
||||||
|
$("#option_settings").trigger('click')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
@@ -6992,6 +7131,9 @@ $(document).ready(function () {
|
|||||||
registerSlashCommand('api', connectAPISlash, [], "(kobold, horde, novel, ooba, oai, claude, windowai) – connect to an API", true, true);
|
registerSlashCommand('api', connectAPISlash, [], "(kobold, horde, novel, ooba, oai, claude, windowai) – connect to an API", true, true);
|
||||||
registerSlashCommand('impersonate', doImpersonate, ['imp'], "- calls an impersonation response", true, true);
|
registerSlashCommand('impersonate', doImpersonate, ['imp'], "- calls an impersonation response", true, true);
|
||||||
registerSlashCommand('delchat', doDeleteChat, [], "- deletes the current chat", true, true);
|
registerSlashCommand('delchat', doDeleteChat, [], "- deletes the current chat", true, true);
|
||||||
|
registerSlashCommand('closechat', doCloseChat, [], "- closes the current chat", true, true);
|
||||||
|
registerSlashCommand('panels', doTogglePanels, ['togglepanels'], "- toggle UI panels on/off", true, true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
@@ -7358,7 +7500,8 @@ $(document).ready(function () {
|
|||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
if (popup_type == "del_ch") {
|
if (popup_type == "del_ch") {
|
||||||
handleDeleteCharacter(popup_type, this_chid, characters);
|
const deleteChats = !!$("#del_char_checkbox").prop("checked");
|
||||||
|
await handleDeleteCharacter(popup_type, this_chid, deleteChats);
|
||||||
}
|
}
|
||||||
if (popup_type == "alternate_greeting" && menu_type !== "create") {
|
if (popup_type == "alternate_greeting" && menu_type !== "create") {
|
||||||
createOrEditCharacter();
|
createOrEditCharacter();
|
||||||
@@ -7435,7 +7578,6 @@ $(document).ready(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#add_avatar_button").change(function () {
|
$("#add_avatar_button").change(function () {
|
||||||
is_mes_reload_avatar = Date.now();
|
|
||||||
read_avatar_load(this);
|
read_avatar_load(this);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -7447,7 +7589,7 @@ $(document).ready(function () {
|
|||||||
<h3>Delete the character?</h3>
|
<h3>Delete the character?</h3>
|
||||||
<b>THIS IS PERMANENT!<br><br>
|
<b>THIS IS PERMANENT!<br><br>
|
||||||
<label for="del_char_checkbox" class="checkbox_label justifyCenter">
|
<label for="del_char_checkbox" class="checkbox_label justifyCenter">
|
||||||
<input type="checkbox" id="del_char_checkbox" checked />
|
<input type="checkbox" id="del_char_checkbox" />
|
||||||
<span>Also delete the chat files</span>
|
<span>Also delete the chat files</span>
|
||||||
</label><br></b>`
|
</label><br></b>`
|
||||||
);
|
);
|
||||||
@@ -7630,16 +7772,28 @@ $(document).ready(function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#api_button_textgenerationwebui").click(function (e) {
|
$("#use-mancer-api-checkbox").on("change", function (e) {
|
||||||
|
const enabled = $("#use-mancer-api-checkbox").prop("checked");
|
||||||
|
$("#mancer-api-ui").toggle(enabled);
|
||||||
|
api_use_mancer_webui = enabled;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
getStatus();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#api_button_textgenerationwebui").click(async function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if ($("#textgenerationwebui_api_url_text").val() != "") {
|
if ($("#textgenerationwebui_api_url_text").val() != "") {
|
||||||
let value = formatKoboldUrl($("#textgenerationwebui_api_url_text").val().trim());
|
let value = formatTextGenURL($("#textgenerationwebui_api_url_text").val().trim(), api_use_mancer_webui);
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
callPopup('Please enter a valid URL.', 'text');
|
callPopup("Please enter a valid URL.<br/>WebUI URLs should end with <tt>/api</tt><br/>Enable 'Relaxed API URLs' to allow other paths.", 'text');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mancer_key = $("#api_key_mancer").val().trim();
|
||||||
|
if (mancer_key.length) {
|
||||||
|
await writeSecret(SECRET_KEYS.MANCER, mancer_key);
|
||||||
|
}
|
||||||
|
|
||||||
$("#textgenerationwebui_api_url_text").val(value);
|
$("#textgenerationwebui_api_url_text").val(value);
|
||||||
$("#api_loading_textgenerationwebui").css("display", "inline-block");
|
$("#api_loading_textgenerationwebui").css("display", "inline-block");
|
||||||
$("#api_button_textgenerationwebui").css("display", "none");
|
$("#api_button_textgenerationwebui").css("display", "none");
|
||||||
|
@@ -380,6 +380,7 @@ export async function favsToHotswap() {
|
|||||||
thisHotSwapSlot.attr('grid', isGroup ? grid : '');
|
thisHotSwapSlot.attr('grid', isGroup ? grid : '');
|
||||||
thisHotSwapSlot.attr('chid', isCharacter ? chid : '');
|
thisHotSwapSlot.attr('chid', isCharacter ? chid : '');
|
||||||
thisHotSwapSlot.data('id', isGroup ? grid : chid);
|
thisHotSwapSlot.data('id', isGroup ? grid : chid);
|
||||||
|
thisHotSwapSlot.attr('title', '');
|
||||||
|
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
const group = groups.find(x => x.id === grid);
|
const group = groups.find(x => x.id === grid);
|
||||||
@@ -534,12 +535,14 @@ export function dragElement(elmnt) {
|
|||||||
|
|
||||||
if (elmntHeader.length) {
|
if (elmntHeader.length) {
|
||||||
elmntHeader.off('mousedown').on('mousedown', (e) => {
|
elmntHeader.off('mousedown').on('mousedown', (e) => {
|
||||||
|
hasBeenDraggedByUser = true
|
||||||
|
observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
|
||||||
dragMouseDown(e);
|
dragMouseDown(e);
|
||||||
});
|
});
|
||||||
$(elmnt).off('mousedown').on('mousedown', () => { isMouseDown = true })
|
$(elmnt).off('mousedown').on('mousedown', () => {
|
||||||
} else {
|
isMouseDown = true
|
||||||
elmnt.off('mousedown').on('mousedown', dragMouseDown);
|
observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const observer = new MutationObserver((mutations) => {
|
const observer = new MutationObserver((mutations) => {
|
||||||
@@ -618,7 +621,7 @@ export function dragElement(elmnt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//prevent resizing from top left into the top bar
|
//prevent resizing from top left into the top bar
|
||||||
if (top <= 40 && maxX >= topBarFirstX && left <= topBarFirstX
|
if (top < 40 && maxX >= topBarFirstX && left <= topBarFirstX
|
||||||
) {
|
) {
|
||||||
console.debug('prevent topbar underlap resize')
|
console.debug('prevent topbar underlap resize')
|
||||||
elmnt.css('width', width - 1 + "px");
|
elmnt.css('width', width - 1 + "px");
|
||||||
@@ -674,8 +677,6 @@ export function dragElement(elmnt) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
observer.observe(elmnt.get(0), { attributes: true, attributeFilter: ['style'] });
|
|
||||||
|
|
||||||
function dragMouseDown(e) {
|
function dragMouseDown(e) {
|
||||||
|
|
||||||
if (e) {
|
if (e) {
|
||||||
@@ -745,6 +746,7 @@ export function dragElement(elmnt) {
|
|||||||
$("body").css("overflow", "");
|
$("body").css("overflow", "");
|
||||||
// Clear the "data-dragged" attribute
|
// Clear the "data-dragged" attribute
|
||||||
elmnt.attr('data-dragged', 'false');
|
elmnt.attr('data-dragged', 'false');
|
||||||
|
observer.disconnect()
|
||||||
console.debug(`Saving ${elmntName} UI position`)
|
console.debug(`Saving ${elmntName} UI position`)
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
|
||||||
@@ -987,6 +989,12 @@ $("document").ready(function () {
|
|||||||
Generate();
|
Generate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($(':focus').attr('id') === 'dialogue_popup_input' && !isMobile()) {
|
||||||
|
if (!event.shiftKey && !event.ctrlKey && event.key == "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
$('#dialogue_popup_ok').trigger('click');
|
||||||
|
}
|
||||||
|
}
|
||||||
//ctrl+shift+up to scroll to context line
|
//ctrl+shift+up to scroll to context line
|
||||||
if (event.shiftKey && event.ctrlKey && event.key == "ArrowUp") {
|
if (event.shiftKey && event.ctrlKey && event.key == "ArrowUp") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -1134,5 +1142,11 @@ $("document").ready(function () {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.ctrlKey && /^[1-9]$/.test(event.key)) {
|
||||||
|
// Your code here
|
||||||
|
event.preventDefault();
|
||||||
|
console.log("Ctrl +" + event.key + " pressed!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
117
public/scripts/extensions/bulk-edit/index.js
Normal file
117
public/scripts/extensions/bulk-edit/index.js
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { characters, getCharacters, handleDeleteCharacter, callPopup } from "../../../script.js";
|
||||||
|
|
||||||
|
let is_bulk_edit = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles bulk edit mode on/off when the edit button is clicked.
|
||||||
|
*/
|
||||||
|
function onEditButtonClick() {
|
||||||
|
console.log("Edit button clicked");
|
||||||
|
// toggle bulk edit mode
|
||||||
|
if (is_bulk_edit) {
|
||||||
|
disableBulkSelect();
|
||||||
|
// hide the delete button
|
||||||
|
$("#bulkDeleteButton").hide();
|
||||||
|
is_bulk_edit = false;
|
||||||
|
} else {
|
||||||
|
enableBulkSelect();
|
||||||
|
// show the delete button
|
||||||
|
$("#bulkDeleteButton").show();
|
||||||
|
is_bulk_edit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the character with the given chid.
|
||||||
|
*
|
||||||
|
* @param {string} this_chid - The chid of the character to delete.
|
||||||
|
*/
|
||||||
|
async function deleteCharacter(this_chid) {
|
||||||
|
await handleDeleteCharacter("del_ch", this_chid, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all characters that have been selected via the bulk checkboxes.
|
||||||
|
*/
|
||||||
|
async function onDeleteButtonClick() {
|
||||||
|
console.log("Delete button clicked");
|
||||||
|
|
||||||
|
// Create a mapping of chid to avatar
|
||||||
|
let toDelete = [];
|
||||||
|
$(".bulk_select_checkbox:checked").each((i, el) => {
|
||||||
|
const chid = $(el).parent().attr("chid");
|
||||||
|
const avatar = characters[chid].avatar;
|
||||||
|
// Add the avatar to the list of avatars to delete
|
||||||
|
toDelete.push(avatar);
|
||||||
|
});
|
||||||
|
|
||||||
|
const confirm = await callPopup('<h3>Are you sure you want to delete these characters?</h3>You would need to delete the chat files manually.<br>', 'confirm');
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
console.log('User cancelled delete');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the characters
|
||||||
|
for (const avatar of toDelete) {
|
||||||
|
console.log(`Deleting character with avatar ${avatar}`);
|
||||||
|
await getCharacters();
|
||||||
|
|
||||||
|
//chid should be the key of the character with the given avatar
|
||||||
|
const chid = Object.keys(characters).find((key) => characters[key].avatar === avatar);
|
||||||
|
console.log(`Deleting character with chid ${chid}`);
|
||||||
|
await deleteCharacter(chid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the bulk edit and delete buttons to the UI.
|
||||||
|
*/
|
||||||
|
function addButtons() {
|
||||||
|
const editButton = $(
|
||||||
|
"<i id='bulkEditButton' class='fa-solid fa-edit menu_button bulkEditButton' title='Bulk edit characters'></i>"
|
||||||
|
);
|
||||||
|
const deleteButton = $(
|
||||||
|
"<i id='bulkDeleteButton' class='fa-solid fa-trash menu_button bulkDeleteButton' title='Bulk delete characters' style='display: none;'></i>"
|
||||||
|
);
|
||||||
|
|
||||||
|
$("#charListGridToggle").after(editButton, deleteButton);
|
||||||
|
|
||||||
|
$("#bulkEditButton").on("click", onEditButtonClick);
|
||||||
|
$("#bulkDeleteButton").on("click", onDeleteButtonClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables bulk selection by adding a checkbox next to each character.
|
||||||
|
*/
|
||||||
|
function enableBulkSelect() {
|
||||||
|
$("#rm_print_characters_block .character_select").each((i, el) => {
|
||||||
|
const character = $(el).text();
|
||||||
|
const checkbox = $("<input type='checkbox' class='bulk_select_checkbox'>");
|
||||||
|
checkbox.on("change", () => {
|
||||||
|
// Do something when the checkbox is changed
|
||||||
|
});
|
||||||
|
$(el).prepend(checkbox);
|
||||||
|
});
|
||||||
|
$("#rm_print_characters_block").addClass("bulk_select");
|
||||||
|
// We also need to disable the default click event for the character_select divs
|
||||||
|
$(document).on("click", ".bulk_select_checkbox", function (event) {
|
||||||
|
event.stopImmediatePropagation();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables bulk selection by removing the checkboxes.
|
||||||
|
*/
|
||||||
|
function disableBulkSelect() {
|
||||||
|
$(".bulk_select_checkbox").remove();
|
||||||
|
$("#rm_print_characters_block").removeClass("bulk_select");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point that runs on page load.
|
||||||
|
*/
|
||||||
|
jQuery(async () => {
|
||||||
|
addButtons();
|
||||||
|
// loadSettings();
|
||||||
|
});
|
11
public/scripts/extensions/bulk-edit/manifest.json
Normal file
11
public/scripts/extensions/bulk-edit/manifest.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"display_name": "Bulk Card Editor",
|
||||||
|
"loading_order": 9,
|
||||||
|
"requires": [],
|
||||||
|
"optional": [],
|
||||||
|
"js": "index.js",
|
||||||
|
"css": "style.css",
|
||||||
|
"author": "city-unit",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"homePage": "https://github.com/city-unit"
|
||||||
|
}
|
7
public/scripts/extensions/bulk-edit/style.css
Normal file
7
public/scripts/extensions/bulk-edit/style.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.bulk_select_checkbox {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rm_print_characters_block.bulk_select .wide100pLess70px {
|
||||||
|
width: calc(100% - 85px);
|
||||||
|
}
|
@@ -9,6 +9,7 @@ const MODULE_NAME = 'expressions';
|
|||||||
const UPDATE_INTERVAL = 2000;
|
const UPDATE_INTERVAL = 2000;
|
||||||
const FALLBACK_EXPRESSION = 'joy';
|
const FALLBACK_EXPRESSION = 'joy';
|
||||||
const DEFAULT_EXPRESSIONS = [
|
const DEFAULT_EXPRESSIONS = [
|
||||||
|
"live2d",
|
||||||
"admiration",
|
"admiration",
|
||||||
"amusement",
|
"amusement",
|
||||||
"anger",
|
"anger",
|
||||||
@@ -392,6 +393,108 @@ function onExpressionsShowDefaultInput() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function unloadLiveChar() {
|
||||||
|
try {
|
||||||
|
const url = new URL(getApiUrl());
|
||||||
|
url.pathname = '/api/live2d/unload';
|
||||||
|
const loadResponse = await doExtrasFetch(url);
|
||||||
|
if (!loadResponse.ok) {
|
||||||
|
throw new Error(loadResponse.statusText);
|
||||||
|
}
|
||||||
|
const loadResponseText = await loadResponse.text();
|
||||||
|
//console.log(`Response: ${loadResponseText}`);
|
||||||
|
} catch (error) {
|
||||||
|
//console.error(`Error unloading - ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadLiveChar() {
|
||||||
|
if (!modules.includes('live2d')) {
|
||||||
|
console.debug('live2d module is disabled');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const context = getContext();
|
||||||
|
let spriteFolderName = context.name2;
|
||||||
|
const message = getLastCharacterMessage();
|
||||||
|
const avatarFileName = getSpriteFolderName(message);
|
||||||
|
const expressionOverride = extension_settings.expressionOverrides.find((e) =>
|
||||||
|
e.name == avatarFileName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (expressionOverride && expressionOverride.path) {
|
||||||
|
spriteFolderName = expressionOverride.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const live2dPath = `/characters/${encodeURIComponent(spriteFolderName)}/live2d.png`;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const spriteResponse = await fetch(live2dPath);
|
||||||
|
|
||||||
|
if (!spriteResponse.ok) {
|
||||||
|
throw new Error(spriteResponse.statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
const spriteBlob = await spriteResponse.blob();
|
||||||
|
const spriteFile = new File([spriteBlob], 'live2d.png', { type: 'image/png' });
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', spriteFile);
|
||||||
|
|
||||||
|
const url = new URL(getApiUrl());
|
||||||
|
url.pathname = '/api/live2d/load';
|
||||||
|
|
||||||
|
const loadResponse = await doExtrasFetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: formData,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!loadResponse.ok) {
|
||||||
|
throw new Error(loadResponse.statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadResponseText = await loadResponse.text();
|
||||||
|
console.log(`Load live2d response: ${loadResponseText}`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error loading live2d image: ${live2dPath} - ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleImageChange() {
|
||||||
|
const imgElement = document.querySelector('img#expression-image.expression');
|
||||||
|
|
||||||
|
if (!imgElement) {
|
||||||
|
console.log("Cannot find addExpressionImage()");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.expressions.live2d) {
|
||||||
|
// Method get IP of endpoint
|
||||||
|
const live2dResultFeedSrc = `${getApiUrl()}/api/live2d/result_feed`;
|
||||||
|
$('#expression-holder').css({ display: '' });
|
||||||
|
if (imgElement.src !== live2dResultFeedSrc) {
|
||||||
|
const expressionImageElement = document.querySelector('.expression_list_image');
|
||||||
|
|
||||||
|
if (expressionImageElement) {
|
||||||
|
doExtrasFetch(expressionImageElement.src, {
|
||||||
|
method: 'HEAD',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
imgElement.src = live2dResultFeedSrc;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error); // Log the error if necessary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
imgElement.src = ""; //remove incase char doesnt have expressions
|
||||||
|
setExpression(getContext().name2, FALLBACK_EXPRESSION, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function moduleWorker() {
|
async function moduleWorker() {
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
|
|
||||||
@@ -405,6 +508,16 @@ async function moduleWorker() {
|
|||||||
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
|
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
|
||||||
removeExpression();
|
removeExpression();
|
||||||
spriteCache = {};
|
spriteCache = {};
|
||||||
|
|
||||||
|
//clear expression
|
||||||
|
let imgElement = document.getElementById('expression-image');
|
||||||
|
imgElement.src = "";
|
||||||
|
|
||||||
|
//set checkbox to global var
|
||||||
|
$('#image_type_toggle').prop('checked', extension_settings.expressions.live2d);
|
||||||
|
if (extension_settings.expressions.live2d) {
|
||||||
|
setLive2dState(extension_settings.expressions.live2d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const vnMode = isVisualNovelMode();
|
const vnMode = isVisualNovelMode();
|
||||||
@@ -509,6 +622,60 @@ async function moduleWorker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function live2dcheck() {
|
||||||
|
const context = getContext();
|
||||||
|
let spriteFolderName = context.name2;
|
||||||
|
const message = getLastCharacterMessage();
|
||||||
|
const avatarFileName = getSpriteFolderName(message);
|
||||||
|
const expressionOverride = extension_settings.expressionOverrides.find((e) =>
|
||||||
|
e.name == avatarFileName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (expressionOverride && expressionOverride.path) {
|
||||||
|
spriteFolderName = expressionOverride.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await validateImages(spriteFolderName);
|
||||||
|
|
||||||
|
let live2dObj = spriteCache[spriteFolderName].find(obj => obj.label === 'live2d');
|
||||||
|
let live2dPath_f = live2dObj ? live2dObj.path : null;
|
||||||
|
|
||||||
|
if (live2dPath_f != null) {
|
||||||
|
//console.log("live2dPath_f " + live2dPath_f);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
//console.log("live2dPath_f is null");
|
||||||
|
unloadLiveChar();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setLive2dState(switch_var) {
|
||||||
|
extension_settings.expressions.live2d = switch_var; // Store setting
|
||||||
|
saveSettingsDebounced();
|
||||||
|
|
||||||
|
live2dcheck().then(result => {
|
||||||
|
if (result) {
|
||||||
|
//console.log("Live2d exists!");
|
||||||
|
|
||||||
|
if (extension_settings.expressions.live2d) {
|
||||||
|
loadLiveChar();
|
||||||
|
} else {
|
||||||
|
unloadLiveChar();
|
||||||
|
}
|
||||||
|
handleImageChange(switch_var); // Change image as needed
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//console.log("Live2d does not exist.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getSpriteFolderName(message) {
|
function getSpriteFolderName(message) {
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
let avatarPath = '';
|
let avatarPath = '';
|
||||||
@@ -654,7 +821,6 @@ async function getSpritesList(name) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await fetch(`/get_sprites?name=${encodeURIComponent(name)}`);
|
const result = await fetch(`/get_sprites?name=${encodeURIComponent(name)}`);
|
||||||
|
|
||||||
let sprites = result.ok ? (await result.json()) : [];
|
let sprites = result.ok ? (await result.json()) : [];
|
||||||
return sprites;
|
return sprites;
|
||||||
}
|
}
|
||||||
@@ -697,114 +863,137 @@ async function getExpressionsList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function setExpression(character, expression, force) {
|
async function setExpression(character, expression, force) {
|
||||||
console.debug('entered setExpressions');
|
if (!extension_settings.expressions.live2d) {
|
||||||
await validateImages(character);
|
console.debug('entered setExpressions');
|
||||||
const img = $('img.expression');
|
await validateImages(character);
|
||||||
const prevExpressionSrc = img.attr('src');
|
const img = $('img.expression');
|
||||||
const expressionClone = img.clone()
|
const prevExpressionSrc = img.attr('src');
|
||||||
|
const expressionClone = img.clone()
|
||||||
|
|
||||||
const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression));
|
const sprite = (spriteCache[character] && spriteCache[character].find(x => x.label === expression));
|
||||||
console.debug('checking for expression images to show..');
|
console.debug('checking for expression images to show..');
|
||||||
if (sprite) {
|
if (sprite) {
|
||||||
console.debug('setting expression from character images folder');
|
console.debug('setting expression from character images folder');
|
||||||
|
|
||||||
if (force && isVisualNovelMode()) {
|
if (force && isVisualNovelMode()) {
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const group = context.groups.find(x => x.id === context.groupId);
|
const group = context.groups.find(x => x.id === context.groupId);
|
||||||
|
|
||||||
for (const member of group.members) {
|
for (const member of group.members) {
|
||||||
const groupMember = context.characters.find(x => x.avatar === member);
|
const groupMember = context.characters.find(x => x.avatar === member);
|
||||||
|
|
||||||
if (!groupMember) {
|
if (!groupMember) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupMember.name == character) {
|
if (groupMember.name == character) {
|
||||||
await setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
|
await setImage($(`.expression-holder[data-avatar="${member}"] img`), sprite.path);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
//only swap expressions when necessary
|
||||||
//only swap expressions when necessary
|
if (prevExpressionSrc !== sprite.path
|
||||||
if (prevExpressionSrc !== sprite.path
|
&& !img.hasClass('expression-animating')) {
|
||||||
&& !img.hasClass('expression-animating')) {
|
//clone expression
|
||||||
//clone expression
|
expressionClone.addClass('expression-clone')
|
||||||
expressionClone.addClass('expression-clone')
|
//make invisible and remove id to prevent double ids
|
||||||
//make invisible and remove id to prevent double ids
|
//must be made invisible to start because they share the same Z-index
|
||||||
//must be made invisible to start because they share the same Z-index
|
expressionClone.attr('id', '').css({ opacity: 0 });
|
||||||
expressionClone.attr('id', '').css({ opacity: 0 });
|
//add new sprite path to clone src
|
||||||
//add new sprite path to clone src
|
expressionClone.attr('src', sprite.path);
|
||||||
expressionClone.attr('src', sprite.path);
|
//add invisible clone to html
|
||||||
//add invisible clone to html
|
expressionClone.appendTo($("#expression-holder"))
|
||||||
expressionClone.appendTo($("#expression-holder"))
|
|
||||||
|
|
||||||
const duration = 200;
|
const duration = 200;
|
||||||
|
|
||||||
//add animation flags to both images
|
//add animation flags to both images
|
||||||
//to prevent multiple expression changes happening simultaneously
|
//to prevent multiple expression changes happening simultaneously
|
||||||
img.addClass('expression-animating');
|
img.addClass('expression-animating');
|
||||||
|
|
||||||
// Set the parent container's min width and height before running the transition
|
// Set the parent container's min width and height before running the transition
|
||||||
const imgWidth = img.width();
|
const imgWidth = img.width();
|
||||||
const imgHeight = img.height();
|
const imgHeight = img.height();
|
||||||
const expressionHolder = img.parent();
|
const expressionHolder = img.parent();
|
||||||
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
|
expressionHolder.css('min-width', imgWidth > 100 ? imgWidth : 100);
|
||||||
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
|
expressionHolder.css('min-height', imgHeight > 100 ? imgHeight : 100);
|
||||||
|
|
||||||
//position absolute prevent the original from jumping around during transition
|
//position absolute prevent the original from jumping around during transition
|
||||||
img.css('position', 'absolute');
|
img.css('position', 'absolute');
|
||||||
expressionClone.addClass('expression-animating');
|
expressionClone.addClass('expression-animating');
|
||||||
//fade the clone in
|
//fade the clone in
|
||||||
expressionClone.css({
|
expressionClone.css({
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}).animate({
|
}).animate({
|
||||||
opacity: 1
|
opacity: 1
|
||||||
}, duration)
|
}, duration)
|
||||||
//when finshed fading in clone, fade out the original
|
//when finshed fading in clone, fade out the original
|
||||||
.promise().done(function () {
|
.promise().done(function () {
|
||||||
img.animate({
|
img.animate({
|
||||||
opacity: 0
|
opacity: 0
|
||||||
}, duration);
|
}, duration);
|
||||||
//remove old expression
|
//remove old expression
|
||||||
img.remove();
|
img.remove();
|
||||||
//replace ID so it becomes the new 'original' expression for next change
|
//replace ID so it becomes the new 'original' expression for next change
|
||||||
expressionClone.attr('id', 'expression-image');
|
expressionClone.attr('id', 'expression-image');
|
||||||
expressionClone.removeClass('expression-animating');
|
expressionClone.removeClass('expression-animating');
|
||||||
|
|
||||||
// Reset the expression holder min height and width
|
// Reset the expression holder min height and width
|
||||||
expressionHolder.css('min-width', 100);
|
expressionHolder.css('min-width', 100);
|
||||||
expressionHolder.css('min-height', 100);
|
expressionHolder.css('min-height', 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
expressionClone.removeClass('expression-clone');
|
||||||
|
|
||||||
|
expressionClone.removeClass('default');
|
||||||
|
expressionClone.off('error');
|
||||||
|
expressionClone.on('error', function () {
|
||||||
|
console.debug('Expression image error', sprite.path);
|
||||||
|
$(this).attr('src', '');
|
||||||
|
$(this).off('error');
|
||||||
|
if (force && extension_settings.expressions.showDefault) {
|
||||||
|
setDefault();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
expressionClone.removeClass('expression-clone');
|
|
||||||
|
|
||||||
expressionClone.removeClass('default');
|
|
||||||
expressionClone.off('error');
|
|
||||||
expressionClone.on('error', function () {
|
|
||||||
console.debug('Expression image error', sprite.path);
|
|
||||||
$(this).attr('src', '');
|
|
||||||
$(this).off('error');
|
|
||||||
if (force && extension_settings.expressions.showDefault) {
|
|
||||||
setDefault();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (extension_settings.expressions.showDefault) {
|
||||||
|
setDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDefault() {
|
||||||
|
console.debug('setting default');
|
||||||
|
const defImgUrl = `/img/default-expressions/${expression}.png`;
|
||||||
|
//console.log(defImgUrl);
|
||||||
|
img.attr('src', defImgUrl);
|
||||||
|
img.addClass('default');
|
||||||
|
}
|
||||||
|
document.getElementById("expression-holder").style.display = '';
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (extension_settings.expressions.showDefault) {
|
|
||||||
setDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDefault() {
|
|
||||||
console.debug('setting default');
|
live2dcheck().then(result => {
|
||||||
const defImgUrl = `/img/default-expressions/${expression}.png`;
|
if (result) {
|
||||||
console.log(defImgUrl);
|
// Find the <img> element with id="expression-image" and class="expression"
|
||||||
img.attr('src', defImgUrl);
|
const imgElement = document.querySelector('img#expression-image.expression');
|
||||||
img.addClass('default');
|
//console.log("searching");
|
||||||
|
if (imgElement) {
|
||||||
|
//console.log("setting value");
|
||||||
|
imgElement.src = getApiUrl() + '/api/live2d/result_feed';
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//console.log("The fetch failed!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
document.getElementById("expression-holder").style.display = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClickExpressionImage() {
|
function onClickExpressionImage() {
|
||||||
@@ -1052,7 +1241,6 @@ function setExpressionOverrideHtml(forceClear = false) {
|
|||||||
$('body').append(element);
|
$('body').append(element);
|
||||||
}
|
}
|
||||||
function addSettings() {
|
function addSettings() {
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
<div class="expression_settings">
|
<div class="expression_settings">
|
||||||
<div class="inline-drawer">
|
<div class="inline-drawer">
|
||||||
@@ -1060,7 +1248,16 @@ function setExpressionOverrideHtml(forceClear = false) {
|
|||||||
<b>Character Expressions</b>
|
<b>Character Expressions</b>
|
||||||
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="inline-drawer-content">
|
<div class="inline-drawer-content">
|
||||||
|
<!-- Toggle button for aituber/static images -->
|
||||||
|
<div class="toggle_button">
|
||||||
|
<label class="switch">
|
||||||
|
<input id="image_type_toggle" type="checkbox">
|
||||||
|
<span class="slider round"></span>
|
||||||
|
<label for="image_type_toggle">Image Type - Live2d (extras)</label>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="offline_mode">
|
<div class="offline_mode">
|
||||||
<small>You are in offline mode. Click on the image below to set the expression.</small>
|
<small>You are in offline mode. Click on the image below to set the expression.</small>
|
||||||
</div>
|
</div>
|
||||||
@@ -1090,6 +1287,7 @@ function setExpressionOverrideHtml(forceClear = false) {
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
$('#extensions_settings').append(html);
|
$('#extensions_settings').append(html);
|
||||||
$('#expression_override_button').on('click', onClickExpressionOverrideButton);
|
$('#expression_override_button').on('click', onClickExpressionOverrideButton);
|
||||||
$('#expressions_show_default').on('input', onExpressionsShowDefaultInput);
|
$('#expressions_show_default').on('input', onExpressionsShowDefaultInput);
|
||||||
@@ -1105,6 +1303,10 @@ function setExpressionOverrideHtml(forceClear = false) {
|
|||||||
$(document).on('click', '.expression_list_delete', onClickExpressionDelete);
|
$(document).on('click', '.expression_list_delete', onClickExpressionDelete);
|
||||||
$(window).on("resize", updateVisualNovelModeDebounced);
|
$(window).on("resize", updateVisualNovelModeDebounced);
|
||||||
$('.expression_settings').hide();
|
$('.expression_settings').hide();
|
||||||
|
|
||||||
|
$('#image_type_toggle').on('click', function () {
|
||||||
|
setLive2dState(this.checked);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addExpressionImage();
|
addExpressionImage();
|
||||||
|
@@ -544,6 +544,30 @@ async function onSelectInjectFile(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets the length of character description in the current context
|
||||||
|
function getCharacterDataLength() {
|
||||||
|
const context = getContext();
|
||||||
|
const character = context.characters[context.characterId];
|
||||||
|
|
||||||
|
if (typeof character?.data !== 'object') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let characterDataLength = 0;
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(character.data)) {
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['description', 'personality', 'scenario'].includes(key)) {
|
||||||
|
characterDataLength += character.data[key].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return characterDataLength;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Automatically adjusts the extension settings for the optimal number of messages to keep and query based
|
* Automatically adjusts the extension settings for the optimal number of messages to keep and query based
|
||||||
* on the chat history and a specified maximum context length.
|
* on the chat history and a specified maximum context length.
|
||||||
@@ -558,6 +582,10 @@ function doAutoAdjust(chat, maxContext) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Adjust max context for character defs length
|
||||||
|
maxContext = Math.floor(maxContext - (getCharacterDataLength() / CHARACTERS_PER_TOKEN_RATIO));
|
||||||
|
console.debug('CHROMADB: Max context adjusted for character defs: %o', maxContext);
|
||||||
|
|
||||||
console.debug('CHROMADB: Mean message length (characters): %o', meanMessageLength);
|
console.debug('CHROMADB: Mean message length (characters): %o', meanMessageLength);
|
||||||
// Convert to number of "tokens"
|
// Convert to number of "tokens"
|
||||||
const meanMessageLengthTokens = Math.ceil(meanMessageLength / CHARACTERS_PER_TOKEN_RATIO);
|
const meanMessageLengthTokens = Math.ceil(meanMessageLength / CHARACTERS_PER_TOKEN_RATIO);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { getStringHash, debounce, waitUntilCondition, extractAllWords } from "../../utils.js";
|
import { getStringHash, debounce, waitUntilCondition, extractAllWords } from "../../utils.js";
|
||||||
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
|
import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
|
||||||
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
|
import { eventSource, event_types, extension_prompt_types, generateQuietPrompt, is_send_press, saveSettingsDebounced, substituteParams } from "../../../script.js";
|
||||||
|
import { is_group_generating, selected_group } from "../../group-chats.js";
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = '1_memory';
|
const MODULE_NAME = '1_memory';
|
||||||
@@ -333,8 +334,12 @@ async function summarizeChat(context) {
|
|||||||
|
|
||||||
async function summarizeChatMain(context, force) {
|
async function summarizeChatMain(context, force) {
|
||||||
try {
|
try {
|
||||||
|
// Wait for group to finish generating
|
||||||
|
if (selected_group) {
|
||||||
|
await waitUntilCondition(() => is_group_generating === false, 1000, 10);
|
||||||
|
}
|
||||||
// Wait for the send button to be released
|
// Wait for the send button to be released
|
||||||
waitUntilCondition(() => is_send_press === false, 10000, 100);
|
waitUntilCondition(() => is_send_press === false, 30000, 100);
|
||||||
} catch {
|
} catch {
|
||||||
console.debug('Timeout waiting for is_send_press');
|
console.debug('Timeout waiting for is_send_press');
|
||||||
return;
|
return;
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { chat_metadata, callPopup, saveSettingsDebounced, getCurrentChatId } from "../../../script.js";
|
import { chat_metadata, callPopup, saveSettingsDebounced, is_send_press } from "../../../script.js";
|
||||||
import { getContext, extension_settings, saveMetadataDebounced } from "../../extensions.js";
|
import { getContext, extension_settings, saveMetadataDebounced } from "../../extensions.js";
|
||||||
import {
|
import {
|
||||||
substituteParams,
|
substituteParams,
|
||||||
@@ -7,6 +7,8 @@ import {
|
|||||||
generateQuietPrompt,
|
generateQuietPrompt,
|
||||||
} from "../../../script.js";
|
} from "../../../script.js";
|
||||||
import { registerSlashCommand } from "../../slash-commands.js";
|
import { registerSlashCommand } from "../../slash-commands.js";
|
||||||
|
import { waitUntilCondition } from "../../utils.js";
|
||||||
|
import { is_group_generating, selected_group } from "../../group-chats.js";
|
||||||
|
|
||||||
const MODULE_NAME = "Objective"
|
const MODULE_NAME = "Objective"
|
||||||
|
|
||||||
@@ -17,6 +19,7 @@ let currentChatId = ""
|
|||||||
let currentObjective = null
|
let currentObjective = null
|
||||||
let currentTask = null
|
let currentTask = null
|
||||||
let checkCounter = 0
|
let checkCounter = 0
|
||||||
|
let lastMessageWasSwipe = false
|
||||||
|
|
||||||
|
|
||||||
const defaultPrompts = {
|
const defaultPrompts = {
|
||||||
@@ -72,6 +75,9 @@ function getTaskByIdRecurse(taskId, task) {
|
|||||||
function substituteParamsPrompts(content) {
|
function substituteParamsPrompts(content) {
|
||||||
content = content.replace(/{{objective}}/gi, currentObjective.description)
|
content = content.replace(/{{objective}}/gi, currentObjective.description)
|
||||||
content = content.replace(/{{task}}/gi, currentTask.description)
|
content = content.replace(/{{task}}/gi, currentTask.description)
|
||||||
|
if (currentTask.parent){
|
||||||
|
content = content.replace(/{{parent}}/gi, currentTask.parent.description)
|
||||||
|
}
|
||||||
content = substituteParams(content)
|
content = substituteParams(content)
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
@@ -96,8 +102,8 @@ async function generateTasks() {
|
|||||||
}
|
}
|
||||||
updateUiTaskList();
|
updateUiTaskList();
|
||||||
setCurrentTask();
|
setCurrentTask();
|
||||||
console.info(`Response for Objective: '${taskTree.description}' was \n'${taskResponse}', \nwhich created tasks \n${JSON.stringify(globalTasks.map(v => {return v.toSaveState()}), null, 2)} `)
|
console.info(`Response for Objective: '${currentObjective.description}' was \n'${taskResponse}', \nwhich created tasks \n${JSON.stringify(currentObjective.children.map(v => {return v.toSaveState()}), null, 2)} `)
|
||||||
toastr.success(`Generated ${globalTasks.length} tasks`, 'Done!');
|
toastr.success(`Generated ${currentObjective.children.length} tasks`, 'Done!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call Quiet Generate to check if a task is completed
|
// Call Quiet Generate to check if a task is completed
|
||||||
@@ -106,6 +112,19 @@ async function checkTaskCompleted() {
|
|||||||
if (jQuery.isEmptyObject(currentTask)) {
|
if (jQuery.isEmptyObject(currentTask)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Wait for group to finish generating
|
||||||
|
if (selected_group) {
|
||||||
|
await waitUntilCondition(() => is_group_generating === false, 1000, 10);
|
||||||
|
}
|
||||||
|
// Another extension might be doing something with the chat, so wait for it to finish
|
||||||
|
await waitUntilCondition(() => is_send_press === false, 30000, 10);
|
||||||
|
} catch {
|
||||||
|
console.debug("Failed to wait for group to finish generating")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
checkCounter = $('#objective-check-frequency').val()
|
checkCounter = $('#objective-check-frequency').val()
|
||||||
toastr.info("Checking for task completion.")
|
toastr.info("Checking for task completion.")
|
||||||
|
|
||||||
@@ -126,7 +145,7 @@ async function checkTaskCompleted() {
|
|||||||
function getNextIncompleteTaskRecurse(task){
|
function getNextIncompleteTaskRecurse(task){
|
||||||
if (task.completed === false // Return task if incomplete
|
if (task.completed === false // Return task if incomplete
|
||||||
&& task.children.length === 0 // Ensure task has no children, it's subtasks will determine completeness
|
&& task.children.length === 0 // Ensure task has no children, it's subtasks will determine completeness
|
||||||
&& task.parentId // Must have parent id. Only root task will be missing this and we dont want that
|
&& task.parentId !== "" // Must have parent id. Only root task will be missing this and we dont want that
|
||||||
){
|
){
|
||||||
return task
|
return task
|
||||||
}
|
}
|
||||||
@@ -513,6 +532,7 @@ const defaultSettings = {
|
|||||||
|
|
||||||
// Convenient single call. Not much at the moment.
|
// Convenient single call. Not much at the moment.
|
||||||
function resetState() {
|
function resetState() {
|
||||||
|
lastMessageWasSwipe = false
|
||||||
loadSettings();
|
loadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,9 +800,12 @@ jQuery(() => {
|
|||||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||||
resetState()
|
resetState()
|
||||||
});
|
});
|
||||||
|
eventSource.on(event_types.MESSAGE_SWIPED, () => {
|
||||||
|
lastMessageWasSwipe = true
|
||||||
|
})
|
||||||
eventSource.on(event_types.MESSAGE_RECEIVED, () => {
|
eventSource.on(event_types.MESSAGE_RECEIVED, () => {
|
||||||
if (currentChatId == undefined || currentTask == undefined) {
|
if (currentChatId == undefined || jQuery.isEmptyObject(currentTask) || lastMessageWasSwipe) {
|
||||||
|
lastMessageWasSwipe = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ($("#objective-check-frequency").val() > 0) {
|
if ($("#objective-check-frequency").val() > 0) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { saveSettingsDebounced, callPopup, getRequestHeaders } from "../../../script.js";
|
import { saveSettingsDebounced, callPopup, getRequestHeaders } from "../../../script.js";
|
||||||
import { getContext, extension_settings } from "../../extensions.js";
|
import { getContext, extension_settings } from "../../extensions.js";
|
||||||
import { initScrollHeight, resetScrollHeight } from "../../utils.js";
|
import { initScrollHeight, resetScrollHeight } from "../../utils.js";
|
||||||
|
import { executeSlashCommands, getSlashCommandsHelp, registerSlashCommand } from "../../slash-commands.js";
|
||||||
|
|
||||||
|
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
@@ -256,7 +257,7 @@ async function applyQuickReplyPreset(name) {
|
|||||||
const quickReplyPreset = presets.find(x => x.name == name);
|
const quickReplyPreset = presets.find(x => x.name == name);
|
||||||
|
|
||||||
if (!quickReplyPreset) {
|
if (!quickReplyPreset) {
|
||||||
console.log(`error, QR preset '${name}' not found`)
|
toastr.warning(`error, QR preset '${name}' not found. Confirm you are using proper case sensitivity!`)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,9 +269,27 @@ async function applyQuickReplyPreset(name) {
|
|||||||
moduleWorker();
|
moduleWorker();
|
||||||
|
|
||||||
$(`#quickReplyPresets option[value="${name}"]`).attr('selected', true);
|
$(`#quickReplyPresets option[value="${name}"]`).attr('selected', true);
|
||||||
|
|
||||||
console.debug('QR Preset applied: ' + name);
|
console.debug('QR Preset applied: ' + name);
|
||||||
//loadMovingUIState()
|
}
|
||||||
|
|
||||||
|
async function doQRPresetSwitch(_, text) {
|
||||||
|
text = String(text)
|
||||||
|
applyQuickReplyPreset(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doQR(_, text) {
|
||||||
|
if (!text) {
|
||||||
|
toastr.warning('must specify which QR # to use')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
text = Number(text)
|
||||||
|
//use scale starting with 0
|
||||||
|
//ex: user inputs "/qr 2" >> qr with data-index 1 (but 2nd item displayed) gets triggered
|
||||||
|
let QRnum = Number(text - 1)
|
||||||
|
if (QRnum <= 0) { QRnum = 0 }
|
||||||
|
const whichQR = $("#quickReplies").find(`[data-index='${QRnum}']`);
|
||||||
|
whichQR.trigger('click')
|
||||||
}
|
}
|
||||||
|
|
||||||
jQuery(async () => {
|
jQuery(async () => {
|
||||||
@@ -326,5 +345,11 @@ jQuery(async () => {
|
|||||||
|
|
||||||
await loadSettings('init');
|
await loadSettings('init');
|
||||||
addQuickReplyBar();
|
addQuickReplyBar();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).ready(() => {
|
||||||
|
registerSlashCommand('qr', doQR, [], "- requires number argument, activates the specified QuickReply", true, true);
|
||||||
|
registerSlashCommand('qrset', doQRPresetSwitch, [], "- arg: QuickReply Preset Name, swaps to that QR preset", true, true);
|
||||||
|
|
||||||
|
})
|
||||||
|
@@ -8,16 +8,21 @@ import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper
|
|||||||
import { VoskSttProvider } from './vosk.js'
|
import { VoskSttProvider } from './vosk.js'
|
||||||
import { WhisperSttProvider } from './whisper.js'
|
import { WhisperSttProvider } from './whisper.js'
|
||||||
import { BrowserSttProvider } from './browser.js'
|
import { BrowserSttProvider } from './browser.js'
|
||||||
|
import { StreamingSttProvider } from './streaming.js'
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = 'Speech Recognition';
|
const MODULE_NAME = 'Speech Recognition';
|
||||||
const DEBUG_PREFIX = "<Speech Recognition module> "
|
const DEBUG_PREFIX = "<Speech Recognition module> "
|
||||||
|
const UPDATE_INTERVAL = 100;
|
||||||
|
|
||||||
|
let inApiCall = false;
|
||||||
|
|
||||||
let sttProviders = {
|
let sttProviders = {
|
||||||
None: null,
|
None: null,
|
||||||
Browser: BrowserSttProvider,
|
Browser: BrowserSttProvider,
|
||||||
Whisper: WhisperSttProvider,
|
Whisper: WhisperSttProvider,
|
||||||
Vosk: VoskSttProvider,
|
Vosk: VoskSttProvider,
|
||||||
|
Streaming: StreamingSttProvider,
|
||||||
}
|
}
|
||||||
|
|
||||||
let sttProvider = null
|
let sttProvider = null
|
||||||
@@ -27,6 +32,82 @@ let audioRecording = false
|
|||||||
const constraints = { audio: { sampleSize: 16, channelCount: 1, sampleRate: 16000 } };
|
const constraints = { audio: { sampleSize: 16, channelCount: 1, sampleRate: 16000 } };
|
||||||
let audioChunks = [];
|
let audioChunks = [];
|
||||||
|
|
||||||
|
async function moduleWorker() {
|
||||||
|
if (sttProviderName != "Streaming") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API is busy
|
||||||
|
if (inApiCall) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
inApiCall = true;
|
||||||
|
const userMessageOriginal = await sttProvider.getUserMessage();
|
||||||
|
let userMessageFormatted = userMessageOriginal.trim();
|
||||||
|
|
||||||
|
if (userMessageFormatted.length > 0)
|
||||||
|
{
|
||||||
|
console.debug(DEBUG_PREFIX+"recorded transcript: \""+userMessageFormatted+"\"");
|
||||||
|
|
||||||
|
let userMessageLower = userMessageFormatted.toLowerCase();
|
||||||
|
// remove punctuation
|
||||||
|
let userMessageRaw = userMessageLower.replace(/[^\w\s\']|_/g, "").replace(/\s+/g, " ");
|
||||||
|
|
||||||
|
console.debug(DEBUG_PREFIX+"raw transcript:",userMessageRaw);
|
||||||
|
|
||||||
|
// Detect trigger words
|
||||||
|
let messageStart = -1;
|
||||||
|
|
||||||
|
if (extension_settings.speech_recognition.Streaming.triggerWordsEnabled) {
|
||||||
|
|
||||||
|
for (const triggerWord of extension_settings.speech_recognition.Streaming.triggerWords) {
|
||||||
|
const triggerPos = userMessageRaw.indexOf(triggerWord.toLowerCase());
|
||||||
|
|
||||||
|
// Trigger word not found or not starting message and just a substring
|
||||||
|
if (triggerPos == -1){ // | (triggerPos > 0 & userMessageFormatted[triggerPos-1] != " ")) {
|
||||||
|
console.debug(DEBUG_PREFIX+"trigger word not found: ", triggerWord);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.debug(DEBUG_PREFIX+"Found trigger word: ", triggerWord, " at index ", triggerPos);
|
||||||
|
if (triggerPos < messageStart | messageStart == -1) { // & (triggerPos + triggerWord.length) < userMessageFormatted.length)) {
|
||||||
|
messageStart = triggerPos; // + triggerWord.length + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messageStart == -1) {
|
||||||
|
console.debug(DEBUG_PREFIX+"message ignored, no trigger word preceding a message. Voice transcript: \""+ userMessageOriginal +"\"");
|
||||||
|
if (extension_settings.speech_recognition.Streaming.debug) {
|
||||||
|
toastr.info(
|
||||||
|
"No trigger word preceding a message. Voice transcript: \""+ userMessageOriginal +"\"",
|
||||||
|
DEBUG_PREFIX+"message ignored.",
|
||||||
|
{ timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
userMessageFormatted = userMessageFormatted.substring(messageStart);
|
||||||
|
processTranscript(userMessageFormatted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.debug(DEBUG_PREFIX+"Received empty transcript, ignored");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.debug(error);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
inApiCall = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function processTranscript(transcript) {
|
async function processTranscript(transcript) {
|
||||||
try {
|
try {
|
||||||
const transcriptOriginal = transcript;
|
const transcriptOriginal = transcript;
|
||||||
@@ -198,13 +279,21 @@ function loadSttProvider(provider) {
|
|||||||
if (sttProviderName == "Browser") {
|
if (sttProviderName == "Browser") {
|
||||||
sttProvider.processTranscriptFunction = processTranscript;
|
sttProvider.processTranscriptFunction = processTranscript;
|
||||||
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
|
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
|
||||||
}
|
|
||||||
else {
|
|
||||||
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
|
|
||||||
loadNavigatorAudioRecording();
|
|
||||||
|
|
||||||
$("#microphone_button").show();
|
$("#microphone_button").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sttProviderName == "Vosk" | sttProviderName == "Whisper") {
|
||||||
|
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
|
||||||
|
loadNavigatorAudioRecording();
|
||||||
|
$("#microphone_button").show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sttProviderName == "Streaming") {
|
||||||
|
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
|
||||||
|
$("#microphone_button").off('click');
|
||||||
|
$("#microphone_button").hide();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSttProviderChange() {
|
function onSttProviderChange() {
|
||||||
@@ -231,7 +320,7 @@ const defaultSettings = {
|
|||||||
messageMode: "append",
|
messageMode: "append",
|
||||||
messageMappingText: "",
|
messageMappingText: "",
|
||||||
messageMapping: [],
|
messageMapping: [],
|
||||||
messageMappingEnabled: false
|
messageMappingEnabled: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
@@ -344,8 +433,7 @@ $(document).ready(function () {
|
|||||||
addExtensionControls(); // No init dependencies
|
addExtensionControls(); // No init dependencies
|
||||||
loadSettings(); // Depends on Extension Controls and loadTtsProvider
|
loadSettings(); // Depends on Extension Controls and loadTtsProvider
|
||||||
loadSttProvider(extension_settings.speech_recognition.currentProvider); // No dependencies
|
loadSttProvider(extension_settings.speech_recognition.currentProvider); // No dependencies
|
||||||
|
const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
||||||
//const wrapper = new ModuleWorkerWrapper(moduleWorker);
|
setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL); // Init depends on all the things
|
||||||
//setInterval(wrapper.update.bind(wrapper), UPDATE_INTERVAL); // Init depends on all the things
|
moduleWorker();
|
||||||
//moduleWorker();
|
|
||||||
})
|
})
|
||||||
|
102
public/scripts/extensions/speech-recognition/streaming.js
Normal file
102
public/scripts/extensions/speech-recognition/streaming.js
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
import { getApiUrl, doExtrasFetch, modules } from "../../extensions.js";
|
||||||
|
export { StreamingSttProvider }
|
||||||
|
|
||||||
|
const DEBUG_PREFIX = "<Speech Recognition module (streaming)> "
|
||||||
|
|
||||||
|
class StreamingSttProvider {
|
||||||
|
//########//
|
||||||
|
// Config //
|
||||||
|
//########//
|
||||||
|
|
||||||
|
settings
|
||||||
|
|
||||||
|
defaultSettings = {
|
||||||
|
triggerWordsText: "",
|
||||||
|
triggerWords : [],
|
||||||
|
triggerWordsEnabled : false,
|
||||||
|
debug : false,
|
||||||
|
}
|
||||||
|
|
||||||
|
get settingsHtml() {
|
||||||
|
let html = '\
|
||||||
|
<div id="speech_recognition_streaming_trigger_words_div">\
|
||||||
|
<span>Trigger words</span>\
|
||||||
|
<textarea id="speech_recognition_streaming_trigger_words" class="text_pole textarea_compact" type="text" rows="4" placeholder="Enter comma separated words that triggers new message, example:\nhey, hey aqua, record, listen"></textarea>\
|
||||||
|
<label class="checkbox_label" for="speech_recognition_streaming_trigger_words_enabled">\
|
||||||
|
<input type="checkbox" id="speech_recognition_streaming_trigger_words_enabled" name="speech_recognition_trigger_words_enabled">\
|
||||||
|
<small>Enable trigger words</small>\
|
||||||
|
</label>\
|
||||||
|
<label class="checkbox_label" for="speech_recognition_streaming_debug">\
|
||||||
|
<input type="checkbox" id="speech_recognition_streaming_debug" name="speech_recognition_streaming_debug">\
|
||||||
|
<small>Enable debug pop ups</small>\
|
||||||
|
</label>\
|
||||||
|
</div>\
|
||||||
|
'
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
onSettingsChange() {
|
||||||
|
this.settings.triggerWordsText = $('#speech_recognition_streaming_trigger_words').val();
|
||||||
|
let array = $('#speech_recognition_streaming_trigger_words').val().split(",");
|
||||||
|
array = array.map(element => {return element.trim().toLowerCase();});
|
||||||
|
array = array.filter((str) => str !== '');
|
||||||
|
this.settings.triggerWords = array;
|
||||||
|
this.settings.triggerWordsEnabled = $("#speech_recognition_streaming_trigger_words_enabled").is(':checked');
|
||||||
|
this.settings.debug = $("#speech_recognition_streaming_debug").is(':checked');
|
||||||
|
console.debug(DEBUG_PREFIX+" Updated settings: ", this.settings);
|
||||||
|
this.loadSettings(this.settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadSettings(settings) {
|
||||||
|
// Populate Provider UI given input settings
|
||||||
|
if (Object.keys(settings).length == 0) {
|
||||||
|
console.debug(DEBUG_PREFIX+"Using default Whisper STT extension settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only accept keys defined in defaultSettings
|
||||||
|
this.settings = this.defaultSettings
|
||||||
|
|
||||||
|
for (const key in settings){
|
||||||
|
if (key in this.settings){
|
||||||
|
this.settings[key] = settings[key]
|
||||||
|
} else {
|
||||||
|
throw `Invalid setting passed to STT extension: ${key}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#speech_recognition_streaming_trigger_words").val(this.settings.triggerWordsText);
|
||||||
|
$("#speech_recognition_streaming_trigger_words_enabled").prop('checked',this.settings.triggerWordsEnabled);
|
||||||
|
$("#speech_recognition_streaming_debug").prop('checked',this.settings.debug);
|
||||||
|
|
||||||
|
console.debug(DEBUG_PREFIX+"streaming STT settings loaded")
|
||||||
|
}
|
||||||
|
|
||||||
|
async getUserMessage() {
|
||||||
|
// Return if module is not loaded
|
||||||
|
if (!modules.includes('streaming-stt')) {
|
||||||
|
console.debug(DEBUG_PREFIX+"Module streaming-stt must be activated in Sillytavern Extras for streaming user voice.")
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = new URL(getApiUrl());
|
||||||
|
url.pathname = '/api/speech-recognition/streaming/record-and-transcript';
|
||||||
|
|
||||||
|
const apiResult = await doExtrasFetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Bypass-Tunnel-Reminder': 'bypass',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ text: "" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!apiResult.ok) {
|
||||||
|
toastr.error(apiResult.statusText, DEBUG_PREFIX+'STT Generation Failed (streaming)', { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
|
||||||
|
throw new Error(`HTTP ${apiResult.status}: ${await apiResult.text()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await apiResult.json();
|
||||||
|
return data.transcript;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
import { callPopup, cancelTtsPlay, eventSource, event_types, isMultigenEnabled, is_send_press, saveSettingsDebounced } from '../../../script.js'
|
import { callPopup, cancelTtsPlay, eventSource, event_types, isMultigenEnabled, is_send_press, saveSettingsDebounced } from '../../../script.js'
|
||||||
import { ModuleWorkerWrapper, extension_settings, getContext } from '../../extensions.js'
|
import { ModuleWorkerWrapper, doExtrasFetch, extension_settings, getApiUrl, getContext } from '../../extensions.js'
|
||||||
import { escapeRegex, getStringHash } from '../../utils.js'
|
import { escapeRegex, getStringHash } from '../../utils.js'
|
||||||
import { EdgeTtsProvider } from './edge.js'
|
import { EdgeTtsProvider } from './edge.js'
|
||||||
import { ElevenLabsTtsProvider } from './elevenlabs.js'
|
import { ElevenLabsTtsProvider } from './elevenlabs.js'
|
||||||
@@ -7,14 +7,13 @@ import { SileroTtsProvider } from './silerotts.js'
|
|||||||
import { CoquiTtsProvider } from './coquitts.js'
|
import { CoquiTtsProvider } from './coquitts.js'
|
||||||
import { SystemTtsProvider } from './system.js'
|
import { SystemTtsProvider } from './system.js'
|
||||||
import { NovelTtsProvider } from './novel.js'
|
import { NovelTtsProvider } from './novel.js'
|
||||||
import { isMobile } from '../../RossAscends-mods.js'
|
|
||||||
import { power_user } from '../../power-user.js'
|
import { power_user } from '../../power-user.js'
|
||||||
|
|
||||||
const UPDATE_INTERVAL = 1000
|
const UPDATE_INTERVAL = 1000
|
||||||
|
|
||||||
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
let voiceMap = {} // {charName:voiceid, charName2:voiceid2}
|
||||||
let audioControl
|
let audioControl
|
||||||
|
let storedvalue = false;
|
||||||
let lastCharacterId = null
|
let lastCharacterId = null
|
||||||
let lastGroupId = null
|
let lastGroupId = null
|
||||||
let lastChatId = null
|
let lastChatId = null
|
||||||
@@ -164,6 +163,20 @@ async function moduleWorker() {
|
|||||||
ttsJobQueue.push(message)
|
ttsJobQueue.push(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function talkingAnimation(switchValue) {
|
||||||
|
const apiUrl = getApiUrl();
|
||||||
|
const animationType = switchValue ? "start" : "stop";
|
||||||
|
|
||||||
|
if (switchValue !== storedvalue) {
|
||||||
|
try {
|
||||||
|
console.log(animationType + " Talking Animation");
|
||||||
|
doExtrasFetch(`${apiUrl}/api/live2d/${animationType}_talking`);
|
||||||
|
storedvalue = switchValue; // Update the storedvalue to the current switchValue
|
||||||
|
} catch (error) {
|
||||||
|
// Handle the error here or simply ignore it to prevent logging
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function resetTtsPlayback() {
|
function resetTtsPlayback() {
|
||||||
// Stop system TTS utterance
|
// Stop system TTS utterance
|
||||||
@@ -291,8 +304,10 @@ function updateUiAudioPlayState() {
|
|||||||
// Give user feedback that TTS is active by setting the stop icon if processing or playing
|
// Give user feedback that TTS is active by setting the stop icon if processing or playing
|
||||||
if (!audioElement.paused || isTtsProcessing()) {
|
if (!audioElement.paused || isTtsProcessing()) {
|
||||||
img = 'fa-solid fa-stop-circle extensionsMenuExtensionButton'
|
img = 'fa-solid fa-stop-circle extensionsMenuExtensionButton'
|
||||||
|
talkingAnimation(true)
|
||||||
} else {
|
} else {
|
||||||
img = 'fa-solid fa-circle-play extensionsMenuExtensionButton'
|
img = 'fa-solid fa-circle-play extensionsMenuExtensionButton'
|
||||||
|
talkingAnimation(false)
|
||||||
}
|
}
|
||||||
$('#tts_media_control').attr('class', img);
|
$('#tts_media_control').attr('class', img);
|
||||||
} else {
|
} else {
|
||||||
@@ -354,6 +369,7 @@ async function processAudioJobQueue() {
|
|||||||
audioQueueProcessorReady = false
|
audioQueueProcessorReady = false
|
||||||
currentAudioJob = audioJobQueue.pop()
|
currentAudioJob = audioJobQueue.pop()
|
||||||
playAudioData(currentAudioJob)
|
playAudioData(currentAudioJob)
|
||||||
|
talkingAnimation(true)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
audioQueueProcessorReady = true
|
audioQueueProcessorReady = true
|
||||||
|
@@ -4,6 +4,10 @@ import {
|
|||||||
getStoppingStrings,
|
getStoppingStrings,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
power_user,
|
||||||
|
} from "./power-user.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
kai_settings,
|
kai_settings,
|
||||||
loadKoboldSettings,
|
loadKoboldSettings,
|
||||||
@@ -31,16 +35,17 @@ const kai_settings = {
|
|||||||
|
|
||||||
const MIN_STOP_SEQUENCE_VERSION = '1.2.2';
|
const MIN_STOP_SEQUENCE_VERSION = '1.2.2';
|
||||||
const MIN_STREAMING_KCPPVERSION = '1.30';
|
const MIN_STREAMING_KCPPVERSION = '1.30';
|
||||||
|
const KOBOLDCPP_ORDER = [6, 0, 1, 3, 4, 2, 5];
|
||||||
|
|
||||||
function formatKoboldUrl(value) {
|
function formatKoboldUrl(value) {
|
||||||
try {
|
try {
|
||||||
const url = new URL(value);
|
const url = new URL(value);
|
||||||
url.pathname = '/api';
|
if (!power_user.relaxed_api_urls) {
|
||||||
|
url.pathname = '/api';
|
||||||
|
}
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
} catch { } // Just using URL as a validation check
|
||||||
catch {
|
return null;
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadKoboldSettings(preset) {
|
function loadKoboldSettings(preset) {
|
||||||
@@ -139,7 +144,7 @@ export async function generateKoboldWithStreaming(generate_data, signal) {
|
|||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,4 +277,10 @@ $(document).ready(function () {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#samplers_order_recommended').on('click', function () {
|
||||||
|
kai_settings.sampler_order = KOBOLDCPP_ORDER;
|
||||||
|
sortItemsByOrder(kai_settings.sampler_order);
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
getRequestHeaders,
|
getRequestHeaders,
|
||||||
saveSettingsDebounced,
|
saveSettingsDebounced,
|
||||||
|
getStoppingStrings,
|
||||||
|
getTextTokens
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
import { tokenizers } from "./power-user.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
nai_settings,
|
nai_settings,
|
||||||
@@ -10,6 +13,8 @@ export {
|
|||||||
getNovelTier,
|
getNovelTier,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const default_preamble = "[ Style: chat, complex, sensory, visceral ]";
|
||||||
|
|
||||||
const nai_settings = {
|
const nai_settings = {
|
||||||
temperature: 0.5,
|
temperature: 0.5,
|
||||||
repetition_penalty: 1,
|
repetition_penalty: 1,
|
||||||
@@ -26,6 +31,7 @@ const nai_settings = {
|
|||||||
model_novel: "euterpe-v2",
|
model_novel: "euterpe-v2",
|
||||||
preset_settings_novel: "Classic-Euterpe",
|
preset_settings_novel: "Classic-Euterpe",
|
||||||
streaming_novel: false,
|
streaming_novel: false,
|
||||||
|
nai_preamble: default_preamble,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nai_tiers = {
|
const nai_tiers = {
|
||||||
@@ -73,6 +79,7 @@ function loadNovelSettings(settings) {
|
|||||||
$(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true);
|
$(`#model_novel_select option[value=${nai_settings.model_novel}]`).attr("selected", true);
|
||||||
$('#model_novel_select').val(nai_settings.model_novel);
|
$('#model_novel_select').val(nai_settings.model_novel);
|
||||||
|
|
||||||
|
if (settings.nai_preamble !== undefined) nai_settings.preamble = settings.nai_preamble;
|
||||||
nai_settings.preset_settings_novel = settings.preset_settings_novel;
|
nai_settings.preset_settings_novel = settings.preset_settings_novel;
|
||||||
nai_settings.temperature = settings.temperature;
|
nai_settings.temperature = settings.temperature;
|
||||||
nai_settings.repetition_penalty = settings.repetition_penalty;
|
nai_settings.repetition_penalty = settings.repetition_penalty;
|
||||||
@@ -154,6 +161,7 @@ function loadNovelSettingsUi(ui_settings) {
|
|||||||
$("#phrase_rep_pen_counter_novel").text(getPhraseRepPenCounter(ui_settings.phrase_rep_pen));
|
$("#phrase_rep_pen_counter_novel").text(getPhraseRepPenCounter(ui_settings.phrase_rep_pen));
|
||||||
$("#min_length_novel").val(ui_settings.min_length);
|
$("#min_length_novel").val(ui_settings.min_length);
|
||||||
$("#min_length_counter_novel").text(Number(ui_settings.min_length).toFixed(0));
|
$("#min_length_counter_novel").text(Number(ui_settings.min_length).toFixed(0));
|
||||||
|
$('#nai_preamble_textarea').val(ui_settings.nai_preamble);
|
||||||
|
|
||||||
$("#streaming_novel").prop('checked', ui_settings.streaming_novel);
|
$("#streaming_novel").prop('checked', ui_settings.streaming_novel);
|
||||||
}
|
}
|
||||||
@@ -245,8 +253,24 @@ const sliders = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getNovelGenerationData(finalPromt, this_settings, this_amount_gen) {
|
export function getNovelGenerationData(finalPromt, this_settings, this_amount_gen, isImpersonate) {
|
||||||
const isNewModel = (nai_settings.model_novel.includes('clio') || nai_settings.model_novel.includes('kayra'));
|
const clio = nai_settings.model_novel.includes('clio');
|
||||||
|
const kayra = nai_settings.model_novel.includes('kayra');
|
||||||
|
const isNewModel = clio || kayra;
|
||||||
|
|
||||||
|
const tokenizerType = kayra ? tokenizers.NERD2 : (clio ? tokenizers.NERD : tokenizers.NONE);
|
||||||
|
const stopSequences = (tokenizerType !== tokenizers.NONE)
|
||||||
|
? getStoppingStrings(isImpersonate, false)
|
||||||
|
.map(t => getTextTokens(tokenizerType, t))
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
let useInstruct = false;
|
||||||
|
if (isNewModel) {
|
||||||
|
// NovelAI claims they scan backwards 1000 characters (not tokens!) to look for instruct brackets. That's really short.
|
||||||
|
const tail = finalPromt.slice(-1500);
|
||||||
|
useInstruct = tail.includes("}");
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"input": finalPromt,
|
"input": finalPromt,
|
||||||
"model": nai_settings.model_novel,
|
"model": nai_settings.model_novel,
|
||||||
@@ -268,12 +292,13 @@ export function getNovelGenerationData(finalPromt, this_settings, this_amount_ge
|
|||||||
"cfg_uc": "",
|
"cfg_uc": "",
|
||||||
"phrase_rep_pen": nai_settings.phrase_rep_pen,
|
"phrase_rep_pen": nai_settings.phrase_rep_pen,
|
||||||
//"stop_sequences": {{187}},
|
//"stop_sequences": {{187}},
|
||||||
|
"stop_sequences": stopSequences,
|
||||||
//bad_words_ids = {{50256}, {0}, {1}};
|
//bad_words_ids = {{50256}, {0}, {1}};
|
||||||
"generate_until_sentence": true,
|
"generate_until_sentence": true,
|
||||||
"use_cache": false,
|
"use_cache": false,
|
||||||
"use_string": true,
|
"use_string": true,
|
||||||
"return_full_text": false,
|
"return_full_text": false,
|
||||||
"prefix": isNewModel ? "special_instruct" : "vanilla",
|
"prefix": useInstruct ? "special_instruct" : (isNewModel ? "special_proseaugmenter" : "vanilla"),
|
||||||
"order": this_settings.order,
|
"order": this_settings.order,
|
||||||
"streaming": nai_settings.streaming_novel,
|
"streaming": nai_settings.streaming_novel,
|
||||||
};
|
};
|
||||||
@@ -321,6 +346,17 @@ export async function generateNovelWithStreaming(generate_data, signal) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#nai_preamble_textarea").on('input', function () {
|
||||||
|
nai_settings.preamble = $('#nai_preamble_textarea').val();
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#nai_preamble_restore").on('click', function () {
|
||||||
|
nai_settings.preamble = default_preamble;
|
||||||
|
$('#nai_preamble_textarea').val(nai_settings.preamble);
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
sliders.forEach(slider => {
|
sliders.forEach(slider => {
|
||||||
$(document).on("input", slider.sliderId, function () {
|
$(document).on("input", slider.sliderId, function () {
|
||||||
|
@@ -692,8 +692,30 @@ function getChatCompletionModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateOpenRouterCost() {
|
||||||
|
if (oai_settings.chat_completion_source !== chat_completion_sources.OPENROUTER) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cost = 'Unknown';
|
||||||
|
const model = model_list.find(x => x.id === oai_settings.openrouter_model);
|
||||||
|
|
||||||
|
if (model?.pricing) {
|
||||||
|
const completionCost = Number(model.pricing.completion);
|
||||||
|
const promptCost = Number(model.pricing.prompt);
|
||||||
|
const completionTokens = oai_settings.openai_max_tokens;
|
||||||
|
const promptTokens = (oai_settings.openai_max_context - completionTokens);
|
||||||
|
const totalCost = (completionCost * completionTokens) + (promptCost * promptTokens);
|
||||||
|
if (!isNaN(totalCost)) {
|
||||||
|
cost = totalCost.toFixed(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#openrouter_max_prompt_cost').text(cost);
|
||||||
|
}
|
||||||
|
|
||||||
function saveModelList(data) {
|
function saveModelList(data) {
|
||||||
model_list = data.map((model) => ({ id: model.id, context_length: model.context_length }));
|
model_list = data.map((model) => ({ id: model.id, context_length: model.context_length, pricing: model.pricing }));
|
||||||
model_list.sort((a, b) => a?.id && b?.id && a.id.localeCompare(b.id));
|
model_list.sort((a, b) => a?.id && b?.id && a.id.localeCompare(b.id));
|
||||||
|
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER) {
|
||||||
@@ -1801,6 +1823,8 @@ async function onModelChange() {
|
|||||||
oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai);
|
oai_settings.temp_openai = Math.min(oai_max_temp, oai_settings.temp_openai);
|
||||||
$('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
|
$('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateOpenRouterCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
|
if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
|
||||||
@@ -2038,11 +2062,13 @@ $(document).ready(function () {
|
|||||||
$(document).on('input', '#openai_max_context', function () {
|
$(document).on('input', '#openai_max_context', function () {
|
||||||
oai_settings.openai_max_context = parseInt($(this).val());
|
oai_settings.openai_max_context = parseInt($(this).val());
|
||||||
$('#openai_max_context_counter').text(`${$(this).val()}`);
|
$('#openai_max_context_counter').text(`${$(this).val()}`);
|
||||||
|
calculateOpenRouterCost();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).on('input', '#openai_max_tokens', function () {
|
$(document).on('input', '#openai_max_tokens', function () {
|
||||||
oai_settings.openai_max_tokens = parseInt($(this).val());
|
oai_settings.openai_max_tokens = parseInt($(this).val());
|
||||||
|
calculateOpenRouterCost();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -27,7 +27,7 @@ import {
|
|||||||
|
|
||||||
import { registerSlashCommand } from "./slash-commands.js";
|
import { registerSlashCommand } from "./slash-commands.js";
|
||||||
|
|
||||||
import { delay, debounce } from "./utils.js";
|
import { delay } from "./utils.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
loadPowerUserSettings,
|
loadPowerUserSettings,
|
||||||
@@ -71,6 +71,7 @@ const tokenizers = {
|
|||||||
NERD: 4,
|
NERD: 4,
|
||||||
NERD2: 5,
|
NERD2: 5,
|
||||||
API: 6,
|
API: 6,
|
||||||
|
BEST_MATCH: 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
const send_on_enter_options = {
|
const send_on_enter_options = {
|
||||||
@@ -87,7 +88,7 @@ export const persona_description_positions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let power_user = {
|
let power_user = {
|
||||||
tokenizer: tokenizers.CLASSIC,
|
tokenizer: tokenizers.BEST_MATCH,
|
||||||
token_padding: 64,
|
token_padding: 64,
|
||||||
collapse_newlines: false,
|
collapse_newlines: false,
|
||||||
pygmalion_formatting: pygmalion_options.AUTO,
|
pygmalion_formatting: pygmalion_options.AUTO,
|
||||||
@@ -163,6 +164,7 @@ let power_user = {
|
|||||||
prefer_character_jailbreak: true,
|
prefer_character_jailbreak: true,
|
||||||
continue_on_send: false,
|
continue_on_send: false,
|
||||||
trim_spaces: true,
|
trim_spaces: true,
|
||||||
|
relaxed_api_urls: false,
|
||||||
|
|
||||||
instruct: {
|
instruct: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@@ -176,6 +178,7 @@ let power_user = {
|
|||||||
preset: 'Alpaca',
|
preset: 'Alpaca',
|
||||||
separator_sequence: '',
|
separator_sequence: '',
|
||||||
macro: false,
|
macro: false,
|
||||||
|
names_force_groups: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
personas: {},
|
personas: {},
|
||||||
@@ -184,9 +187,12 @@ let power_user = {
|
|||||||
|
|
||||||
persona_description: '',
|
persona_description: '',
|
||||||
persona_description_position: persona_description_positions.BEFORE_CHAR,
|
persona_description_position: persona_description_positions.BEFORE_CHAR,
|
||||||
|
persona_show_notifications: true,
|
||||||
|
|
||||||
custom_stopping_strings: '',
|
custom_stopping_strings: '',
|
||||||
|
custom_stopping_strings_macro: true,
|
||||||
fuzzy_search: false,
|
fuzzy_search: false,
|
||||||
|
encode_tags: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let themes = [];
|
let themes = [];
|
||||||
@@ -670,6 +676,7 @@ function loadPowerUserSettings(settings, data) {
|
|||||||
power_user.chat_width = 50;
|
power_user.chat_width = 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$('#relaxed_api_urls').prop("checked", power_user.relaxed_api_urls);
|
||||||
$('#trim_spaces').prop("checked", power_user.trim_spaces);
|
$('#trim_spaces').prop("checked", power_user.trim_spaces);
|
||||||
$('#continue_on_send').prop("checked", power_user.continue_on_send);
|
$('#continue_on_send').prop("checked", power_user.continue_on_send);
|
||||||
$('#auto_swipe').prop("checked", power_user.auto_swipe);
|
$('#auto_swipe').prop("checked", power_user.auto_swipe);
|
||||||
@@ -677,7 +684,10 @@ function loadPowerUserSettings(settings, data) {
|
|||||||
$('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", "));
|
$('#auto_swipe_blacklist').val(power_user.auto_swipe_blacklist.join(", "));
|
||||||
$('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold);
|
$('#auto_swipe_blacklist_threshold').val(power_user.auto_swipe_blacklist_threshold);
|
||||||
$('#custom_stopping_strings').val(power_user.custom_stopping_strings);
|
$('#custom_stopping_strings').val(power_user.custom_stopping_strings);
|
||||||
|
$("#custom_stopping_strings_macro").prop("checked", power_user.custom_stopping_strings_macro);
|
||||||
$('#fuzzy_search_checkbox').prop("checked", power_user.fuzzy_search);
|
$('#fuzzy_search_checkbox').prop("checked", power_user.fuzzy_search);
|
||||||
|
$('#persona_show_notifications').prop("checked", power_user.persona_show_notifications);
|
||||||
|
$('#encode_tags').prop("checked", power_user.encode_tags);
|
||||||
|
|
||||||
$("#console_log_prompts").prop("checked", power_user.console_log_prompts);
|
$("#console_log_prompts").prop("checked", power_user.console_log_prompts);
|
||||||
$('#auto_fix_generated_markdown').prop("checked", power_user.auto_fix_generated_markdown);
|
$('#auto_fix_generated_markdown').prop("checked", power_user.auto_fix_generated_markdown);
|
||||||
@@ -848,8 +858,13 @@ function loadInstructMode() {
|
|||||||
{ id: "instruct_stop_sequence", property: "stop_sequence", isCheckbox: false },
|
{ id: "instruct_stop_sequence", property: "stop_sequence", isCheckbox: false },
|
||||||
{ id: "instruct_names", property: "names", isCheckbox: true },
|
{ id: "instruct_names", property: "names", isCheckbox: true },
|
||||||
{ id: "instruct_macro", property: "macro", isCheckbox: true },
|
{ id: "instruct_macro", property: "macro", isCheckbox: true },
|
||||||
|
{ id: "instruct_names_force_groups", property: "names_force_groups", isCheckbox: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (power_user.instruct.names_force_groups === undefined) {
|
||||||
|
power_user.instruct.names_force_groups = true;
|
||||||
|
}
|
||||||
|
|
||||||
controls.forEach(control => {
|
controls.forEach(control => {
|
||||||
const $element = $(`#${control.id}`);
|
const $element = $(`#${control.id}`);
|
||||||
|
|
||||||
@@ -860,7 +875,7 @@ function loadInstructMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$element.on('input', function () {
|
$element.on('input', function () {
|
||||||
power_user.instruct[control.property] = control.isCheckbox ? $(this).prop('checked') : $(this).val();
|
power_user.instruct[control.property] = control.isCheckbox ? !!$(this).prop('checked') : $(this).val();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -924,7 +939,12 @@ export function fuzzySearchCharacters(searchValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvatar, name1, name2) {
|
export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvatar, name1, name2) {
|
||||||
const includeNames = isNarrator ? false : (power_user.instruct.names || !!selected_group || !!forceAvatar);
|
let includeNames = isNarrator ? false : power_user.instruct.names;
|
||||||
|
|
||||||
|
if (!isNarrator && power_user.instruct.names_force_groups && (selected_group || forceAvatar)) {
|
||||||
|
includeNames = true;
|
||||||
|
}
|
||||||
|
|
||||||
let sequence = (isUser || isNarrator) ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
|
let sequence = (isUser || isNarrator) ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
|
||||||
|
|
||||||
if (power_user.instruct.macro) {
|
if (power_user.instruct.macro) {
|
||||||
@@ -952,7 +972,7 @@ export function formatInstructStoryString(story, systemPrompt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2) {
|
export function formatInstructModePrompt(name, isImpersonate, promptBias, name1, name2) {
|
||||||
const includeNames = power_user.instruct.names || !!selected_group;
|
const includeNames = power_user.instruct.names || (!!selected_group && power_user.instruct.names_force_groups);
|
||||||
let sequence = isImpersonate ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
|
let sequence = isImpersonate ? power_user.instruct.input_sequence : power_user.instruct.output_sequence;
|
||||||
|
|
||||||
if (power_user.instruct.macro) {
|
if (power_user.instruct.macro) {
|
||||||
@@ -1977,6 +1997,12 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#relaxed_api_urls").on("input", function () {
|
||||||
|
const value = !!$(this).prop('checked');
|
||||||
|
power_user.relaxed_api_urls = value;
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$('#spoiler_free_mode').on('input', function () {
|
$('#spoiler_free_mode').on('input', function () {
|
||||||
power_user.spoiler_free_mode = !!$(this).prop('checked');
|
power_user.spoiler_free_mode = !!$(this).prop('checked');
|
||||||
switchSpoilerMode();
|
switchSpoilerMode();
|
||||||
@@ -1993,11 +2019,27 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$("#custom_stopping_strings_macro").change(function () {
|
||||||
|
power_user.custom_stopping_strings_macro = !!$(this).prop("checked");
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$('#fuzzy_search_checkbox').on('input', function () {
|
$('#fuzzy_search_checkbox').on('input', function () {
|
||||||
power_user.fuzzy_search = !!$(this).prop('checked');
|
power_user.fuzzy_search = !!$(this).prop('checked');
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#persona_show_notifications').on('input', function () {
|
||||||
|
power_user.persona_show_notifications = !!$(this).prop('checked');
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#encode_tags').on('input', async function () {
|
||||||
|
power_user.encode_tags = !!$(this).prop('checked');
|
||||||
|
await reloadCurrentChat();
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$(window).on('focus', function () {
|
$(window).on('focus', function () {
|
||||||
browser_has_focus = true;
|
browser_has_focus = true;
|
||||||
});
|
});
|
||||||
|
@@ -2,6 +2,7 @@ import { callPopup, getRequestHeaders } from "../script.js";
|
|||||||
|
|
||||||
export const SECRET_KEYS = {
|
export const SECRET_KEYS = {
|
||||||
HORDE: 'api_key_horde',
|
HORDE: 'api_key_horde',
|
||||||
|
MANCER: 'api_key_mancer',
|
||||||
OPENAI: 'api_key_openai',
|
OPENAI: 'api_key_openai',
|
||||||
NOVEL: 'api_key_novel',
|
NOVEL: 'api_key_novel',
|
||||||
CLAUDE: 'api_key_claude',
|
CLAUDE: 'api_key_claude',
|
||||||
@@ -11,6 +12,7 @@ export const SECRET_KEYS = {
|
|||||||
|
|
||||||
const INPUT_MAP = {
|
const INPUT_MAP = {
|
||||||
[SECRET_KEYS.HORDE]: '#horde_api_key',
|
[SECRET_KEYS.HORDE]: '#horde_api_key',
|
||||||
|
[SECRET_KEYS.MANCER]: '#api_key_mancer',
|
||||||
[SECRET_KEYS.OPENAI]: '#api_key_openai',
|
[SECRET_KEYS.OPENAI]: '#api_key_openai',
|
||||||
[SECRET_KEYS.NOVEL]: '#api_key_novel',
|
[SECRET_KEYS.NOVEL]: '#api_key_novel',
|
||||||
[SECRET_KEYS.CLAUDE]: '#api_key_claude',
|
[SECRET_KEYS.CLAUDE]: '#api_key_claude',
|
||||||
|
@@ -423,7 +423,11 @@ function helpCommandCallback(_, type) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window['displayHelp'] = (page) => helpCommandCallback(null, page);
|
$(document).on('click', '[data-displayHelp]', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const page = String($(this).data('displayhelp'));
|
||||||
|
helpCommandCallback(null, page);
|
||||||
|
});
|
||||||
|
|
||||||
function setBackgroundCallback(_, bg) {
|
function setBackgroundCallback(_, bg) {
|
||||||
if (!bg) {
|
if (!bg) {
|
||||||
|
@@ -499,7 +499,7 @@ function onViewTagsListClick() {
|
|||||||
$(list).append('<h3>Tags</h3><i>Click on the tag name to edit it.</i><br>');
|
$(list).append('<h3>Tags</h3><i>Click on the tag name to edit it.</i><br>');
|
||||||
$(list).append('<i>Click on color box to assign new color.</i><br><br>');
|
$(list).append('<i>Click on color box to assign new color.</i><br><br>');
|
||||||
|
|
||||||
for (const tag of tags) {
|
for (const tag of tags.slice().sort((a, b) => a?.name?.localeCompare(b?.name))) {
|
||||||
const count = everything.filter(x => x == tag.id).length;
|
const count = everything.filter(x => x == tag.id).length;
|
||||||
const template = $('#tag_view_template .tag_view_item').clone();
|
const template = $('#tag_view_template .tag_view_item').clone();
|
||||||
template.attr('id', tag.id);
|
template.attr('id', tag.id);
|
||||||
|
@@ -6,10 +6,15 @@ import {
|
|||||||
setGenerationParamsFromPreset,
|
setGenerationParamsFromPreset,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
power_user,
|
||||||
|
} from "./power-user.js";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
textgenerationwebui_settings,
|
textgenerationwebui_settings,
|
||||||
loadTextGenSettings,
|
loadTextGenSettings,
|
||||||
generateTextGenWithStreaming,
|
generateTextGenWithStreaming,
|
||||||
|
formatTextGenURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
const textgenerationwebui_settings = {
|
const textgenerationwebui_settings = {
|
||||||
@@ -94,6 +99,23 @@ function selectPreset(name) {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatTextGenURL(value, use_mancer) {
|
||||||
|
try {
|
||||||
|
const url = new URL(value);
|
||||||
|
if (!power_user.relaxed_api_urls) {
|
||||||
|
if (use_mancer) { // If Mancer is in use, only require the URL to *end* with `/api`.
|
||||||
|
if (!url.pathname.endsWith('/api')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
url.pathname = '/api';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return url.toString();
|
||||||
|
} catch { } // Just using URL as a validation check
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function convertPresets(presets) {
|
function convertPresets(presets) {
|
||||||
return Array.isArray(presets) ? presets.map(JSON.parse) : [];
|
return Array.isArray(presets) ? presets.map(JSON.parse) : [];
|
||||||
}
|
}
|
||||||
|
@@ -1,154 +0,0 @@
|
|||||||
import cloneDeep from 'lodash.clonedeep';
|
|
||||||
|
|
||||||
import userAgents from './user-agents.json';
|
|
||||||
|
|
||||||
|
|
||||||
// Normalizes the total weight to 1 and constructs a cumulative distribution.
|
|
||||||
const makeCumulativeWeightIndexPairs = (weightIndexPairs) => {
|
|
||||||
const totalWeight = weightIndexPairs.reduce((sum, [weight]) => sum + weight, 0);
|
|
||||||
let sum = 0;
|
|
||||||
return weightIndexPairs.map(([weight, index]) => {
|
|
||||||
sum += weight / totalWeight;
|
|
||||||
return [sum, index];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Precompute these so that we can quickly generate unfiltered user agents.
|
|
||||||
const defaultWeightIndexPairs = userAgents.map(({ weight }, index) => [weight, index]);
|
|
||||||
const defaultCumulativeWeightIndexPairs = makeCumulativeWeightIndexPairs(defaultWeightIndexPairs);
|
|
||||||
|
|
||||||
|
|
||||||
// Turn the various filter formats into a single filter function that acts on raw user agents.
|
|
||||||
const constructFilter = (filters, accessor = parentObject => parentObject) => {
|
|
||||||
let childFilters;
|
|
||||||
if (typeof filters === 'function') {
|
|
||||||
childFilters = [filters];
|
|
||||||
} else if (filters instanceof RegExp) {
|
|
||||||
childFilters = [
|
|
||||||
value => (
|
|
||||||
typeof value === 'object' && value && value.userAgent
|
|
||||||
? filters.test(value.userAgent)
|
|
||||||
: filters.test(value)
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} else if (filters instanceof Array) {
|
|
||||||
childFilters = filters.map(childFilter => constructFilter(childFilter));
|
|
||||||
} else if (typeof filters === 'object') {
|
|
||||||
childFilters = Object.entries(filters).map(([key, valueFilter]) => (
|
|
||||||
constructFilter(valueFilter, parentObject => parentObject[key])
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
childFilters = [
|
|
||||||
value => (
|
|
||||||
typeof value === 'object' && value && value.userAgent
|
|
||||||
? filters === value.userAgent
|
|
||||||
: filters === value
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return (parentObject) => {
|
|
||||||
try {
|
|
||||||
const value = accessor(parentObject);
|
|
||||||
return childFilters.every(childFilter => childFilter(value));
|
|
||||||
} catch (error) {
|
|
||||||
// This happens when a user-agent lacks a nested property.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Construct normalized cumulative weight index pairs given the filters.
|
|
||||||
const constructCumulativeWeightIndexPairsFromFilters = (filters) => {
|
|
||||||
if (!filters) {
|
|
||||||
return defaultCumulativeWeightIndexPairs;
|
|
||||||
}
|
|
||||||
|
|
||||||
const filter = constructFilter(filters);
|
|
||||||
|
|
||||||
const weightIndexPairs = [];
|
|
||||||
userAgents.forEach((rawUserAgent, index) => {
|
|
||||||
if (filter(rawUserAgent)) {
|
|
||||||
weightIndexPairs.push([rawUserAgent.weight, index]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return makeCumulativeWeightIndexPairs(weightIndexPairs);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const setCumulativeWeightIndexPairs = (userAgent, cumulativeWeightIndexPairs) => {
|
|
||||||
Object.defineProperty(userAgent, 'cumulativeWeightIndexPairs', {
|
|
||||||
configurable: true,
|
|
||||||
enumerable: false,
|
|
||||||
writable: false,
|
|
||||||
value: cumulativeWeightIndexPairs,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default class UserAgent extends Function {
|
|
||||||
constructor(filters) {
|
|
||||||
super();
|
|
||||||
setCumulativeWeightIndexPairs(this, constructCumulativeWeightIndexPairsFromFilters(filters));
|
|
||||||
if (this.cumulativeWeightIndexPairs.length === 0) {
|
|
||||||
throw new Error('No user agents matched your filters.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.randomize();
|
|
||||||
|
|
||||||
return new Proxy(this, {
|
|
||||||
apply: () => this.random(),
|
|
||||||
get: (target, property, receiver) => {
|
|
||||||
const dataCandidate = target.data && typeof property === 'string'
|
|
||||||
&& Object.prototype.hasOwnProperty.call(target.data, property)
|
|
||||||
&& Object.prototype.propertyIsEnumerable.call(target.data, property);
|
|
||||||
if (dataCandidate) {
|
|
||||||
const value = target.data[property];
|
|
||||||
if (value !== undefined) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Reflect.get(target, property, receiver);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static random = (filters) => {
|
|
||||||
try {
|
|
||||||
return new UserAgent(filters);
|
|
||||||
} catch (error) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
|
||||||
// Standard Object Methods
|
|
||||||
//
|
|
||||||
|
|
||||||
[Symbol.toPrimitive] = () => (
|
|
||||||
this.data.userAgent
|
|
||||||
);
|
|
||||||
|
|
||||||
toString = () => (
|
|
||||||
this.data.userAgent
|
|
||||||
);
|
|
||||||
|
|
||||||
random = () => {
|
|
||||||
const userAgent = new UserAgent();
|
|
||||||
setCumulativeWeightIndexPairs(userAgent, this.cumulativeWeightIndexPairs);
|
|
||||||
userAgent.randomize();
|
|
||||||
return userAgent;
|
|
||||||
};
|
|
||||||
|
|
||||||
randomize = () => {
|
|
||||||
// Find a random raw random user agent.
|
|
||||||
const randomNumber = Math.random();
|
|
||||||
const [, index] = this.cumulativeWeightIndexPairs
|
|
||||||
.find(([cumulativeWeight]) => cumulativeWeight > randomNumber);
|
|
||||||
const rawUserAgent = userAgents[index];
|
|
||||||
|
|
||||||
this.data = cloneDeep(rawUserAgent);
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,10 @@ export function onlyUnique(value, index, array) {
|
|||||||
return array.indexOf(value) === index;
|
return array.indexOf(value) === index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isDigitsOnly(str) {
|
||||||
|
return /^\d+$/.test(str);
|
||||||
|
}
|
||||||
|
|
||||||
export function shuffle(array) {
|
export function shuffle(array) {
|
||||||
let currentIndex = array.length,
|
let currentIndex = array.length,
|
||||||
randomIndex;
|
randomIndex;
|
||||||
|
@@ -1511,7 +1511,7 @@ jQuery(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$('#world_info_overflow_alert').on('change', function () {
|
$('#world_info_overflow_alert').on('change', function () {
|
||||||
world_info_overflow_alert = $(this).val();
|
world_info_overflow_alert = !!$(this).prop('checked');
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -217,12 +217,22 @@ table.responsiveTable {
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mes_text q,
|
.mes_text q {
|
||||||
.mes_text blockquote {
|
|
||||||
color: var(--SmartThemeQuoteColor);
|
color: var(--SmartThemeQuoteColor);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mes_text rp {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mes_text blockquote {
|
||||||
|
border-left: 3px solid var(--SmartThemeQuoteColor);
|
||||||
|
padding-left: 10px;
|
||||||
|
background-color: var(--black30a);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.mes_text strong em,
|
.mes_text strong em,
|
||||||
.mes_text strong,
|
.mes_text strong,
|
||||||
.mes_text h2,
|
.mes_text h2,
|
||||||
@@ -948,10 +958,6 @@ select {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rm_ch_create_block textarea {
|
|
||||||
min-height: 190px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.margin-bot-10px,
|
.margin-bot-10px,
|
||||||
.marginBot10 {
|
.marginBot10 {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
@@ -1293,7 +1299,8 @@ body.charListGrid #rm_print_characters_block .tags_inline {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating_prompt_radio_group, .radio_group {
|
.floating_prompt_radio_group,
|
||||||
|
.radio_group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
@@ -1717,11 +1724,14 @@ body.big-avatars .ch_description {
|
|||||||
|
|
||||||
|
|
||||||
#form_create {
|
#form_create {
|
||||||
display: grid;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
grid-template-rows:
|
}
|
||||||
[avatar] min-content [hr] min-content [descriptionHeader] min-content [description] auto [firstmessageHeader] min-content [firstMessage] auto [hidden] min-content;
|
|
||||||
|
#form_create textarea {
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar_div {
|
.avatar_div {
|
||||||
@@ -1752,7 +1762,6 @@ body.big-avatars #avatar_div_div.avatar img {
|
|||||||
#avatar-and-name-block {
|
#avatar-and-name-block {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 0 0 100%;
|
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
/* margin-bottom: 4px; */
|
/* margin-bottom: 4px; */
|
||||||
}
|
}
|
||||||
@@ -2155,6 +2164,9 @@ grammarly-extension {
|
|||||||
transition: background-color 200ms ease-in-out;
|
transition: background-color 200ms ease-in-out;
|
||||||
position: relative;
|
position: relative;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
#kobold_order>div:hover {
|
#kobold_order>div:hover {
|
||||||
@@ -2767,7 +2779,6 @@ input[type="range"]::-webkit-slider-thumb {
|
|||||||
#power-user-option-checkboxes {
|
#power-user-option-checkboxes {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
row-gap: 5px;
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3040,9 +3051,23 @@ h5 {
|
|||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.PastChat_cross:hover {
|
.PastChat_cross:hover {
|
||||||
color: red;
|
color: red;
|
||||||
filter: drop-shadow(0 0 2px red);
|
filter: drop-shadow(0 0 2px red);
|
||||||
|
-webkit-animation: infinite-spinning 1s ease-out 0s infinite normal;
|
||||||
|
animation: infinite-spinning 1s ease-out 0s infinite normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* HEINOUS */
|
||||||
|
@keyframes infinite-spinning {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#export_character_div {
|
#export_character_div {
|
||||||
@@ -4409,6 +4434,10 @@ toolcool-color-picker {
|
|||||||
width: 50px;
|
width: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.indent20p {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.wi-enter-footer-text {
|
.wi-enter-footer-text {
|
||||||
font-size: calc(var(--mainFontSize) * 0.8);
|
font-size: calc(var(--mainFontSize) * 0.8);
|
||||||
color: var(--SmartThemeBodyColor);
|
color: var(--SmartThemeBodyColor);
|
||||||
@@ -5083,11 +5112,6 @@ body.waifuMode .zoomed_avatar {
|
|||||||
margin: 5px auto;
|
margin: 5px auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#form_create {
|
|
||||||
grid-template-rows:
|
|
||||||
[avatar] min-content [hr] min-content [descriptionHeader] min-content [description] auto [firstmessageHeader] min-content [firstMessage] auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#result_info {
|
#result_info {
|
||||||
font-size: calc(var(--mainFontSize) - .1rem);
|
font-size: calc(var(--mainFontSize) - .1rem);
|
||||||
}
|
}
|
||||||
@@ -5103,10 +5127,6 @@ body.waifuMode .zoomed_avatar {
|
|||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#rm_ch_create_block textarea {
|
|
||||||
max-height: 190px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.drawer25pWidth {
|
.drawer25pWidth {
|
||||||
flex-basis: max(calc(100% / 4 - 10px), 190px);
|
flex-basis: max(calc(100% / 4 - 10px), 190px);
|
||||||
}
|
}
|
||||||
|
232
server.js
232
server.js
@@ -34,7 +34,11 @@ if (net.setDefaultAutoSelectFamily) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cliArguments = yargs(hideBin(process.argv))
|
const cliArguments = yargs(hideBin(process.argv))
|
||||||
.option('ssl', {
|
.option('disableCsrf', {
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
describe: 'Disables CSRF protection'
|
||||||
|
}).option('ssl', {
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
default: false,
|
default: false,
|
||||||
describe: 'Enables SSL'
|
describe: 'Enables SSL'
|
||||||
@@ -119,10 +123,15 @@ const allowKeysExposure = config.allowKeysExposure;
|
|||||||
const axios = require('axios');
|
const axios = require('axios');
|
||||||
const tiktoken = require('@dqbd/tiktoken');
|
const tiktoken = require('@dqbd/tiktoken');
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
const AIHorde = require("./src/horde");
|
|
||||||
const ai_horde = new AIHorde({
|
function getHordeClient() {
|
||||||
client_agent: getVersion()?.agent || 'SillyTavern:UNKNOWN:Cohee#1207',
|
const AIHorde = require("./src/horde");
|
||||||
});
|
const ai_horde = new AIHorde({
|
||||||
|
client_agent: getVersion()?.agent || 'SillyTavern:UNKNOWN:Cohee#1207',
|
||||||
|
});
|
||||||
|
return ai_horde;
|
||||||
|
}
|
||||||
|
|
||||||
const ipMatching = require('ip-matching');
|
const ipMatching = require('ip-matching');
|
||||||
const yauzl = require('yauzl');
|
const yauzl = require('yauzl');
|
||||||
|
|
||||||
@@ -146,6 +155,14 @@ let response_getstatus;
|
|||||||
let first_run = true;
|
let first_run = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function get_mancer_headers() {
|
||||||
|
const api_key_mancer = readSecret(SECRET_KEYS.MANCER);
|
||||||
|
return api_key_mancer ? { "X-API-KEY": api_key_mancer } : {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//RossAscends: Added function to format dates used in files and chat timestamps to a humanized format.
|
//RossAscends: Added function to format dates used in files and chat timestamps to a humanized format.
|
||||||
//Mostly I wanted this to be for file names, but couldn't figure out exactly where the filename save code was as everything seemed to be connected.
|
//Mostly I wanted this to be for file names, but couldn't figure out exactly where the filename save code was as everything seemed to be connected.
|
||||||
//During testing, this performs the same as previous date.now() structure.
|
//During testing, this performs the same as previous date.now() structure.
|
||||||
@@ -178,13 +195,19 @@ async function loadSentencepieceTokenizer(modelPath) {
|
|||||||
async function countSentencepieceTokens(spp, text) {
|
async function countSentencepieceTokens(spp, text) {
|
||||||
// Fallback to strlen estimation
|
// Fallback to strlen estimation
|
||||||
if (!spp) {
|
if (!spp) {
|
||||||
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
return {
|
||||||
|
ids: [],
|
||||||
|
count: Math.ceil(text.length / CHARS_PER_TOKEN)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let cleaned = cleanText(text);
|
let cleaned = text; // cleanText(text); <-- cleaning text can result in an incorrect tokenization
|
||||||
|
|
||||||
let ids = spp.encodeIds(cleaned);
|
let ids = spp.encodeIds(cleaned);
|
||||||
return ids.length;
|
return {
|
||||||
|
ids,
|
||||||
|
count: ids.length
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadClaudeTokenizer(modelPath) {
|
async function loadClaudeTokenizer(modelPath) {
|
||||||
@@ -294,31 +317,40 @@ const directories = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// CSRF Protection //
|
// CSRF Protection //
|
||||||
const doubleCsrf = require('csrf-csrf').doubleCsrf;
|
if (cliArguments.disableCsrf === false) {
|
||||||
|
const doubleCsrf = require('csrf-csrf').doubleCsrf;
|
||||||
|
|
||||||
const CSRF_SECRET = crypto.randomBytes(8).toString('hex');
|
const CSRF_SECRET = crypto.randomBytes(8).toString('hex');
|
||||||
const COOKIES_SECRET = crypto.randomBytes(8).toString('hex');
|
const COOKIES_SECRET = crypto.randomBytes(8).toString('hex');
|
||||||
|
|
||||||
const { generateToken, doubleCsrfProtection } = doubleCsrf({
|
const { generateToken, doubleCsrfProtection } = doubleCsrf({
|
||||||
getSecret: () => CSRF_SECRET,
|
getSecret: () => CSRF_SECRET,
|
||||||
cookieName: "X-CSRF-Token",
|
cookieName: "X-CSRF-Token",
|
||||||
cookieOptions: {
|
cookieOptions: {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
sameSite: "strict",
|
sameSite: "strict",
|
||||||
secure: false
|
secure: false
|
||||||
},
|
},
|
||||||
size: 64,
|
size: 64,
|
||||||
getTokenFromRequest: (req) => req.headers["x-csrf-token"]
|
getTokenFromRequest: (req) => req.headers["x-csrf-token"]
|
||||||
});
|
|
||||||
|
|
||||||
app.get("/csrf-token", (req, res) => {
|
|
||||||
res.json({
|
|
||||||
"token": generateToken(res)
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
app.use(cookieParser(COOKIES_SECRET));
|
app.get("/csrf-token", (req, res) => {
|
||||||
app.use(doubleCsrfProtection);
|
res.json({
|
||||||
|
"token": generateToken(res)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use(cookieParser(COOKIES_SECRET));
|
||||||
|
app.use(doubleCsrfProtection);
|
||||||
|
} else {
|
||||||
|
console.warn("\nCSRF protection is disabled. This will make your server vulnerable to CSRF attacks.\n");
|
||||||
|
app.get("/csrf-token", (req, res) => {
|
||||||
|
res.json({
|
||||||
|
"token": 'disabled'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// CORS Settings //
|
// CORS Settings //
|
||||||
const cors = require('cors');
|
const cors = require('cors');
|
||||||
@@ -506,8 +538,16 @@ app.post("/generate", jsonParser, async function (request, response_generate = r
|
|||||||
return response.body.pipe(response_generate);
|
return response.body.pipe(response_generate);
|
||||||
} else {
|
} else {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.log(`Kobold returned error: ${response.status} ${response.statusText} ${await response.text()}`);
|
const errorText = await response.text();
|
||||||
return response.status(response.status).send({ error: true });
|
console.log(`Kobold returned error: ${response.status} ${response.statusText} ${errorText}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const errorJson = JSON.parse(errorText);
|
||||||
|
const message = errorJson?.detail?.msg || errorText;
|
||||||
|
return response_generate.status(400).send({ error: { message } });
|
||||||
|
} catch {
|
||||||
|
return response_generate.status(400).send({ error: { message: errorText } });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -626,13 +666,22 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
|||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (request.body.use_mancer) {
|
||||||
|
args.headers = Object.assign(args.headers, get_mancer_headers());
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await postAsync(api_server + "/v1/generate", args);
|
const data = await postAsync(api_server + "/v1/generate", args);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
return response_generate.send(data);
|
return response_generate.send(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
retval = { error: true, status: error.status, response: error.statusText };
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return response_generate.send({ error: true });
|
try {
|
||||||
|
retval.response = await error.json();
|
||||||
|
retval.response = retval.response.result;
|
||||||
|
} catch { }
|
||||||
|
return response_generate.send(retval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -696,6 +745,11 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus =
|
|||||||
var args = {
|
var args = {
|
||||||
headers: { "Content-Type": "application/json" }
|
headers: { "Content-Type": "application/json" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
|
||||||
|
args.headers = Object.assign(args.headers, get_mancer_headers());
|
||||||
|
}
|
||||||
|
|
||||||
var url = api_server + "/v1/model";
|
var url = api_server + "/v1/model";
|
||||||
let version = '';
|
let version = '';
|
||||||
let koboldVersion = {};
|
let koboldVersion = {};
|
||||||
@@ -716,18 +770,18 @@ app.post("/getstatus", jsonParser, async function (request, response_getstatus =
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
client.get(url, args, function (data, response) {
|
client.get(url, args, async function (data, response) {
|
||||||
if (typeof data !== 'object') {
|
if (typeof data !== 'object') {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
data.version = version;
|
data.version = version;
|
||||||
data.koboldVersion = koboldVersion;
|
data.koboldVersion = koboldVersion;
|
||||||
if (data.result != "ReadOnly") {
|
if (data.result == "ReadOnly") {
|
||||||
} else {
|
|
||||||
data.result = "no_connection";
|
data.result = "no_connection";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
data.response = data.result;
|
||||||
data.result = "no_connection";
|
data.result = "no_connection";
|
||||||
}
|
}
|
||||||
response_getstatus.send(data);
|
response_getstatus.send(data);
|
||||||
@@ -1133,7 +1187,7 @@ app.post("/deletecharacter", jsonParser, async function (request, response) {
|
|||||||
return response.sendStatus(403);
|
return response.sendStatus(403);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.body.delete_chats == 'true') {
|
if (request.body.delete_chats == true) {
|
||||||
try {
|
try {
|
||||||
await fs.promises.rm(path.join(chatsPath, sanitize(dir_name)), { recursive: true, force: true })
|
await fs.promises.rm(path.join(chatsPath, sanitize(dir_name)), { recursive: true, force: true })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -1755,13 +1809,12 @@ app.post("/getstatus_novelai", jsonParser, function (request, response_getstatus
|
|||||||
const api_key_novel = readSecret(SECRET_KEYS.NOVEL);
|
const api_key_novel = readSecret(SECRET_KEYS.NOVEL);
|
||||||
|
|
||||||
if (!api_key_novel) {
|
if (!api_key_novel) {
|
||||||
return response_generate_novel.sendStatus(401);
|
return response_getstatus_novel.sendStatus(401);
|
||||||
}
|
}
|
||||||
|
|
||||||
var data = {};
|
var data = {};
|
||||||
var args = {
|
var args = {
|
||||||
data: data,
|
data: data,
|
||||||
|
|
||||||
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + api_key_novel }
|
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + api_key_novel }
|
||||||
};
|
};
|
||||||
client.get(api_novelai + "/user/subscription", args, function (data, response) {
|
client.get(api_novelai + "/user/subscription", args, function (data, response) {
|
||||||
@@ -1769,17 +1822,15 @@ app.post("/getstatus_novelai", jsonParser, function (request, response_getstatus
|
|||||||
//console.log(data);
|
//console.log(data);
|
||||||
response_getstatus_novel.send(data);//data);
|
response_getstatus_novel.send(data);//data);
|
||||||
}
|
}
|
||||||
if (response.statusCode == 401) {
|
else {
|
||||||
console.log('Access Token is incorrect.');
|
if (response.statusCode == 401) {
|
||||||
response_getstatus_novel.send({ error: true });
|
console.log('Access Token is incorrect.');
|
||||||
}
|
}
|
||||||
if (response.statusCode == 500 || response.statusCode == 501 || response.statusCode == 501 || response.statusCode == 503 || response.statusCode == 507) {
|
|
||||||
console.log(data);
|
console.log(data);
|
||||||
response_getstatus_novel.send({ error: true });
|
response_getstatus_novel.send({ error: true });
|
||||||
}
|
}
|
||||||
}).on('error', function () {
|
}).on('error', function () {
|
||||||
//console.log('');
|
|
||||||
//console.log('something went wrong on the request', err.request.options);
|
|
||||||
response_getstatus_novel.send({ error: true });
|
response_getstatus_novel.send({ error: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1824,6 +1875,7 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
|||||||
"cfg_scale": request.body.cfg_scale,
|
"cfg_scale": request.body.cfg_scale,
|
||||||
"cfg_uc": request.body.cfg_uc,
|
"cfg_uc": request.body.cfg_uc,
|
||||||
"phrase_rep_pen": request.body.phrase_rep_pen,
|
"phrase_rep_pen": request.body.phrase_rep_pen,
|
||||||
|
"stop_sequences": request.body.stop_sequences,
|
||||||
//"stop_sequences": {{187}},
|
//"stop_sequences": {{187}},
|
||||||
"bad_words_ids": isNewModel ? novelai.badWordsList : (isKrake ? novelai.krakeBadWordsList : novelai.euterpeBadWordsList),
|
"bad_words_ids": isNewModel ? novelai.badWordsList : (isKrake ? novelai.krakeBadWordsList : novelai.euterpeBadWordsList),
|
||||||
"logit_bias_exp": isNewModel ? novelai.logitBiasExp : null,
|
"logit_bias_exp": isNewModel ? novelai.logitBiasExp : null,
|
||||||
@@ -1864,8 +1916,19 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.log(`Novel API returned error: ${response.status} ${response.statusText} ${await response.text()}`);
|
const text = await response.text();
|
||||||
return response.status(response.status).send({ error: true });
|
let message = text;
|
||||||
|
console.log(`Novel API returned error: ${response.status} ${response.statusText} ${text}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(text);
|
||||||
|
message = data.message;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
|
||||||
|
return response_generate_novel.status(response.status).send({ error: { message } });
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
@@ -1923,14 +1986,16 @@ app.post("/getallchatsofcharacter", jsonParser, function (request, response) {
|
|||||||
ii--;
|
ii--;
|
||||||
if (lastLine) {
|
if (lastLine) {
|
||||||
|
|
||||||
let jsonData = json5.parse(lastLine);
|
let jsonData = tryParse(lastLine);
|
||||||
if (jsonData.name !== undefined || jsonData.character_name !== undefined) {
|
if (jsonData && (jsonData.name !== undefined || jsonData.character_name !== undefined)) {
|
||||||
chatData[i] = {};
|
chatData[i] = {};
|
||||||
chatData[i]['file_name'] = file;
|
chatData[i]['file_name'] = file;
|
||||||
chatData[i]['file_size'] = fileSizeInKB;
|
chatData[i]['file_size'] = fileSizeInKB;
|
||||||
chatData[i]['chat_items'] = itemCounter - 1;
|
chatData[i]['chat_items'] = itemCounter - 1;
|
||||||
chatData[i]['mes'] = jsonData['mes'] || '[The chat is empty]';
|
chatData[i]['mes'] = jsonData['mes'] || '[The chat is empty]';
|
||||||
chatData[i]['last_mes'] = jsonData['send_date'] || Date.now();
|
chatData[i]['last_mes'] = jsonData['send_date'] || Date.now();
|
||||||
|
} else {
|
||||||
|
console.log('Found an invalid or corrupted chat file: ' + fullPathAndFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ii === 0) {
|
if (ii === 0) {
|
||||||
@@ -3174,16 +3239,19 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
|||||||
let api_url;
|
let api_url;
|
||||||
let api_key_openai;
|
let api_key_openai;
|
||||||
let headers;
|
let headers;
|
||||||
|
let bodyParams;
|
||||||
|
|
||||||
if (!request.body.use_openrouter) {
|
if (!request.body.use_openrouter) {
|
||||||
api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
||||||
api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.OPENAI);
|
api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.OPENAI);
|
||||||
headers = {};
|
headers = {};
|
||||||
|
bodyParams = {};
|
||||||
} else {
|
} else {
|
||||||
api_url = 'https://openrouter.ai/api/v1';
|
api_url = 'https://openrouter.ai/api/v1';
|
||||||
api_key_openai = readSecret(SECRET_KEYS.OPENROUTER);
|
api_key_openai = readSecret(SECRET_KEYS.OPENROUTER);
|
||||||
// OpenRouter needs to pass the referer: https://openrouter.ai/docs
|
// OpenRouter needs to pass the referer: https://openrouter.ai/docs
|
||||||
headers = { 'HTTP-Referer': request.headers.referer };
|
headers = { 'HTTP-Referer': request.headers.referer };
|
||||||
|
bodyParams = { 'transforms': ["middle-out"] };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!api_key_openai && !request.body.reverse_proxy) {
|
if (!api_key_openai && !request.body.reverse_proxy) {
|
||||||
@@ -3220,7 +3288,8 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
|||||||
"top_p": request.body.top_p,
|
"top_p": request.body.top_p,
|
||||||
"top_k": request.body.top_k,
|
"top_k": request.body.top_k,
|
||||||
"stop": request.body.stop,
|
"stop": request.body.stop,
|
||||||
"logit_bias": request.body.logit_bias
|
"logit_bias": request.body.logit_bias,
|
||||||
|
...bodyParams,
|
||||||
},
|
},
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
};
|
};
|
||||||
@@ -3258,7 +3327,22 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
|||||||
makeRequest(config, response_generate_openai, request, retries - 1);
|
makeRequest(config, response_generate_openai, request, retries - 1);
|
||||||
}, timeout);
|
}, timeout);
|
||||||
} else {
|
} else {
|
||||||
handleError(error, response_generate_openai, request);
|
let errorData = error?.response?.data;
|
||||||
|
|
||||||
|
if (request.body.stream) {
|
||||||
|
try {
|
||||||
|
const chunks = await readAllChunks(errorData);
|
||||||
|
const blob = new Blob(chunks, { type: 'application/json' });
|
||||||
|
const text = await blob.text();
|
||||||
|
errorData = JSON.parse(text);
|
||||||
|
} catch {
|
||||||
|
console.warn('Error parsing streaming response');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errorData = typeof errorData === 'string' ? tryParse(errorData) : errorData;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleError(error, response_generate_openai, errorData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3270,27 +3354,28 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleError(error, response_generate_openai, request) {
|
function handleError(error, response_generate_openai, errorData) {
|
||||||
console.error('Error:', error.message);
|
console.error('Error:', error?.message);
|
||||||
|
|
||||||
let message = error?.response?.statusText;
|
let message = error?.response?.statusText;
|
||||||
|
|
||||||
switch (error?.response?.status) {
|
const statusMessages = {
|
||||||
case 402:
|
400: 'Bad request',
|
||||||
message = 'Credit limit reached';
|
401: 'Unauthorized',
|
||||||
console.log(message);
|
402: 'Credit limit reached',
|
||||||
break;
|
403: 'Forbidden',
|
||||||
case 403:
|
404: 'Not found',
|
||||||
message = 'API key disabled or exhausted';
|
429: 'Too many requests',
|
||||||
console.log(message);
|
451: 'Unavailable for legal reasons',
|
||||||
break;
|
};
|
||||||
case 451:
|
|
||||||
message = error?.response?.data?.error?.message || 'Unavailable for legal reasons';
|
const status = error?.response?.status;
|
||||||
console.log(message);
|
if (statusMessages.hasOwnProperty(status)) {
|
||||||
break;
|
message = errorData?.error?.message || statusMessages[status];
|
||||||
|
console.log(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const quota_error = error?.response?.status === 429 && error?.response?.data?.error?.type === 'insufficient_quota';
|
const quota_error = error?.response?.status === 429 && errorData?.error?.type === 'insufficient_quota';
|
||||||
const response = { error: { message }, quota_error: quota_error }
|
const response = { error: { message }, quota_error: quota_error }
|
||||||
if (!response_generate_openai.headersSent) {
|
if (!response_generate_openai.headersSent) {
|
||||||
response_generate_openai.send(response);
|
response_generate_openai.send(response);
|
||||||
@@ -3415,8 +3500,8 @@ function createTokenizationHandler(getTokenizerFn) {
|
|||||||
|
|
||||||
const text = request.body.text || '';
|
const text = request.body.text || '';
|
||||||
const tokenizer = getTokenizerFn();
|
const tokenizer = getTokenizerFn();
|
||||||
const count = await countSentencepieceTokens(tokenizer, text);
|
const { ids, count } = await countSentencepieceTokens(tokenizer, text);
|
||||||
return response.send({ count });
|
return response.send({ ids, count });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3435,6 +3520,10 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
|
|||||||
headers: { "Content-Type": "application/json" }
|
headers: { "Content-Type": "application/json" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
|
||||||
|
args.headers = Object.assign(args.headers, get_mancer_headers());
|
||||||
|
}
|
||||||
|
|
||||||
const data = await postAsync(api_server + "/v1/token-count", args);
|
const data = await postAsync(api_server + "/v1/token-count", args);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
return response.send({ count: data['results'][0]['tokens'] });
|
return response.send({ count: data['results'][0]['tokens'] });
|
||||||
@@ -3640,6 +3729,7 @@ const SECRETS_FILE = './secrets.json';
|
|||||||
const SETTINGS_FILE = './public/settings.json';
|
const SETTINGS_FILE = './public/settings.json';
|
||||||
const SECRET_KEYS = {
|
const SECRET_KEYS = {
|
||||||
HORDE: 'api_key_horde',
|
HORDE: 'api_key_horde',
|
||||||
|
MANCER: 'api_key_mancer',
|
||||||
OPENAI: 'api_key_openai',
|
OPENAI: 'api_key_openai',
|
||||||
NOVEL: 'api_key_novel',
|
NOVEL: 'api_key_novel',
|
||||||
CLAUDE: 'api_key_claude',
|
CLAUDE: 'api_key_claude',
|
||||||
@@ -3771,6 +3861,7 @@ app.post('/viewsecrets', jsonParser, async (_, response) => {
|
|||||||
|
|
||||||
app.post('/horde_samplers', jsonParser, async (_, response) => {
|
app.post('/horde_samplers', jsonParser, async (_, response) => {
|
||||||
try {
|
try {
|
||||||
|
const ai_horde = getHordeClient();
|
||||||
const samplers = Object.values(ai_horde.ModelGenerationInputStableSamplers);
|
const samplers = Object.values(ai_horde.ModelGenerationInputStableSamplers);
|
||||||
response.send(samplers);
|
response.send(samplers);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -3781,6 +3872,7 @@ app.post('/horde_samplers', jsonParser, async (_, response) => {
|
|||||||
|
|
||||||
app.post('/horde_models', jsonParser, async (_, response) => {
|
app.post('/horde_models', jsonParser, async (_, response) => {
|
||||||
try {
|
try {
|
||||||
|
const ai_horde = getHordeClient();
|
||||||
const models = await ai_horde.getModels();
|
const models = await ai_horde.getModels();
|
||||||
response.send(models);
|
response.send(models);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -3797,6 +3889,7 @@ app.post('/horde_userinfo', jsonParser, async (_, response) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const ai_horde = getHordeClient();
|
||||||
const user = await ai_horde.findUser({ token: api_key_horde });
|
const user = await ai_horde.findUser({ token: api_key_horde });
|
||||||
return response.send(user);
|
return response.send(user);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -3812,6 +3905,7 @@ app.post('/horde_generateimage', jsonParser, async (request, response) => {
|
|||||||
console.log('Stable Horde request:', request.body);
|
console.log('Stable Horde request:', request.body);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const ai_horde = getHordeClient();
|
||||||
const generation = await ai_horde.postAsyncImageGenerate(
|
const generation = await ai_horde.postAsyncImageGenerate(
|
||||||
{
|
{
|
||||||
prompt: `${request.body.prompt_prefix} ${request.body.prompt} ### ${request.body.negative_prompt}`,
|
prompt: `${request.body.prompt_prefix} ${request.body.prompt} ### ${request.body.negative_prompt}`,
|
||||||
|
@@ -61,6 +61,11 @@ const parse = async (cardUrl, format) => {
|
|||||||
return PNGtext.decode(chunk.data);
|
return PNGtext.decode(chunk.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (textChunks.length === 0) {
|
||||||
|
console.error('PNG metadata does not contain any character data.');
|
||||||
|
throw new Error('No PNG metadata.');
|
||||||
|
}
|
||||||
|
|
||||||
return Buffer.from(textChunks[0].text, 'base64').toString('utf8');
|
return Buffer.from(textChunks[0].text, 'base64').toString('utf8');
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user