mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-07 15:48:46 +01:00
Merge branch 'staging' of https://github.com/city-unit/SillyTavern into feature/exorcism
This commit is contained in:
commit
838cd81f8e
551
Launcher.bat
Normal file
551
Launcher.bat
Normal file
@ -0,0 +1,551 @@
|
||||
@echo off
|
||||
REM --------------------------------------------
|
||||
REM This script was created by: Deffcolony
|
||||
REM --------------------------------------------
|
||||
title SillyTavern Launcher
|
||||
setlocal
|
||||
|
||||
REM ANSI Escape Code for Colors
|
||||
set "reset=[0m"
|
||||
|
||||
REM Strong Foreground Colors
|
||||
set "white_fg_strong=[90m"
|
||||
set "red_fg_strong=[91m"
|
||||
set "green_fg_strong=[92m"
|
||||
set "yellow_fg_strong=[93m"
|
||||
set "blue_fg_strong=[94m"
|
||||
set "magenta_fg_strong=[95m"
|
||||
set "cyan_fg_strong=[96m"
|
||||
|
||||
REM Normal Background Colors
|
||||
set "red_bg=[41m"
|
||||
set "blue_bg=[44m"
|
||||
|
||||
REM Environment Variables (TOOLBOX 7-Zip)
|
||||
set "zip7version=7z2301-x64"
|
||||
set "zip7_install_path=%ProgramFiles%\7-Zip"
|
||||
set "zip7_download_path=%TEMP%\%zip7version%.exe"
|
||||
|
||||
REM Environment Variables (TOOLBOX FFmpeg)
|
||||
set "ffmpeg_url=https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z"
|
||||
set "ffdownload_path=%TEMP%\ffmpeg.7z"
|
||||
set "ffextract_path=C:\ffmpeg"
|
||||
set "bin_path=%ffextract_path%\bin"
|
||||
|
||||
REM Environment Variables (TOOLBOX Node.js)
|
||||
set "node_installer_path=%temp%\NodejsInstaller.msi"
|
||||
|
||||
REM Environment Variables (winget)
|
||||
set "winget_path=%userprofile%\AppData\Local\Microsoft\WindowsApps"
|
||||
|
||||
|
||||
REM Check if Winget is installed; if not, then install it
|
||||
winget --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %blue_fg_strong%[INFO]%reset% Winget is not installed on this system.
|
||||
echo %blue_fg_strong%[INFO]%reset% Installing Winget...
|
||||
bitsadmin /transfer "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe" /download /priority FOREGROUND "https://github.com/microsoft/winget-cli/releases/download/v1.5.2201/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" "%temp%\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
|
||||
start "" "%temp%\Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"
|
||||
echo %green_fg_strong%Winget is now installed.%reset%
|
||||
) else (
|
||||
echo %blue_fg_strong%[INFO] Winget is already installed.%reset%
|
||||
)
|
||||
|
||||
rem Get the current PATH value from the registry
|
||||
for /f "tokens=2*" %%A in ('reg query "HKCU\Environment" /v PATH') do set "current_path=%%B"
|
||||
|
||||
rem Check if the paths are already in the current PATH
|
||||
echo %current_path% | find /i "%winget_path%" > nul
|
||||
set "ff_path_exists=%errorlevel%"
|
||||
|
||||
rem Append the new paths to the current PATH only if they don't exist
|
||||
if %ff_path_exists% neq 0 (
|
||||
set "new_path=%current_path%;%winget_path%"
|
||||
|
||||
rem Update the PATH value in the registry
|
||||
reg add "HKCU\Environment" /v PATH /t REG_EXPAND_SZ /d "%new_path%" /f
|
||||
|
||||
rem Update the PATH value for the current session
|
||||
setx PATH "%new_path%" > nul
|
||||
echo %green_fg_strong%winget added to PATH.%reset%
|
||||
) else (
|
||||
set "new_path=%current_path%"
|
||||
echo %blue_fg_strong%[INFO] winget already exists in PATH.%reset%
|
||||
)
|
||||
|
||||
|
||||
REM Check if Git is installed if not then install git
|
||||
git --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %yellow_fg_strong%[WARN] Git is not installed on this system.%reset%
|
||||
echo %blue_fg_strong%[INFO]%reset% Installing Git using Winget...
|
||||
winget install -e --id Git.Git
|
||||
echo %green_fg_strong%Git is installed. Please restart the Launcher.%reset%
|
||||
pause
|
||||
exit
|
||||
) else (
|
||||
echo %blue_fg_strong%[INFO] Git is already installed.%reset%
|
||||
)
|
||||
|
||||
REM Check for updates
|
||||
git fetch origin
|
||||
|
||||
for /f %%i in ('git rev-list HEAD...origin/%current_branch%') do (
|
||||
set "update_status=%yellow_fg_strong%Update Available%reset%"
|
||||
goto :found_update
|
||||
)
|
||||
|
||||
set "update_status=%green_fg_strong%Up to Date%reset%"
|
||||
:found_update
|
||||
|
||||
|
||||
REM Home - frontend
|
||||
:home
|
||||
cls
|
||||
echo %blue_fg_strong%/ Home%reset%
|
||||
echo -------------------------------------
|
||||
echo What would you like to do?
|
||||
echo 1. Start SillyTavern
|
||||
echo 2. Update
|
||||
echo 3. Switch to release branch
|
||||
echo 4. Switch to staging branch
|
||||
echo 5. Backup
|
||||
echo 6. Toolbox
|
||||
echo 7. Exit
|
||||
|
||||
REM Get the current Git branch
|
||||
for /f %%i in ('git branch --show-current') do set current_branch=%%i
|
||||
echo ======== VERSION STATUS =========
|
||||
echo Current branch: %cyan_fg_strong%%current_branch%%reset%
|
||||
echo Update Status: %update_status%
|
||||
echo =================================
|
||||
set /p choice=Choose Your Destiny:
|
||||
|
||||
|
||||
REM Home - backend
|
||||
if "%choice%"=="1" (
|
||||
call :start
|
||||
) else if "%choice%"=="2" (
|
||||
call :update
|
||||
) else if "%choice%"=="3" (
|
||||
call :switch_release
|
||||
) else if "%choice%"=="4" (
|
||||
call :switch_staging
|
||||
) else if "%choice%"=="5" (
|
||||
call :backup_menu
|
||||
) else if "%choice%"=="6" (
|
||||
call :toolbox
|
||||
) else if "%choice%"=="7" (
|
||||
exit
|
||||
) else (
|
||||
color 6
|
||||
echo WARNING: Invalid number. Please insert a valid number.
|
||||
pause
|
||||
goto :home
|
||||
)
|
||||
|
||||
:start
|
||||
REM Check if Node.js is installed
|
||||
node --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] node command not found in PATH%reset%
|
||||
echo %red_bg%Please make sure Node.js is installed and added to your PATH.%reset%
|
||||
echo %blue_bg%To install Node.js go to Toolbox%reset%
|
||||
pause
|
||||
goto :home
|
||||
)
|
||||
|
||||
echo Launching SillyTavern...
|
||||
cls
|
||||
pushd %~dp0
|
||||
call npm install --no-audit
|
||||
node server.js
|
||||
pause
|
||||
popd
|
||||
goto :home
|
||||
|
||||
:update
|
||||
echo Updating...
|
||||
pushd %~dp0
|
||||
|
||||
REM Check if git is installed
|
||||
git --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] git command not found in PATH. Skipping update.%reset%
|
||||
echo %red_bg%Please make sure Git is installed and added to your PATH.%reset%
|
||||
echo %blue_bg%To install Git go to Toolbox%reset%
|
||||
) else (
|
||||
call git pull --rebase --autostash
|
||||
if %errorlevel% neq 0 (
|
||||
REM incase there is still something wrong
|
||||
echo There were errors while updating. Please download the latest version manually.
|
||||
)
|
||||
)
|
||||
pause
|
||||
goto :home
|
||||
|
||||
|
||||
:switch_release
|
||||
REM Check if git is installed
|
||||
git --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] git command not found in PATH%reset%
|
||||
echo %red_bg%Please make sure Git is installed and added to your PATH.%reset%
|
||||
echo %blue_bg%To install Git go to Toolbox%reset%
|
||||
pause
|
||||
goto :home
|
||||
)
|
||||
echo Switching to release branch...
|
||||
git switch release
|
||||
pause
|
||||
goto :home
|
||||
|
||||
|
||||
:switch_staging
|
||||
REM Check if git is installed
|
||||
git --version > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] git command not found in PATH%reset%
|
||||
echo %red_bg%Please make sure git is installed and added to your PATH.%reset%
|
||||
pause
|
||||
goto :home
|
||||
)
|
||||
echo Switching to staging branch...
|
||||
git switch staging
|
||||
pause
|
||||
goto :home
|
||||
|
||||
|
||||
|
||||
REM backup - frontend
|
||||
:backup_menu
|
||||
REM Check if 7-Zip is installed
|
||||
7z > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] 7z command not found in PATH%reset%
|
||||
echo %red_bg%Please make sure 7-Zip is installed and added to your PATH.%reset%
|
||||
echo %blue_bg%To install 7-Zip go to Toolbox%reset%
|
||||
pause
|
||||
goto :home
|
||||
)
|
||||
|
||||
cls
|
||||
echo %blue_fg_strong%/ Home / Backup%reset%
|
||||
echo -------------------------------------
|
||||
echo What would you like to do?
|
||||
REM color 7
|
||||
echo 1. Create Backup
|
||||
echo 2. Restore Backup
|
||||
echo 3. Back to Home
|
||||
|
||||
set /p backup_choice=Choose Your Destiny:
|
||||
|
||||
REM backup - backend
|
||||
if "%backup_choice%"=="1" (
|
||||
call :create_backup
|
||||
) else if "%backup_choice%"=="2" (
|
||||
call :restore_backup
|
||||
) else if "%backup_choice%"=="3" (
|
||||
goto :home
|
||||
) else (
|
||||
color 6
|
||||
echo WARNING: Invalid number. Please insert a valid number.
|
||||
pause
|
||||
goto :backup_menu
|
||||
)
|
||||
|
||||
|
||||
REM toolbox - frontend
|
||||
:toolbox
|
||||
cls
|
||||
echo %blue_fg_strong%/ Home / Toolbox%reset%
|
||||
echo -------------------------------------
|
||||
echo What would you like to do?
|
||||
REM color 7
|
||||
echo 1. Install 7-Zip
|
||||
echo 2. Install FFmpeg
|
||||
echo 3. Install Node.js
|
||||
echo 4. Edit Environment - Power Users only!
|
||||
echo 5. Reinstall SillyTavern
|
||||
echo 6. Back to Home
|
||||
|
||||
set /p toolbox_choice=Choose Your Destiny:
|
||||
|
||||
REM toolbox - backend
|
||||
if "%toolbox_choice%"=="1" (
|
||||
call :install7zip
|
||||
) else if "%toolbox_choice%"=="2" (
|
||||
call :installffmpeg
|
||||
) else if "%toolbox_choice%"=="3" (
|
||||
call :installnodejs
|
||||
) else if "%toolbox_choice%"=="4" (
|
||||
call :editenvironment
|
||||
) else if "%toolbox_choice%"=="5" (
|
||||
call :reinstallsillytavern
|
||||
) else if "%toolbox_choice%"=="6" (
|
||||
goto :home
|
||||
) else (
|
||||
color 6
|
||||
echo WARNING: Invalid number. Please insert a valid number.
|
||||
pause
|
||||
goto :toolbox
|
||||
)
|
||||
|
||||
|
||||
:install7zip
|
||||
echo %blue_fg_strong%[INFO] Installing 7-Zip...%reset%
|
||||
winget install -e --id 7zip.7zip
|
||||
|
||||
|
||||
rem Get the current PATH value from the registry
|
||||
for /f "tokens=2*" %%A in ('reg query "HKCU\Environment" /v PATH') do set "current_path=%%B"
|
||||
|
||||
rem Check if the paths are already in the current PATH
|
||||
echo %current_path% | find /i "%zip7_install_path%" > nul
|
||||
set "zip7_path_exists=%errorlevel%"
|
||||
|
||||
rem Append the new paths to the current PATH only if they don't exist
|
||||
if %zip7_path_exists% neq 0 (
|
||||
set "new_path=%current_path%;%zip7_install_path%"
|
||||
echo %green_fg_strong%7-Zip added to PATH.%reset%
|
||||
) else (
|
||||
set "new_path=%current_path%"
|
||||
echo %blue_fg_strong%[INFO] 7-Zip already exists in PATH.%reset%
|
||||
)
|
||||
|
||||
rem Update the PATH value in the registry
|
||||
reg add "HKCU\Environment" /v PATH /t REG_EXPAND_SZ /d "%new_path%" /f
|
||||
|
||||
rem Update the PATH value for the current session
|
||||
setx PATH "%new_path%"
|
||||
|
||||
echo %green_fg_strong%7-Zip is installed. Please restart the Launcher.%reset%
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
:installffmpeg
|
||||
REM Check if 7-Zip is installed
|
||||
7z > nul 2>&1
|
||||
if %errorlevel% neq 0 (
|
||||
echo %red_fg_strong%[ERROR] 7z command not found in PATH%reset%
|
||||
echo %red_bg%Please make sure 7-Zip is installed and added to your PATH.%reset%
|
||||
echo %blue_bg%To install 7-Zip go to Toolbox%reset%
|
||||
pause
|
||||
goto :toolbox
|
||||
)
|
||||
|
||||
echo %blue_fg_strong%[INFO]%reset% Downloading FFmpeg archive...
|
||||
rem bitsadmin /transfer "ffmpeg" /download /priority FOREGROUND "%ffmpeg_url%" "%ffdownload_path%"
|
||||
curl -o "%ffdownload_path%" "%ffmpeg_url%"
|
||||
|
||||
echo %blue_fg_strong%[INFO]%reset% Creating ffmpeg directory if it doesn't exist...
|
||||
if not exist "%ffextract_path%" (
|
||||
mkdir "%ffextract_path%"
|
||||
)
|
||||
|
||||
echo %blue_fg_strong%[INFO]%reset% Extracting FFmpeg archive...
|
||||
7z x "%ffdownload_path%" -o"%ffextract_path%"
|
||||
|
||||
|
||||
echo %blue_fg_strong%[INFO]%reset% Moving FFmpeg contents to C:\ffmpeg...
|
||||
for /d %%i in ("%ffextract_path%\ffmpeg-*-full_build") do (
|
||||
xcopy "%%i\bin" "%ffextract_path%\bin" /E /I /Y
|
||||
xcopy "%%i\doc" "%ffextract_path%\doc" /E /I /Y
|
||||
xcopy "%%i\presets" "%ffextract_path%\presets" /E /I /Y
|
||||
rd "%%i" /S /Q
|
||||
)
|
||||
|
||||
rem Get the current PATH value from the registry
|
||||
for /f "tokens=2*" %%A in ('reg query "HKCU\Environment" /v PATH') do set "current_path=%%B"
|
||||
|
||||
rem Check if the paths are already in the current PATH
|
||||
echo %current_path% | find /i "%bin_path%" > nul
|
||||
set "ff_path_exists=%errorlevel%"
|
||||
|
||||
rem Append the new paths to the current PATH only if they don't exist
|
||||
if %ff_path_exists% neq 0 (
|
||||
set "new_path=%current_path%;%bin_path%"
|
||||
echo %green_fg_strong%ffmpeg added to PATH.%reset%
|
||||
) else (
|
||||
set "new_path=%current_path%"
|
||||
echo %blue_fg_strong%[INFO] ffmpeg already exists in PATH.%reset%
|
||||
)
|
||||
|
||||
rem Update the PATH value in the registry
|
||||
reg add "HKCU\Environment" /v PATH /t REG_EXPAND_SZ /d "%new_path%" /f
|
||||
|
||||
rem Update the PATH value for the current session
|
||||
setx PATH "%new_path%" > nul
|
||||
|
||||
del "%ffdownload_path%"
|
||||
echo %green_fg_strong%FFmpeg is installed. Please restart the Launcher.%reset%
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
:installnodejs
|
||||
echo %blue_fg_strong%[INFO]%reset% Installing Node.js...
|
||||
winget install -e --id OpenJS.NodeJS
|
||||
echo %green_fg_strong%Node.js is installed. Please restart the Launcher.%reset%
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
:editenvironment
|
||||
rundll32.exe sysdm.cpl,EditEnvironmentVariables
|
||||
goto :toolbox
|
||||
|
||||
|
||||
:reinstallsillytavern
|
||||
setlocal enabledelayedexpansion
|
||||
chcp 65001 > nul
|
||||
REM Define the names of items to be excluded
|
||||
set "script_name=%~nx0"
|
||||
set "excluded_folders=backups"
|
||||
set "excluded_files=!script_name!"
|
||||
|
||||
REM Confirm with the user before proceeding
|
||||
echo.
|
||||
echo %red_bg%╔════ DANGER ZONE ══════════════════════════════════════════════════════════════════════════════╗%reset%
|
||||
echo %red_bg%║ WARNING: This will delete all data in the current branch except the Backups. ║%reset%
|
||||
echo %red_bg%║ If you want to keep any data, make sure to create a backup before proceeding. ║%reset%
|
||||
echo %red_bg%╚═══════════════════════════════════════════════════════════════════════════════════════════════╝%reset%
|
||||
echo.
|
||||
echo Are you sure you want to proceed? (Y/N)
|
||||
set /p "confirmation="
|
||||
if /i "!confirmation!"=="Y" (
|
||||
REM Remove non-excluded folders
|
||||
for /d %%D in (*) do (
|
||||
set "exclude_folder="
|
||||
for %%E in (!excluded_folders!) do (
|
||||
if "%%D"=="%%E" set "exclude_folder=true"
|
||||
)
|
||||
if not defined exclude_folder (
|
||||
rmdir /s /q "%%D" 2>nul
|
||||
)
|
||||
)
|
||||
|
||||
REM Remove non-excluded files
|
||||
for %%F in (*) do (
|
||||
set "exclude_file="
|
||||
for %%E in (!excluded_files!) do (
|
||||
if "%%F"=="%%E" set "exclude_file=true"
|
||||
)
|
||||
if not defined exclude_file (
|
||||
del /f /q "%%F" 2>nul
|
||||
)
|
||||
)
|
||||
|
||||
REM Clone repo into %temp% folder
|
||||
git clone https://github.com/SillyTavern/SillyTavern.git "%temp%\SillyTavernTemp"
|
||||
|
||||
REM Move the contents of the temporary folder to the current directory
|
||||
xcopy /e /y "%temp%\SillyTavernTemp\*" .
|
||||
|
||||
REM Clean up the temporary folder
|
||||
rmdir /s /q "%temp%\SillyTavernTemp"
|
||||
|
||||
echo %green_fg_strong%SillyTavern reinstalled successfully!%reset%
|
||||
) else (
|
||||
echo Reinstall canceled.
|
||||
)
|
||||
endlocal
|
||||
pause
|
||||
goto :toolbox
|
||||
|
||||
|
||||
:create_backup
|
||||
REM Create a backup using 7zip
|
||||
7z a "backups\backup_.7z" ^
|
||||
"public\assets\*" ^
|
||||
"public\Backgrounds\*" ^
|
||||
"public\Characters\*" ^
|
||||
"public\Chats\*" ^
|
||||
"public\context\*" ^
|
||||
"public\Group chats\*" ^
|
||||
"public\Groups\*" ^
|
||||
"public\instruct\*" ^
|
||||
"public\KoboldAI Settings\*" ^
|
||||
"public\movingUI\*" ^
|
||||
"public\NovelAI Settings\*" ^
|
||||
"public\OpenAI Settings\*" ^
|
||||
"public\QuickReplies\*" ^
|
||||
"public\TextGen Settings\*" ^
|
||||
"public\themes\*" ^
|
||||
"public\User Avatars\*" ^
|
||||
"public\user\*" ^
|
||||
"public\worlds\*" ^
|
||||
"public\settings.json" ^
|
||||
"secrets.json"
|
||||
|
||||
REM Get current date and time components
|
||||
for /f "tokens=1-3 delims=/- " %%d in ("%date%") do (
|
||||
set "day=%%d"
|
||||
set "month=%%e"
|
||||
set "year=%%f"
|
||||
)
|
||||
|
||||
for /f "tokens=1-2 delims=:." %%h in ("%time%") do (
|
||||
set "hour=%%h"
|
||||
set "minute=%%i"
|
||||
)
|
||||
|
||||
REM Pad single digits with leading zeros
|
||||
setlocal enabledelayedexpansion
|
||||
set "day=0!day!"
|
||||
set "month=0!month!"
|
||||
set "hour=0!hour!"
|
||||
set "minute=0!minute!"
|
||||
|
||||
set "formatted_date=%month:~-2%-%day:~-2%-%year%_%hour:~-2%%minute:~-2%"
|
||||
|
||||
REM Rename the backup file with the formatted date and time
|
||||
rename "backups\backup_.7z" "backup_%formatted_date%.7z"
|
||||
|
||||
endlocal
|
||||
|
||||
|
||||
echo %green_fg_strong%Backup created successfully!%reset%
|
||||
pause
|
||||
endlocal
|
||||
goto :backup_menu
|
||||
|
||||
|
||||
:restore_backup
|
||||
REM Restore a backup using 7zip
|
||||
|
||||
echo List of available backups:
|
||||
echo =========================
|
||||
|
||||
setlocal enabledelayedexpansion
|
||||
set "backup_count=0"
|
||||
|
||||
for %%F in ("backups\backup_*.7z") do (
|
||||
set /a "backup_count+=1"
|
||||
set "backup_files[!backup_count!]=%%~nF"
|
||||
echo !backup_count!. %cyan_fg_strong%%%~nF%reset%
|
||||
)
|
||||
|
||||
echo =========================
|
||||
set /p "restore_choice=Enter number of backup to restore: "
|
||||
|
||||
if "%restore_choice%" geq "1" (
|
||||
if "%restore_choice%" leq "%backup_count%" (
|
||||
set "selected_backup=!backup_files[%restore_choice%]!"
|
||||
echo Restoring backup !selected_backup!...
|
||||
REM Extract the contents of the "public" folder directly into the existing "public" folder
|
||||
7z x "backups\!selected_backup!.7z" -o"temp" -aoa
|
||||
xcopy /y /e "temp\public\*" "public\"
|
||||
rmdir /s /q "temp"
|
||||
echo %green_fg_strong%!selected_backup! restored successfully.%reset%
|
||||
) else (
|
||||
color 6
|
||||
echo WARNING: Invalid backup number. Please insert a valid number.
|
||||
)
|
||||
) else (
|
||||
color 6
|
||||
echo WARNING: Invalid number. Please insert a valid number.
|
||||
)
|
||||
pause
|
||||
goto :backup_menu
|
@ -116,6 +116,17 @@
|
||||
"!npm install -g localtunnel\n",
|
||||
"!pip install -r requirements-complete.txt\n",
|
||||
"!pip install tensorflow==2.12\n",
|
||||
"!pip install Flask-Cors\n",
|
||||
"!pip install Flask-Compress\n",
|
||||
"!pip install transformers\n",
|
||||
"!pip install Flask_Cloudflared\n",
|
||||
"!pip install webuiapi\n",
|
||||
"!pip install diffusers\n",
|
||||
"!pip install accelerate\n",
|
||||
"!pip install silero_api_server\n",
|
||||
"!pip install edge_tts\n",
|
||||
"!pip install chromadb\n",
|
||||
"!pip install sentence_transformers\n",
|
||||
"!wget https://github.com/cloudflare/cloudflared/releases/download/2023.5.0/cloudflared-linux-amd64 -O /tmp/cloudflared-linux-amd64\n",
|
||||
"!chmod +x /tmp/cloudflared-linux-amd64\n",
|
||||
"\n",
|
||||
|
@ -15,17 +15,21 @@ const skipContentCheck = false; // If true, no new default content will be deliv
|
||||
// Change this setting only on "trusted networks". Do not change this value unless you are aware of the issues that can arise from changing this setting and configuring a insecure setting.
|
||||
const securityOverride = false;
|
||||
|
||||
// Request overrides for additional headers
|
||||
const requestOverrides = [];
|
||||
|
||||
module.exports = {
|
||||
port,
|
||||
whitelist,
|
||||
whitelistMode,
|
||||
basicAuthMode,
|
||||
basicAuthUser,
|
||||
autorun,
|
||||
enableExtensions,
|
||||
listen,
|
||||
disableThumbnails,
|
||||
allowKeysExposure,
|
||||
securityOverride,
|
||||
skipContentCheck,
|
||||
port,
|
||||
whitelist,
|
||||
whitelistMode,
|
||||
basicAuthMode,
|
||||
basicAuthUser,
|
||||
autorun,
|
||||
enableExtensions,
|
||||
listen,
|
||||
disableThumbnails,
|
||||
allowKeysExposure,
|
||||
securityOverride,
|
||||
skipContentCheck,
|
||||
requestOverrides,
|
||||
};
|
||||
|
121
package-lock.json
generated
121
package-lock.json
generated
@ -12,7 +12,6 @@
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"axios": "^1.4.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
@ -32,8 +31,7 @@
|
||||
"mime-types": "^2.1.35",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^2.6.11",
|
||||
"node-rest-client": "^3.1.1",
|
||||
"open": "^8.4.0",
|
||||
"open": "^8.4.2",
|
||||
"piexifjs": "^1.0.6",
|
||||
"png-chunk-text": "^1.0.0",
|
||||
"png-chunks-encode": "^1.0.0",
|
||||
@ -769,11 +767,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
@ -783,16 +776,6 @@
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz",
|
||||
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/base64-js": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||
@ -1011,17 +994,6 @@
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dependencies": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/command-exists": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz",
|
||||
@ -1205,14 +1177,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
@ -1481,38 +1445,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/RubenVerborgh"
|
||||
}
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"debug": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
@ -2272,40 +2204,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-rest-client": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-rest-client/-/node-rest-client-3.1.1.tgz",
|
||||
"integrity": "sha512-O8RUGGhGLLbzlL7SFOBza1AgUWP3uITv4mas4f5Q7A87HAy6qtYpa8Sj5x4UG9cDf4374v7lWyvgWladI04zzQ==",
|
||||
"dependencies": {
|
||||
"debug": "~4.3.3",
|
||||
"follow-redirects": ">=1.14.7",
|
||||
"xml2js": ">=0.4.23"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/node-rest-client/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/node-rest-client/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@ -2752,11 +2650,6 @@
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
@ -3581,18 +3474,6 @@
|
||||
"resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
|
||||
"integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.0.tgz",
|
||||
"integrity": "sha512-eLTh0kA8uHceqesPqSE+VvO1CDDJWMwlQfB6LuN6T8w6MaDJ8Txm8P7s5cHD0miF0V+GGTZrDQfxPZQVsur33w==",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
|
@ -3,7 +3,6 @@
|
||||
"@agnai/sentencepiece-js": "^1.1.1",
|
||||
"@agnai/web-tokenizers": "^0.1.3",
|
||||
"@dqbd/tiktoken": "^1.0.2",
|
||||
"axios": "^1.4.0",
|
||||
"command-exists": "^1.2.9",
|
||||
"compression": "^1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
@ -23,8 +22,7 @@
|
||||
"mime-types": "^2.1.35",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^2.6.11",
|
||||
"node-rest-client": "^3.1.1",
|
||||
"open": "^8.4.0",
|
||||
"open": "^8.4.2",
|
||||
"piexifjs": "^1.0.6",
|
||||
"png-chunk-text": "^1.0.0",
|
||||
"png-chunks-encode": "^1.0.0",
|
||||
|
@ -60,6 +60,7 @@
|
||||
#completion_prompt_manager #completion_prompt_manager_list li.completion_prompt_manager_prompt .prompt_manager_prompt_controls {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: calc(var(--mainFontSize)*1.2);
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list li.completion_prompt_manager_prompt .prompt_manager_prompt_controls span {
|
||||
@ -77,7 +78,7 @@
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
filter: drop-shadow(0px 0px 2px black);
|
||||
opacity: 0.2;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list li.completion_prompt_manager_prompt span span:hover {
|
||||
@ -171,6 +172,10 @@
|
||||
color: var(--white30a);
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list .completion_prompt_manager_prompt:not(.completion_prompt_manager_prompt_disabled) .prompt-manager-toggle-action {
|
||||
color: var(--SmartThemeQuoteColor);
|
||||
}
|
||||
|
||||
#completion_prompt_manager #completion_prompt_manager_list .completion_prompt_manager_prompt.completion_prompt_manager_prompt_disabled {
|
||||
border: 1px solid var(--white20a);
|
||||
}
|
||||
|
@ -8,15 +8,10 @@ body.tts .mes_narrate {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
body.no-hotswap .hotswap {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.no-timer .mes_timer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body.no-hotswap .hotswap,
|
||||
body.no-timer .mes_timer,
|
||||
body.no-timestamps .timestamp,
|
||||
body.no-tokenCount .tokenCounterDisplay,
|
||||
body.no-mesIDDisplay .mesIDDisplay,
|
||||
body.no-modelIcons .icon-svg {
|
||||
display: none !important;
|
||||
|
387
public/i18n.json
387
public/i18n.json
@ -1713,19 +1713,19 @@
|
||||
"Enable this if the streaming doesn't work with your proxy": "Включите это, если потоковый вывод текста не работает с вашим прокси",
|
||||
"Context Size (tokens)": "Размер контекста (в токенах)",
|
||||
"Max Response Length (tokens)": "Максимальная длина ответа (в токенах)",
|
||||
"Temperature": "Temperature",
|
||||
"Frequency Penalty": "Frequency Penalty",
|
||||
"Presence Penalty": "Presence Penalty",
|
||||
"Temperature": "Температура",
|
||||
"Frequency Penalty": "Штраф за частоту",
|
||||
"Presence Penalty": "Штраф за присутствие",
|
||||
"Top-p": "Top-p",
|
||||
"Display bot response text chunks as they are generated": "Отображать ответ ИИ по мере генерации текста",
|
||||
"Top A": "Top-a",
|
||||
"Typical Sampling": "Typical Sampling",
|
||||
"Tail Free Sampling": "Tail Free Sampling",
|
||||
"Rep. Pen. Slope": "Rep. Pen. Slope",
|
||||
"Typical Sampling": "Типичная выборка",
|
||||
"Tail Free Sampling": "Бесхвостовая выборка",
|
||||
"Rep. Pen. Slope": "Rep. Pen. Склон",
|
||||
"Single-line mode": "Режим одной строки",
|
||||
"Top K": "Top-k",
|
||||
"Top P": "Top-p",
|
||||
"Do Sample": "Do Sample",
|
||||
"Do Sample": "Сделать образец",
|
||||
"Add BOS Token": "Добавить BOS-токен",
|
||||
"Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative.": "Добавлять BOS-токен в начале инструкции. Выключение этого может сделать ответы более креативными. ",
|
||||
"Ban EOS Token": "Заблокировать EOS-токен",
|
||||
@ -1733,11 +1733,24 @@
|
||||
"Skip Special Tokens": "Пропускать специальные токены",
|
||||
"Beam search": "Поиск Beam",
|
||||
"Number of Beams": "Количество Beam",
|
||||
"Length Penalty": "Length Penalty",
|
||||
"Length Penalty": "Штраф за длину",
|
||||
"Early Stopping": "Преждевременная остановка",
|
||||
"Contrastive search": "Contrastive search",
|
||||
"Penalty Alpha": "Penalty Alpha",
|
||||
"Contrastive search": "Контрастный поиск",
|
||||
"Penalty Alpha": "Штраф Альфа",
|
||||
"Seed": "Зерно",
|
||||
"Epsilon Cutoff": "Отсечение эпсилона",
|
||||
"Eta Cutoff": "Отсечка Eta",
|
||||
"Negative Prompt": "Отрицательная подсказка",
|
||||
"Mirostat (mode=1 is only for llama.cpp)": "Mirostat (режим = 1 только для llama.cpp)",
|
||||
"Add text here that would make the AI generate things you don't want in your outputs.": "Добавьте сюда текст, который заставит ИИ генерировать то, что вы не хотите видеть в своих выводах",
|
||||
"Phrase Repetition Penalty": "Штраф за повторение фразы",
|
||||
"Preamble": "Преамбула",
|
||||
"Use style tags to modify the writing style of the output.": "Используйте теги стиля, чтобы изменить стиль написания вывода.",
|
||||
"Banned Tokens": "Запрещенные токены",
|
||||
"Sequences you don't want to appear in the output. One per line.": "Последовательности, которые вы не хотите отображать в выводе. По одному на строку.",
|
||||
"AI Module": "Модуль ИИ",
|
||||
"Changes the style of the generated text.": "Изменяет стиль создаваемого текста.",
|
||||
"Used if CFG Scale is unset globally, per chat or character": "Используется, если масштаб CFG не установлен глобально, для каждого чата или персонажа.",
|
||||
"Inserts jailbreak as a last system message.": "Вставлять JailBreak последним системным сообщением.",
|
||||
"This tells the AI to ignore its usual content restrictions.": "Сообщает AI о необходимости игнорировать стандартные ограничения контента.",
|
||||
"NSFW Encouraged": "Поощрять NSFW",
|
||||
@ -1760,7 +1773,7 @@
|
||||
"Prompt that is used when the Jailbreak toggle is on": "Инструкция, отправляемая ИИ при включенном JailBreak.",
|
||||
"Impersonation prompt": "Инструкция для перевоплощения",
|
||||
"Prompt that is used for Impersonation function": "Инструкция, отправляемая ИИ для генерации действий за пользователя",
|
||||
"Logit Bias": "Logit Bias",
|
||||
"Logit Bias": "Ошибка логита",
|
||||
"Helps to ban or reenforce the usage of certain words": "Позволяет запретить или поощрять использование определенных слов",
|
||||
"View / Edit bias preset": "Посмотреть/Настроить предустановку для bias",
|
||||
"Add bias entry": "Добавить инструкцию в Bias",
|
||||
@ -1770,21 +1783,27 @@
|
||||
"Bot must send this back to confirm jailbreak": "Это сообщение будет отправлено ИИ при успешном включении JailBreak.",
|
||||
"Character Note": "Заметки о персонаже",
|
||||
"Influences bot behavior in its responses": "Влияет на поведение ИИ и его ответы.",
|
||||
"Connect": "Подключить",
|
||||
"Test Message": "Тестовое сообщение",
|
||||
"API": "API",
|
||||
"KoboldAI": "KoboldAI",
|
||||
"Use Horde": "Использовать Horde",
|
||||
"API url": "API URL",
|
||||
"Register a Horde account for faster queue times": "Заведите учетную запись Horde для ускорения генерации",
|
||||
"Learn how to contribute your idle GPU cycles to the Hord": "Узнайте подробнее о том, как использовать время простоя GPU для Hord",
|
||||
"Adjust context size to worker capabilities": "Уточнить размер контекста для возможностей рабочих",
|
||||
"Adjust response length to worker capabilities": "Уточнить длинну ответа для возможностей рабочий",
|
||||
"Adjust context size to worker capabilities": "Уточнить размер контекста в соответствии с возможностями рабочих машин",
|
||||
"Adjust response length to worker capabilities": "Уточнить длинну ответа в соответствии с возможностями рабочих машин",
|
||||
"API key": "API-ключ",
|
||||
"Register": "Регист",
|
||||
"Get it here:": "Получить здесь:",
|
||||
"Register": "Регистрация",
|
||||
"View my Kudos": "Посмотреть мой рейтинг(Kudos)",
|
||||
"Enter": "Вставьте",
|
||||
"to use anonymous mode.": "чтобы использовать анонимный режим.",
|
||||
"For privacy reasons": "В целях конфиденциальности API-ключ будет скрыт после перезагрузки страницы",
|
||||
"Model": "Модель",
|
||||
"Models": "Модели",
|
||||
"Hold Control / Command key to select multiple models.": "Удерживайте Control / Command для выбора нескольких моделей.",
|
||||
"Horde models not loaded": "Модели Horde не загружены",
|
||||
"Not connected": "Нет подключения",
|
||||
"Not connected...": "Не подключено...",
|
||||
"Novel API key": "API-ключ для NovelAI",
|
||||
"Follow": "Следуйте",
|
||||
"these directions": "данным инструкциям",
|
||||
@ -1793,19 +1812,43 @@
|
||||
"Novel AI Model": "Модель NovelAI",
|
||||
"Euterpe": "Euterpe",
|
||||
"Krake": "Krake",
|
||||
"No connection": "Нет подключения",
|
||||
"If you are using:": "Если вы используете:",
|
||||
"oobabooga/text-generation-webui": "",
|
||||
"Make sure you run it with": "Убедитесь, что при запуске указали аргумент --api",
|
||||
"Blocking API url": "Блокирующий API URL",
|
||||
"Mancer AI": "",
|
||||
"Use API key (Only required for Mancer)": "Нажмите на ячейку (и добавьте свой API ключ!):",
|
||||
"Blocking API url": "Блокирующий API url",
|
||||
"Example: http://127.0.0.1:5000/api": "Пример: http://127.0.0.1:5000/api",
|
||||
"Streaming API url": "Потоковый API URL",
|
||||
"Example: ws://127.0.0.1:5005/api/v1/stream": "Пример: ws://127.0.0.1:5005/api/v1/stream",
|
||||
"Mancer API key": "Mancer API ключ",
|
||||
"Example: https://neuro.mancer.tech/webui/MODEL/api": "Пример: https://neuro.mancer.tech/webui/MODEL/api",
|
||||
"to get your OpenAI API key.": "для получения API-ключа OpenAI",
|
||||
"Window AI Model": "Модель Window AI",
|
||||
"OpenAI Model": "Модель OpenAI",
|
||||
"Claude API Key": "Claude API ключ",
|
||||
"Get your key from": "Получить ключ из",
|
||||
"Anthropic's developer console": "Консоли разработчика Anthropic",
|
||||
"Slack and Poe cookies will not work here, do not bother trying.": "Файлы cookie Slack и Poe здесь не подойдут, не пытайтесь.",
|
||||
"Claude Model": "Модель Claude",
|
||||
"Scale API Key": "Scale API ключ",
|
||||
"Alt Method": "Альтернативный метод",
|
||||
"AI21 API Key": "AI21 API ключ",
|
||||
"AI21 Model": "Модель AI21",
|
||||
"View API Usage Metrics": "Посмотреть статистику использования API",
|
||||
"Show External models (provided by API)": "Показать \"сторонние\" модели (предоставленные API)",
|
||||
"Bot": "Бот:",
|
||||
"Allow fallback routes": "Разрешить резервные маршруты",
|
||||
"Allow fallback routes Description": "Автоматически выбирает альтернативную модель, если выбранная модель не может удовлетворить ваш запрос.",
|
||||
"OpenRouter API Key": "OpenRouter API ключ",
|
||||
"Connect to the API": "Соединение с API",
|
||||
"OpenRouter Model": "Модель OpenRouter",
|
||||
"View Remaining Credits": "Посмотреть оставшиеся кредиты",
|
||||
"Click Authorize below or get the key from": "Нажмите «Авторизовать» ниже или получите ключ от",
|
||||
"Auto-connect to Last Server": "Автоматическое подключение к последнему серверу",
|
||||
"View hidden API keys": "Посмотреть скрытые API-ключи",
|
||||
"Advanced Formatting": "Расширенное форматирование",
|
||||
"Context Template": "Шаблон контекста",
|
||||
"AutoFormat Overrides": "Замена АвтоФормата",
|
||||
"Disable description formatting": "Отключить форматирование описания",
|
||||
"Disable personality formatting": "Отключить форматирование личности",
|
||||
@ -1813,18 +1856,26 @@
|
||||
"Disable example chats formatting": "Отключить форматирование примеров чата",
|
||||
"Disable chat start formatting": "Отключить форматирование начала чата",
|
||||
"Custom Chat Separator": "Пользовательское разделение чата",
|
||||
"Instruct Mode": "Режим Instruct",
|
||||
"Replace Macro in Custom Stopping Strings": "Заменить макрос в пользовательских стоп-строках",
|
||||
"Strip Example Messages from Prompt": "Удалить примеры сообщений из подсказки",
|
||||
"Story String": "Строка истории",
|
||||
"Example Separator": "Пример разделителя",
|
||||
"Chat Start": "Начало чата",
|
||||
"Activation Regex": "Активация Regex",
|
||||
"Instruct Mode": "Режим \"Инструктаж\"",
|
||||
"Enabled": "Включен",
|
||||
"Wrap Sequences with Newline": "Отделять последовательности красной строкой",
|
||||
"Include Names": "Показывать имена",
|
||||
"Force for Groups and Personas": "Усилия для Групп и Персон",
|
||||
"System Prompt": "Системная инструкция",
|
||||
"Instruct Mode Sequences": "Последовательности режима обучения",
|
||||
"Input Sequence": "Input Sequence",
|
||||
"Input Sequence": "Входная последовательность",
|
||||
"Output Sequence": "Выходная последовательность",
|
||||
"First Output Sequence": "Первая выходная последовательность",
|
||||
"Last Output Sequence": "Последняя выходная последовательность",
|
||||
"System Sequence Prefix": "Префикс системной последовательности",
|
||||
"System Sequence Suffix": "Суффикс системной последовательности",
|
||||
"Stop Sequence": "Stop Sequence",
|
||||
"Stop Sequence": "Последовательность остановки",
|
||||
"Context Formatting": "Форматирование контекста",
|
||||
"Tokenizer": "Токенайзер",
|
||||
"None / Estimated": "Отсутствует/Приблизительно",
|
||||
@ -1847,6 +1898,9 @@
|
||||
"Style Anchor": "Стиль Anchors",
|
||||
"World Info": "Информация о мире",
|
||||
"Scan Depth": "Глубина сканирования",
|
||||
"Context %": "Процент контекста",
|
||||
"Budget Cap": "Бюджетный лимит",
|
||||
"(0 = disabled)": "(0 = отключено)",
|
||||
"depth": "глубина",
|
||||
"Token Budget": "Объем токенов",
|
||||
"budget": "объем",
|
||||
@ -1855,7 +1909,10 @@
|
||||
"About soft prompts": "О мягких инструкциях",
|
||||
"None": "Отсутствует",
|
||||
"User Settings": "Настройки пользователя",
|
||||
"UI Customization": "Настройки UI",
|
||||
"UI Mode": "Режим интерфейса",
|
||||
"UI Language": "Язык интерфейса",
|
||||
"MovingUI Preset": "Предустановка MovingUI",
|
||||
"UI Customization": "Настройки интерфейса",
|
||||
"Avatar Style": "Стиль аватаров",
|
||||
"Circle": "Круглые",
|
||||
"Rectangle": "Прямоугольные",
|
||||
@ -1867,6 +1924,14 @@
|
||||
"No Text Shadows": "Отключить тень текста",
|
||||
"Waifu Mode": "!!!РЕЖИМ ВАЙФУ!!!",
|
||||
"Message Timer": "Таймер сообщений",
|
||||
"Model Icon": "Показать значки модели",
|
||||
"Lazy Chat Loading": "Ленивая загрузка чата",
|
||||
"# of messages (0 = disabled)": "# сообщений (0 = отключено)",
|
||||
"Advanced Character Search": "Расширенный поиск персонажей",
|
||||
"Allow {{char}}: in bot messages": "Показывать {{char}}: в ответах",
|
||||
"Allow {{user}}: in bot messages": "Показать {{user}}: в ответах",
|
||||
"Show tags in responses": "Показывать <теги> в ответах",
|
||||
"Relaxed API URLS": "Смягченные URL-адреса API",
|
||||
"Characters Hotswap": "Смена персонажей на лету",
|
||||
"Movable UI Panels": "Перемещение панелей интерфейса",
|
||||
"Reset Panels": "Сбросить панели",
|
||||
@ -1894,6 +1959,7 @@
|
||||
"Always disabled": "Всегда выключена",
|
||||
"Automatic (desktop)": "Автоматически (системные настройки)",
|
||||
"Always enabled": "Всегда включена",
|
||||
"Debug Menu": "Меню отладки",
|
||||
"Name": "Имя",
|
||||
"Your Avatar": "Ваш Аватар",
|
||||
"Extensions API:": "API для расширений",
|
||||
@ -1977,9 +2043,9 @@
|
||||
"Unrestricted maximum value for the context slider": "Неограниченное максимальное значение для ползунка с размером контекста",
|
||||
"Chat Completion Source": "Источник для Chat Completion",
|
||||
"Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde",
|
||||
"Review the Privacy statement": "Посмотреть Privacy statement",
|
||||
"Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности",
|
||||
"Learn how to contribute your idel GPU cycles to the Horde": "Изучите, как использовать GPU в состоянии простоя на благо Horde",
|
||||
"Trusted workers only": "Только доверенные рабочие",
|
||||
"Trusted workers only": "Только доверенные рабочие машины",
|
||||
"For privacy reasons, your API key will be hidden after you reload the page.": "По причинам безопасности ваш API-ключ будет скрыт после перезагрузки страницы.",
|
||||
"-- Horde models not loaded --": "--Модель Horde не загружена--",
|
||||
"Example: http://127.0.0.1:5000/api ": "Пример: http://127.0.0.1:5000/api",
|
||||
@ -1993,7 +2059,7 @@
|
||||
"Trim spaces": "Обрезать пробелы",
|
||||
"Trim Incomplete Sentences": "Обрезать неоконченные предложения",
|
||||
"Include Newline": "Использовать красную строку",
|
||||
"Non-markdown strings": "Неподчеркиваемые Strings",
|
||||
"Non-markdown strings": "Строки без разметки",
|
||||
"Replace Macro in Sequences": "Заменить макросы в последовательности",
|
||||
"Presets": "Предустановки",
|
||||
"Separator": "Разделитель",
|
||||
@ -2003,12 +2069,16 @@
|
||||
"Active World(s)": "Активные миры",
|
||||
"Character Lore Insertion Strategy": "Порядок включения сведений",
|
||||
"Sorted Evenly": "Равномерная сортировка",
|
||||
"Active World(s) for all chats": "Активные миры для всех чатов",
|
||||
"-- World Info not found --": "-- Информация о мире не найдена --",
|
||||
"--- Pick to Edit ---": "Редактировать",
|
||||
"or": "или",
|
||||
"Character Lore First": "Сначала сведения о персонаже",
|
||||
"Global Lore First": "Сначала общие сведения",
|
||||
"-- World Info not found --": "Информация о Мире не найдена",
|
||||
"Recursive Scan": "Рекурсивное сканирование",
|
||||
"Case Sensitive": "Учитывать регистр",
|
||||
"Match whole words": "Только полное совпадение",
|
||||
"Alert On Overflow": "Оповещение о переполнении",
|
||||
"World/Lore Editor": "Редактировать Мир/Сведения",
|
||||
"--- None ---": "---Отсутствует---",
|
||||
"Comma seperated (ignored if empty)": "Разделение запятыми (не используется, если оставлено пустым)",
|
||||
@ -2045,8 +2115,12 @@
|
||||
"Not Connected": "Не подключено",
|
||||
"Persona Management": "Управление Персоной",
|
||||
"Persona Description": "Описание Персоны",
|
||||
"Your Persona": "Ваша Персона",
|
||||
"Show notifications on switching personas": "Показывать уведомления о смене персоны",
|
||||
"Blank": "Пустой",
|
||||
"In Story String / Chat Completion: Before Character Card": "В строке истории / Дополнение диалога: Перед Карточкой Персонажа",
|
||||
"In Story String / Chat Completion: After Character Card": "В строке истории / Дополнение диалога: После Карточки Персонажа",
|
||||
"In Story String / Prompt Manager": "В строке истории/Менеджер подсказок",
|
||||
"Top of Author's Note": "Перед Авторскими Заметками",
|
||||
"Bottom of Author's Note": "После Авторских Заметок",
|
||||
"How do I use this?": "Как мне это использовать?",
|
||||
@ -2081,8 +2155,6 @@
|
||||
"Samplers Order": "Порядок семплирования",
|
||||
"Samplers will be applied in a top-down order. Use with caution.": "Семплирование будет применено в порядке сверху-вниз. Используйте с осторожностью.",
|
||||
"Repetition Penalty": "Наказание за повторы",
|
||||
"Epsilon Cutoff": "Epsilon Cutoff",
|
||||
"Eta Cutoff": "Eta Cutoff",
|
||||
"Rep. Pen. Range.": "Размер наказания за повторы",
|
||||
"Rep. Pen. Freq.": "Частота наказания за повторы",
|
||||
"Rep. Pen. Presence": "Наличие наказания за повторы",
|
||||
@ -2093,7 +2165,8 @@
|
||||
"Show suggested replies. Not all bots support this.": "Показывать предлагаемые ответы. Не все боты поддерживают это.",
|
||||
"Use 'Unlocked Context' to enable chunked generation.": "Использовать 'Безлимитный контекст' для активации кусочной генерации",
|
||||
"It extends the context window in exchange for reply generation speed.": "Увеличивает размер контекста в обмен на скорость генерации.",
|
||||
"Continue": "Пролдолжить",
|
||||
"Continue": "Продолжить",
|
||||
"CFG Scale": "Масштаб CFG",
|
||||
"Editing:": "Изменения",
|
||||
"AI reply prefix": "Префикс Ответ ИИ",
|
||||
"Custom Stopping Strings": "Настройка ограничивающий нитей",
|
||||
@ -2244,7 +2317,7 @@
|
||||
"Change persona image": "Сменить изображение личности",
|
||||
"Delete persona": "Удалить личность"
|
||||
},
|
||||
"it-it": {
|
||||
"it-it": {
|
||||
"clickslidertips": "consigli per gli slider",
|
||||
"kobldpresets": "Preset Kobold",
|
||||
"guikoboldaisettings": "settaggi KoboldAI",
|
||||
@ -2800,133 +2873,131 @@
|
||||
"Select this as default persona for the new chats.": "Seleziona questo alterego come predefinito per tutte le nuove chat",
|
||||
"Change persona image": "Cambia l'immagine del tuo alterego",
|
||||
"Delete persona": "Elimina il tuo alterego",
|
||||
"--- Pick to Edit ---": "--- Scegli per modificare ---",
|
||||
"Add text here that would make the AI generate things you don't want in your outputs.": "Scrivi qui ciò che non vuoi l'IA generi nel suo output.",
|
||||
"write short replies, write replies using past tense": "Scrivi risposte brevi, scrivi risposte usando il passato",
|
||||
"Alert if your world info is greater than the allocated budget.": "Questo avvisa nel momento in cui le 'Info Mondo' consumano più di quanto allocato nel budget.",
|
||||
"Clear your cookie": "Cancella i cookie",
|
||||
"Restore new group chat prompt": "Ripristina il prompt della nuova chat di gruppo",
|
||||
"Save movingUI changes to a new file": "Salva i cambiamenti apportati alla posizione dei pannelli dell'UI (MovingUI) in un nuovo file",
|
||||
"Export all": "Esporta tutto",
|
||||
"Import": "Importa",
|
||||
"Insert": "Inserisci",
|
||||
"New": "Nuovo",
|
||||
"Prompts": "Prompt",
|
||||
"Tokens": "Token",
|
||||
"Reset current character": "Ripristina il personaggio attuale",
|
||||
"(0 = disabled)": "(0 = disabilitato)",
|
||||
"1 = disabled": "1 = disabilitato",
|
||||
"Activation Regex": "Attivazione Regex",
|
||||
"Active World(s) for all chats": "Attiva i Mondi per tutte le chat",
|
||||
"Add character names": "Aggiungi i nomi dei personaggi",
|
||||
"Add Memo": "Aggiungi note",
|
||||
"Advanced Character Search": "Ricerca dei personaggi avanzata",
|
||||
"Aggressive": "Aggressivo",
|
||||
"AI21 Model": "Modello AI21",
|
||||
"Alert On Overflow": "Avviso in caso di Overflow",
|
||||
"Allow fallback routes": "Permetti fallback routes",
|
||||
"Allow fallback routes Description": "Permetti la descrizione di fallback routes",
|
||||
"Alt Method": "Metodo Alt",
|
||||
"Alternate Greetings": "Alterna i saluti",
|
||||
"Alternate Greetings Hint": "Suggerimenti per i saluti alternati",
|
||||
"Alternate Greetings Subtitle": "Sottotitoli per i saluti alternati",
|
||||
"Assistant Prefill": "Assistant Prefill",
|
||||
"Banned Tokens": "Token banditi",
|
||||
"Blank": "In bianco",
|
||||
"Browser default": "Predefinito del browser",
|
||||
"Budget Cap": "Limite budget",
|
||||
"CFG": "CFG",
|
||||
"CFG Scale": "CFG Scale",
|
||||
"Changes the style of the generated text.": "Cambia lo stile del testo generato.",
|
||||
"Character Negatives": "Character Negatives",
|
||||
"Chat Negatives": "Chat Negatives",
|
||||
"Chat Scenario Override": "Sovrascrittura dello scenario della chat",
|
||||
"Chat Start": "Avvio della chat",
|
||||
"Claude Model": "Modello Claude",
|
||||
"Close chat": "Chiudi chat",
|
||||
"Context %": "Context %",
|
||||
"Context Template": "Context Template",
|
||||
"Count Penalty": "Count Penalty",
|
||||
"Example Separator": "Separatore d'esempio",
|
||||
"Exclude Assistant suffix": "Escludi il suffisso assistente",
|
||||
"Exclude the assistant suffix from being added to the end of prompt.": "Esclude il suffisso assistente dall'essere aggiunto alla fine del prompt.",
|
||||
"Force for Groups and Personas": "Forzalo per gruppi e alterego",
|
||||
"Global Negatives": "Global Negatives",
|
||||
"In Story String / Chat Completion: After Character Card": "Nella stringa narrativa / Chat Completion: Dopo la 'Carta Personaggio'",
|
||||
"In Story String / Chat Completion: Before Character Card": "Nella stringa narrativa / Chat Completion: Prima della 'Carta Personaggio",
|
||||
"Instruct": "Instruct",
|
||||
"Instruct Mode": "Modalità Instruct",
|
||||
"Last Sequence": "Ultima sequenza",
|
||||
"Lazy Chat Loading": "Caricamento svogliato della chat",
|
||||
"Least tokens": "Token minimi",
|
||||
"Light": "Leggero",
|
||||
"Load koboldcpp order": "Ripristina l'ordine di koboldcpp",
|
||||
"Main": "Principale",
|
||||
"Mancer API key": "Chiave API di Mancer",
|
||||
"Mancer API url": "Url API di Mancer",
|
||||
"May help the model to understand context. Names must only contain letters or numbers.": "Può aiutare il modello a comprendere meglio il contesto. I nomi devono contenere solo numeri e lettere.",
|
||||
"Medium": "Medium",
|
||||
"Mirostat": "Mirostat",
|
||||
"Mirostat (mode=1 is only for llama.cpp)": "Mirostat (mode=1 è valido solo per llama.cpp)",
|
||||
"Mirostat Eta": "Mirostat Eta",
|
||||
"Mirostat LR": "Mirostat LR",
|
||||
"Mirostat Mode": "Mirostat Mode",
|
||||
"Mirostat Tau": "Mirostat Tau",
|
||||
"Model Icon": "Icona del modello",
|
||||
"Most tokens": "Token massimi",
|
||||
"MovingUI Preset": "Preset MovingUI",
|
||||
"Negative Prompt": "Prompt negativo",
|
||||
"No Module": "Nessun modulo",
|
||||
"NSFW": "NSFW",
|
||||
"Nucleus Sampling": "Nucleus Sampling",
|
||||
"Off": "Spento",
|
||||
"OpenRouter API Key": "Chiave API di OpenRouter",
|
||||
"OpenRouter Model": "Modello OpenRouter",
|
||||
"or": "o",
|
||||
"Phrase Repetition Penalty": "Phrase Repetition Penalty",
|
||||
"Positive Prompt": "Prompt positivo",
|
||||
"Preamble": "Premessa",
|
||||
"Prompt Overrides (For OpenAI/Claude/Scale APIs, Window/OpenRouter, and Instruct Mode)": "Sovrascrittura del prompt (Per le API di OpenAI/Claude/Scale, Window/OpenRouter, e la Modalità Instruct)",
|
||||
"Prompt that is used when the NSFW toggle is O": "Prompt utilizzato quando l'interruttore NSFW è disattivato.",
|
||||
"Prose Augmenter": "Prose Augmenter",
|
||||
"Proxy Password": "Password proxy",
|
||||
"Quick Edit": "Editing rapido",
|
||||
"Random": "Casuale",
|
||||
"Relaxed API URLS": "URL API sciatto",
|
||||
"Replace Macro in Custom Stopping Strings": "Rimpiazza le macro nelle stringe d'arresto personalizzate",
|
||||
"Scale": "Scale",
|
||||
"Scale": "Scale",
|
||||
"Sequences you don't want to appear in the output. One per line.": "Sequenze che non vuoi appaiano nell'output. Una per linea.",
|
||||
"Set at the beginning of Dialogue examples to indicate that a new example chat is about to start.": "Impostato all'inizio degli Esempi di dialogo per indicare che un nuovo esempio di chat sta per iniziare.",
|
||||
"Set at the beginning of the chat history to indicate that a new chat is about to start.": "Impostato all'inizio degli esempi di dialogo per indicare che una nuova chat sta per iniziare.",
|
||||
"Set at the beginning of the chat history to indicate that a new chat is about to start.": "Impostato all'inizio della cronologia chat per indicare che una nuova chat sta per iniziare.",
|
||||
"Set at the beginning of the chat history to indicate that a new group chat is about to start.": "Impostato all'inizio della cronologia chat per indicare che un nuova chat di gruppo sta per iniziare.",
|
||||
"Show External models (provided by API)": "Mostra modelli esterni (Forniti dall'API)",
|
||||
"Show Notifications Show notifications on switching personas": "Mostra una notifica quando l'alterego viene cambiato",
|
||||
"Show tags in responses": "Mostra i tag nelle risposte",
|
||||
"Story String": "Stringa narrativa",
|
||||
"Text Adventure": "Avventura testuale",
|
||||
"Text Gen WebUI (ooba/Mancer) presets": "Preset Text Gen WebUI (ooba/Mancer)",
|
||||
"Toggle Panels": "Interruttore pannelli",
|
||||
"Top A Sampling": "Top A Sampling",
|
||||
"Top K Sampling": "Top K Sampling",
|
||||
"UI Language": "Linguaggio interfaccia grafica",
|
||||
"Unlocked Context Size": "Sblocca dimensione contesto",
|
||||
"Usage Stats": "Statistiche di utilizzo",
|
||||
"Use AI21 Tokenizer": "Utilizza il Tokenizer di AI21",
|
||||
"Use API key (Only required for Mancer)": "Utilizza la chiave API (Necessario soltanto per Mancer)",
|
||||
"Use character author's note": "Utilizza le note d'autore del personaggio",
|
||||
"Use character CFG scales": "Utilizza CFG scales del personaggio",
|
||||
"Use Proxy password field instead. This input will be ignored.": "Utilizza il campo del password proxy al suo posto. Questo input verrà ignorato.",
|
||||
"Use style tags to modify the writing style of the output": "Utilizza lo stile delle tag per modificare lo stile di scrittura in output",
|
||||
"Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.": "Utilizza il tokenizer appropiato per i modelli giurassici, visto che è più efficente di quello di GPT.",
|
||||
"Used if CFG Scale is unset globally, per chat or character": "Usato se CFG Scale non è settato globalmente, per le chat o per i personaggi",
|
||||
"Very aggressive": "Esageratamente aggressivo",
|
||||
"Very light": "Esageratamente leggero",
|
||||
"Welcome to SillyTavern!": "Benvenuto in SillyTavern!",
|
||||
"Will be used as a password for the proxy instead of API key.": "Verrà usato come password per il proxy invece che la chiave API.",
|
||||
"Window AI Model": "Modello Window AI",
|
||||
"Your Persona": "Il tuo alterego"
|
||||
"--- Pick to Edit ---": "--- Scegli per modificare ---",
|
||||
"Add text here that would make the AI generate things you don't want in your outputs.": "Scrivi qui ciò che non vuoi l'IA generi nel suo output.",
|
||||
"write short replies, write replies using past tense": "Scrivi risposte brevi, scrivi risposte usando il passato",
|
||||
"Alert if your world info is greater than the allocated budget.": "Questo avvisa nel momento in cui le 'Info Mondo' consumano più di quanto allocato nel budget.",
|
||||
"Clear your cookie": "Cancella i cookie",
|
||||
"Restore new group chat prompt": "Ripristina il prompt della nuova chat di gruppo",
|
||||
"Save movingUI changes to a new file": "Salva i cambiamenti apportati alla posizione dei pannelli dell'UI (MovingUI) in un nuovo file",
|
||||
"Export all": "Esporta tutto",
|
||||
"Import": "Importa",
|
||||
"Insert": "Inserisci",
|
||||
"New": "Nuovo",
|
||||
"Prompts": "Prompt",
|
||||
"Tokens": "Token",
|
||||
"Reset current character": "Ripristina il personaggio attuale",
|
||||
"(0 = disabled)": "(0 = disabilitato)",
|
||||
"1 = disabled": "1 = disabilitato",
|
||||
"Activation Regex": "Attivazione Regex",
|
||||
"Active World(s) for all chats": "Attiva i Mondi per tutte le chat",
|
||||
"Add character names": "Aggiungi i nomi dei personaggi",
|
||||
"Add Memo": "Aggiungi note",
|
||||
"Advanced Character Search": "Ricerca dei personaggi avanzata",
|
||||
"Aggressive": "Aggressivo",
|
||||
"AI21 Model": "Modello AI21",
|
||||
"Alert On Overflow": "Avviso in caso di Overflow",
|
||||
"Allow fallback routes": "Permetti fallback routes",
|
||||
"Allow fallback routes Description": "Permetti la descrizione di fallback routes",
|
||||
"Alt Method": "Metodo Alt",
|
||||
"Alternate Greetings": "Alterna i saluti",
|
||||
"Alternate Greetings Hint": "Suggerimenti per i saluti alternati",
|
||||
"Alternate Greetings Subtitle": "Sottotitoli per i saluti alternati",
|
||||
"Assistant Prefill": "Assistant Prefill",
|
||||
"Banned Tokens": "Token banditi",
|
||||
"Blank": "In bianco",
|
||||
"Browser default": "Predefinito del browser",
|
||||
"Budget Cap": "Limite budget",
|
||||
"CFG": "CFG",
|
||||
"CFG Scale": "CFG Scale",
|
||||
"Changes the style of the generated text.": "Cambia lo stile del testo generato.",
|
||||
"Character Negatives": "Character Negatives",
|
||||
"Chat Negatives": "Chat Negatives",
|
||||
"Chat Scenario Override": "Sovrascrittura dello scenario della chat",
|
||||
"Chat Start": "Avvio della chat",
|
||||
"Claude Model": "Modello Claude",
|
||||
"Close chat": "Chiudi chat",
|
||||
"Context %": "Context %",
|
||||
"Context Template": "Context Template",
|
||||
"Count Penalty": "Count Penalty",
|
||||
"Example Separator": "Separatore d'esempio",
|
||||
"Exclude Assistant suffix": "Escludi il suffisso assistente",
|
||||
"Exclude the assistant suffix from being added to the end of prompt.": "Esclude il suffisso assistente dall'essere aggiunto alla fine del prompt.",
|
||||
"Force for Groups and Personas": "Forzalo per gruppi e alterego",
|
||||
"Global Negatives": "Global Negatives",
|
||||
"In Story String / Chat Completion: After Character Card": "Nella stringa narrativa / Chat Completion: Dopo la 'Carta Personaggio'",
|
||||
"In Story String / Chat Completion: Before Character Card": "Nella stringa narrativa / Chat Completion: Prima della 'Carta Personaggio",
|
||||
"Instruct": "Instruct",
|
||||
"Instruct Mode": "Modalità Instruct",
|
||||
"Last Sequence": "Ultima sequenza",
|
||||
"Lazy Chat Loading": "Caricamento svogliato della chat",
|
||||
"Least tokens": "Token minimi",
|
||||
"Light": "Leggero",
|
||||
"Load koboldcpp order": "Ripristina l'ordine di koboldcpp",
|
||||
"Main": "Principale",
|
||||
"Mancer API key": "Chiave API di Mancer",
|
||||
"Mancer API url": "Url API di Mancer",
|
||||
"May help the model to understand context. Names must only contain letters or numbers.": "Può aiutare il modello a comprendere meglio il contesto. I nomi devono contenere solo numeri e lettere.",
|
||||
"Medium": "Medium",
|
||||
"Mirostat": "Mirostat",
|
||||
"Mirostat (mode=1 is only for llama.cpp)": "Mirostat (mode=1 è valido solo per llama.cpp)",
|
||||
"Mirostat Eta": "Mirostat Eta",
|
||||
"Mirostat LR": "Mirostat LR",
|
||||
"Mirostat Mode": "Mirostat Mode",
|
||||
"Mirostat Tau": "Mirostat Tau",
|
||||
"Model Icon": "Icona del modello",
|
||||
"Most tokens": "Token massimi",
|
||||
"MovingUI Preset": "Preset MovingUI",
|
||||
"Negative Prompt": "Prompt negativo",
|
||||
"No Module": "Nessun modulo",
|
||||
"NSFW": "NSFW",
|
||||
"Nucleus Sampling": "Nucleus Sampling",
|
||||
"Off": "Spento",
|
||||
"OpenRouter API Key": "Chiave API di OpenRouter",
|
||||
"OpenRouter Model": "Modello OpenRouter",
|
||||
"or": "o",
|
||||
"Phrase Repetition Penalty": "Phrase Repetition Penalty",
|
||||
"Positive Prompt": "Prompt positivo",
|
||||
"Preamble": "Premessa",
|
||||
"Prompt Overrides (For OpenAI/Claude/Scale APIs, Window/OpenRouter, and Instruct Mode)": "Sovrascrittura del prompt (Per le API di OpenAI/Claude/Scale, Window/OpenRouter, e la Modalità Instruct)",
|
||||
"Prompt that is used when the NSFW toggle is O": "Prompt utilizzato quando l'interruttore NSFW è disattivato.",
|
||||
"Prose Augmenter": "Prose Augmenter",
|
||||
"Proxy Password": "Password proxy",
|
||||
"Quick Edit": "Editing rapido",
|
||||
"Random": "Casuale",
|
||||
"Relaxed API URLS": "URL API sciatto",
|
||||
"Replace Macro in Custom Stopping Strings": "Rimpiazza le macro nelle stringe d'arresto personalizzate",
|
||||
"Scale": "Scale",
|
||||
"Sequences you don't want to appear in the output. One per line.": "Sequenze che non vuoi appaiano nell'output. Una per linea.",
|
||||
"Set at the beginning of Dialogue examples to indicate that a new example chat is about to start.": "Impostato all'inizio degli Esempi di dialogo per indicare che un nuovo esempio di chat sta per iniziare.",
|
||||
"Set at the beginning of the chat history to indicate that a new chat is about to start.": "Impostato all'inizio della cronologia chat per indicare che una nuova chat sta per iniziare.",
|
||||
"Set at the beginning of the chat history to indicate that a new group chat is about to start.": "Impostato all'inizio della cronologia chat per indicare che un nuova chat di gruppo sta per iniziare.",
|
||||
"Show External models (provided by API)": "Mostra modelli esterni (Forniti dall'API)",
|
||||
"Show Notifications Show notifications on switching personas": "Mostra una notifica quando l'alterego viene cambiato",
|
||||
"Show tags in responses": "Mostra i tag nelle risposte",
|
||||
"Story String": "Stringa narrativa",
|
||||
"Text Adventure": "Avventura testuale",
|
||||
"Text Gen WebUI (ooba/Mancer) presets": "Preset Text Gen WebUI (ooba/Mancer)",
|
||||
"Toggle Panels": "Interruttore pannelli",
|
||||
"Top A Sampling": "Top A Sampling",
|
||||
"Top K Sampling": "Top K Sampling",
|
||||
"UI Language": "Linguaggio interfaccia grafica",
|
||||
"Unlocked Context Size": "Sblocca dimensione contesto",
|
||||
"Usage Stats": "Statistiche di utilizzo",
|
||||
"Use AI21 Tokenizer": "Utilizza il Tokenizer di AI21",
|
||||
"Use API key (Only required for Mancer)": "Utilizza la chiave API (Necessario soltanto per Mancer)",
|
||||
"Use character author's note": "Utilizza le note d'autore del personaggio",
|
||||
"Use character CFG scales": "Utilizza CFG scales del personaggio",
|
||||
"Use Proxy password field instead. This input will be ignored.": "Utilizza il campo del password proxy al suo posto. Questo input verrà ignorato.",
|
||||
"Use style tags to modify the writing style of the output": "Utilizza lo stile delle tag per modificare lo stile di scrittura in output",
|
||||
"Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.": "Utilizza il tokenizer appropiato per i modelli giurassici, visto che è più efficente di quello di GPT.",
|
||||
"Used if CFG Scale is unset globally, per chat or character": "Usato se CFG Scale non è settato globalmente, per le chat o per i personaggi",
|
||||
"Very aggressive": "Esageratamente aggressivo",
|
||||
"Very light": "Esageratamente leggero",
|
||||
"Welcome to SillyTavern!": "Benvenuto in SillyTavern!",
|
||||
"Will be used as a password for the proxy instead of API key.": "Verrà usato come password per il proxy invece che la chiave API.",
|
||||
"Window AI Model": "Modello Window AI",
|
||||
"Your Persona": "Il tuo alterego"
|
||||
},
|
||||
"nl-nl": {
|
||||
"clickslidertips": "klikregel tips",
|
||||
@ -3615,4 +3686,4 @@
|
||||
"Rep. Pen. Freq.": "Rep. Pen. Freq.",
|
||||
"Rep. Pen. Presence": "Rep. Pen. Presence."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +191,7 @@
|
||||
|
||||
<div data-newbie-hidden id="ai_module_block_novel" class="width100p">
|
||||
<div class="range-block">
|
||||
<div class="range-block-title justifyLeft">
|
||||
<div class="range-block-title justifyLeft" data-i18n="AI Module">
|
||||
AI Module
|
||||
</div>
|
||||
<div class="toggle-description justifyLeft" data-i18n="Changes the style of the generated text.">
|
||||
@ -1018,11 +1018,67 @@
|
||||
Single-line mode</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<label class="checkbox_label" for="use_default_badwordids">
|
||||
<input id="use_default_badwordids" type="checkbox" />
|
||||
<span data-i18n="Ban EOS Token">
|
||||
Ban EOS Token
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<hr>
|
||||
<h4 data-i18n="Mirostat">Mirostat</h4>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title" data-i18n="Mirostat Mode">
|
||||
Mirostat Mode
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range">
|
||||
<input type="range" id="mirostat_mode_kobold" name="volume" min="0" max="2" step="1" />
|
||||
</div>
|
||||
<div class="range-block-counter">
|
||||
<div contenteditable="true" data-for="mirostat_mode_kobold" id="mirostat_mode_counter_kobold">
|
||||
select
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title" data-i18n="Mirostat Tau">
|
||||
Mirostat Tau
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range">
|
||||
<input type="range" id="mirostat_tau_kobold" name="volume" min="0" max="10" step="0.01" />
|
||||
</div>
|
||||
<div class="range-block-counter">
|
||||
<div contenteditable="true" data-for="mirostat_tau_kobold" id="mirostat_tau_counter_kobold">
|
||||
select
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title" data-i18n="Mirostat Eta">
|
||||
Mirostat Eta
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range">
|
||||
<input type="range" id="mirostat_eta_kobold" name="volume" min="0" max="1" step="0.01" />
|
||||
</div>
|
||||
<div class="range-block-counter">
|
||||
<div contenteditable="true" data-for="mirostat_eta_kobold" id="mirostat_eta_counter_kobold">
|
||||
select
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="range-block flexFlowColumn">
|
||||
<div class="range-block-title">
|
||||
<span data-i18n="Samplers Order">Samplers Order</span>
|
||||
</div>
|
||||
<div class="toggle-description" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
||||
<div class="toggle-description widthUnset" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
||||
Samplers will be applied in a top-down order.
|
||||
Use with caution.
|
||||
</div>
|
||||
@ -1070,7 +1126,7 @@
|
||||
<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">
|
||||
<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">
|
||||
@ -1240,7 +1296,7 @@
|
||||
<div class="range-block-title">
|
||||
<span data-i18n="Samplers Order">Samplers Order</span>
|
||||
</div>
|
||||
<div class="toggle-description" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
||||
<div class="toggle-description widthUnset" data-i18n="Samplers will be applied in a top-down order. Use with caution.">
|
||||
Samplers will be applied in a top-down order. Use with caution.
|
||||
</div>
|
||||
<div id="novel_order" class="prompt_order">
|
||||
@ -1350,7 +1406,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title">
|
||||
<div class="range-block-title" data-i18n="Tail Free Sampling">
|
||||
Tail Free Sampling
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
@ -1691,8 +1747,9 @@
|
||||
</label>
|
||||
|
||||
<h4 data-i18n="API key">API key</h4>
|
||||
<small>Get it here: <a target="_blank" href="https://horde.koboldai.net/register">Register</a> (<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>)<br>
|
||||
Enter <span class="monospace">0000000000</span> to use anonymous mode.
|
||||
<small>
|
||||
<span data-i18n="Get it here:">Get it here: </span> <a target="_blank" href="https://horde.koboldai.net/register" data-i18n="Register">Register</a> (<a id="horde_kudos" href="javascript:void(0);" data-i18n="View my Kudos">View my Kudos</a>)<br>
|
||||
<span data-i18n="Enter">Enter </span> <span class="monospace">0000000000</span> <span data-i18n="to use anonymous mode.">to use anonymous mode. </span>
|
||||
</small>
|
||||
<!-- <div>
|
||||
<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>
|
||||
@ -1705,7 +1762,7 @@
|
||||
For privacy reasons, your API key will be hidden after you reload the page.
|
||||
</div>
|
||||
<h4 class="horde_model_title">
|
||||
Models
|
||||
<span data-i18n="Models">Models </span>
|
||||
<div id="horde_refresh" title="Refresh models" data-i18n="[title]Refresh models" class="right_menu_button">
|
||||
<div class="fa-solid fa-repeat "></div>
|
||||
</div>
|
||||
@ -1716,7 +1773,7 @@
|
||||
</div>
|
||||
<div id="online_status_horde">
|
||||
<div id="online_status_indicator_horde"></div>
|
||||
<div id="online_status_text_horde" data-i18n="Not connected">Not connected</div>
|
||||
<div id="online_status_text_horde" data-i18n="Not connected...">Not connected...</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1726,12 +1783,12 @@
|
||||
<h4 data-i18n="API url">API url</h4>
|
||||
<small data-i18n="Example: http://127.0.0.1:5000/api ">Example: http://127.0.0.1:5000/api </small>
|
||||
<input id="api_url_text" name="api_url" class="text_pole" placeholder="http://127.0.0.1:5000/api" maxlength="500" value="" autocomplete="off">
|
||||
<input id="api_button" class="menu_button" type="submit" value="Connect">
|
||||
<div id="api_button" class="menu_button" type="submit" data-i18n="Connect">Connect</div>
|
||||
<div id="api_loading" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
||||
</div>
|
||||
<div id="online_status2">
|
||||
<div id="online_status_indicator2"></div>
|
||||
<div id="online_status_text2" data-i18n="Not connected">Not connected</div>
|
||||
<div id="online_status_text2" data-i18n="Not connected...">Not connected...</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@ -1756,7 +1813,7 @@
|
||||
<div data-for="api_key_novel" 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>
|
||||
<input id="api_button_novel" class="menu_button" type="submit" value="Connect">
|
||||
<div id="api_button_novel" class="menu_button" type="submit" data-i18n="Connect">Connect</div>
|
||||
<div id="api_loading_novel" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
||||
<h4><span data-i18n="Novel AI Model">Novel AI Model</span>
|
||||
<a href="https://docs.sillytavern.app/usage/api-connections/novelai/#models" class="notes-link" target="_blank">
|
||||
@ -1772,12 +1829,12 @@
|
||||
</form>
|
||||
<div id="online_status3">
|
||||
<div id="online_status_indicator3"></div>
|
||||
<div id="online_status_text3" data-i18n="No connection...">No connection...</div>
|
||||
<div id="online_status_text3" data-i18n="No connection...">No connection... </div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="textgenerationwebui_api" style="display: none;position: relative;">
|
||||
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
If you are using:
|
||||
<span data-i18n="If you are using:"> If you are using:</span>
|
||||
<div class="flex-container indent20p">
|
||||
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
|
||||
oobabooga/text-generation-webui
|
||||
@ -1810,29 +1867,29 @@
|
||||
</div>
|
||||
<div class="flex1">
|
||||
<h4 data-i18n="Mancer API url">Mancer API url</h4>
|
||||
<small>Example: https://neuro.mancer.tech/webui/MODEL/api</small>
|
||||
<small data-i18n="Example: https://neuro.mancer.tech/webui/MODEL/api">Example: https://neuro.mancer.tech/webui/MODEL/api </small>
|
||||
<input id="mancer_api_url_text" name="mancer_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div id="tgwebui_api_subpanel" class="flex-container flexFlowColumn">
|
||||
<div class="flex1">
|
||||
<h4 data-i18n="Blocking API url">Blocking API url</h4>
|
||||
<small>Example: http://127.0.0.1:5000/api</small>
|
||||
<small data-i18n="Example: http://127.0.0.1:5000/api ">Example: http://127.0.0.1:5000/api </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>
|
||||
<small data-i18n="Example: ws://127.0.0.1:5005/api/v1/stream">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_button_textgenerationwebui" class="menu_button" type="submit" data-i18n="Connect">Connect</div>
|
||||
<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_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>
|
||||
</div>
|
||||
</div>
|
||||
<div id="openai_api" style="display: none;position: relative;">
|
||||
@ -1916,10 +1973,10 @@
|
||||
<form id="claude_form" data-source="claude" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
<h4>Claude API Key</h4>
|
||||
<div>
|
||||
Get your key from <a target="_blank" href="https://console.anthropic.com/account/keys">Anthropic's developer console</a>.
|
||||
<span data-i18n="Get your key from">Get your key from </span> <a target="_blank" href="https://console.anthropic.com/account/keys" data-i18n="Anthropic's developer console">Anthropic's developer console</a>.
|
||||
</div>
|
||||
<div>
|
||||
<b>
|
||||
<b data-i18n="Slack and Poe cookies will not work here, do not bother trying.">
|
||||
Slack and Poe cookies will not work here, do not bother trying.
|
||||
</b>
|
||||
</div>
|
||||
@ -1996,10 +2053,10 @@
|
||||
</div>
|
||||
<h4 data-i18n="OpenRouter API Key">OpenRouter API Key</h4>
|
||||
<div>
|
||||
<small>
|
||||
Click "Authorize" below or get the key from <a target="_blank" href="https://openrouter.ai/keys/">OpenRouter</a>.
|
||||
</small><br>
|
||||
<a href="https://openrouter.ai/account" target="_blank">View Remaining Credits</a>
|
||||
<small data-i18n="Click Authorize below or get the key from">
|
||||
Click "Authorize" below or get the key from </small> <a target="_blank" href="https://openrouter.ai/keys/">OpenRouter</a>.
|
||||
<br>
|
||||
<a href="https://openrouter.ai/account" target="_blank" data-i18n="View Remaining Credits">View Remaining Credits</a>
|
||||
</div>
|
||||
<div class="flex-container">
|
||||
<input id="api_key_openrouter" name="api_key_openrouter" class="text_pole flex1" maxlength="500" value="" type="text" autocomplete="off">
|
||||
@ -2012,7 +2069,7 @@
|
||||
|
||||
<form id="scale_form" data-source="scale" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
<div id="normal_scale_form">
|
||||
<h4>Scale API Key</h4>
|
||||
<h4 data-i18n="Scale API Key">Scale API Key</h4>
|
||||
<div class="flex-container">
|
||||
<input id="api_key_scale" name="api_key_scale" class="text_pole flex1" maxlength="500" value="" 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_scale"></div>
|
||||
@ -2042,7 +2099,7 @@
|
||||
</form>
|
||||
|
||||
<form id="ai21_form" data-source="ai21" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
<h4>AI21 API Key</h4>
|
||||
<h4 data-i18n="AI21 API Key">AI21 API Key</h4>
|
||||
<div class="flex-container">
|
||||
<input id="api_key_ai21" name="api_key_ai21" class="text_pole flex1" maxlength="500" value="" 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_ai21"></div>
|
||||
@ -2063,14 +2120,14 @@
|
||||
</form>
|
||||
|
||||
<div class="flex-container flex">
|
||||
<input id="api_button_openai" class="menu_button" type="submit" value="Connect">
|
||||
<input data-source="openrouter" id="openrouter_authorize" class="menu_button" type="button" value="Authorize" title="Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai" data-i18n="[title]Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai">
|
||||
<input id="test_api_button" class="menu_button" type="button" value="Test Message" title="Verifies your API connection by sending a short test message. Be aware that you'll be credited for it!" data-i18n="[title]Verifies your API connection by sending a short test message. Be aware that you'll be credited for it!">
|
||||
<div id="api_button_openai" class="menu_button menu_button_icon" type="submit" data-i18n="Connect">Connect</div>
|
||||
<div data-source="openrouter" id="openrouter_authorize" class="menu_button menu_button_icon" title="Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai" data-i18n="[title]Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai">Authorize</div>
|
||||
<div id="test_api_button" class="menu_button menu_button_icon" title="Verifies your API connection by sending a short test message. Be aware that you'll be credited for it!" data-i18n="[title]Verifies your API connection by sending a short test message. Be aware that you'll be credited for it!">Test Message</div>
|
||||
</div>
|
||||
<div id="api_loading_openai" class=" api-load-icon fa-solid fa-hourglass fa-spin"></div>
|
||||
<div class="online_status4">
|
||||
<div class="online_status_indicator4"></div>
|
||||
<div class="online_status_text4">No connection...</div>
|
||||
<div class="online_status_text4" data-i18n="No connection...">No connection...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2133,7 +2190,45 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div data-newbie-hidden class="inline-drawer wide100p flexFlowColumn margin-bot-10px" style="display:none;">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
<b><span data-i18n="Context Order">Context Order</span></b>
|
||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||
</div>
|
||||
<div class="inline-drawer-content">
|
||||
<div id="context_order" class="prompt_order">
|
||||
<div data-id="0">
|
||||
<span data-i18n="Story String">Story String</span>
|
||||
<small>0</small>
|
||||
</div>
|
||||
<div data-id="1">
|
||||
<span data-i18n="Summary">Summary</span>
|
||||
<small>1</small>
|
||||
</div>
|
||||
<div data-id="2">
|
||||
<span data-i18n="Author's Note">Author's Note</span>
|
||||
<small>2</small>
|
||||
</div>
|
||||
<div data-id="3">
|
||||
<span data-i18n="Example Dialogues">Example Dialogues</span>
|
||||
<small>3</small>
|
||||
</div>
|
||||
<div data-id="4">
|
||||
<span data-i18n="Chat Start">Chat History</span>
|
||||
<small>4</small>
|
||||
</div>
|
||||
</div>
|
||||
<small>
|
||||
<b data-i18n="Hint">Hint:</b>
|
||||
<span data-i18n="In-Chat Position not affected">
|
||||
Summary and Author's Note orders are only affected when they don't have an In-Chat position set.
|
||||
</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 data-i18n="Instruct Mode">Instruct Mode
|
||||
<a href="https://docs.sillytavern.app/usage/core-concepts/instructmode/" class="notes-link" target="_blank">
|
||||
@ -2208,7 +2303,7 @@
|
||||
<small data-i18n="Input Sequence">Input Sequence</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_input_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_input_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
@ -2216,7 +2311,7 @@
|
||||
<small data-i18n="Output Sequence">Output Sequence</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_output_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_output_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2226,7 +2321,7 @@
|
||||
<small data-i18n="First Output Sequence">First Output Sequence</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_first_output_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_first_output_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
@ -2234,7 +2329,7 @@
|
||||
<small data-i18n="Last Output Sequence">Last Output Sequence</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_last_output_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_last_output_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2244,7 +2339,7 @@
|
||||
<small data-i18n="System Sequence Prefix">System Sequence Prefix</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_system_sequence_prefix" class="text_pole textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_system_sequence_prefix" class="text_pole textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
@ -2252,7 +2347,7 @@
|
||||
<small data-i18n="System Sequence Suffix">System Sequence Suffix</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_system_sequence_suffix" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_system_sequence_suffix" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2262,7 +2357,7 @@
|
||||
<small data-i18n="Stop Sequence">Stop Sequence</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_stop_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_stop_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="200k0" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex1">
|
||||
@ -2270,7 +2365,7 @@
|
||||
<small data-i18n="Separator">Separator</small>
|
||||
</label>
|
||||
<div>
|
||||
<textarea id="instruct_separator_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="500" placeholder="—" rows="1"></textarea>
|
||||
<textarea id="instruct_separator_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2320,7 +2415,9 @@
|
||||
</label>
|
||||
<label data-newbie-hidden class="checkbox_label" for="remove-examples-checkbox">
|
||||
<input id="remove-examples-checkbox" type="checkbox" />
|
||||
Strip Example Messages from Prompt
|
||||
<span data-i18n="Strip Example Messages from Prompt">
|
||||
Strip Example Messages from Prompt
|
||||
</span>
|
||||
</label>
|
||||
<label class="checkbox_label" for="collapse-newlines-checkbox"><input id="collapse-newlines-checkbox" type="checkbox" />
|
||||
<span data-i18n="Remove Empty New Lines from Output">
|
||||
@ -2761,7 +2858,7 @@
|
||||
<div data-newbie-hidden class="range-block">
|
||||
<div class="range-block-title">
|
||||
<span data-i18n="Lazy Chat Loading">Lazy Chat Loading</span><br>
|
||||
<small># of messages (0 = disabled)</small>
|
||||
<small data-i18n="# of messages (0 = disabled)"># of messages (0 = disabled)</small>
|
||||
</div>
|
||||
<div class="range-block-range-and-counter">
|
||||
<div class="range-block-range">
|
||||
@ -2841,6 +2938,11 @@
|
||||
<span data-i18n="Message IDs">Show Message IDs</span>
|
||||
</label>
|
||||
|
||||
<label data-newbie-hidden for="messageTokensEnabled" class="checkbox_label">
|
||||
<input id="messageTokensEnabled" type="checkbox" />
|
||||
<span data-i18n="Show Message Token Count">Show Message Token Count</span>
|
||||
</label>
|
||||
|
||||
<label data-newbie-hidden for="auto_scroll_chat_to_bottom" class="checkbox_label">
|
||||
<input id="auto_scroll_chat_to_bottom" type="checkbox" />
|
||||
<span data-i18n="Auto-scroll Chat">Auto-scroll Chat</span>
|
||||
@ -3035,7 +3137,7 @@
|
||||
</a>
|
||||
</h3>
|
||||
<div class="flex-container">
|
||||
<div id="extensions_status" data-i18n="Not Connected">Not Connected</div>
|
||||
<div id="extensions_status" data-i18n="Not connected...">Not connected...</div>
|
||||
<label for="extensions_autoconnect">
|
||||
<input id="extensions_autoconnect" type="checkbox">
|
||||
<span data-i18n="Auto-connect">Auto-connect</span>
|
||||
@ -3047,7 +3149,7 @@
|
||||
<input id="extensions_api_key" type="text" class="flex1 heightFitContent text_pole widthNatural" maxlength="250" data-i18n="[placeholder]API key" placeholder="API key">
|
||||
<div class="alignitemsflexstart extensions_url_block">
|
||||
<div class="" style="text-align: center">
|
||||
<input id="extensions_connect" class="menu_button" type="submit" value="Connect">
|
||||
<input id="extensions_connect" class="menu_button" type="submit" data-i18n="Connect">Connect</input>
|
||||
</div>
|
||||
<input id="extensions_details" class="alignitemsflexstart menu_button" type="button" value="Manage extensions">
|
||||
<div id="third_party_extension_button" title="Import Extension From Git Repo" class="menu_button fa-solid fa-cloud-arrow-down faSmallFontSquareFix"></div>
|
||||
@ -3100,7 +3202,7 @@
|
||||
<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">
|
||||
<span data-i18n="Show notifications on switching personas">
|
||||
Show notifications on switching personas
|
||||
</span>
|
||||
</label>
|
||||
@ -4010,6 +4112,7 @@
|
||||
</div>
|
||||
<div class="mesIDDisplay"></div>
|
||||
<div class="mes_timer"></div>
|
||||
<div class="tokenCounterDisplay"></div>
|
||||
</div>
|
||||
<div class="swipe_left fa-solid fa-chevron-left"></div>
|
||||
<div class="mes_block">
|
||||
@ -4392,7 +4495,7 @@
|
||||
<div class="panelControlBar flex-container">
|
||||
<div class="fa-solid fa-grip drag-grabber"></div>
|
||||
<div class="fa-solid fa-circle-xmark dragClose"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -4445,4 +4548,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
210
public/script.js
210
public/script.js
@ -6,9 +6,8 @@ import {
|
||||
loadKoboldSettings,
|
||||
formatKoboldUrl,
|
||||
getKoboldGenerationData,
|
||||
canUseKoboldStopSequence,
|
||||
canUseKoboldStreaming,
|
||||
canUseKoboldTokenization,
|
||||
kai_flags,
|
||||
setKoboldFlags,
|
||||
} from "./scripts/kai-settings.js";
|
||||
|
||||
import {
|
||||
@ -280,7 +279,8 @@ export const event_types = {
|
||||
CHATCOMPLETION_SOURCE_CHANGED: 'chatcompletion_source_changed',
|
||||
CHATCOMPLETION_MODEL_CHANGED: 'chatcompletion_model_changed',
|
||||
OAI_BEFORE_CHATCOMPLETION: 'oai_before_chatcompletion',
|
||||
OAI_PRESET_CHANGED: 'oai_preset_changed',
|
||||
OAI_PRESET_CHANGED_BEFORE: 'oai_preset_changed_before',
|
||||
OAI_PRESET_CHANGED_AFTER: 'oai_preset_changed_after',
|
||||
WORLDINFO_SETTINGS_UPDATED: 'worldinfo_settings_updated',
|
||||
CHARACTER_EDITED: 'character_edited',
|
||||
USER_MESSAGE_RENDERED: 'user_message_rendered',
|
||||
@ -702,9 +702,16 @@ $.ajaxPrefilter((options, originalOptions, xhr) => {
|
||||
xhr.setRequestHeader("X-CSRF-Token", token);
|
||||
});
|
||||
|
||||
///// initialization protocol ////////
|
||||
$.get("/csrf-token").then(async (data) => {
|
||||
token = data.token;
|
||||
async function firstLoadInit() {
|
||||
try {
|
||||
const tokenResponse = await fetch('/csrf-token');
|
||||
const tokenData = await tokenResponse.json();
|
||||
token = tokenData.token;
|
||||
} catch {
|
||||
toastr.error("Couldn't get CSRF token. Please refresh the page.", "Error", { timeOut: 0, extendedTimeOut: 0, preventDuplicates: true });
|
||||
throw new Error("Initialization failed");
|
||||
}
|
||||
|
||||
getSystemMessages();
|
||||
sendSystemMessage(system_message_types.WELCOME);
|
||||
await readSecretState();
|
||||
@ -713,7 +720,10 @@ $.get("/csrf-token").then(async (data) => {
|
||||
await getUserAvatars();
|
||||
await getCharacters();
|
||||
await getBackgrounds();
|
||||
});
|
||||
initAuthorsNote();
|
||||
initPersonas();
|
||||
initRossMods();
|
||||
}
|
||||
|
||||
function checkOnlineStatus() {
|
||||
///////// REMOVED LINES THAT DUPLICATE RA_CHeckOnlineStatus FEATURES
|
||||
@ -798,9 +808,7 @@ async function getStatus() {
|
||||
|
||||
// determine if we can use stop sequence and streaming
|
||||
if (main_api === "kobold" || main_api === "koboldhorde") {
|
||||
kai_settings.use_stop_sequence = canUseKoboldStopSequence(data.version);
|
||||
kai_settings.can_use_streaming = canUseKoboldStreaming(data.koboldVersion);
|
||||
kai_settings.can_use_tokenization = canUseKoboldTokenization(data.koboldVersion);
|
||||
setKoboldFlags(data.version, data.koboldVersion);
|
||||
}
|
||||
|
||||
// We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress.
|
||||
@ -1236,7 +1244,7 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
|
||||
}
|
||||
|
||||
if (power_user.auto_fix_generated_markdown) {
|
||||
mes = fixMarkdown(mes);
|
||||
mes = fixMarkdown(mes, true);
|
||||
}
|
||||
|
||||
if (!isSystem && power_user.encode_tags) {
|
||||
@ -1299,7 +1307,7 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
|
||||
* the function fetches the "claude.svg". Otherwise, it fetches the SVG named after
|
||||
* the value in `extra.api`.
|
||||
*
|
||||
* @param {jQuery} mes - The message element containing the timestamp where the icon should be inserted or replaced.
|
||||
* @param {JQuery<HTMLElement>} mes - The message element containing the timestamp where the icon should be inserted or replaced.
|
||||
* @param {Object} extra - Contains the API and model details.
|
||||
* @param {string} extra.api - The name of the API, used to determine which SVG to fetch.
|
||||
* @param {string} extra.model - The model name, used to check for the substring "claude".
|
||||
@ -1361,6 +1369,7 @@ function getMessageFromTemplate({
|
||||
bookmarkLink,
|
||||
forceAvatar,
|
||||
timestamp,
|
||||
tokenCount,
|
||||
extra,
|
||||
} = {}) {
|
||||
const mes = $('#message_template .mes').clone();
|
||||
@ -1378,6 +1387,7 @@ function getMessageFromTemplate({
|
||||
mes.find('.mes_bias').html(bias);
|
||||
mes.find('.timestamp').text(timestamp).attr('title', `${extra?.api ? extra.api + ' - ' : ''}${extra?.model ?? ''}`);
|
||||
mes.find('.mesIDDisplay').text(`#${mesId}`);
|
||||
tokenCount && mes.find('.tokenCounterDisplay').text(`${tokenCount}t`);
|
||||
title && mes.attr('title', title);
|
||||
timerValue && mes.find('.mes_timer').attr('title', timerTitle).text(timerValue);
|
||||
|
||||
@ -1508,7 +1518,8 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
|
||||
forceAvatar: mes.force_avatar,
|
||||
timestamp: timestamp,
|
||||
extra: mes.extra,
|
||||
...formatGenerationTimer(mes.gen_started, mes.gen_finished),
|
||||
tokenCount: mes.extra?.token_count,
|
||||
...formatGenerationTimer(mes.gen_started, mes.gen_finished, mes.extra?.token_count),
|
||||
};
|
||||
|
||||
const HTMLForEachMes = getMessageFromTemplate(params);
|
||||
@ -1581,20 +1592,23 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
|
||||
});
|
||||
|
||||
if (type === 'swipe') {
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.mes_text').html('');
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.mes_text').append(messageText);
|
||||
appendImageToMessage(mes, $("#chat").find(`[mesid="${count_view_mes - 1}"]`));
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).attr('title', title);
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`);
|
||||
const swipeMessage = $("#chat").find(`[mesid="${count_view_mes - 1}"]`);
|
||||
swipeMessage.find('.mes_text').html('');
|
||||
swipeMessage.find('.mes_text').append(messageText);
|
||||
appendImageToMessage(mes, swipeMessage);
|
||||
swipeMessage.attr('title', title);
|
||||
swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`);
|
||||
if (power_user.timestamp_model_icon && params.extra?.api) {
|
||||
insertSVGIcon($("#chat").find(`[mesid="${count_view_mes - 1}"]`), params.extra);
|
||||
insertSVGIcon(swipeMessage, params.extra);
|
||||
}
|
||||
|
||||
if (mes.swipe_id == mes.swipes.length - 1) {
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.mes_timer').text(params.timerValue);
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.mes_timer').attr('title', params.timerTitle);
|
||||
swipeMessage.find('.mes_timer').text(params.timerValue);
|
||||
swipeMessage.find('.mes_timer').attr('title', params.timerTitle);
|
||||
swipeMessage.find('.tokenCounterDisplay').text(`${params.tokenCount}t`);
|
||||
} else {
|
||||
$("#chat").find(`[mesid="${count_view_mes - 1}"]`).find('.mes_timer').html('');
|
||||
swipeMessage.find('.mes_timer').html('');
|
||||
swipeMessage.find('.tokenCounterDisplay').html('');
|
||||
}
|
||||
} else {
|
||||
$("#chat").find(`[mesid="${count_view_mes}"]`).find('.mes_text').append(messageText);
|
||||
@ -1620,7 +1634,18 @@ function getUserAvatar(avatarImg) {
|
||||
return `User Avatars/${avatarImg}`;
|
||||
}
|
||||
|
||||
function formatGenerationTimer(gen_started, gen_finished) {
|
||||
/**
|
||||
* Formats the title for the generation timer.
|
||||
* @param {Date} gen_started Date when generation was started
|
||||
* @param {Date} gen_finished Date when generation was finished
|
||||
* @param {number} tokenCount Number of tokens generated (0 if not available)
|
||||
* @returns {Object} Object containing the formatted timer value and title
|
||||
* @example
|
||||
* const { timerValue, timerTitle } = formatGenerationTimer(gen_started, gen_finished, tokenCount);
|
||||
* console.log(timerValue); // 1.2s
|
||||
* console.log(timerTitle); // Generation queued: 12:34:56 7 Jan 2021\nReply received: 12:34:57 7 Jan 2021\nTime to generate: 1.2 seconds\nToken rate: 5 t/s
|
||||
*/
|
||||
function formatGenerationTimer(gen_started, gen_finished, tokenCount) {
|
||||
if (!gen_started || !gen_finished) {
|
||||
return {};
|
||||
}
|
||||
@ -1634,6 +1659,7 @@ function formatGenerationTimer(gen_started, gen_finished) {
|
||||
`Generation queued: ${start.format(dateFormat)}`,
|
||||
`Reply received: ${finish.format(dateFormat)}`,
|
||||
`Time to generate: ${seconds} seconds`,
|
||||
tokenCount > 0 ? `Token rate: ${Number(tokenCount / seconds).toFixed(1)} t/s` : '',
|
||||
].join('\n');
|
||||
|
||||
return { timerValue, timerTitle };
|
||||
@ -1998,7 +2024,7 @@ function baseChatReplace(value, name1, name2) {
|
||||
|
||||
function isStreamingEnabled() {
|
||||
return ((main_api == 'openai' && oai_settings.stream_openai && oai_settings.chat_completion_source !== chat_completion_sources.SCALE && oai_settings.chat_completion_source !== chat_completion_sources.AI21)
|
||||
|| (main_api == 'kobold' && kai_settings.streaming_kobold && kai_settings.can_use_streaming)
|
||||
|| (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)
|
||||
|| (main_api == 'novel' && nai_settings.streaming_novel)
|
||||
|| (main_api == 'textgenerationwebui' && textgenerationwebui_settings.streaming))
|
||||
&& !isMultigenEnabled(); // Multigen has a quasi-streaming mode which breaks the real streaming
|
||||
@ -2086,12 +2112,24 @@ class StreamingProcessor {
|
||||
}
|
||||
else {
|
||||
let currentTime = new Date();
|
||||
const timePassed = formatGenerationTimer(this.timeStarted, currentTime);
|
||||
// Don't waste time calculating token count for streaming
|
||||
let currentTokenCount = isFinal && power_user.message_token_count_enabled ? getTokenCount(processedText, 0) : 0;
|
||||
const timePassed = formatGenerationTimer(this.timeStarted, currentTime, currentTokenCount);
|
||||
chat[messageId]['is_name'] = isName;
|
||||
chat[messageId]['mes'] = processedText;
|
||||
chat[messageId]['gen_started'] = this.timeStarted;
|
||||
chat[messageId]['gen_finished'] = currentTime;
|
||||
|
||||
if (currentTokenCount) {
|
||||
if (!chat[messageId]['extra']) {
|
||||
chat[messageId]['extra'] = {};
|
||||
}
|
||||
|
||||
chat[messageId]['extra']['token_count'] = currentTokenCount;
|
||||
const tokenCounter = $(`#chat .mes[mesid="${messageId}"] .tokenCounterDisplay`);
|
||||
tokenCounter.text(`${currentTokenCount}t`);
|
||||
}
|
||||
|
||||
if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId]['swipes'])) {
|
||||
chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText;
|
||||
chat[messageId]['swipe_info'][chat[messageId]['swipe_id']] = { 'send_date': chat[messageId]['send_date'], 'gen_started': chat[messageId]['gen_started'], 'gen_finished': chat[messageId]['gen_finished'], 'extra': JSON.parse(JSON.stringify(chat[messageId]['extra'])) };
|
||||
@ -2278,7 +2316,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
||||
return;
|
||||
}
|
||||
|
||||
if (main_api == 'kobold' && kai_settings.streaming_kobold && !kai_settings.can_use_streaming) {
|
||||
if (main_api == 'kobold' && kai_settings.streaming_kobold && !kai_flags.can_use_streaming) {
|
||||
toastr.error('Streaming is enabled, but the version of Kobold used does not support token streaming.', undefined, { timeOut: 10000, preventDuplicates: true, });
|
||||
is_send_press = false;
|
||||
return;
|
||||
@ -3327,6 +3365,10 @@ export async function sendMessageAsUser(textareaText, messageBias) {
|
||||
chat[chat.length - 1]['mes'] = substituteParams(textareaText);
|
||||
chat[chat.length - 1]['extra'] = {};
|
||||
|
||||
if (power_user.message_token_count_enabled) {
|
||||
chat[chat.length - 1]['extra']['token_count'] = getTokenCount(chat[chat.length - 1]['mes'], 0);
|
||||
}
|
||||
|
||||
// Lock user avatar to a persona.
|
||||
if (user_avatar in power_user.personas) {
|
||||
chat[chat.length - 1]['force_avatar'] = getUserAvatar(user_avatar);
|
||||
@ -3862,7 +3904,7 @@ function cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete
|
||||
}
|
||||
}
|
||||
if (power_user.auto_fix_generated_markdown) {
|
||||
getMessage = fixMarkdown(getMessage);
|
||||
getMessage = fixMarkdown(getMessage, false);
|
||||
}
|
||||
return getMessage;
|
||||
}
|
||||
@ -3892,6 +3934,9 @@ async function saveReply(type, getMessage, this_mes_is_name, title) {
|
||||
chat[chat.length - 1]['send_date'] = getMessageTimeStamp();
|
||||
chat[chat.length - 1]['extra']['api'] = getGeneratingApi();
|
||||
chat[chat.length - 1]['extra']['model'] = getGeneratingModel();
|
||||
if (power_user.message_token_count_enabled) {
|
||||
chat[chat.length - 1]['extra']['token_count'] = getTokenCount(chat[chat.length - 1]['mes'], 0);
|
||||
}
|
||||
await eventSource.emit(event_types.MESSAGE_RECEIVED, (chat.length - 1));
|
||||
addOneMessage(chat[chat.length - 1], { type: 'swipe' });
|
||||
await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, (chat.length - 1));
|
||||
@ -3908,6 +3953,9 @@ async function saveReply(type, getMessage, this_mes_is_name, title) {
|
||||
chat[chat.length - 1]['send_date'] = getMessageTimeStamp();
|
||||
chat[chat.length - 1]["extra"]["api"] = getGeneratingApi();
|
||||
chat[chat.length - 1]["extra"]["model"] = getGeneratingModel();
|
||||
if (power_user.message_token_count_enabled) {
|
||||
chat[chat.length - 1]['extra']['token_count'] = getTokenCount(chat[chat.length - 1]['mes'], 0);
|
||||
}
|
||||
await eventSource.emit(event_types.MESSAGE_RECEIVED, (chat.length - 1));
|
||||
addOneMessage(chat[chat.length - 1], { type: 'swipe' });
|
||||
await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, (chat.length - 1));
|
||||
@ -3921,6 +3969,9 @@ async function saveReply(type, getMessage, this_mes_is_name, title) {
|
||||
chat[chat.length - 1]['send_date'] = getMessageTimeStamp();
|
||||
chat[chat.length - 1]["extra"]["api"] = getGeneratingApi();
|
||||
chat[chat.length - 1]["extra"]["model"] = getGeneratingModel();
|
||||
if (power_user.message_token_count_enabled) {
|
||||
chat[chat.length - 1]['extra']['token_count'] = getTokenCount(chat[chat.length - 1]['mes'], 0);
|
||||
}
|
||||
await eventSource.emit(event_types.MESSAGE_RECEIVED, (chat.length - 1));
|
||||
addOneMessage(chat[chat.length - 1], { type: 'swipe' });
|
||||
await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, (chat.length - 1));
|
||||
@ -3943,6 +3994,10 @@ async function saveReply(type, getMessage, this_mes_is_name, title) {
|
||||
chat[chat.length - 1]['gen_started'] = generation_started;
|
||||
chat[chat.length - 1]['gen_finished'] = generationFinished;
|
||||
|
||||
if (power_user.message_token_count_enabled) {
|
||||
chat[chat.length - 1]['extra']['token_count'] = getTokenCount(chat[chat.length - 1]['mes'], 0);
|
||||
}
|
||||
|
||||
if (selected_group) {
|
||||
console.debug('entering chat update for groups');
|
||||
let avatarImg = 'img/ai4.png';
|
||||
@ -4614,9 +4669,6 @@ export async function getUserAvatars() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function highlightSelectedAvatar() {
|
||||
$("#user_avatar_block").find(".avatar").removeClass("selected");
|
||||
$("#user_avatar_block")
|
||||
@ -4664,7 +4716,6 @@ export function setUserName(value) {
|
||||
saveSettings("change_name");
|
||||
}
|
||||
|
||||
|
||||
function setUserAvatar() {
|
||||
user_avatar = $(this).attr("imgfile");
|
||||
reloadUserAvatar();
|
||||
@ -4728,8 +4779,6 @@ async function uploadUserAvatar(e) {
|
||||
$("#form_upload_avatar").trigger("reset");
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function doOnboarding(avatarId) {
|
||||
let simpleUiMode = false;
|
||||
const template = $('#onboarding_template .onboarding');
|
||||
@ -5022,18 +5071,6 @@ export function setGenerationParamsFromPreset(preset) {
|
||||
}
|
||||
}
|
||||
|
||||
function setCharacterBlockHeight() {
|
||||
const $children = $("#rm_print_characters_block").children();
|
||||
const originalHeight = $children.length * $children.find(':visible').first().outerHeight();
|
||||
$("#rm_print_characters_block").css('height', originalHeight);
|
||||
//show and hide charlist divs on pageload (causes load lag)
|
||||
//$children.each(function () { setCharListVisible($(this)) });
|
||||
|
||||
|
||||
//delay timer to allow for charlist to populate,
|
||||
//should be set to an onload for rm_print_characters or windows?
|
||||
}
|
||||
|
||||
// Common code for message editor done and auto-save
|
||||
function updateMessage(div) {
|
||||
const mesBlock = div.closest(".mes_block");
|
||||
@ -6390,6 +6427,18 @@ function swipe_left() { // when we swipe left..but no generation.
|
||||
const is_animation_scroll = ($('#chat').scrollTop() >= ($('#chat').prop("scrollHeight") - $('#chat').outerHeight()) - 10);
|
||||
//console.log('on left swipe click calling addOneMessage');
|
||||
addOneMessage(chat[chat.length - 1], { type: 'swipe' });
|
||||
|
||||
if (power_user.message_token_count_enabled) {
|
||||
if (!chat[chat.length - 1].extra) {
|
||||
chat[chat.length - 1].extra = {};
|
||||
}
|
||||
|
||||
const swipeMessage = $("#chat").find(`[mesid="${count_view_mes - 1}"]`);
|
||||
const tokenCount = getTokenCount(chat[chat.length - 1].mes, 0);
|
||||
chat[chat.length -1]['extra']['token_count'] = tokenCount;
|
||||
swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`);
|
||||
}
|
||||
|
||||
let new_height = this_mes_div_height - (this_mes_block_height - this_mes_block[0].scrollHeight);
|
||||
if (new_height < 103) new_height = 103;
|
||||
this_mes_div.animate({ height: new_height + 'px' }, {
|
||||
@ -6545,23 +6594,27 @@ const swipe_right = () => {
|
||||
const is_animation_scroll = ($('#chat').scrollTop() >= ($('#chat').prop("scrollHeight") - $('#chat').outerHeight()) - 10);
|
||||
//console.log(parseInt(chat[chat.length-1]['swipe_id']));
|
||||
//console.log(chat[chat.length-1]['swipes'].length);
|
||||
const swipeMessage = $("#chat").find('[mesid="' + (count_view_mes - 1) + '"]');
|
||||
if (run_generate && parseInt(chat[chat.length - 1]['swipe_id']) === chat[chat.length - 1]['swipes'].length) {
|
||||
//console.log('showing ""..."');
|
||||
/* if (!selected_group) {
|
||||
} else { */
|
||||
$("#chat")
|
||||
.find('[mesid="' + (count_view_mes - 1) + '"]')
|
||||
.find('.mes_text')
|
||||
.html('...'); //shows "..." while generating
|
||||
$("#chat")
|
||||
.find('[mesid="' + (count_view_mes - 1) + '"]')
|
||||
.find('.mes_timer')
|
||||
.html(''); // resets the timer
|
||||
/* } */
|
||||
//shows "..." while generating
|
||||
swipeMessage.find('.mes_text').html('...');
|
||||
// resets the timer
|
||||
swipeMessage.find('.mes_timer').html('');
|
||||
swipeMessage.find('.tokenCounterDisplay').text('');
|
||||
} else {
|
||||
//console.log('showing previously generated swipe candidate, or "..."');
|
||||
//console.log('onclick right swipe calling addOneMessage');
|
||||
addOneMessage(chat[chat.length - 1], { type: 'swipe' });
|
||||
|
||||
if (power_user.message_token_count_enabled) {
|
||||
if (!chat[chat.length - 1].extra) {
|
||||
chat[chat.length - 1].extra = {};
|
||||
}
|
||||
|
||||
const tokenCount = getTokenCount(chat[chat.length - 1].mes, 0);
|
||||
chat[chat.length -1]['extra']['token_count'] = tokenCount;
|
||||
swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`);
|
||||
}
|
||||
}
|
||||
let new_height = this_mes_div_height - (this_mes_block_height - this_mes_block[0].scrollHeight);
|
||||
if (new_height < 103) new_height = 103;
|
||||
@ -6855,7 +6908,6 @@ export async function handleDeleteCharacter(popup_type, this_chid, delete_chats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to delete a character from UI after character deletion API success.
|
||||
* It manages necessary UI changes such as closing advanced editing popup, unsetting
|
||||
@ -6889,8 +6941,7 @@ function doTogglePanels() {
|
||||
$("#option_settings").trigger('click')
|
||||
}
|
||||
|
||||
|
||||
$(document).ready(function () {
|
||||
jQuery(async function () {
|
||||
|
||||
if (isMobile() === true) {
|
||||
console.debug('hiding movingUI and sheldWidth toggles for mobile')
|
||||
@ -7178,6 +7229,7 @@ $(document).ready(function () {
|
||||
$("#character_popup").css("display", "none");
|
||||
}
|
||||
});
|
||||
|
||||
$("#character_cross").click(function () {
|
||||
is_advanced_char_open = false;
|
||||
$("#character_popup").transition({
|
||||
@ -7187,10 +7239,12 @@ $(document).ready(function () {
|
||||
});
|
||||
setTimeout(function () { $("#character_popup").css("display", "none"); }, 200);
|
||||
});
|
||||
|
||||
$("#character_popup_ok").click(function () {
|
||||
is_advanced_char_open = false;
|
||||
$("#character_popup").css("display", "none");
|
||||
});
|
||||
|
||||
$("#dialogue_popup_ok").click(async function (e) {
|
||||
$("#shadow_popup").transition({
|
||||
opacity: 0,
|
||||
@ -7285,6 +7339,7 @@ $(document).ready(function () {
|
||||
dialogueResolve = null;
|
||||
}
|
||||
});
|
||||
|
||||
$("#dialogue_popup_cancel").click(function (e) {
|
||||
$("#shadow_popup").transition({
|
||||
opacity: 0,
|
||||
@ -7817,8 +7872,6 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
const sliders = [
|
||||
{
|
||||
sliderId: "#amount_gen",
|
||||
@ -7908,7 +7961,6 @@ $(document).ready(function () {
|
||||
$('#rawPromptPopup').toggle();
|
||||
})
|
||||
|
||||
|
||||
//********************
|
||||
//***Message Editor***
|
||||
$(document).on("click", ".mes_edit", async function () {
|
||||
@ -8155,7 +8207,6 @@ $(document).ready(function () {
|
||||
setUserName($('#your_name').val());
|
||||
});
|
||||
|
||||
|
||||
$('#sync_name_button').on('click', async function () {
|
||||
const confirmation = await callPopup(`<h3>Are you sure?</h3>All user-sent messages in this chat will be attributed to ${name1}.`, 'confirm');
|
||||
|
||||
@ -8200,6 +8251,7 @@ $(document).ready(function () {
|
||||
$("#character_import_button").click(function () {
|
||||
$("#character_import_file").click();
|
||||
});
|
||||
|
||||
$("#character_import_file").on("change", function (e) {
|
||||
$("#rm_info_avatar").html("");
|
||||
if (!e.target.files.length) {
|
||||
@ -8210,10 +8262,12 @@ $(document).ready(function () {
|
||||
importCharacter(file);
|
||||
}
|
||||
});
|
||||
|
||||
$("#export_button").on('click', function (e) {
|
||||
$('#export_format_popup').toggle();
|
||||
exportPopper.update();
|
||||
});
|
||||
|
||||
$(document).on('click', '.export_format', async function () {
|
||||
const format = $(this).data('format');
|
||||
|
||||
@ -8579,7 +8633,6 @@ $(document).ready(function () {
|
||||
$("#char-management-dropdown").prop('selectedIndex', 0);
|
||||
});
|
||||
|
||||
|
||||
$(document).on('click', '.mes_img_enlarge', enlargeMessageImage);
|
||||
$(document).on('click', '.mes_img_delete', deleteMessageImage);
|
||||
|
||||
@ -8782,7 +8835,26 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
// Added here to prevent execution before script.js is loaded and get rid of quirky timeouts
|
||||
initAuthorsNote();
|
||||
initRossMods();
|
||||
initPersonas();
|
||||
await firstLoadInit();
|
||||
|
||||
registerDebugFunction('backfillTokenCounts', 'Backfill token counters',
|
||||
`Recalculates token counts of all messages in the current chat to refresh the counters.
|
||||
Useful when you switch between models that have different tokenizers.
|
||||
This is a visual change only. Your chat will be reloaded.`, async () => {
|
||||
for (const message of chat) {
|
||||
// System messages are not counted
|
||||
if (message.is_system) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!message.extra) {
|
||||
message.extra = {};
|
||||
}
|
||||
|
||||
message.extra.token_count = getTokenCount(message.mes, 0);
|
||||
}
|
||||
|
||||
await saveChatConditional();
|
||||
await reloadCurrentChat();
|
||||
});
|
||||
});
|
||||
|
@ -53,7 +53,7 @@ const registerPromptManagerMigration = () => {
|
||||
};
|
||||
|
||||
eventSource.on(event_types.SETTINGS_LOADED_BEFORE, settings => migrate(settings));
|
||||
eventSource.on(event_types.OAI_PRESET_CHANGED, event => migrate(event.preset, event.savePreset, event.presetName));
|
||||
eventSource.on(event_types.OAI_PRESET_CHANGED_BEFORE, event => migrate(event.preset, event.savePreset, event.presetName));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -604,22 +604,20 @@ PromptManagerModule.prototype.init = function (moduleConfiguration, serviceSetti
|
||||
document.getElementById(this.configuration.prefix + 'prompt_manager_popup_close_button').addEventListener('click', closeAndClearPopup);
|
||||
|
||||
// Re-render prompt manager on openai preset change
|
||||
eventSource.on(event_types.OAI_PRESET_CHANGED, settings => {
|
||||
// Save configuration and wrap everything up.
|
||||
this.saveServiceSettings().then(() => {
|
||||
const mainPrompt = this.getPromptById('main');
|
||||
this.updateQuickEdit('main', mainPrompt);
|
||||
eventSource.on(event_types.OAI_PRESET_CHANGED_AFTER, () => {
|
||||
this.sanitizeServiceSettings();
|
||||
const mainPrompt = this.getPromptById('main');
|
||||
this.updateQuickEdit('main', mainPrompt);
|
||||
|
||||
const nsfwPrompt = this.getPromptById('nsfw');
|
||||
this.updateQuickEdit('nsfw', nsfwPrompt);
|
||||
const nsfwPrompt = this.getPromptById('nsfw');
|
||||
this.updateQuickEdit('nsfw', nsfwPrompt);
|
||||
|
||||
const jailbreakPrompt = this.getPromptById('jailbreak');
|
||||
this.updateQuickEdit('jailbreak', jailbreakPrompt);
|
||||
const jailbreakPrompt = this.getPromptById('jailbreak');
|
||||
this.updateQuickEdit('jailbreak', jailbreakPrompt);
|
||||
|
||||
this.hidePopup();
|
||||
this.clearEditForm();
|
||||
this.renderDebounced();
|
||||
});
|
||||
this.hidePopup();
|
||||
this.clearEditForm();
|
||||
this.renderDebounced();
|
||||
});
|
||||
|
||||
// Re-render prompt manager on world settings update
|
||||
@ -643,19 +641,13 @@ PromptManagerModule.prototype.render = function (afterTryGenerate = true) {
|
||||
if (true === afterTryGenerate) {
|
||||
// Executed during dry-run for determining context composition
|
||||
this.profileStart('filling context');
|
||||
this.tryGenerate().then(() => {
|
||||
this.tryGenerate().finally(() => {
|
||||
this.profileEnd('filling context');
|
||||
this.profileStart('render');
|
||||
this.renderPromptManager();
|
||||
this.renderPromptManagerListItems()
|
||||
this.makeDraggable();
|
||||
this.profileEnd('render');
|
||||
}).catch(error => {
|
||||
this.profileEnd('filling context');
|
||||
this.log('Error caught during render: ' + error);
|
||||
this.renderPromptManager();
|
||||
this.renderPromptManagerListItems()
|
||||
this.makeDraggable();
|
||||
});
|
||||
} else {
|
||||
// Executed during live communication
|
||||
@ -1383,6 +1375,9 @@ PromptManagerModule.prototype.renderPromptManagerListItems = function () {
|
||||
</li>
|
||||
`;
|
||||
|
||||
console.log(this.activeCharacter)
|
||||
console.log(this.serviceSettings)
|
||||
console.log(this.getPromptsForCharacter(this.activeCharacter))
|
||||
this.getPromptsForCharacter(this.activeCharacter).forEach(prompt => {
|
||||
if (!prompt) return;
|
||||
|
||||
|
@ -580,6 +580,7 @@ export function dragElement(elmnt) {
|
||||
}
|
||||
|
||||
//prevent underlap with topbar div
|
||||
/*
|
||||
if (top < topBarLastY
|
||||
&& (maxX >= topBarFirstX && left <= topBarFirstX //elmnt is hitting topbar from left side
|
||||
|| left <= topBarLastX && maxX >= topBarLastX //elmnt is hitting topbar from right side
|
||||
@ -588,6 +589,7 @@ export function dragElement(elmnt) {
|
||||
console.debug('topbar hit')
|
||||
elmnt.css('top', top + 1 + "px");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
// Check if the element header exists and set the listener on the grabber
|
||||
@ -906,7 +908,7 @@ export function initRossMods() {
|
||||
//Enter to send when send_textarea in focus
|
||||
if ($(':focus').attr('id') === 'send_textarea') {
|
||||
const sendOnEnter = shouldSendOnEnter();
|
||||
if (!event.shiftKey && !event.ctrlKey && event.key == "Enter" && is_send_press == false && sendOnEnter) {
|
||||
if (!event.shiftKey && !event.ctrlKey && !event.altKey && event.key == "Enter" && is_send_press == false && sendOnEnter) {
|
||||
event.preventDefault();
|
||||
Generate();
|
||||
}
|
||||
@ -949,9 +951,13 @@ export function initRossMods() {
|
||||
console.debug("Ctrl+Enter ignored");
|
||||
}
|
||||
}
|
||||
//ctrl+left to show all local stored vars (debug)
|
||||
if (event.ctrlKey && event.key == "ArrowLeft") {
|
||||
CheckLocal();
|
||||
|
||||
// Alt+Enter to Continue
|
||||
if (event.altKey && event.key == "Enter") {
|
||||
if (is_send_press == false) {
|
||||
console.debug("Continuing with Alt+Enter");
|
||||
$('#option_continue').trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to check if nanogallery2's lightbox is active
|
||||
|
@ -22,6 +22,8 @@ let lastGroupId = null
|
||||
let lastChatId = null
|
||||
let lastMessageHash = null
|
||||
|
||||
const DEFAULT_VOICE_MARKER = '[Default Voice]';
|
||||
|
||||
export function getPreviewString(lang) {
|
||||
const previewStrings = {
|
||||
'en-US': 'The quick brown fox jumps over the lazy dog',
|
||||
@ -460,10 +462,12 @@ async function processTtsQueue() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!voiceMap[char]) {
|
||||
const voiceMapEntry = voiceMap[char] || voiceMap[DEFAULT_VOICE_MARKER]
|
||||
|
||||
if (!voiceMapEntry) {
|
||||
throw `${char} not in voicemap. Configure character in extension settings voice map`
|
||||
}
|
||||
const voice = await ttsProvider.getVoice((voiceMap[char]))
|
||||
const voice = await ttsProvider.getVoice(voiceMapEntry)
|
||||
const voiceId = voice.voice_id
|
||||
if (voiceId == null) {
|
||||
toastr.error(`Specified voice for ${char} was not found. Check the TTS extension settings.`)
|
||||
@ -636,10 +640,12 @@ function getCharacters(){
|
||||
let characters = []
|
||||
if (context.groupId === null){
|
||||
// Single char chat
|
||||
characters.push(DEFAULT_VOICE_MARKER)
|
||||
characters.push(context.name1)
|
||||
characters.push(context.name2)
|
||||
} else {
|
||||
// Group chat
|
||||
characters.push(DEFAULT_VOICE_MARKER)
|
||||
characters.push(context.name1)
|
||||
const group = context.groups.find(group => context.groupId == group.id)
|
||||
for (let member of group.members) {
|
||||
|
@ -20,15 +20,29 @@ export const kai_settings = {
|
||||
tfs: 1,
|
||||
rep_pen_slope: 0.9,
|
||||
single_line: false,
|
||||
use_stop_sequence: false,
|
||||
can_use_tokenization: false,
|
||||
streaming_kobold: false,
|
||||
sampler_order: [0, 1, 2, 3, 4, 5, 6],
|
||||
mirostat: 0,
|
||||
mirostat_tau: 5.0,
|
||||
mirostat_eta: 0.1,
|
||||
use_default_badwordsids: true,
|
||||
};
|
||||
|
||||
export const kai_flags = {
|
||||
can_use_tokenization: false,
|
||||
can_use_stop_sequence: false,
|
||||
can_use_streaming: false,
|
||||
can_use_default_badwordsids: false,
|
||||
can_use_mirostat: false,
|
||||
};
|
||||
|
||||
const defaultValues = Object.freeze(structuredClone(kai_settings));
|
||||
|
||||
const MIN_STOP_SEQUENCE_VERSION = '1.2.2';
|
||||
const MIN_UNBAN_VERSION = '1.2.4';
|
||||
const MIN_STREAMING_KCPPVERSION = '1.30';
|
||||
const MIN_TOKENIZATION_KCPPVERSION = '1.41';
|
||||
const MIN_MIROSTAT_KCPPVERSION = '1.35';
|
||||
const KOBOLDCPP_ORDER = [6, 0, 1, 3, 4, 2, 5];
|
||||
|
||||
export function formatKoboldUrl(value) {
|
||||
@ -44,16 +58,16 @@ export function formatKoboldUrl(value) {
|
||||
|
||||
export function loadKoboldSettings(preset) {
|
||||
for (const name of Object.keys(kai_settings)) {
|
||||
const value = preset[name];
|
||||
const value = preset[name] ?? defaultValues[name];
|
||||
const slider = sliders.find(x => x.name === name);
|
||||
|
||||
if (value === undefined || !slider) {
|
||||
if (!slider) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const formattedValue = slider.format(value);
|
||||
slider.setValue(preset[name]);
|
||||
$(slider.sliderId).val(preset[name]);
|
||||
slider.setValue(value);
|
||||
$(slider.sliderId).val(value);
|
||||
$(slider.counterId).text(formattedValue);
|
||||
}
|
||||
|
||||
@ -66,6 +80,10 @@ export function loadKoboldSettings(preset) {
|
||||
kai_settings.streaming_kobold = preset.streaming_kobold;
|
||||
$('#streaming_kobold').prop('checked', kai_settings.streaming_kobold);
|
||||
}
|
||||
if (preset.hasOwnProperty('use_default_badwordids')) {
|
||||
kai_settings.use_default_badwordids = preset.use_default_badwordids;
|
||||
$('#use_default_badwordids').prop('checked', kai_settings.use_default_badwordids);
|
||||
}
|
||||
}
|
||||
|
||||
export function getKoboldGenerationData(finalPrompt, this_settings, this_amount_gen, this_max_context, isImpersonate, type) {
|
||||
@ -94,9 +112,13 @@ export function getKoboldGenerationData(finalPrompt, this_settings, this_amount_
|
||||
s7: sampler_order[6],
|
||||
use_world_info: false,
|
||||
singleline: kai_settings.single_line,
|
||||
stop_sequence: kai_settings.use_stop_sequence ? getStoppingStrings(isImpersonate, false) : undefined,
|
||||
streaming: kai_settings.streaming_kobold && kai_settings.can_use_streaming && type !== 'quiet',
|
||||
can_abort: kai_settings.can_use_streaming,
|
||||
stop_sequence: kai_flags.can_use_stop_sequence ? getStoppingStrings(isImpersonate, false) : undefined,
|
||||
streaming: kai_settings.streaming_kobold && kai_flags.can_use_streaming && type !== 'quiet',
|
||||
can_abort: kai_flags.can_use_streaming,
|
||||
mirostat: kai_flags.can_use_mirostat ? kai_settings.mirostat : undefined,
|
||||
mirostat_tau: kai_flags.can_use_mirostat ? kai_settings.mirostat_tau : undefined,
|
||||
mirostat_eta: kai_flags.can_use_mirostat ? kai_settings.mirostat_eta : undefined,
|
||||
use_default_badwordsids: kai_flags.can_use_default_badwordsids ? kai_settings.use_default_badwordsids : undefined,
|
||||
};
|
||||
return generate_data;
|
||||
}
|
||||
@ -213,24 +235,62 @@ const sliders = [
|
||||
counterId: "#no_op_selector",
|
||||
format: (val) => val,
|
||||
setValue: (val) => { sortItemsByOrder(val); kai_settings.sampler_order = val; },
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "mirostat",
|
||||
sliderId: "#mirostat_mode_kobold",
|
||||
counterId: "#mirostat_mode_counter_kobold",
|
||||
format: (val) => val,
|
||||
setValue: (val) => { kai_settings.mirostat = Number(val); },
|
||||
},
|
||||
{
|
||||
name: "mirostat_tau",
|
||||
sliderId: "#mirostat_tau_kobold",
|
||||
counterId: "#mirostat_tau_counter_kobold",
|
||||
format: (val) => val,
|
||||
setValue: (val) => { kai_settings.mirostat_tau = Number(val); },
|
||||
},
|
||||
{
|
||||
name: "mirostat_eta",
|
||||
sliderId: "#mirostat_eta_kobold",
|
||||
counterId: "#mirostat_eta_counter_kobold",
|
||||
format: (val) => val,
|
||||
setValue: (val) => { kai_settings.mirostat_eta = Number(val); },
|
||||
},
|
||||
];
|
||||
|
||||
export function setKoboldFlags(version, koboldVersion) {
|
||||
kai_flags.can_use_stop_sequence = canUseKoboldStopSequence(version);
|
||||
kai_flags.can_use_streaming = canUseKoboldStreaming(koboldVersion);
|
||||
kai_flags.can_use_tokenization = canUseKoboldTokenization(koboldVersion);
|
||||
kai_flags.can_use_default_badwordsids = canUseDefaultBadwordIds(version);
|
||||
kai_flags.can_use_mirostat = canUseMirostat(koboldVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Kobold stop sequence can be used with the given version.
|
||||
* @param {string} version KoboldAI version to check.
|
||||
* @returns {boolean} True if the Kobold stop sequence can be used, false otherwise.
|
||||
*/
|
||||
export function canUseKoboldStopSequence(version) {
|
||||
function canUseKoboldStopSequence(version) {
|
||||
return (version || '0.0.0').localeCompare(MIN_STOP_SEQUENCE_VERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Kobold default badword ids can be used with the given version.
|
||||
* @param {string} version KoboldAI version to check.
|
||||
* @returns {boolean} True if the Kobold default badword ids can be used, false otherwise.
|
||||
*/
|
||||
function canUseDefaultBadwordIds(version) {
|
||||
return (version || '0.0.0').localeCompare(MIN_UNBAN_VERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the Kobold streaming API can be used with the given version.
|
||||
* @param {{ result: string; version: string; }} koboldVersion KoboldAI version object.
|
||||
* @returns {boolean} True if the Kobold streaming API can be used, false otherwise.
|
||||
*/
|
||||
export function canUseKoboldStreaming(koboldVersion) {
|
||||
function canUseKoboldStreaming(koboldVersion) {
|
||||
if (koboldVersion && koboldVersion.result == 'KoboldCpp') {
|
||||
return (koboldVersion.version || '0.0').localeCompare(MIN_STREAMING_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1;
|
||||
} else return false;
|
||||
@ -241,12 +301,18 @@ export function canUseKoboldStreaming(koboldVersion) {
|
||||
* @param {{ result: string; version: string; }} koboldVersion KoboldAI version object.
|
||||
* @returns {boolean} True if the Kobold tokenization API can be used, false otherwise.
|
||||
*/
|
||||
export function canUseKoboldTokenization(koboldVersion) {
|
||||
function canUseKoboldTokenization(koboldVersion) {
|
||||
if (koboldVersion && koboldVersion.result == 'KoboldCpp') {
|
||||
return (koboldVersion.version || '0.0').localeCompare(MIN_TOKENIZATION_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
function canUseMirostat(koboldVersion) {
|
||||
if (koboldVersion && koboldVersion.result == 'KoboldCpp') {
|
||||
return (koboldVersion.version || '0.0').localeCompare(MIN_MIROSTAT_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1;
|
||||
} else return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the sampler items by the given order.
|
||||
* @param {any[]} orderArray Sampler order array.
|
||||
@ -274,17 +340,23 @@ jQuery(function () {
|
||||
});
|
||||
|
||||
$('#single_line').on("input", function () {
|
||||
const value = $(this).prop('checked');
|
||||
const value = !!$(this).prop('checked');
|
||||
kai_settings.single_line = value;
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#streaming_kobold').on("input", function () {
|
||||
const value = $(this).prop('checked');
|
||||
const value = !!$(this).prop('checked');
|
||||
kai_settings.streaming_kobold = value;
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#use_default_badwordids').on("input", function () {
|
||||
const value = !!$(this).prop('checked');
|
||||
kai_settings.use_default_badwordids = value;
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#kobold_order').sortable({
|
||||
delay: getSortableDelay(),
|
||||
stop: function () {
|
||||
|
@ -354,7 +354,11 @@ function setupChatCompletionPromptManager(openAiSettings) {
|
||||
}
|
||||
|
||||
promptManager.tryGenerate = () => {
|
||||
return Generate('normal', {}, true);
|
||||
if (characters[this_chid]) {
|
||||
return Generate('normal', {}, true);
|
||||
} else{
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
promptManager.tokenHandler = tokenHandler;
|
||||
@ -613,7 +617,7 @@ function populateChatCompletion(prompts, chatCompletion, { bias, quietPrompt, ty
|
||||
|
||||
// Insert nsfw avoidance prompt into main, if no nsfw prompt is present
|
||||
if (false === chatCompletion.has('nsfw') && oai_settings.nsfw_avoidance_prompt)
|
||||
if (prompts.has('nsfwAvoidance')) chatCompletion.insert(Message.fromPrompt(prompts.get('nsfwAvoidance')), 'main');
|
||||
if (prompts.has('nsfwAvoidance') && prompts.has('main')) chatCompletion.insert(Message.fromPrompt(prompts.get('nsfwAvoidance')), 'main');
|
||||
|
||||
// Bias
|
||||
if (bias && bias.trim().length) addToChatCompletion('bias');
|
||||
@ -2463,7 +2467,7 @@ function onSettingsPresetChange() {
|
||||
const updateCheckbox = (selector, value) => $(selector).prop('checked', value).trigger('input');
|
||||
|
||||
// Allow subscribers to alter the preset before applying deltas
|
||||
eventSource.emit(event_types.OAI_PRESET_CHANGED, {
|
||||
eventSource.emit(event_types.OAI_PRESET_CHANGED_BEFORE, {
|
||||
preset: preset,
|
||||
presetName: presetName,
|
||||
settingsToUpdate: settingsToUpdate,
|
||||
@ -2485,6 +2489,7 @@ function onSettingsPresetChange() {
|
||||
$(`#openai_logit_bias_preset`).trigger('change');
|
||||
|
||||
saveSettingsDebounced();
|
||||
eventSource.emit(event_types.OAI_PRESET_CHANGED_AFTER);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ import {
|
||||
import { registerSlashCommand } from "./slash-commands.js";
|
||||
import { tokenizers } from "./tokenizers.js";
|
||||
|
||||
import { delay, resetScrollHeight } from "./utils.js";
|
||||
import { countOccurrences, delay, isOdd, resetScrollHeight, sortMoments, timestampToMoment } from "./utils.js";
|
||||
|
||||
export {
|
||||
loadPowerUserSettings,
|
||||
@ -159,6 +159,7 @@ let power_user = {
|
||||
timestamp_model_icon: false,
|
||||
mesIDDisplay_enabled: false,
|
||||
max_context_unlocked: false,
|
||||
message_token_count_enabled: false,
|
||||
prefer_character_prompt: true,
|
||||
prefer_character_jailbreak: true,
|
||||
quick_continue: false,
|
||||
@ -240,6 +241,7 @@ const storage_keys = {
|
||||
timestamps_enabled: 'TimestampsEnabled',
|
||||
timestamp_model_icon: 'TimestampModelIcon',
|
||||
mesIDDisplay_enabled: 'mesIDDisplayEnabled',
|
||||
message_token_count_enabled: 'MessageTokenCountEnabled',
|
||||
};
|
||||
|
||||
let browser_has_focus = true;
|
||||
@ -283,6 +285,7 @@ function collapseNewlines(x) {
|
||||
/**
|
||||
* Fix formatting problems in markdown.
|
||||
* @param {string} text Text to be processed.
|
||||
* @param {boolean} forDisplay Whether the text is being processed for display.
|
||||
* @returns {string} Processed text.
|
||||
* @example
|
||||
* "^example * text*\n" // "^example *text*\n"
|
||||
@ -296,7 +299,7 @@ function collapseNewlines(x) {
|
||||
* // and you HAVE to handle the cases where multiple pairs of asterisks exist in the same line
|
||||
* "^example * text* * harder problem *\n" // "^example *text* *harder problem*\n"
|
||||
*/
|
||||
function fixMarkdown(text) {
|
||||
function fixMarkdown(text, forDisplay) {
|
||||
// Find pairs of formatting characters and capture the text in between them
|
||||
const format = /([\*_]{1,2})([\s\S]*?)\1/gm;
|
||||
let matches = [];
|
||||
@ -313,6 +316,27 @@ function fixMarkdown(text) {
|
||||
newText = newText.slice(0, matches[i].index) + replacementText + newText.slice(matches[i].index + matchText.length);
|
||||
}
|
||||
|
||||
// Don't auto-fix asterisks if this is a message clean-up procedure.
|
||||
// It botches the continue function. Apply this to display only.
|
||||
if (!forDisplay) {
|
||||
return newText;
|
||||
}
|
||||
|
||||
const splitText = newText.split('\n');
|
||||
|
||||
// Fix asterisks, and quotes that are not paired
|
||||
for (let index = 0; index < splitText.length; index++) {
|
||||
const line = splitText[index];
|
||||
const charsToCheck = ['*', '"'];
|
||||
for (const char of charsToCheck) {
|
||||
if (line.includes(char) && isOdd(countOccurrences(line, char))) {
|
||||
splitText[index] = line.trimEnd() + char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newText = splitText.join('\n');
|
||||
|
||||
return newText;
|
||||
}
|
||||
|
||||
@ -344,6 +368,13 @@ function switchIcons() {
|
||||
$("#messageModelIconEnabled").prop("checked", power_user.timestamp_model_icon);
|
||||
}
|
||||
|
||||
function switchTokenCount() {
|
||||
const value = localStorage.getItem(storage_keys.message_token_count_enabled);
|
||||
power_user.message_token_count_enabled = value === null ? false : value == "true";
|
||||
$("body").toggleClass("no-tokenCount", !power_user.message_token_count_enabled);
|
||||
$("#messageTokensEnabled").prop("checked", power_user.message_token_count_enabled);
|
||||
}
|
||||
|
||||
function switchMesIDDisplay() {
|
||||
const value = localStorage.getItem(storage_keys.mesIDDisplay_enabled);
|
||||
power_user.mesIDDisplay_enabled = value === null ? true : value == "true";
|
||||
@ -599,42 +630,49 @@ async function applyTheme(name) {
|
||||
power_user.chat_width = 50;
|
||||
}
|
||||
|
||||
localStorage.setItem(storage_keys.chat_width, power_user.chat_width);
|
||||
localStorage.setItem(storage_keys.chat_width, String(power_user.chat_width));
|
||||
applyChatWidth();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'timer_enabled',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.timer_enabled, power_user.timer_enabled);
|
||||
localStorage.setItem(storage_keys.timer_enabled, String(power_user.timer_enabled));
|
||||
switchTimer();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'timestamps_enabled',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.timestamps_enabled, power_user.timestamps_enabled);
|
||||
localStorage.setItem(storage_keys.timestamps_enabled, String(power_user.timestamps_enabled));
|
||||
switchTimestamps();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'timestamp_model_icon',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.timestamp_model_icon, power_user.timestamp_model_icon);
|
||||
localStorage.setItem(storage_keys.timestamp_model_icon, String(power_user.timestamp_model_icon));
|
||||
switchIcons();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'message_token_count',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.message_token_count_enabled, String(power_user.message_token_count_enabled));
|
||||
switchTokenCount();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'mesIDDisplay_enabled',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.mesIDDisplay_enabled, power_user.mesIDDisplay_enabled);
|
||||
localStorage.setItem(storage_keys.mesIDDisplay_enabled, String(power_user.mesIDDisplay_enabled));
|
||||
switchMesIDDisplay();
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'hotswap_enabled',
|
||||
action: async () => {
|
||||
localStorage.setItem(storage_keys.hotswap_enabled, power_user.hotswap_enabled);
|
||||
localStorage.setItem(storage_keys.hotswap_enabled, String(power_user.hotswap_enabled));
|
||||
switchHotswap();
|
||||
}
|
||||
}
|
||||
@ -701,6 +739,7 @@ switchTimer();
|
||||
switchTimestamps();
|
||||
switchIcons();
|
||||
switchMesIDDisplay();
|
||||
switchTokenCount();
|
||||
|
||||
function loadPowerUserSettings(settings, data) {
|
||||
// Load from settings.json
|
||||
@ -1126,6 +1165,11 @@ const compareFunc = (first, second) => {
|
||||
case 'boolean':
|
||||
const a = first[power_user.sort_field];
|
||||
const b = second[power_user.sort_field];
|
||||
|
||||
if (power_user.sort_field === 'create_date') {
|
||||
return sortMoments(timestampToMoment(a), timestampToMoment(b));
|
||||
}
|
||||
|
||||
if (a === true || a === 'true') return 1; // Prioritize 'true' or true
|
||||
if (b === true || b === 'true') return -1; // Prioritize 'true' or true
|
||||
if (a && !b) return -1; // Move truthy values to the end
|
||||
@ -2069,6 +2113,13 @@ $(document).ready(() => {
|
||||
switchIcons();
|
||||
});
|
||||
|
||||
$("#messageTokensEnabled").on("input", function () {
|
||||
const value = !!$(this).prop('checked');
|
||||
power_user.message_token_count_enabled = value;
|
||||
localStorage.setItem(storage_keys.message_token_count_enabled, String(power_user.message_token_count_enabled));
|
||||
switchTokenCount();
|
||||
});
|
||||
|
||||
$("#mesIDDisplayEnabled").on("input", function () {
|
||||
const value = !!$(this).prop('checked');
|
||||
power_user.mesIDDisplay_enabled = value;
|
||||
|
@ -4,10 +4,10 @@ Hotkeys/Keybinds:
|
||||
<li><tt>Ctrl+Up</tt> = Edit last USER message in chat</li>
|
||||
<li><tt>Left</tt> = swipe left</li>
|
||||
<li><tt>Right</tt> = swipe right (NOTE: swipe hotkeys are disabled when chatbar has something typed into it)</li>
|
||||
<li><tt>Ctrl+Left</tt> = view locally stored variables (in the browser console window)</li>
|
||||
<li><tt>Enter</tt> (with chat bar selected) = send your message to AI</li>
|
||||
<li><tt>Ctrl+Enter</tt> = Regenerate the last AI response</li>
|
||||
<li><tt>Escape</tt> = stop AI response generation</li>
|
||||
<li><tt>Alt+Enter</tt> = Continue the last AI response</li>
|
||||
<li><tt>Escape</tt> = stop AI response generation, close UI panels, cancel message edit</li>
|
||||
<li><tt>Ctrl+Shift+Up</tt> = Scroll to context line</li>
|
||||
<li><tt>Ctrl+Shift+Down</tt> = Scroll chat to bottom</li>
|
||||
</ul>
|
||||
|
@ -3,7 +3,7 @@ import { power_user, registerDebugFunction } from "./power-user.js";
|
||||
import { chat_completion_sources, oai_settings } from "./openai.js";
|
||||
import { groups, selected_group } from "./group-chats.js";
|
||||
import { getStringHash } from "./utils.js";
|
||||
import { kai_settings } from "./kai-settings.js";
|
||||
import { kai_flags } from "./kai-settings.js";
|
||||
|
||||
export const CHARACTERS_PER_TOKEN_RATIO = 3.35;
|
||||
const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';
|
||||
@ -82,7 +82,7 @@ function getTokenizerBestMatch() {
|
||||
// - API must be connected
|
||||
// - Kobold must pass a version check
|
||||
// - Tokenizer haven't reported an error previously
|
||||
if (kai_settings.can_use_tokenization && !sessionStorage.getItem(TOKENIZER_WARNING_KEY) && online_status !== 'no_connection') {
|
||||
if (kai_flags.can_use_tokenization && !sessionStorage.getItem(TOKENIZER_WARNING_KEY) && online_status !== 'no_connection') {
|
||||
return tokenizers.API;
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1103,7 @@ async function checkWorldInfo(chat, maxContext) {
|
||||
console.debug(`WI budget reached, stopping`);
|
||||
if (world_info_overflow_alert) {
|
||||
console.log("Alerting");
|
||||
toastr.warning(`World info budget reached after ${count} entries.`, 'World Info');
|
||||
toastr.warning(`World info budget reached after ${allActivatedEntries.size} entries.`, 'World Info');
|
||||
}
|
||||
needsToScan = false;
|
||||
break;
|
||||
|
@ -287,7 +287,8 @@ table.responsiveTable {
|
||||
}
|
||||
|
||||
.mes .mes_timer,
|
||||
.mes .mesIDDisplay {
|
||||
.mes .mesIDDisplay,
|
||||
.mes .tokenCounterDisplay {
|
||||
cursor: default;
|
||||
opacity: 0.7;
|
||||
font-size: calc(var(--mainFontSize) * 0.9);
|
||||
@ -399,9 +400,10 @@ hr {
|
||||
#sheld {
|
||||
display: grid;
|
||||
grid-template-rows: auto min-content;
|
||||
height: calc(100vh - var(--topBarBlockSize));
|
||||
height: calc(100svh - var(--topBarBlockSize));
|
||||
max-height: calc(100svh - var(--topBarBlockSize));
|
||||
/* -1px to give sheld some wiggle room to bounce off tobar when moving*/
|
||||
height: calc(100vh - var(--topBarBlockSize) - 1px);
|
||||
height: calc(100svh - var(--topBarBlockSize) - 1px);
|
||||
max-height: calc(100svh - var(--topBarBlockSize) - 1px);
|
||||
overflow-x: hidden;
|
||||
/* max-width: 50vw; */
|
||||
position: absolute;
|
||||
@ -3436,8 +3438,10 @@ a {
|
||||
|
||||
/* Hide scrollbar for IE, Edge, and Firefox */
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none;
|
||||
/* IE and Edge */
|
||||
scrollbar-width: none;
|
||||
/* Firefox */
|
||||
}
|
||||
|
||||
#groupMemberListPopoutClose {
|
||||
@ -3560,7 +3564,7 @@ a {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.onboarding > h3 {
|
||||
.onboarding>h3 {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
@ -3600,4 +3604,4 @@ a {
|
||||
height: 100vh;
|
||||
z-index: 9999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
325
server.js
325
server.js
@ -32,13 +32,11 @@ const multer = require("multer");
|
||||
const responseTime = require('response-time');
|
||||
|
||||
// net related library imports
|
||||
const axios = require('axios');
|
||||
const DeviceDetector = require("device-detector-js");
|
||||
const fetch = require('node-fetch').default;
|
||||
const ipaddr = require('ipaddr.js');
|
||||
const ipMatching = require('ip-matching');
|
||||
const json5 = require('json5');
|
||||
const RESTClient = require('node-rest-client').Client;
|
||||
const WebSocket = require('ws');
|
||||
|
||||
// image processing related library imports
|
||||
@ -154,16 +152,12 @@ function getHordeClient() {
|
||||
return ai_horde;
|
||||
}
|
||||
|
||||
const restClient = new RESTClient();
|
||||
|
||||
restClient.on('error', (err) => {
|
||||
console.error('An error occurred:', err);
|
||||
});
|
||||
const API_NOVELAI = "https://api.novelai.net";
|
||||
const API_OPENAI = "https://api.openai.com/v1";
|
||||
const API_CLAUDE = "https://api.anthropic.com/v1";
|
||||
|
||||
// These should be gone and come from the frontend. But for now, they're here.
|
||||
let api_server = "http://0.0.0.0:5000";
|
||||
let api_novelai = "https://api.novelai.net";
|
||||
let api_openai = "https://api.openai.com/v1";
|
||||
let api_claude = "https://api.anthropic.com/v1";
|
||||
let main_api = "kobold";
|
||||
|
||||
let characters = {};
|
||||
@ -190,7 +184,14 @@ function get_mancer_headers() {
|
||||
return api_key_mancer ? { "X-API-KEY": api_key_mancer } : {};
|
||||
}
|
||||
|
||||
|
||||
function getOverrideHeaders(urlHost) {
|
||||
const overrideHeaders = config.requestOverrides?.find((e) => e.hosts?.includes(urlHost))?.headers;
|
||||
if (overrideHeaders && urlHost) {
|
||||
return overrideHeaders;
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
//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.
|
||||
@ -311,7 +312,6 @@ function humanizedISO8601DateTime() {
|
||||
return HumanizedDateTime;
|
||||
};
|
||||
|
||||
var is_colab = process.env.colaburl !== undefined;
|
||||
var charactersPath = 'public/characters/';
|
||||
var chatsPath = 'public/chats/';
|
||||
const UPLOADS_PATH = './uploads';
|
||||
@ -319,7 +319,6 @@ const AVATAR_WIDTH = 400;
|
||||
const AVATAR_HEIGHT = 600;
|
||||
const jsonParser = express.json({ limit: '100mb' });
|
||||
const urlencodedParser = express.urlencoded({ extended: true, limit: '100mb' });
|
||||
const baseRequestArgs = { headers: { "Content-Type": "application/json" } };
|
||||
const directories = {
|
||||
worlds: 'public/worlds/',
|
||||
avatars: 'public/User Avatars',
|
||||
@ -534,6 +533,10 @@ app.post("/generate", jsonParser, async function (request, response_generate) {
|
||||
typical: request.body.typical,
|
||||
sampler_order: sampler_order,
|
||||
singleline: !!request.body.singleline,
|
||||
use_default_badwordsids: request.body.use_default_badwordsids,
|
||||
mirostat: request.body.mirostat,
|
||||
mirostat_eta: request.body.mirostat_eta,
|
||||
mirostat_tau: request.body.mirostat_tau,
|
||||
};
|
||||
if (!!request.body.stop_sequence) {
|
||||
this_settings['stop_sequence'] = request.body.stop_sequence;
|
||||
@ -543,7 +546,10 @@ app.post("/generate", jsonParser, async function (request, response_generate) {
|
||||
console.log(this_settings);
|
||||
const args = {
|
||||
body: JSON.stringify(this_settings),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
headers: Object.assign(
|
||||
{ "Content-Type": "application/json" },
|
||||
getOverrideHeaders((new URL(api_server))?.host)
|
||||
),
|
||||
signal: controller.signal,
|
||||
};
|
||||
|
||||
@ -633,11 +639,19 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
||||
});
|
||||
|
||||
async function* readWebsocket() {
|
||||
const streamingUrlString = request.header('X-Streaming-URL').replace("localhost", "127.0.0.1");
|
||||
const streamingUrl = new URL(streamingUrlString);
|
||||
const websocket = new WebSocket(streamingUrl);
|
||||
|
||||
websocket.on('open', async function () {
|
||||
console.log('WebSocket opened');
|
||||
const combined_args = Object.assign(request.body.use_mancer ? get_mancer_headers() : {}, request.body);
|
||||
const combined_args = Object.assign(
|
||||
{},
|
||||
request.body.use_mancer ? get_mancer_headers() : getOverrideHeaders(streamingUrl?.host),
|
||||
request.body
|
||||
);
|
||||
console.log(combined_args);
|
||||
|
||||
websocket.send(JSON.stringify(combined_args));
|
||||
});
|
||||
|
||||
@ -719,6 +733,8 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
|
||||
|
||||
if (request.body.use_mancer) {
|
||||
args.headers = Object.assign(args.headers, get_mancer_headers());
|
||||
} else {
|
||||
args.headers = Object.assign(args.headers, getOverrideHeaders((new URL(api_server))?.host));
|
||||
}
|
||||
|
||||
try {
|
||||
@ -786,6 +802,7 @@ app.post("/getchat", jsonParser, function (request, response) {
|
||||
}
|
||||
});
|
||||
|
||||
// Only called for kobold and ooba/mancer
|
||||
app.post("/getstatus", jsonParser, async function (request, response) {
|
||||
if (!request.body) return response.sendStatus(400);
|
||||
api_server = request.body.api_server;
|
||||
@ -800,6 +817,8 @@ app.post("/getstatus", jsonParser, async function (request, response) {
|
||||
|
||||
if (main_api == 'textgenerationwebui' && request.body.use_mancer) {
|
||||
args.headers = Object.assign(args.headers, get_mancer_headers());
|
||||
} else {
|
||||
args.headers = Object.assign(args.headers, getOverrideHeaders((new URL(api_server))?.host));
|
||||
}
|
||||
|
||||
const url = api_server + "/v1/model";
|
||||
@ -808,13 +827,13 @@ app.post("/getstatus", jsonParser, async function (request, response) {
|
||||
|
||||
if (main_api == "kobold") {
|
||||
try {
|
||||
version = (await getAsync(api_server + "/v1/info/version")).result;
|
||||
version = (await fetchJSON(api_server + "/v1/info/version")).result
|
||||
}
|
||||
catch {
|
||||
version = '0.0.0';
|
||||
}
|
||||
try {
|
||||
koboldVersion = (await getAsync(api_server + "/extra/version"));
|
||||
koboldVersion = (await fetchJSON(api_server + "/extra/version"));
|
||||
}
|
||||
catch {
|
||||
koboldVersion = {
|
||||
@ -825,7 +844,7 @@ app.post("/getstatus", jsonParser, async function (request, response) {
|
||||
}
|
||||
|
||||
try {
|
||||
let data = await getAsync(url, args);
|
||||
let data = await fetchJSON(url, args);
|
||||
|
||||
if (!data || typeof data !== 'object') {
|
||||
data = {};
|
||||
@ -954,6 +973,7 @@ function readFromV2(char) {
|
||||
});
|
||||
|
||||
char['chat'] = char['chat'] ?? humanizedISO8601DateTime();
|
||||
char['create_date'] = char['create_date'] || humanizedISO8601DateTime();
|
||||
|
||||
return char;
|
||||
}
|
||||
@ -1256,7 +1276,7 @@ async function charaWrite(img_url, data, target_img, response = undefined, mes =
|
||||
|
||||
// Get the chunks
|
||||
const chunks = extract(image);
|
||||
const tEXtChunks = chunks.filter(chunk => chunk.create_date === 'tEXt' || chunk.name === 'tEXt');
|
||||
const tEXtChunks = chunks.filter(chunk => chunk.name === 'tEXt');
|
||||
|
||||
// Remove all existing tEXt chunks
|
||||
for (let tEXtChunk of tEXtChunks) {
|
||||
@ -1267,7 +1287,7 @@ async function charaWrite(img_url, data, target_img, response = undefined, mes =
|
||||
chunks.splice(-1, 0, PNGtext.encode('chara', base64EncodedData));
|
||||
//chunks.splice(-1, 0, text.encode('lorem', 'ipsum'));
|
||||
|
||||
writeFileAtomicSync(charactersPath + target_img + '.png', new Buffer.from(encode(chunks)));
|
||||
writeFileAtomicSync(charactersPath + target_img + '.png', Buffer.from(encode(chunks)));
|
||||
if (response !== undefined) response.send(mes);
|
||||
return true;
|
||||
} catch (err) {
|
||||
@ -1309,7 +1329,7 @@ async function charaRead(img_url, input_format) {
|
||||
* calculateChatSize - Calculates the total chat size for a given character.
|
||||
*
|
||||
* @param {string} charDir The directory where the chats are stored.
|
||||
* @return {number} The total chat size.
|
||||
* @return { {chatSize: number, dateLastChat: number} } The total chat size.
|
||||
*/
|
||||
const calculateChatSize = (charDir) => {
|
||||
let chatSize = 0;
|
||||
@ -1344,6 +1364,8 @@ const calculateDataSize = (data) => {
|
||||
const processCharacter = async (item, i) => {
|
||||
try {
|
||||
const img_data = await charaRead(charactersPath + item);
|
||||
if (img_data === false || img_data === undefined) throw new Error("Failed to read character file");
|
||||
|
||||
let jsonObject = getCharaCardV2(json5.parse(img_data));
|
||||
jsonObject.avatar = item;
|
||||
characters[i] = jsonObject;
|
||||
@ -1458,14 +1480,7 @@ app.post("/getbackgrounds", jsonParser, function (request, response) {
|
||||
response.send(JSON.stringify(images));
|
||||
|
||||
});
|
||||
app.post("/iscolab", jsonParser, function (request, response) {
|
||||
let send_data = false;
|
||||
if (is_colab) {
|
||||
send_data = String(process.env.colaburl).trim();
|
||||
}
|
||||
response.send({ colaburl: send_data });
|
||||
|
||||
});
|
||||
app.post("/getuseravatars", jsonParser, function (request, response) {
|
||||
var images = getImages("public/User Avatars");
|
||||
response.send(JSON.stringify(images));
|
||||
@ -1632,7 +1647,7 @@ function readAndParseFromDirectory(directoryPath, fileExtension = '.json') {
|
||||
}
|
||||
|
||||
function sortByModifiedDate(directory) {
|
||||
return (a, b) => new Date(fs.statSync(`${directory}/${b}`).mtime) - new Date(fs.statSync(`${directory}/${a}`).mtime);
|
||||
return (a, b) => +(new Date(fs.statSync(`${directory}/${b}`).mtime)) - +(new Date(fs.statSync(`${directory}/${a}`).mtime));
|
||||
}
|
||||
|
||||
function sortByName(_) {
|
||||
@ -1666,11 +1681,12 @@ function readPresetsFromDirectory(directoryPath, options = {}) {
|
||||
|
||||
// Wintermute's code
|
||||
app.post('/getsettings', jsonParser, (request, response) => {
|
||||
const settings = fs.readFileSync('public/settings.json', 'utf8', (err, data) => {
|
||||
if (err) return response.sendStatus(500);
|
||||
|
||||
return data;
|
||||
});
|
||||
let settings
|
||||
try {
|
||||
settings = fs.readFileSync('public/settings.json', 'utf8');
|
||||
} catch (e) {
|
||||
return response.sendStatus(500);
|
||||
}
|
||||
|
||||
// NovelAI Settings
|
||||
const { fileContents: novelai_settings, fileNames: novelai_setting_names }
|
||||
@ -1700,7 +1716,7 @@ app.post('/getsettings', jsonParser, (request, response) => {
|
||||
const worldFiles = fs
|
||||
.readdirSync(directories.worlds)
|
||||
.filter(file => path.extname(file).toLowerCase() === '.json')
|
||||
.sort((a, b) => a < b);
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
const world_names = worldFiles.map(item => path.parse(item).name);
|
||||
|
||||
const themes = readAndParseFromDirectory(directories.themes);
|
||||
@ -1862,7 +1878,7 @@ app.post("/getstatus_novelai", jsonParser, async function (request, response_get
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(api_novelai + "/user/subscription", {
|
||||
const response = await fetch(API_NOVELAI + "/user/subscription", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@ -1887,7 +1903,7 @@ app.post("/getstatus_novelai", jsonParser, async function (request, response_get
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/generate_novelai", jsonParser, async function (request, response_generate_novel = response) {
|
||||
app.post("/generate_novelai", jsonParser, async function (request, response_generate_novel) {
|
||||
if (!request.body) return response_generate_novel.sendStatus(400);
|
||||
|
||||
const api_key_novel = readSecret(SECRET_KEYS.NOVEL);
|
||||
@ -1925,7 +1941,7 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
||||
"input": request.body.input,
|
||||
"model": request.body.model,
|
||||
"parameters": {
|
||||
"use_string": request.body.use_string,
|
||||
"use_string": request.body.use_string ?? true,
|
||||
"temperature": request.body.temperature,
|
||||
"max_length": request.body.max_length,
|
||||
"min_length": request.body.min_length,
|
||||
@ -1950,7 +1966,6 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
||||
"logit_bias_exp": logit_bias_exp,
|
||||
"generate_until_sentence": request.body.generate_until_sentence,
|
||||
"use_cache": request.body.use_cache,
|
||||
"use_string": request.body.use_string ?? true,
|
||||
"return_full_text": request.body.return_full_text,
|
||||
"prefix": request.body.prefix,
|
||||
"order": request.body.order
|
||||
@ -1966,7 +1981,7 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
|
||||
};
|
||||
|
||||
try {
|
||||
const url = request.body.streaming ? `${api_novelai}/ai/generate-stream` : `${api_novelai}/ai/generate`;
|
||||
const url = request.body.streaming ? `${API_NOVELAI}/ai/generate-stream` : `${API_NOVELAI}/ai/generate`;
|
||||
const response = await fetch(url, { method: 'POST', timeout: 0, ...args });
|
||||
|
||||
if (request.body.streaming) {
|
||||
@ -2094,7 +2109,7 @@ function getPngName(file) {
|
||||
|
||||
app.post("/importcharacter", urlencodedParser, async function (request, response) {
|
||||
|
||||
if (!request.body) return response.sendStatus(400);
|
||||
if (!request.body || request.file === undefined) return response.sendStatus(400);
|
||||
|
||||
let png_name = '';
|
||||
let filedata = request.file;
|
||||
@ -2145,8 +2160,8 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
||||
"tags": jsonData.tags ?? '',
|
||||
};
|
||||
char = convertToV2(char);
|
||||
char = JSON.stringify(char);
|
||||
charaWrite(defaultAvatarPath, char, png_name, response, { file_name: png_name });
|
||||
let charJSON = JSON.stringify(char);
|
||||
charaWrite(defaultAvatarPath, charJSON, png_name, response, { file_name: png_name });
|
||||
} else if (jsonData.char_name !== undefined) {//json Pygmalion notepad
|
||||
console.log('importing from gradio json');
|
||||
jsonData.char_name = sanitize(jsonData.char_name);
|
||||
@ -2170,8 +2185,8 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
||||
"tags": jsonData.tags ?? '',
|
||||
};
|
||||
char = convertToV2(char);
|
||||
char = JSON.stringify(char);
|
||||
charaWrite(defaultAvatarPath, char, png_name, response, { file_name: png_name });
|
||||
let charJSON = JSON.stringify(char);
|
||||
charaWrite(defaultAvatarPath, charJSON, png_name, response, { file_name: png_name });
|
||||
} else {
|
||||
console.log('Incorrect character format .json');
|
||||
response.send({ error: true });
|
||||
@ -2180,6 +2195,8 @@ app.post("/importcharacter", urlencodedParser, async function (request, response
|
||||
} else {
|
||||
try {
|
||||
var img_data = await charaRead(uploadPath, format);
|
||||
if (img_data === false || img_data === undefined) throw new Error('Failed to read character data');
|
||||
|
||||
let jsonData = json5.parse(img_data);
|
||||
|
||||
jsonData.name = sanitize(jsonData.data?.name || jsonData.name);
|
||||
@ -2871,7 +2888,7 @@ app.post('/deletegroup', jsonParser, async (request, response) => {
|
||||
|
||||
try {
|
||||
// Delete group chats
|
||||
const group = json5.parse(fs.readFileSync(pathToGroup));
|
||||
const group = json5.parse(fs.readFileSync(pathToGroup, 'utf8'));
|
||||
|
||||
if (group && Array.isArray(group.chats)) {
|
||||
for (const chat of group.chats) {
|
||||
@ -2985,6 +3002,8 @@ function getOriginalFolder(type) {
|
||||
|
||||
function invalidateThumbnail(type, file) {
|
||||
const folder = getThumbnailFolder(type);
|
||||
if (folder === undefined) throw new Error("Invalid thumbnail type")
|
||||
|
||||
const pathToThumbnail = path.join(folder, file);
|
||||
|
||||
if (fs.existsSync(pathToThumbnail)) {
|
||||
@ -3034,8 +3053,12 @@ async function ensureThumbnailCache() {
|
||||
}
|
||||
|
||||
async function generateThumbnail(type, file) {
|
||||
const pathToCachedFile = path.join(getThumbnailFolder(type), file);
|
||||
const pathToOriginalFile = path.join(getOriginalFolder(type), file);
|
||||
let thumbnailFolder = getThumbnailFolder(type)
|
||||
let originalFolder = getOriginalFolder(type)
|
||||
if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error("Invalid thumbnail type")
|
||||
|
||||
const pathToCachedFile = path.join(thumbnailFolder, file);
|
||||
const pathToOriginalFile = path.join(originalFolder, file);
|
||||
|
||||
const cachedFileExists = fs.existsSync(pathToCachedFile);
|
||||
const originalFileExists = fs.existsSync(pathToOriginalFile);
|
||||
@ -3086,6 +3109,8 @@ async function generateThumbnail(type, file) {
|
||||
}
|
||||
|
||||
app.get('/thumbnail', jsonParser, async function (request, response) {
|
||||
if (typeof request.query.file !== 'string' || typeof request.query.type !== 'string') return response.sendStatus(400);
|
||||
|
||||
const type = request.query.type;
|
||||
const file = sanitize(request.query.file);
|
||||
|
||||
@ -3103,7 +3128,9 @@ app.get('/thumbnail', jsonParser, async function (request, response) {
|
||||
}
|
||||
|
||||
if (config.disableThumbnails == true) {
|
||||
const pathToOriginalFile = path.join(getOriginalFolder(type), file);
|
||||
let folder = getOriginalFolder(type);
|
||||
if (folder === undefined) return response.sendStatus(400);
|
||||
const pathToOriginalFile = path.join(folder, file);
|
||||
return response.sendFile(pathToOriginalFile, { root: process.cwd() });
|
||||
}
|
||||
|
||||
@ -3117,7 +3144,7 @@ app.get('/thumbnail', jsonParser, async function (request, response) {
|
||||
});
|
||||
|
||||
/* OpenAI */
|
||||
app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_openai) {
|
||||
app.post("/getstatus_openai", jsonParser, async function (request, response_getstatus_openai) {
|
||||
if (!request.body) return response_getstatus_openai.sendStatus(400);
|
||||
|
||||
let api_url;
|
||||
@ -3125,7 +3152,7 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
||||
let headers;
|
||||
|
||||
if (request.body.use_openrouter == false) {
|
||||
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);
|
||||
headers = {};
|
||||
} else {
|
||||
@ -3139,17 +3166,22 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
||||
return response_getstatus_openai.status(401).send({ error: true });
|
||||
}
|
||||
|
||||
const args = {
|
||||
headers: {
|
||||
"Authorization": "Bearer " + api_key_openai,
|
||||
...headers,
|
||||
},
|
||||
};
|
||||
restClient.get(api_url + "/models", args, function (data, response) {
|
||||
if (response.statusCode == 200) {
|
||||
try {
|
||||
const response = await fetch(api_url + "/models", {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
"Authorization": "Bearer " + api_key_openai,
|
||||
...headers,
|
||||
},
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
response_getstatus_openai.send(data);
|
||||
|
||||
if (request.body.use_openrouter) {
|
||||
let models = [];
|
||||
|
||||
data.data.forEach(model => {
|
||||
const context_length = model.context_length;
|
||||
const tokens_dollar = Number(1 / (1000 * model.pricing.prompt));
|
||||
@ -3159,27 +3191,21 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
||||
context_length: context_length,
|
||||
};
|
||||
});
|
||||
|
||||
console.log('Available OpenRouter models:', models);
|
||||
} else {
|
||||
const modelIds = data?.data?.map(x => x.id)?.sort();
|
||||
console.log('Available OpenAI models:', modelIds);
|
||||
}
|
||||
}
|
||||
if (response.statusCode == 401) {
|
||||
else {
|
||||
console.log('Access Token is incorrect.');
|
||||
response_getstatus_openai.send({ error: true });
|
||||
}
|
||||
if (response.statusCode == 404) {
|
||||
console.log('Endpoint not found.');
|
||||
response_getstatus_openai.send({ error: true });
|
||||
}
|
||||
if (response.statusCode == 500 || response.statusCode == 501 || response.statusCode == 501 || response.statusCode == 503 || response.statusCode == 507) {
|
||||
console.log(data);
|
||||
response_getstatus_openai.send({ error: true });
|
||||
}
|
||||
}).on('error', function () {
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
response_getstatus_openai.send({ error: true });
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/openai_bias", jsonParser, async function (request, response) {
|
||||
@ -3407,9 +3433,13 @@ app.post("/generate_altscale", jsonParser, function (request, response_generate_
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {express.Request} request
|
||||
* @param {express.Response} response
|
||||
*/
|
||||
async function sendClaudeRequest(request, response) {
|
||||
|
||||
const api_url = new URL(request.body.reverse_proxy || api_claude).toString();
|
||||
const api_url = new URL(request.body.reverse_proxy || API_CLAUDE).toString();
|
||||
const api_key_claude = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.CLAUDE);
|
||||
|
||||
if (!api_key_claude) {
|
||||
@ -3463,7 +3493,7 @@ async function sendClaudeRequest(request, response) {
|
||||
generateResponse.body.pipe(response);
|
||||
|
||||
request.socket.on('close', function () {
|
||||
generateResponse.body.destroy(); // Close the remote stream
|
||||
if (generateResponse.body instanceof Readable) generateResponse.body.destroy(); // Close the remote stream
|
||||
response.end(); // End the Express response
|
||||
});
|
||||
|
||||
@ -3514,7 +3544,7 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
||||
let bodyParams;
|
||||
|
||||
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);
|
||||
headers = {};
|
||||
bodyParams = {};
|
||||
@ -3549,15 +3579,15 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
||||
controller.abort();
|
||||
});
|
||||
|
||||
/** @type {import('node-fetch').RequestInit} */
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: endpointUrl,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + api_key_openai,
|
||||
...headers,
|
||||
},
|
||||
data: {
|
||||
body: JSON.stringify({
|
||||
"messages": isTextCompletion === false ? request.body.messages : undefined,
|
||||
"prompt": isTextCompletion === true ? textPrompt : undefined,
|
||||
"model": request.body.model,
|
||||
@ -3571,74 +3601,62 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
||||
"stop": request.body.stop,
|
||||
"logit_bias": request.body.logit_bias,
|
||||
...bodyParams,
|
||||
},
|
||||
}),
|
||||
signal: controller.signal,
|
||||
timeout: 0,
|
||||
};
|
||||
|
||||
console.log(config.data);
|
||||
console.log(JSON.parse(String(config.body)));
|
||||
|
||||
if (request.body.stream) {
|
||||
config.responseType = 'stream';
|
||||
}
|
||||
makeRequest(config, response_generate_openai, request);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} config
|
||||
* @param {express.Response} response_generate_openai
|
||||
* @param {express.Request} request
|
||||
* @param {Number} retries
|
||||
* @param {Number} timeout
|
||||
*/
|
||||
async function makeRequest(config, response_generate_openai, request, retries = 5, timeout = 5000) {
|
||||
try {
|
||||
const response = await axios(config);
|
||||
const fetchResponse = await fetch(endpointUrl, config)
|
||||
|
||||
if (response.status <= 299) {
|
||||
if (fetchResponse.ok) {
|
||||
if (request.body.stream) {
|
||||
console.log('Streaming request in progress');
|
||||
response.data.pipe(response_generate_openai);
|
||||
response.data.on('end', () => {
|
||||
fetchResponse.body.pipe(response_generate_openai);
|
||||
fetchResponse.body.on('end', () => {
|
||||
console.log('Streaming request finished');
|
||||
response_generate_openai.end();
|
||||
});
|
||||
} else {
|
||||
response_generate_openai.send(response.data);
|
||||
console.log(response.data);
|
||||
console.log(response.data?.choices[0]?.message);
|
||||
let json = await fetchResponse.json()
|
||||
response_generate_openai.send(json);
|
||||
console.log(json);
|
||||
console.log(json?.choices[0]?.message);
|
||||
}
|
||||
} else {
|
||||
handleErrorResponse(response, response_generate_openai, request);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.response && error.response.status === 429 && retries > 0) {
|
||||
} else if (fetchResponse.status === 429 && retries > 0) {
|
||||
console.log(`Out of quota, retrying in ${Math.round(timeout / 1000)}s`);
|
||||
setTimeout(() => {
|
||||
makeRequest(config, response_generate_openai, request, retries - 1);
|
||||
}, timeout);
|
||||
} else {
|
||||
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);
|
||||
await handleErrorResponse(fetchResponse);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Generation failed', error);
|
||||
if (!response_generate_openai.headersSent) {
|
||||
response_generate_openai.send({ error: true });
|
||||
} else {
|
||||
response_generate_openai.end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleErrorResponse(response, response_generate_openai, request) {
|
||||
if (response.status >= 400 && response.status <= 504) {
|
||||
console.log('Error occurred:', response.status, response.data);
|
||||
response_generate_openai.send({ error: true });
|
||||
}
|
||||
}
|
||||
|
||||
function handleError(error, response_generate_openai, errorData) {
|
||||
console.error('Error:', error?.message);
|
||||
|
||||
let message = error?.response?.statusText;
|
||||
async function handleErrorResponse(response) {
|
||||
const responseText = await response.text();
|
||||
const errorData = tryParse(responseText);
|
||||
|
||||
const statusMessages = {
|
||||
400: 'Bad request',
|
||||
@ -3648,24 +3666,21 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
|
||||
404: 'Not found',
|
||||
429: 'Too many requests',
|
||||
451: 'Unavailable for legal reasons',
|
||||
502: 'Bad gateway',
|
||||
};
|
||||
|
||||
const status = error?.response?.status;
|
||||
if (statusMessages.hasOwnProperty(status)) {
|
||||
message = errorData?.error?.message || statusMessages[status];
|
||||
console.log(message);
|
||||
}
|
||||
const message = errorData?.error?.message || statusMessages[response.status] || 'Unknown error occurred';
|
||||
const quota_error = response.status === 429 && errorData?.error?.type === 'insufficient_quota';
|
||||
console.log(message);
|
||||
|
||||
const quota_error = error?.response?.status === 429 && errorData?.error?.type === 'insufficient_quota';
|
||||
const response = { error: { message }, quota_error: quota_error }
|
||||
if (!response_generate_openai.headersSent) {
|
||||
response_generate_openai.send(response);
|
||||
response_generate_openai.send({ error: { message }, quota_error: quota_error });
|
||||
} else if (!response_generate_openai.writableEnded) {
|
||||
response_generate_openai.write(response);
|
||||
} else {
|
||||
response_generate_openai.end();
|
||||
}
|
||||
}
|
||||
|
||||
makeRequest(config, response_generate_openai, request);
|
||||
});
|
||||
|
||||
app.post("/tokenize_openai", jsonParser, function (request, response_tokenize_openai) {
|
||||
@ -3776,7 +3791,7 @@ async function sendAI21Request(request, response) {
|
||||
|
||||
}
|
||||
|
||||
app.post("/tokenize_ai21", jsonParser, function (request, response_tokenize_ai21) {
|
||||
app.post("/tokenize_ai21", jsonParser, async function (request, response_tokenize_ai21) {
|
||||
if (!request.body) return response_tokenize_ai21.sendStatus(400);
|
||||
const options = {
|
||||
method: 'POST',
|
||||
@ -3788,10 +3803,14 @@ app.post("/tokenize_ai21", jsonParser, function (request, response_tokenize_ai21
|
||||
body: JSON.stringify({ text: request.body[0].content })
|
||||
};
|
||||
|
||||
fetch('https://api.ai21.com/studio/v1/tokenize', options)
|
||||
.then(response => response.json())
|
||||
.then(response => response_tokenize_ai21.send({ "token_count": response.tokens.length }))
|
||||
.catch(err => console.error(err));
|
||||
try {
|
||||
const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options);
|
||||
const data = await response.json();
|
||||
return response_tokenize_ai21.send({ "token_count": data?.tokens?.length || 0 });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return response_tokenize_ai21.send({ "token_count": 0 });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/save_preset", jsonParser, function (request, response) {
|
||||
@ -3836,10 +3855,9 @@ app.post("/delete_preset", jsonParser, function (request, response) {
|
||||
});
|
||||
|
||||
app.post("/savepreset_openai", jsonParser, function (request, response) {
|
||||
if (!request.body || typeof request.query.name !== 'string') return response.sendStatus(400);
|
||||
const name = sanitize(request.query.name);
|
||||
if (!request.body || !name) {
|
||||
return response.sendStatus(400);
|
||||
}
|
||||
if (!name) return response.sendStatus(400);
|
||||
|
||||
const filename = `${name}.settings`;
|
||||
const fullpath = path.join(directories.openAI_Settings, filename);
|
||||
@ -3982,8 +4000,14 @@ app.post("/tokenize_via_api", jsonParser, async function (request, response) {
|
||||
|
||||
// ** REST CLIENT ASYNC WRAPPERS **
|
||||
|
||||
async function postAsync(url, args) {
|
||||
const response = await fetch(url, { method: 'POST', timeout: 0, ...args });
|
||||
/**
|
||||
* Convenience function for fetch requests (default GET) returning as JSON.
|
||||
* @param {string} url
|
||||
* @param {import('node-fetch').RequestInit} args
|
||||
*/
|
||||
async function fetchJSON(url, args = {}) {
|
||||
if (args.method === undefined) args.method = 'GET';
|
||||
const response = await fetch(url, args);
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
@ -3992,17 +4016,13 @@ async function postAsync(url, args) {
|
||||
|
||||
throw response;
|
||||
}
|
||||
/**
|
||||
* Convenience function for fetch requests (default POST with no timeout) returning as JSON.
|
||||
* @param {string} url
|
||||
* @param {import('node-fetch').RequestInit} args
|
||||
*/
|
||||
async function postAsync(url, args) { return fetchJSON(url, { method: 'POST', timeout: 0, ...args }) }
|
||||
|
||||
function getAsync(url, args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
restClient.get(url, args, (data, response) => {
|
||||
if (response.statusCode >= 400) {
|
||||
reject(data);
|
||||
}
|
||||
resolve(data);
|
||||
}).on('error', e => reject(e));
|
||||
})
|
||||
}
|
||||
// ** END **
|
||||
|
||||
const tavernUrl = new URL(
|
||||
@ -4029,8 +4049,7 @@ const setupTasks = async function () {
|
||||
contentManager.checkForNewContent();
|
||||
cleanUploads();
|
||||
|
||||
// Colab users could run the embedded tool
|
||||
if (!is_colab) await convertWebp();
|
||||
await convertWebp();
|
||||
|
||||
[spp_llama, spp_nerd, spp_nerd_v2, claude_tokenizer] = await Promise.all([
|
||||
loadSentencepieceTokenizer('src/sentencepiece/tokenizer.model'),
|
||||
@ -4277,10 +4296,10 @@ app.post('/generate_horde', jsonParser, async (request, response) => {
|
||||
"body": JSON.stringify(request.body),
|
||||
"headers": {
|
||||
"Content-Type": "application/json",
|
||||
"Client-Agent": request.header('Client-Agent'),
|
||||
"apikey": api_key_horde,
|
||||
}
|
||||
};
|
||||
if (request.header('Client-Agent') !== undefined) args.headers['Client-Agent'] = request.header('Client-Agent');
|
||||
|
||||
console.log(args.body);
|
||||
try {
|
||||
@ -4554,7 +4573,7 @@ app.post('/novel_tts', jsonParser, async (request, response) => {
|
||||
}
|
||||
|
||||
try {
|
||||
const url = `${api_novelai}/ai/generate-voice?text=${encodeURIComponent(text)}&voice=-1&seed=${encodeURIComponent(voice)}&opus=false&version=v2`;
|
||||
const url = `${API_NOVELAI}/ai/generate-voice?text=${encodeURIComponent(text)}&voice=-1&seed=${encodeURIComponent(voice)}&opus=false&version=v2`;
|
||||
const result = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user