Blame Raw
Cohee · e3f41666 · · 142 lines (4.9 KB)
1 contributor
1import { saveSettingsDebounced } from '../script.js';
2import { getTextTokens } from './tokenizers.js';
3import { getSortableDelay, uuidv4 } from './utils.js';
4
5export const BIAS_CACHE = new Map();
6
7/**
8 * Displays the logit bias list in the specified container.
9 * @param {object} logitBias Logit bias object
10 * @param {string} containerSelector Container element selector
11 * @returns
12 */
13export function displayLogitBias(logitBias, containerSelector) {
14 if (!Array.isArray(logitBias)) {
15 console.log('Logit bias set not found');
16 return;
17 }
18
19 const list = $(containerSelector).find('.logit_bias_list');
20 list.empty();
21
22 for (const entry of logitBias) {
23 if (entry) {
24 createLogitBiasListItem(entry, logitBias, containerSelector);
25 }
26 }
27
28 // Check if a sortable instance exists
29 if (list.sortable('instance') !== undefined) {
30 // Destroy the instance
31 list.sortable('destroy');
32 }
33
34 // Make the list sortable
35 list.sortable({
36 delay: getSortableDelay(),
37 handle: '.drag-handle',
38 stop: function () {
39 const order = [];
40 list.children().each(function () {
41 order.unshift($(this).data('id'));
42 });
43 logitBias.sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id));
44 console.log('Logit bias reordered:', logitBias);
45 saveSettingsDebounced();
46 },
47 });
48
49 BIAS_CACHE.delete(containerSelector);
50}
51
52/**
53 * Creates a new logit bias entry
54 * @param {object[]} logitBias Array of logit bias objects
55 * @param {string} containerSelector Container element ID
56 */
57export function createNewLogitBiasEntry(logitBias, containerSelector) {
58 const entry = { id: uuidv4(), text: '', value: 0 };
59 logitBias.push(entry);
60 BIAS_CACHE.delete(containerSelector);
61 createLogitBiasListItem(entry, logitBias, containerSelector);
62 saveSettingsDebounced();
63}
64
65/**
66 * Creates a logit bias list item.
67 * @param {object} entry Logit bias entry
68 * @param {object[]} logitBias Array of logit bias objects
69 * @param {string} containerSelector Container element ID
70 */
71function createLogitBiasListItem(entry, logitBias, containerSelector) {
72 const id = entry.id;
73 const template = $('#logit_bias_template .logit_bias_form').clone();
74 template.data('id', id);
75 template.find('.logit_bias_text').val(entry.text).on('input', function () {
76 entry.text = $(this).val();
77 BIAS_CACHE.delete(containerSelector);
78 saveSettingsDebounced();
79 });
80 template.find('.logit_bias_value').val(entry.value).on('input', function () {
81 entry.value = Number($(this).val());
82 BIAS_CACHE.delete(containerSelector);
83 saveSettingsDebounced();
84 });
85 template.find('.logit_bias_remove').on('click', function () {
86 $(this).closest('.logit_bias_form').remove();
87 const index = logitBias.indexOf(entry);
88 if (index > -1) {
89 logitBias.splice(index, 1);
90 }
91 BIAS_CACHE.delete(containerSelector);
92 saveSettingsDebounced();
93 });
94 $(containerSelector).find('.logit_bias_list').prepend(template);
95}
96
97/**
98 * Populate logit bias list from preset.
99 * @param {object[]} biasPreset Bias preset
100 * @param {number} tokenizerType Tokenizer type (see tokenizers.js)
101 * @param {(bias: number, sequence: number[]) => object} getBiasObject Transformer function to create bias object
102 * @returns {object[]} Array of logit bias objects
103 */
104export function getLogitBiasListResult(biasPreset, tokenizerType, getBiasObject) {
105 const result = [];
106
107 for (const entry of biasPreset) {
108 if (entry.text?.length > 0) {
109 const text = entry.text.trim();
110
111 // Skip empty lines
112 if (text.length === 0) {
113 continue;
114 }
115
116 // Verbatim text
117 if (text.startsWith('{') && text.endsWith('}')) {
118 const tokens = getTextTokens(tokenizerType, text.slice(1, -1));
119 result.push(getBiasObject(entry.value, tokens));
120 } else if (text.startsWith('[') && text.endsWith(']')) {
121 // Raw token ids, JSON serialized
122 try {
123 const tokens = JSON.parse(text);
124
125 if (Array.isArray(tokens) && tokens.every(t => Number.isInteger(t))) {
126 result.push(getBiasObject(entry.value, tokens));
127 } else {
128 throw new Error('Not an array of integers');
129 }
130 } catch (err) {
131 console.log(`Failed to parse logit bias token list: ${text}`, err);
132 }
133 } else {
134 // Text with a leading space
135 const biasText = ` ${text}`;
136 const tokens = getTextTokens(tokenizerType, biasText);
137 result.push(getBiasObject(entry.value, tokens));
138 }
139 }
140 }
141 return result;
142}