| 176 | 176 | throw new Error('Custom API URL is not set.'); |
| 177 | 177 | } |
| 178 | 178 | } |
| 179 | + |
| 180 | +/** |
| 181 | + * Check if the WebLLM extension is installed and supported. |
| 182 | + * @returns {boolean} Whether the extension is installed and supported |
| 183 | + */ |
| 184 | +export function isWebLlmSupported() { |
| 185 | + if (!('gpu' in navigator)) { |
| 186 | + toastr.error('Your browser does not support the WebGPU API. Please use a different browser.', 'WebLLM', { |
| 187 | + preventDuplicates: true, |
| 188 | + timeOut: 0, |
| 189 | + extendedTimeOut: 0, |
| 190 | + }); |
| 191 | + return false; |
| 192 | + } |
| 193 | + |
| 194 | + if (!('llm' in SillyTavern)) { |
| 195 | + toastr.error('WebLLM extension is not installed. Click here to install it.', 'WebLLM', { |
| 196 | + timeOut: 0, |
| 197 | + extendedTimeOut: 0, |
| 198 | + preventDuplicates: true, |
| 199 | + onclick: () => { |
| 200 | + const button = document.getElementById('third_party_extension_button'); |
| 201 | + if (button) { |
| 202 | + button.click(); |
| 203 | + } |
| 204 | + |
| 205 | + const input = document.querySelector('dialog textarea'); |
| 206 | + |
| 207 | + if (input instanceof HTMLTextAreaElement) { |
| 208 | + input.value = 'https://github.com/SillyTavern/Extension-WebLLM'; |
| 209 | + } |
| 210 | + }, |
| 211 | + }); |
| 212 | + return false; |
| 213 | + } |
| 214 | + |
| 215 | + return true; |
| 216 | +} |
| 217 | + |
| 218 | +/** |
| 219 | + * Generates text in response to a chat prompt using WebLLM. |
| 220 | + * @param {any[]} messages Messages to use for generating |
| 221 | + * @returns {Promise<string>} Generated response |
| 222 | + */ |
| 223 | +export async function generateWebLlmChatPrompt(messages) { |
| 224 | + if (!isWebLlmSupported()) { |
| 225 | + throw new Error('WebLLM extension is not installed.'); |
| 226 | + } |
| 227 | + |
| 228 | + const engine = SillyTavern.llm; |
| 229 | + const response = await engine.generateChatPrompt(messages); |
| 230 | + return response; |
| 231 | +} |
| 232 | + |
| 233 | +/** |
| 234 | + * Counts the number of tokens in the provided text using WebLLM's default model. |
| 235 | + * @param {string} text Text to count tokens in |
| 236 | + * @returns {Promise<number>} Number of tokens in the text |
| 237 | + */ |
| 238 | +export async function countWebLlmTokens(text) { |
| 239 | + if (!isWebLlmSupported()) { |
| 240 | + throw new Error('WebLLM extension is not installed.'); |
| 241 | + } |
| 242 | + |
| 243 | + const engine = SillyTavern.llm; |
| 244 | + const response = await engine.countTokens(text); |
| 245 | + return response; |
| 246 | +} |
| 247 | + |
| 248 | +/** |
| 249 | + * Gets the size of the context in the WebLLM's default model. |
| 250 | + * @returns {Promise<number>} Size of the context in the WebLLM model |
| 251 | + */ |
| 252 | +export async function getWebLlmContextSize() { |
| 253 | + if (!isWebLlmSupported()) { |
| 254 | + throw new Error('WebLLM extension is not installed.'); |
| 255 | + } |
| 256 | + |
| 257 | + const engine = SillyTavern.llm; |
| 258 | + await engine.loadModel(); |
| 259 | + const model = await engine.getCurrentModelInfo(); |
| 260 | + return model?.context_size; |
| 261 | +} |