import { saveSettingsDebounced, getCurrentChatId, system_message_types } from "../../../script.js"; import { humanizedDateTime } from "../../RossAscends-mods.js"; import { getApiUrl, extension_settings } from "../../extensions.js"; import { getFileText, onlyUnique, splitRecursive } from "../../utils.js"; export { MODULE_NAME }; const MODULE_NAME = 'chromadb'; const defaultSettings = { keep_context: 10, keep_context_min: 1, keep_context_max: 100, keep_context_step: 1, n_results: 20, n_results_min: 1, n_results_max: 100, n_results_step: 1, split_length: 384, split_length_min: 64, split_length_max: 4096, split_length_step: 64, file_split_length: 1024, file_split_length_min: 512, file_split_length_max: 4096, file_split_length_step: 128, }; const postHeaders = { 'Content-Type': 'application/json', 'Bypass-Tunnel-Reminder': 'bypass', }; async function loadSettings() { if (Object.keys(extension_settings.chromadb).length === 0) { Object.assign(extension_settings.chromadb, defaultSettings); } $('#chromadb_keep_context').val(extension_settings.chromadb.keep_context).trigger('input'); $('#chromadb_n_results').val(extension_settings.chromadb.n_results).trigger('input'); $('#chromadb_split_length').val(extension_settings.chromadb.split_length).trigger('input'); $('#chromadb_file_split_length').val(extension_settings.chromadb.file_split_length).trigger('input'); } function onKeepContextInput() { extension_settings.chromadb.keep_context = Number($('#chromadb_keep_context').val()); $('#chromadb_keep_context_value').text(extension_settings.chromadb.keep_context); saveSettingsDebounced(); } function onNResultsInput() { extension_settings.chromadb.n_results = Number($('#chromadb_n_results').val()); $('#chromadb_n_results_value').text(extension_settings.chromadb.n_results); saveSettingsDebounced(); } function onSplitLengthInput() { extension_settings.chromadb.split_length = Number($('#chromadb_split_length').val()); $('#chromadb_split_length_value').text(extension_settings.chromadb.split_length); saveSettingsDebounced(); } function onFileSplitLengthInput() { extension_settings.chromadb.file_split_length = Number($('#chromadb_file_split_length').val()); $('#chromadb_file_split_length_value').text(extension_settings.chromadb.file_split_length); saveSettingsDebounced(); } async function addMessages(chat_id, messages) { const url = new URL(getApiUrl()); url.pathname = '/api/chromadb'; const messagesDeepCopy = JSON.parse(JSON.stringify(messages)); const splittedMessages = []; let id = 0; messagesDeepCopy.forEach(m => { const split = splitRecursive(m.mes, extension_settings.chromadb.split_length); splittedMessages.push(...split.map(text => ({ ...m, mes: text, send_date: id, id: `msg-${id++}`, }))); }); const transformedMessages = splittedMessages.map((m) => ({ id: m.id, role: m.is_user ? 'user' : 'assistant', content: m.mes, date: m.send_date, meta: JSON.stringify(m), })); const addMessagesResult = await fetch(url, { method: 'POST', headers: postHeaders, body: JSON.stringify({ chat_id, messages: transformedMessages }), }); if (addMessagesResult.ok) { const addMessagesData = await addMessagesResult.json(); return addMessagesData; // { count: 1 } } return { count: 0 }; } async function onPurgeClick() { const chat_id = getCurrentChatId(); const url = new URL(getApiUrl()); url.pathname = '/api/chromadb/purge'; const purgeResult = await fetch(url, { method: 'POST', headers: postHeaders, body: JSON.stringify({ chat_id }), }); if (purgeResult.ok) { toastr.success('ChromaDB context has been successfully cleared'); } } async function queryMessages(chat_id, query) { const url = new URL(getApiUrl()); url.pathname = '/api/chromadb/query'; const queryMessagesResult = await fetch(url, { method: 'POST', headers: postHeaders, body: JSON.stringify({ chat_id, query, n_results: extension_settings.chromadb.n_results }), }); if (queryMessagesResult.ok) { const queryMessagesData = await queryMessagesResult.json(); return queryMessagesData; } return []; } async function onSelectInjectFile(e) { const file = e.target.files[0]; if (!file) { return; } try { toastr.info('This may take some time, depending on the file size', 'Processing...'); const currentChatId = getCurrentChatId(); const text = await getFileText(file); const split = splitRecursive(text, extension_settings.chromadb.file_split_length).filter(onlyUnique); const messages = split.map(m => ({ id: `${file.name}-${split.indexOf(m)}`, role: 'system', content: m, date: Date.now(), meta: JSON.stringify({ name: file.name, is_user: false, is_name: false, is_system: false, send_date: humanizedDateTime(), mes: m, extra: { type: system_message_types.NARRATOR, } }), })); const url = new URL(getApiUrl()); url.pathname = '/api/chromadb'; const addMessagesResult = await fetch(url, { method: 'POST', headers: postHeaders, body: JSON.stringify({ chat_id: currentChatId, messages: messages }), }); if (addMessagesResult.ok) { const addMessagesData = await addMessagesResult.json(); toastr.success(`Number of chunks: ${addMessagesData.count}`, 'Injected successfully!'); return addMessagesData; } else { throw new Error(); } } catch (error) { console.log(error); toastr.error('Something went wrong while injecting the data'); } finally { e.target.form.reset(); } } window.chromadb_interceptGeneration = async (chat) => { const currentChatId = getCurrentChatId(); if (currentChatId) { const messagesToStore = chat.slice(0, -extension_settings.chromadb.keep_context); if (messagesToStore.length > 0) { await addMessages(currentChatId, messagesToStore); const lastMessage = chat[chat.length - 1]; if (lastMessage) { const queriedMessages = await queryMessages(currentChatId, lastMessage.mes); queriedMessages.sort((a, b) => a.date - b.date); const newChat = queriedMessages.map(m => JSON.parse(m.meta)); chat.splice(0, messagesToStore.length, ...newChat); console.log('ChromaDB chat after injection', chat); } } } } jQuery(async () => { const settingsHtml = `