"N" support for llama.cpp (#4869) * llama.cpp supports 'n' now * Fix response parsing --------- Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
Signed| @@ -1249,7 +1249,7 @@ | |||
| 1249 | <div class="fa-solid fa-circle-info opacity50p" title="Customize displayed samplers or add custom samplers." data-i18n="[title]Customize displayed samplers or add custom samplers."></div> | 1249 | <div class="fa-solid fa-circle-info opacity50p" title="Customize displayed samplers or add custom samplers." data-i18n="[title]Customize displayed samplers or add custom samplers."></div> |
| 1250 | </small> | 1250 | </small> |
| 1251 | </div> | 1251 | </div> |
| 1252 | <div data-tg-type="mancer, vllm, aphrodite, tabby, infermaticai" data-tg-samplers="n" class="flex-container flexFlowColumn alignitemscenter flexBasis100p flexGrow flexShrink gap0"> | 1252 | <div data-tg-type="mancer, vllm, aphrodite, tabby, infermaticai, llamacpp" data-tg-samplers="n" class="flex-container flexFlowColumn alignitemscenter flexBasis100p flexGrow flexShrink gap0"> |
| 1253 | <small data-i18n="Multiple swipes per generation">Multiple swipes per generation</small> | 1253 | <small data-i18n="Multiple swipes per generation">Multiple swipes per generation</small> |
| 1254 | <input type="number" id="n_textgenerationwebui" class="text_pole textAlignCenter" min="1" value="1" step="1" /> | 1254 | <input type="number" id="n_textgenerationwebui" class="text_pole textAlignCenter" min="1" value="1" step="1" /> |
| 1255 | </div> | 1255 | </div> |
| @@ -5872,7 +5872,7 @@ export function extractMessageFromData(data, activeApi = null) { | |||
| 5872 | case 'koboldhorde': | 5872 | case 'koboldhorde': |
| 5873 | return data.text; | 5873 | return data.text; |
| 5874 | case 'textgenerationwebui': | 5874 | case 'textgenerationwebui': |
| 5875 | return data.choices?.[0]?.text ?? data.choices?.[0]?.message?.content ?? data.content ?? data.response ?? ''; | 5875 | return data.choices?.[0]?.text ?? data.choices?.[0]?.message?.content ?? data.content ?? data.response ?? data[0]?.content ?? ''; |
| 5876 | case 'novel': | 5876 | case 'novel': |
| 5877 | return data.output; | 5877 | return data.output; |
| 5878 | case 'openai': | 5878 | case 'openai': |
| @@ -5959,6 +5959,22 @@ function extractMultiSwipes(data, type) { | |||
| 5959 | return swipes; | 5959 | return swipes; |
| 5960 | } | 5960 | } |
| 5961 | 5961 | ||
| 5962 | if (main_api === 'textgenerationwebui' && textgen_settings.type === textgen_types.LLAMACPP) { | ||
| 5963 | if (!Array.isArray(data)) { | ||
| 5964 | return swipes; | ||
| 5965 | } | ||
| 5966 | |||
| 5967 | const multiSwipeCount = data.length - 1; | ||
| 5968 | if (multiSwipeCount <= 0) { | ||
| 5969 | return swipes; | ||
| 5970 | } | ||
| 5971 | |||
| 5972 | for (let i = 1; i < data.length; i++) { | ||
| 5973 | const text = data?.[i]?.content ?? ''; | ||
| 5974 | swipes.push(text); | ||
| 5975 | } | ||
| 5976 | } | ||
| 5977 | |||
| 5962 | if (main_api === 'openai' || (main_api === 'textgenerationwebui' && [textgen_types.MANCER, textgen_types.VLLM, textgen_types.APHRODITE, textgen_types.TABBY, textgen_types.INFERMATICAI].includes(textgen_settings.type))) { | 5978 | if (main_api === 'openai' || (main_api === 'textgenerationwebui' && [textgen_types.MANCER, textgen_types.VLLM, textgen_types.APHRODITE, textgen_types.TABBY, textgen_types.INFERMATICAI].includes(textgen_settings.type))) { |
| 5963 | if (!Array.isArray(data.choices)) { | 5979 | if (!Array.isArray(data.choices)) { |
| 5964 | return swipes; | 5980 | return swipes; |
| @@ -5972,18 +5988,18 @@ function extractMultiSwipes(data, type) { | |||
| 5972 | 5988 | ||
| 5973 | for (let i = 1; i < data.choices.length; i++) { | 5989 | for (let i = 1; i < data.choices.length; i++) { |
| 5974 | const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? ''; | 5990 | const text = data?.choices[i]?.message?.content ?? data?.choices[i]?.text ?? ''; |
| 5975 | const cleanedText = cleanUpMessage({ | 5991 | swipes.push(text); |
| 5992 | } | ||
| 5993 | } | ||
| 5994 | |||
| 5995 | const cleanedSwipes = swipes.map(text => cleanUpMessage({ | ||
| 5976 | getMessage: text, | 5996 | getMessage: text, |
| 5977 | isImpersonate: false, | 5997 | isImpersonate: false, |
| 5978 | isContinue: false, | 5998 | isContinue: false, |
| 5979 | displayIncompleteSentences: false, | 5999 | displayIncompleteSentences: false, |
| 5980 | }); | 6000 | })); |
| 5981 | |||
| 5982 | swipes.push(cleanedText); | ||
| 5983 | } | ||
| 5984 | } | ||
| 5985 | 6001 | ||
| 5986 | return swipes; | 6002 | return cleanedSwipes; |
| 5987 | } | 6003 | } |
| 5988 | 6004 | ||
| 5989 | /** | 6005 | /** |
| @@ -1,6 +1,9 @@ | |||
| 1 | import { power_user } from './power-user.js'; | 1 | import { power_user } from './power-user.js'; |
| 2 | import { delay } from './utils.js'; | 2 | import { delay } from './utils.js'; |
| 3 | 3 | ||
| 4 | // Symbol for not primary swipe error | ||
| 5 | const NOT_PRIMARY = Symbol('not_primary_swipe'); | ||
| 6 | |||
| 4 | /** | 7 | /** |
| 5 | * A stream which handles Server-Sent Events from a binary ReadableStream like you get from the fetch API. | 8 | * A stream which handles Server-Sent Events from a binary ReadableStream like you get from the fetch API. |
| 6 | */ | 9 | */ |
| @@ -198,6 +201,10 @@ async function* parseStreamData(json) { | |||
| 198 | } | 201 | } |
| 199 | // llama.cpp? | 202 | // llama.cpp? |
| 200 | else if (typeof json.content === 'string' && json.content.length > 0 && json.object !== 'chat.completion.chunk') { | 203 | else if (typeof json.content === 'string' && json.content.length > 0 && json.object !== 'chat.completion.chunk') { |
| 204 | const isNotPrimary = json?.index > 0; | ||
| 205 | if (isNotPrimary) { | ||
| 206 | throw new Error('Not a primary swipe', { cause: NOT_PRIMARY }); | ||
| 207 | } | ||
| 201 | for (let i = 0; i < json.content.length; i++) { | 208 | for (let i = 0; i < json.content.length; i++) { |
| 202 | const str = json.content[i]; | 209 | const str = json.content[i]; |
| 203 | yield { | 210 | yield { |
| @@ -211,7 +218,7 @@ async function* parseStreamData(json) { | |||
| 211 | else if (Array.isArray(json.choices)) { | 218 | else if (Array.isArray(json.choices)) { |
| 212 | const isNotPrimary = json?.choices?.[0]?.index > 0; | 219 | const isNotPrimary = json?.choices?.[0]?.index > 0; |
| 213 | if (isNotPrimary || json.choices.length === 0) { | 220 | if (isNotPrimary || json.choices.length === 0) { |
| 214 | throw new Error('Not a primary swipe'); | 221 | throw new Error('Not a primary swipe', { cause: NOT_PRIMARY }); |
| 215 | } | 222 | } |
| 216 | 223 | ||
| 217 | if (typeof json.choices[0].text === 'string' && json.choices[0].text.length > 0) { | 224 | if (typeof json.choices[0].text === 'string' && json.choices[0].text.length > 0) { |
| @@ -357,7 +364,9 @@ export class SmoothEventSourceStream extends EventSourceStream { | |||
| 357 | lastStr = parsed.chunk; | 364 | lastStr = parsed.chunk; |
| 358 | } | 365 | } |
| 359 | } catch (error) { | 366 | } catch (error) { |
| 367 | if (error instanceof Error && error.cause !== NOT_PRIMARY) { | ||
| 360 | console.debug('Smooth Streaming parsing error', error); | 368 | console.debug('Smooth Streaming parsing error', error); |
| 369 | } | ||
| 361 | controller.enqueue(event); | 370 | controller.enqueue(event); |
| 362 | } | 371 | } |
| 363 | }, | 372 | }, |
| @@ -1284,6 +1284,10 @@ export async function generateTextGenWithStreaming(generate_data, signal) { | |||
| 1284 | if (data?.choices?.[0]?.index > 0) { | 1284 | if (data?.choices?.[0]?.index > 0) { |
| 1285 | const swipeIndex = data.choices[0].index - 1; | 1285 | const swipeIndex = data.choices[0].index - 1; |
| 1286 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + data.choices[0].text; | 1286 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + data.choices[0].text; |
| 1287 | } else if (data?.index > 0) { | ||
| 1288 | // llama.cpp streaming swipe | ||
| 1289 | const swipeIndex = data.index - 1; | ||
| 1290 | swipes[swipeIndex] = (swipes[swipeIndex] || '') + data.content; | ||
| 1287 | } else { | 1291 | } else { |
| 1288 | const newText = data?.choices?.[0]?.text || data?.content || ''; | 1292 | const newText = data?.choices?.[0]?.text || data?.content || ''; |
| 1289 | text += newText; | 1293 | text += newText; |
| @@ -1724,7 +1728,7 @@ export function createTextGenGenerationData(settings, model, finalPrompt = null, | |||
| 1724 | params.dry_sequence_breakers = params.parseSequenceBreakers(); | 1728 | params.dry_sequence_breakers = params.parseSequenceBreakers(); |
| 1725 | } | 1729 | } |
| 1726 | 1730 | ||
| 1727 | if (settings.type === TABBY) { | 1731 | if (settings.type === TABBY || settings.type === LLAMACPP) { |
| 1728 | params.n = canMultiSwipe ? settings.n : 1; | 1732 | params.n = canMultiSwipe ? settings.n : 1; |
| 1729 | } | 1733 | } |
| 1730 | 1734 | ||