2023-07-20 19:32:15 +02:00
import {
2023-09-28 18:10:00 +02:00
api _server _textgenerationwebui ,
2023-07-20 19:32:15 +02:00
getRequestHeaders ,
getStoppingStrings ,
max _context ,
2023-11-07 23:17:13 +01:00
online _status ,
2023-07-20 19:32:15 +02:00
saveSettingsDebounced ,
2023-07-23 22:52:31 +02:00
setGenerationParamsFromPreset ,
2023-11-08 01:52:03 +01:00
setOnlineStatus ,
2023-11-16 15:58:49 +01:00
substituteParams ,
2023-07-20 19:32:15 +02:00
} from "../script.js" ;
2023-08-07 22:46:32 +02:00
import {
power _user ,
2023-11-13 10:13:39 +01:00
registerDebugFunction ,
2023-08-07 22:46:32 +02:00
} from "./power-user.js" ;
2023-11-21 00:04:27 +01:00
import { SENTENCEPIECE _TOKENIZERS , getTextTokens , tokenizers } from "./tokenizers.js" ;
2023-11-21 00:47:57 +01:00
import { getSortableDelay , onlyUnique } from "./utils.js" ;
2023-08-07 22:46:32 +02:00
2023-07-20 19:32:15 +02:00
export {
textgenerationwebui _settings ,
loadTextGenSettings ,
generateTextGenWithStreaming ,
2023-08-03 12:07:54 +02:00
formatTextGenURL ,
2023-07-20 19:32:15 +02:00
}
2023-09-28 18:10:00 +02:00
export const textgen _types = {
OOBA : 'ooba' ,
MANCER : 'mancer' ,
APHRODITE : 'aphrodite' ,
2023-11-19 16:14:53 +01:00
TABBY : 'tabby' ,
KOBOLDCPP : 'koboldcpp' ,
2023-09-28 18:10:00 +02:00
} ;
2023-11-07 23:17:13 +01:00
// Maybe let it be configurable in the future?
2023-11-13 10:13:39 +01:00
// (7 days later) The future has come.
const MANCER _SERVER _KEY = 'mancer_server' ;
const MANCER _SERVER _DEFAULT = 'https://neuro.mancer.tech' ;
export let MANCER _SERVER = localStorage . getItem ( MANCER _SERVER _KEY ) ? ? MANCER _SERVER _DEFAULT ;
2023-11-07 23:17:13 +01:00
2023-11-21 00:47:57 +01:00
const KOBOLDCPP _ORDER = [ 6 , 0 , 1 , 3 , 4 , 2 , 5 ] ;
2023-07-23 01:09:03 +02:00
const textgenerationwebui _settings = {
2023-07-20 19:32:15 +02:00
temp : 0.7 ,
2023-11-05 15:50:07 +01:00
temperature _last : true ,
2023-07-20 19:32:15 +02:00
top _p : 0.5 ,
top _k : 40 ,
top _a : 0 ,
tfs : 1 ,
epsilon _cutoff : 0 ,
eta _cutoff : 0 ,
typical _p : 1 ,
2023-11-05 15:08:06 +01:00
min _p : 0 ,
2023-07-20 19:32:15 +02:00
rep _pen : 1.2 ,
2023-07-22 00:38:35 +02:00
rep _pen _range : 0 ,
2023-07-20 19:32:15 +02:00
no _repeat _ngram _size : 0 ,
penalty _alpha : 0 ,
num _beams : 1 ,
length _penalty : 1 ,
min _length : 0 ,
encoder _rep _pen : 1 ,
2023-10-25 21:21:49 +02:00
freq _pen : 0 ,
presence _pen : 0 ,
2023-07-20 19:32:15 +02:00
do _sample : true ,
early _stopping : false ,
seed : - 1 ,
preset : 'Default' ,
add _bos _token : true ,
stopping _strings : [ ] ,
truncation _length : 2048 ,
ban _eos _token : false ,
skip _special _tokens : true ,
streaming : false ,
mirostat _mode : 0 ,
mirostat _tau : 5 ,
mirostat _eta : 0.1 ,
2023-08-14 12:06:20 +02:00
guidance _scale : 1 ,
negative _prompt : '' ,
2023-09-27 21:09:09 +02:00
grammar _string : '' ,
banned _tokens : '' ,
2023-11-04 03:16:12 +01:00
//n_aphrodite: 1,
//best_of_aphrodite: 1,
2023-11-13 08:36:01 +01:00
ignore _eos _token _aphrodite : false ,
spaces _between _special _tokens _aphrodite : true ,
2023-11-04 03:16:12 +01:00
//logits_processors_aphrodite: [],
//log_probs_aphrodite: 0,
//prompt_log_probs_aphrodite: 0,
2023-09-28 18:10:00 +02:00
type : textgen _types . OOBA ,
2023-11-07 23:17:13 +01:00
mancer _model : 'mytholite' ,
2023-11-08 09:13:28 +01:00
legacy _api : false ,
2023-11-21 00:47:57 +01:00
sampler _order : KOBOLDCPP _ORDER ,
2023-07-20 19:32:15 +02:00
} ;
2023-10-05 12:10:41 +02:00
export let textgenerationwebui _banned _in _macros = [ ] ;
2023-07-23 22:52:31 +02:00
export let textgenerationwebui _presets = [ ] ;
export let textgenerationwebui _preset _names = [ ] ;
2023-07-20 19:32:15 +02:00
const setting _names = [
"temp" ,
2023-11-05 15:50:07 +01:00
"temperature_last" ,
2023-07-20 19:32:15 +02:00
"rep_pen" ,
2023-07-22 00:38:35 +02:00
"rep_pen_range" ,
2023-07-20 19:32:15 +02:00
"no_repeat_ngram_size" ,
"top_k" ,
"top_p" ,
"top_a" ,
"tfs" ,
"epsilon_cutoff" ,
"eta_cutoff" ,
"typical_p" ,
2023-11-05 15:08:06 +01:00
"min_p" ,
2023-07-20 19:32:15 +02:00
"penalty_alpha" ,
"num_beams" ,
"length_penalty" ,
"min_length" ,
"encoder_rep_pen" ,
2023-10-25 21:21:49 +02:00
"freq_pen" ,
"presence_pen" ,
2023-07-20 19:32:15 +02:00
"do_sample" ,
"early_stopping" ,
"seed" ,
"add_bos_token" ,
"ban_eos_token" ,
"skip_special_tokens" ,
"streaming" ,
"mirostat_mode" ,
"mirostat_tau" ,
"mirostat_eta" ,
2023-08-14 12:06:20 +02:00
"guidance_scale" ,
"negative_prompt" ,
2023-09-27 21:09:09 +02:00
"grammar_string" ,
"banned_tokens" ,
2023-11-08 09:13:28 +01:00
"legacy_api" ,
2023-11-04 03:16:12 +01:00
//'n_aphrodite',
//'best_of_aphrodite',
2023-11-13 08:36:01 +01:00
'ignore_eos_token_aphrodite' ,
'spaces_between_special_tokens_aphrodite' ,
2023-11-04 03:16:12 +01:00
//'logits_processors_aphrodite',
//'log_probs_aphrodite',
//'prompt_log_probs_aphrodite'
2023-11-21 00:47:57 +01:00
"sampler_order" ,
2023-07-20 19:32:15 +02:00
] ;
2023-11-05 15:08:06 +01:00
async function selectPreset ( name ) {
2023-07-20 19:32:15 +02:00
const preset = textgenerationwebui _presets [ textgenerationwebui _preset _names . indexOf ( name ) ] ;
if ( ! preset ) {
return ;
}
textgenerationwebui _settings . preset = name ;
for ( const name of setting _names ) {
const value = preset [ name ] ;
setSettingByName ( name , value , true ) ;
}
2023-07-23 22:52:31 +02:00
setGenerationParamsFromPreset ( preset ) ;
2023-07-20 19:32:15 +02:00
saveSettingsDebounced ( ) ;
}
2023-11-07 23:17:13 +01:00
function formatTextGenURL ( value ) {
2023-08-03 12:07:54 +02:00
try {
2023-11-08 17:16:47 +01:00
// Mancer doesn't need any formatting (it's hardcoded)
if ( isMancer ( ) ) {
return value ;
}
2023-08-03 12:07:54 +02:00
const url = new URL ( value ) ;
2023-11-08 09:13:28 +01:00
if ( url . pathname === '/api' && ! textgenerationwebui _settings . legacy _api ) {
2023-11-08 16:54:08 +01:00
toastr . info ( ` Enable Legacy API or start Ooba with the OpenAI extension enabled. ` , 'Legacy API URL detected. Generation may fail.' , { preventDuplicates : true , timeOut : 10000 , extendedTimeOut : 20000 } ) ;
url . pathname = '' ;
2023-08-03 12:07:54 +02:00
}
2023-11-08 09:25:49 +01:00
2023-11-08 17:16:47 +01:00
if ( ! power _user . relaxed _api _urls && textgenerationwebui _settings . legacy _api ) {
2023-11-08 09:25:49 +01:00
url . pathname = '/api' ;
}
2023-08-07 22:46:32 +02:00
return url . toString ( ) ;
2023-08-07 23:10:05 +02:00
} catch { } // Just using URL as a validation check
2023-08-03 12:07:54 +02:00
return null ;
}
2023-07-20 19:32:15 +02:00
function convertPresets ( presets ) {
2023-10-05 12:10:41 +02:00
return Array . isArray ( presets ) ? presets . map ( ( p ) => JSON . parse ( p ) ) : [ ] ;
2023-07-20 19:32:15 +02:00
}
2023-09-27 21:09:09 +02:00
/ * *
* @ returns { string } String with comma - separated banned token IDs
* /
function getCustomTokenBans ( ) {
2023-10-05 12:10:41 +02:00
if ( ! textgenerationwebui _settings . banned _tokens && ! textgenerationwebui _banned _in _macros . length ) {
2023-09-27 21:09:09 +02:00
return '' ;
}
2023-11-21 00:04:27 +01:00
const tokenizer = SENTENCEPIECE _TOKENIZERS . includes ( power _user . tokenizer ) ? power _user . tokenizer : tokenizers . LLAMA ;
2023-09-27 21:09:09 +02:00
const result = [ ] ;
2023-10-05 12:10:41 +02:00
const sequences = textgenerationwebui _settings . banned _tokens
. split ( '\n' )
. concat ( textgenerationwebui _banned _in _macros )
. filter ( x => x . length > 0 )
. filter ( onlyUnique ) ;
//debug
if ( textgenerationwebui _banned _in _macros . length ) {
console . log ( "=== Found banned word sequences in the macros:" , textgenerationwebui _banned _in _macros , "Resulting array of banned sequences (will be used this generation turn):" , sequences ) ;
}
//clean old temporary bans found in macros before, for the next generation turn.
textgenerationwebui _banned _in _macros = [ ] ;
2023-09-27 21:09:09 +02:00
for ( const line of sequences ) {
// Raw token ids, JSON serialized
if ( line . startsWith ( '[' ) && line . endsWith ( ']' ) ) {
try {
const tokens = JSON . parse ( line ) ;
if ( Array . isArray ( tokens ) && tokens . every ( t => Number . isInteger ( t ) ) ) {
result . push ( ... tokens ) ;
} else {
throw new Error ( 'Not an array of integers' ) ;
}
} catch ( err ) {
console . log ( ` Failed to parse bad word token list: ${ line } ` , err ) ;
}
} else {
try {
2023-11-21 00:04:27 +01:00
const tokens = getTextTokens ( tokenizer , line ) ;
2023-09-27 21:09:09 +02:00
result . push ( ... tokens ) ;
} catch {
console . log ( ` Could not tokenize raw text: ${ line } ` ) ;
}
}
}
return result . filter ( onlyUnique ) . map ( x => String ( x ) ) . join ( ',' ) ;
}
2023-07-20 19:32:15 +02:00
function loadTextGenSettings ( data , settings ) {
textgenerationwebui _presets = convertPresets ( data . textgenerationwebui _presets ) ;
textgenerationwebui _preset _names = data . textgenerationwebui _preset _names ? ? [ ] ;
Object . assign ( textgenerationwebui _settings , settings . textgenerationwebui _settings ? ? { } ) ;
2023-09-28 18:10:00 +02:00
if ( settings . api _use _mancer _webui ) {
textgenerationwebui _settings . type = textgen _types . MANCER ;
}
2023-07-20 19:32:15 +02:00
for ( const name of textgenerationwebui _preset _names ) {
const option = document . createElement ( 'option' ) ;
option . value = name ;
option . innerText = name ;
$ ( '#settings_preset_textgenerationwebui' ) . append ( option ) ;
}
if ( textgenerationwebui _settings . preset ) {
$ ( '#settings_preset_textgenerationwebui' ) . val ( textgenerationwebui _settings . preset ) ;
}
for ( const i of setting _names ) {
const value = textgenerationwebui _settings [ i ] ;
setSettingByName ( i , value ) ;
}
2023-09-28 18:10:00 +02:00
2023-11-08 01:52:03 +01:00
$ ( '#textgen_type' ) . val ( textgenerationwebui _settings . type ) ;
showTypeSpecificControls ( textgenerationwebui _settings . type ) ;
2023-11-13 08:36:01 +01:00
//this is needed because showTypeSpecificControls() does not handle NOT declarations
if ( isAphrodite ( ) ) {
$ ( '[data-forAphro=False]' ) . each ( function ( ) {
$ ( this ) . hide ( )
} )
} else {
$ ( '[data-forAphro=False]' ) . each ( function ( ) {
$ ( this ) . show ( )
} )
}
2023-11-13 10:13:39 +01:00
registerDebugFunction ( 'change-mancer-url' , 'Change Mancer base URL' , 'Change Mancer API server base URL' , ( ) => {
const result = prompt ( ` Enter Mancer base URL \n Default: ${ MANCER _SERVER _DEFAULT } ` , MANCER _SERVER ) ;
if ( result ) {
localStorage . setItem ( MANCER _SERVER _KEY , result ) ;
MANCER _SERVER = result ;
}
} ) ;
2023-09-28 18:10:00 +02:00
}
export function isMancer ( ) {
return textgenerationwebui _settings . type === textgen _types . MANCER ;
}
export function isAphrodite ( ) {
return textgenerationwebui _settings . type === textgen _types . APHRODITE ;
}
2023-11-17 06:32:49 +01:00
export function isTabby ( ) {
return textgenerationwebui _settings . type === textgen _types . TABBY ;
}
2023-10-08 22:42:28 +02:00
export function isOoba ( ) {
return textgenerationwebui _settings . type === textgen _types . OOBA ;
}
2023-11-19 16:14:53 +01:00
export function isKoboldCpp ( ) {
return textgenerationwebui _settings . type === textgen _types . KOBOLDCPP ;
}
2023-09-28 18:10:00 +02:00
export function getTextGenUrlSourceId ( ) {
switch ( textgenerationwebui _settings . type ) {
case textgen _types . OOBA :
return "#textgenerationwebui_api_url_text" ;
case textgen _types . APHRODITE :
return "#aphrodite_api_url_text" ;
2023-11-17 06:32:49 +01:00
case textgen _types . TABBY :
return "#tabby_api_url_text" ;
2023-11-19 16:14:53 +01:00
case textgen _types . KOBOLDCPP :
return "#koboldcpp_api_url_text" ;
2023-09-28 18:10:00 +02:00
}
2023-07-20 19:32:15 +02:00
}
2023-11-21 00:47:57 +01:00
/ * *
* Sorts the sampler items by the given order .
* @ param { any [ ] } orderArray Sampler order array .
* /
function sortItemsByOrder ( orderArray ) {
console . debug ( 'Preset samplers order: ' + orderArray ) ;
const $draggableItems = $ ( "#koboldcpp_order" ) ;
for ( let i = 0 ; i < orderArray . length ; i ++ ) {
const index = orderArray [ i ] ;
const $item = $draggableItems . find ( ` [data-id=" ${ index } "] ` ) . detach ( ) ;
$draggableItems . append ( $item ) ;
}
}
2023-09-28 18:10:00 +02:00
jQuery ( function ( ) {
2023-11-21 00:47:57 +01:00
$ ( '#koboldcpp_order' ) . sortable ( {
delay : getSortableDelay ( ) ,
stop : function ( ) {
const order = [ ] ;
$ ( '#koboldcpp_order' ) . children ( ) . each ( function ( ) {
order . push ( $ ( this ) . data ( 'id' ) ) ;
} ) ;
textgenerationwebui _settings . sampler _order = order ;
console . log ( 'Samplers reordered:' , textgenerationwebui _settings . sampler _order ) ;
saveSettingsDebounced ( ) ;
} ,
} ) ;
$ ( '#koboldcpp_default_order' ) . on ( 'click' , function ( ) {
textgenerationwebui _settings . sampler _order = KOBOLDCPP _ORDER ;
sortItemsByOrder ( textgenerationwebui _settings . sampler _order ) ;
saveSettingsDebounced ( ) ;
} ) ;
2023-09-28 18:10:00 +02:00
$ ( '#textgen_type' ) . on ( 'change' , function ( ) {
const type = String ( $ ( this ) . val ( ) ) ;
textgenerationwebui _settings . type = type ;
2023-11-13 08:36:01 +01:00
if ( isAphrodite ( ) ) {
//this is needed because showTypeSpecificControls() does not handle NOT declarations
$ ( '[data-forAphro=False]' ) . each ( function ( ) {
$ ( this ) . hide ( )
} )
$ ( '#mirostat_mode_textgenerationwebui' ) . attr ( 'step' , 2 ) //Aphro disallows mode 1
$ ( "#do_sample_textgenerationwebui" ) . prop ( 'checked' , true ) //Aphro should always do sample; 'otherwise set temp to 0 to mimic no sample'
$ ( "#ban_eos_token_textgenerationwebui" ) . prop ( 'checked' , false ) //Aphro should not ban EOS, just ignore it; 'add token '2' to ban list do to this'
//special handling for Aphrodite topK -1 disable state
$ ( '#top_k_textgenerationwebui' ) . attr ( 'min' , - 1 )
if ( $ ( '#top_k_textgenerationwebui' ) . val ( ) === '0' || textgenerationwebui _settings [ 'top_k' ] === 0 ) {
textgenerationwebui _settings [ 'top_k' ] = - 1
$ ( '#top_k_textgenerationwebui' ) . val ( '-1' ) . trigger ( 'input' )
}
} else {
//this is needed because showTypeSpecificControls() does not handle NOT declarations
$ ( '[data-forAphro=False]' ) . each ( function ( ) {
$ ( this ) . show ( )
} )
$ ( '#mirostat_mode_textgenerationwebui' ) . attr ( 'step' , 1 )
//undo special Aphrodite setup for topK
$ ( '#top_k_textgenerationwebui' ) . attr ( 'min' , 0 )
if ( $ ( '#top_k_textgenerationwebui' ) . val ( ) === '-1' || textgenerationwebui _settings [ 'top_k' ] === - 1 ) {
textgenerationwebui _settings [ 'top_k' ] = 0
$ ( '#top_k_textgenerationwebui' ) . val ( '0' ) . trigger ( 'input' )
}
}
2023-11-04 03:16:12 +01:00
2023-11-08 01:52:03 +01:00
showTypeSpecificControls ( type ) ;
setOnlineStatus ( 'no_connection' ) ;
2023-09-28 18:10:00 +02:00
2023-11-08 01:52:03 +01:00
$ ( '#main_api' ) . trigger ( 'change' ) ;
$ ( '#api_button_textgenerationwebui' ) . trigger ( 'click' ) ;
2023-09-28 18:10:00 +02:00
saveSettingsDebounced ( ) ;
} ) ;
2023-09-27 21:09:09 +02:00
$ ( '#settings_preset_textgenerationwebui' ) . on ( 'change' , function ( ) {
2023-07-20 19:32:15 +02:00
const presetName = $ ( this ) . val ( ) ;
selectPreset ( presetName ) ;
} ) ;
for ( const i of setting _names ) {
$ ( ` # ${ i } _textgenerationwebui ` ) . attr ( "x-setting-id" , i ) ;
$ ( document ) . on ( "input" , ` # ${ i } _textgenerationwebui ` , function ( ) {
const isCheckbox = $ ( this ) . attr ( 'type' ) == 'checkbox' ;
2023-08-14 12:06:20 +02:00
const isText = $ ( this ) . attr ( 'type' ) == 'text' || $ ( this ) . is ( 'textarea' ) ;
2023-07-20 19:32:15 +02:00
const id = $ ( this ) . attr ( "x-setting-id" ) ;
if ( isCheckbox ) {
const value = $ ( this ) . prop ( 'checked' ) ;
textgenerationwebui _settings [ id ] = value ;
}
else if ( isText ) {
const value = $ ( this ) . val ( ) ;
textgenerationwebui _settings [ id ] = value ;
}
else {
2023-08-22 18:35:56 +02:00
const value = Number ( $ ( this ) . val ( ) ) ;
2023-10-26 13:41:12 +02:00
$ ( ` # ${ id } _counter_textgenerationwebui ` ) . val ( value ) ;
2023-08-22 18:35:56 +02:00
textgenerationwebui _settings [ id ] = value ;
2023-11-13 08:36:01 +01:00
//special handling for aphrodite using -1 as disabled instead of 0
if ( $ ( this ) . attr ( 'id' ) === 'top_k_textgenerationwebui' && isAphrodite ( ) && value === 0 ) {
textgenerationwebui _settings [ id ] = - 1
$ ( this ) . val ( - 1 )
}
2023-07-20 19:32:15 +02:00
}
saveSettingsDebounced ( ) ;
} ) ;
}
} )
2023-11-08 01:52:03 +01:00
function showTypeSpecificControls ( type ) {
$ ( '[data-tg-type]' ) . each ( function ( ) {
const tgType = $ ( this ) . attr ( 'data-tg-type' ) ;
if ( tgType == type ) {
$ ( this ) . show ( ) ;
} else {
$ ( this ) . hide ( ) ;
}
} ) ;
}
2023-11-21 00:47:57 +01:00
function setSettingByName ( setting , value , trigger ) {
2023-07-20 19:32:15 +02:00
if ( value === null || value === undefined ) {
return ;
}
2023-11-21 00:47:57 +01:00
if ( 'sampler_order' === setting ) {
value = Array . isArray ( value ) ? value : KOBOLDCPP _ORDER ;
sortItemsByOrder ( value ) ;
textgenerationwebui _settings . sampler _order = value ;
return ;
}
const isCheckbox = $ ( ` # ${ setting } _textgenerationwebui ` ) . attr ( 'type' ) == 'checkbox' ;
const isText = $ ( ` # ${ setting } _textgenerationwebui ` ) . attr ( 'type' ) == 'text' || $ ( ` # ${ setting } _textgenerationwebui ` ) . is ( 'textarea' ) ;
2023-07-20 19:32:15 +02:00
if ( isCheckbox ) {
const val = Boolean ( value ) ;
2023-11-21 00:47:57 +01:00
$ ( ` # ${ setting } _textgenerationwebui ` ) . prop ( 'checked' , val ) ;
2023-07-20 19:32:15 +02:00
}
else if ( isText ) {
2023-11-21 00:47:57 +01:00
$ ( ` # ${ setting } _textgenerationwebui ` ) . val ( value ) ;
2023-07-20 19:32:15 +02:00
}
else {
const val = parseFloat ( value ) ;
2023-11-21 00:47:57 +01:00
$ ( ` # ${ setting } _textgenerationwebui ` ) . val ( val ) ;
$ ( ` # ${ setting } _counter_textgenerationwebui ` ) . val ( val ) ;
2023-11-05 15:08:06 +01:00
if ( power _user . enableZenSliders ) {
2023-11-21 00:47:57 +01:00
let zenSlider = $ ( ` # ${ setting } _textgenerationwebui_zenslider ` ) . slider ( )
2023-11-05 15:08:06 +01:00
zenSlider . slider ( 'option' , 'value' , val )
zenSlider . slider ( 'option' , 'slide' )
. call ( zenSlider , null , {
handle : $ ( '.ui-slider-handle' , zenSlider ) , value : val
} ) ;
}
2023-07-20 19:32:15 +02:00
}
if ( trigger ) {
2023-11-21 00:47:57 +01:00
$ ( ` # ${ setting } _textgenerationwebui ` ) . trigger ( 'input' ) ;
2023-07-20 19:32:15 +02:00
}
}
async function generateTextGenWithStreaming ( generate _data , signal ) {
2023-11-07 23:17:13 +01:00
generate _data . stream = true ;
2023-10-08 22:42:28 +02:00
2023-11-07 23:17:13 +01:00
const response = await fetch ( '/api/textgenerationwebui/generate' , {
2023-07-20 19:32:15 +02:00
headers : {
... getRequestHeaders ( ) ,
} ,
body : JSON . stringify ( generate _data ) ,
method : 'POST' ,
signal : signal ,
} ) ;
return async function * streamData ( ) {
const decoder = new TextDecoder ( ) ;
const reader = response . body . getReader ( ) ;
let getMessage = '' ;
2023-11-07 23:17:13 +01:00
let messageBuffer = "" ;
2023-07-20 19:32:15 +02:00
while ( true ) {
const { done , value } = await reader . read ( ) ;
2023-11-07 23:17:13 +01:00
// We don't want carriage returns in our messages
let response = decoder . decode ( value ) . replace ( /\r/g , "" ) ;
2023-07-20 19:32:15 +02:00
2023-11-07 23:17:13 +01:00
tryParseStreamingError ( response ) ;
2023-07-20 19:32:15 +02:00
2023-11-07 23:17:13 +01:00
let eventList = [ ] ;
2023-09-28 18:10:00 +02:00
2023-11-07 23:17:13 +01:00
messageBuffer += response ;
eventList = messageBuffer . split ( "\n\n" ) ;
// Last element will be an empty string or a leftover partial message
messageBuffer = eventList . pop ( ) ;
2023-10-05 12:10:41 +02:00
2023-11-07 23:17:13 +01:00
for ( let event of eventList ) {
if ( event . startsWith ( 'event: completion' ) ) {
event = event . split ( "\n" ) [ 1 ] ;
2023-09-28 18:10:00 +02:00
}
2023-11-07 23:17:13 +01:00
if ( typeof event !== 'string' || ! event . length )
continue ;
2023-10-05 12:10:41 +02:00
2023-11-07 23:17:13 +01:00
if ( ! event . startsWith ( "data" ) )
continue ;
if ( event == "data: [DONE]" ) {
2023-09-28 18:10:00 +02:00
return ;
}
2023-11-07 23:17:13 +01:00
let data = JSON . parse ( event . substring ( 6 ) ) ;
// the first and last messages are undefined, protect against that
getMessage += data ? . choices [ 0 ] ? . text || '' ;
2023-09-28 18:10:00 +02:00
yield getMessage ;
}
2023-11-07 23:17:13 +01:00
if ( done ) {
return ;
}
2023-07-20 19:32:15 +02:00
}
}
}
2023-11-07 23:17:13 +01:00
/ * *
* Parses errors in streaming responses and displays them in toastr .
* @ param { string } response - Response from the server .
* @ returns { void } Nothing .
* /
function tryParseStreamingError ( response ) {
let data = { } ;
try {
data = JSON . parse ( response ) ;
} catch {
// No JSON. Do nothing.
}
2023-11-07 23:25:06 +01:00
const message = data ? . error ? . message || data ? . message ;
if ( message ) {
toastr . error ( message , 'API Error' ) ;
throw new Error ( message ) ;
2023-11-07 23:17:13 +01:00
}
}
function toIntArray ( string ) {
if ( ! string ) {
return [ ] ;
}
return string . split ( ',' ) . map ( x => parseInt ( x ) ) . filter ( x => ! isNaN ( x ) ) ;
}
function getModel ( ) {
if ( isMancer ( ) ) {
return textgenerationwebui _settings . mancer _model ;
}
if ( isAphrodite ( ) ) {
return online _status ;
}
return undefined ;
}
2023-11-22 15:16:48 +01:00
export function getTextGenGenerationData ( finalPrompt , maxTokens , isImpersonate , isContinue , cfgValues ) {
2023-11-13 08:36:01 +01:00
let APIflags = {
2023-08-23 16:44:38 +02:00
'prompt' : finalPrompt ,
2023-11-07 23:17:13 +01:00
'model' : getModel ( ) ,
2023-11-22 15:16:48 +01:00
'max_new_tokens' : maxTokens ,
'max_tokens' : maxTokens ,
2023-07-20 19:32:15 +02:00
'temperature' : textgenerationwebui _settings . temp ,
'top_p' : textgenerationwebui _settings . top _p ,
'typical_p' : textgenerationwebui _settings . typical _p ,
2023-11-05 15:08:06 +01:00
'min_p' : textgenerationwebui _settings . min _p ,
2023-07-20 19:32:15 +02:00
'repetition_penalty' : textgenerationwebui _settings . rep _pen ,
2023-10-25 21:21:49 +02:00
'frequency_penalty' : textgenerationwebui _settings . freq _pen ,
'presence_penalty' : textgenerationwebui _settings . presence _pen ,
2023-07-20 19:32:15 +02:00
'top_k' : textgenerationwebui _settings . top _k ,
'min_length' : textgenerationwebui _settings . min _length ,
2023-11-07 23:17:13 +01:00
'min_tokens' : textgenerationwebui _settings . min _length ,
2023-07-20 19:32:15 +02:00
'num_beams' : textgenerationwebui _settings . num _beams ,
'length_penalty' : textgenerationwebui _settings . length _penalty ,
'early_stopping' : textgenerationwebui _settings . early _stopping ,
'add_bos_token' : textgenerationwebui _settings . add _bos _token ,
2023-11-22 15:16:48 +01:00
'stopping_strings' : getStoppingStrings ( isImpersonate , isContinue ) ,
'stop' : getStoppingStrings ( isImpersonate , isContinue ) ,
2023-07-20 19:32:15 +02:00
'truncation_length' : max _context ,
'ban_eos_token' : textgenerationwebui _settings . ban _eos _token ,
'skip_special_tokens' : textgenerationwebui _settings . skip _special _tokens ,
'top_a' : textgenerationwebui _settings . top _a ,
'tfs' : textgenerationwebui _settings . tfs ,
'epsilon_cutoff' : textgenerationwebui _settings . epsilon _cutoff ,
'eta_cutoff' : textgenerationwebui _settings . eta _cutoff ,
'mirostat_mode' : textgenerationwebui _settings . mirostat _mode ,
'mirostat_tau' : textgenerationwebui _settings . mirostat _tau ,
'mirostat_eta' : textgenerationwebui _settings . mirostat _eta ,
2023-11-07 23:17:13 +01:00
'custom_token_bans' : isAphrodite ( ) ? toIntArray ( getCustomTokenBans ( ) ) : getCustomTokenBans ( ) ,
2023-10-11 16:56:52 +02:00
'use_mancer' : isMancer ( ) ,
'use_aphrodite' : isAphrodite ( ) ,
2023-11-17 06:32:49 +01:00
'use_tabby' : isTabby ( ) ,
2023-11-19 16:14:53 +01:00
'use_koboldcpp' : isKoboldCpp ( ) ,
2023-11-07 23:17:13 +01:00
'use_ooba' : isOoba ( ) ,
'api_server' : isMancer ( ) ? MANCER _SERVER : api _server _textgenerationwebui ,
2023-11-08 17:16:47 +01:00
'legacy_api' : textgenerationwebui _settings . legacy _api && ! isMancer ( ) ,
2023-11-21 00:47:57 +01:00
'sampler_order' : isKoboldCpp ( ) ? textgenerationwebui _settings . sampler _order : undefined ,
2023-11-13 08:36:01 +01:00
} ;
let aphroditeExclusionFlags = {
'repetition_penalty_range' : textgenerationwebui _settings . rep _pen _range ,
'encoder_repetition_penalty' : textgenerationwebui _settings . encoder _rep _pen ,
'no_repeat_ngram_size' : textgenerationwebui _settings . no _repeat _ngram _size ,
'penalty_alpha' : textgenerationwebui _settings . penalty _alpha ,
'temperature_last' : textgenerationwebui _settings . temperature _last ,
'do_sample' : textgenerationwebui _settings . do _sample ,
'seed' : textgenerationwebui _settings . seed ,
'guidance_scale' : cfgValues ? . guidanceScale ? . value ? ? textgenerationwebui _settings . guidance _scale ? ? 1 ,
2023-11-16 15:58:49 +01:00
'negative_prompt' : cfgValues ? . negativePrompt ? ? substituteParams ( textgenerationwebui _settings . negative _prompt ) ? ? '' ,
2023-11-13 08:36:01 +01:00
'grammar_string' : textgenerationwebui _settings . grammar _string ,
}
let aphroditeFlags = {
2023-11-04 03:16:12 +01:00
//'n': textgenerationwebui_settings.n_aphrodite,
//'best_of': textgenerationwebui_settings.n_aphrodite, //n must always == best_of and vice versa
2023-11-13 08:36:01 +01:00
'ignore_eos' : textgenerationwebui _settings . ignore _eos _token _aphrodite ,
'spaces_between_special_tokens' : textgenerationwebui _settings . spaces _between _special _tokens _aphrodite ,
//'logits_processors': textgenerationwebui_settings.logits_processors_aphrodite,
2023-11-04 03:16:12 +01:00
//'logprobs': textgenerationwebui_settings.log_probs_aphrodite,
//'prompt_logprobs': textgenerationwebui_settings.prompt_log_probs_aphrodite,
2023-11-13 08:36:01 +01:00
}
if ( isAphrodite ( ) ) {
APIflags = Object . assign ( APIflags , aphroditeFlags ) ;
} else {
APIflags = Object . assign ( APIflags , aphroditeExclusionFlags ) ;
}
return APIflags
2023-07-20 19:32:15 +02:00
}
2023-11-07 23:17:13 +01:00