Merge branch 'staging' into tool-calling

576352817edb7282a3ec31affe134ca90a3e5a82

Cohee <18619528+Cohee1207@users.noreply.github.com>

9 files changed, +70 -10Showing whitespace changes
public/index.html+19 -4
@@ -2954,16 +2954,31 @@
2954 </div>2954 </div>
2955 <h4 data-i18n="Groq Model">Groq Model</h4>2955 <h4 data-i18n="Groq Model">Groq Model</h4>
2956 <select id="model_groq_select">2956 <select id="model_groq_select">
2957 <option value="llama-3.1-405b-reasoning">llama-3.1-405b-reasoning</option>2957 <optgroup label="Llama 3.2">
2958 <option value="llama-3.1-70b-versatile">llama-3.1-70b-versatile</option>2958 <option value="llama-3.2-1b-preview">llama-3.2-1b-preview</option>
2959 <option value="llama-3.2-3b-preview">llama-3.2-3b-preview</option>
2960 <option value="llama-3.2-11b-vision-preview">llama-3.2-11b-vision-preview</option>
2961 <option value="llama-3.2-90b-vision-preview">llama-3.2-90b-vision-preview</option>
2962 </optgroup>
2963 <optgroup label="Llama 3.1">
2959 <option value="llama-3.1-8b-instant">llama-3.1-8b-instant</option>2964 <option value="llama-3.1-8b-instant">llama-3.1-8b-instant</option>
2960 <option value="llama3-groq-70b-8192-tool-use-preview">llama3-groq-70b-8192-tool-use-preview</option>2965 <option value="llama-3.1-70b-versatile">llama-3.1-70b-versatile</option>
2966 <option value="llama-3.1-405b-reasoning">llama-3.1-405b-reasoning</option>
2967 </optgroup>
2968 <optgroup label="Llama 3">
2961 <option value="llama3-groq-8b-8192-tool-use-preview">llama3-groq-8b-8192-tool-use-preview</option>2969 <option value="llama3-groq-8b-8192-tool-use-preview">llama3-groq-8b-8192-tool-use-preview</option>
2970 <option value="llama3-groq-70b-8192-tool-use-preview">llama3-groq-70b-8192-tool-use-preview</option>
2962 <option value="llama3-8b-8192">llama3-8b-8192</option>2971 <option value="llama3-8b-8192">llama3-8b-8192</option>
2963 <option value="llama3-70b-8192">llama3-70b-8192</option>2972 <option value="llama3-70b-8192">llama3-70b-8192</option>
2964 <option value="mixtral-8x7b-32768">mixtral-8x7b-32768</option>2973 </optgroup>
2974 <optgroup label="Gemma">
2965 <option value="gemma-7b-it">gemma-7b-it</option>2975 <option value="gemma-7b-it">gemma-7b-it</option>
2966 <option value="gemma2-9b-it">gemma2-9b-it</option>2976 <option value="gemma2-9b-it">gemma2-9b-it</option>
2977 </optgroup>
2978 <optgroup label="Other">
2979 <option value="mixtral-8x7b-32768">mixtral-8x7b-32768</option>
2980 <option value="llava-v1.5-7b-4096-preview">llava-v1.5-7b-4096-preview</option>
2981 </optgroup>
2967 </select>2982 </select>
2968 </div>2983 </div>
2969 <div id="perplexity_form" data-source="perplexity">2984 <div id="perplexity_form" data-source="perplexity">
public/scripts/extensions/attachments/index.js+21 -0
@@ -1,3 +1,4 @@
1import { event_types, eventSource, saveSettingsDebounced } from '../../../script.js';
1import { deleteAttachment, getDataBankAttachments, getDataBankAttachmentsForSource, getFileAttachment, uploadFileAttachmentToServer } from '../../chats.js';2import { deleteAttachment, getDataBankAttachments, getDataBankAttachmentsForSource, getFileAttachment, uploadFileAttachmentToServer } from '../../chats.js';
2import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';3import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';
3import { SlashCommand } from '../../slash-commands/SlashCommand.js';4import { SlashCommand } from '../../slash-commands/SlashCommand.js';
@@ -196,7 +197,27 @@ async function enableDataBankAttachment(args, value) {
196 return '';197 return '';
197}198}
198199
200function cleanUpAttachments() {
201 let shouldSaveSettings = false;
202 if (extension_settings.character_attachments) {
203 Object.values(extension_settings.character_attachments).flat().filter(a => a.text).forEach(a => {
204 shouldSaveSettings = true;
205 delete a.text;
206 });
207 }
208 if (Array.isArray(extension_settings.attachments)) {
209 extension_settings.attachments.filter(a => a.text).forEach(a => {
210 shouldSaveSettings = true;
211 delete a.text;
212 });
213 }
214 if (shouldSaveSettings) {
215 saveSettingsDebounced();
216 }
217}
218
199jQuery(async () => {219jQuery(async () => {
220 eventSource.on(event_types.APP_READY, cleanUpAttachments);
200 const manageButton = await renderExtensionTemplateAsync('attachments', 'manage-button', {});221 const manageButton = await renderExtensionTemplateAsync('attachments', 'manage-button', {});
201 const attachButton = await renderExtensionTemplateAsync('attachments', 'attach-button', {});222 const attachButton = await renderExtensionTemplateAsync('attachments', 'attach-button', {});
202 $('#data_bank_wand_container').append(manageButton);223 $('#data_bank_wand_container').append(manageButton);
public/scripts/extensions/caption/index.js+1 -0
@@ -403,6 +403,7 @@ jQuery(async function () {
403 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openai' && (secret_state[SECRET_KEYS.OPENAI] || extension_settings.caption.allow_reverse_proxy)) ||403 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openai' && (secret_state[SECRET_KEYS.OPENAI] || extension_settings.caption.allow_reverse_proxy)) ||
404 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openrouter' && secret_state[SECRET_KEYS.OPENROUTER]) ||404 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openrouter' && secret_state[SECRET_KEYS.OPENROUTER]) ||
405 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'zerooneai' && secret_state[SECRET_KEYS.ZEROONEAI]) ||405 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'zerooneai' && secret_state[SECRET_KEYS.ZEROONEAI]) ||
406 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'groq' && secret_state[SECRET_KEYS.GROQ]) ||
406 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'mistral' && (secret_state[SECRET_KEYS.MISTRALAI] || extension_settings.caption.allow_reverse_proxy)) ||407 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'mistral' && (secret_state[SECRET_KEYS.MISTRALAI] || extension_settings.caption.allow_reverse_proxy)) ||
407 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && (secret_state[SECRET_KEYS.MAKERSUITE] || extension_settings.caption.allow_reverse_proxy)) ||408 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && (secret_state[SECRET_KEYS.MAKERSUITE] || extension_settings.caption.allow_reverse_proxy)) ||
408 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'anthropic' && (secret_state[SECRET_KEYS.CLAUDE] || extension_settings.caption.allow_reverse_proxy)) ||409 (extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'anthropic' && (secret_state[SECRET_KEYS.CLAUDE] || extension_settings.caption.allow_reverse_proxy)) ||
public/scripts/extensions/caption/settings.html+4 -0
@@ -21,6 +21,7 @@
21 <option value="anthropic">Anthropic</option>21 <option value="anthropic">Anthropic</option>
22 <option value="custom" data-i18n="Custom (OpenAI-compatible)">Custom (OpenAI-compatible)</option>22 <option value="custom" data-i18n="Custom (OpenAI-compatible)">Custom (OpenAI-compatible)</option>
23 <option value="google">Google AI Studio</option>23 <option value="google">Google AI Studio</option>
24 <option value="groq">Groq</option>
24 <option value="koboldcpp">KoboldCpp</option>25 <option value="koboldcpp">KoboldCpp</option>
25 <option value="llamacpp">llama.cpp</option>26 <option value="llamacpp">llama.cpp</option>
26 <option value="mistral">MistralAI</option>27 <option value="mistral">MistralAI</option>
@@ -60,6 +61,9 @@
60 <option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option>61 <option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option>
61 <option data-type="google" value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option>62 <option data-type="google" value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option>
62 <option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>63 <option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>
64 <option data-type="groq" value="llama-3.2-11b-vision-preview">llama-3.2-11b-vision-preview</option>
65 <option data-type="groq" value="llama-3.2-90b-vision-preview">llama-3.2-90b-vision-preview</option>
66 <option data-type="groq" value="llava-v1.5-7b-4096-preview">llava-v1.5-7b-4096-preview</option>
63 <option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>67 <option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>
64 <option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option>68 <option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option>
65 <option data-type="openrouter" value="openai/gpt-4o-2024-05-13">openai/gpt-4o-2024-05-13</option>69 <option data-type="openrouter" value="openai/gpt-4o-2024-05-13">openai/gpt-4o-2024-05-13</option>
public/scripts/extensions/shared.js+5 -1
@@ -36,7 +36,7 @@ export async function getMultimodalCaption(base64Img, prompt) {
36 const isVllm = extension_settings.caption.multimodal_api === 'vllm';36 const isVllm = extension_settings.caption.multimodal_api === 'vllm';
37 const base64Bytes = base64Img.length * 0.75;37 const base64Bytes = base64Img.length * 0.75;
38 const compressionLimit = 2 * 1024 * 1024;38 const compressionLimit = 2 * 1024 * 1024;
39 if ((['google', 'openrouter', 'mistral'].includes(extension_settings.caption.multimodal_api) && base64Bytes > compressionLimit) || isOoba || isKoboldCpp) {39 if ((['google', 'openrouter', 'mistral', 'groq'].includes(extension_settings.caption.multimodal_api) && base64Bytes > compressionLimit) || isOoba || isKoboldCpp) {
40 const maxSide = 1024;40 const maxSide = 1024;
41 base64Img = await createThumbnail(base64Img, maxSide, maxSide, 'image/jpeg');41 base64Img = await createThumbnail(base64Img, maxSide, maxSide, 'image/jpeg');
42 }42 }
@@ -135,6 +135,10 @@ function throwIfInvalidModel(useReverseProxy) {
135 throw new Error('01.AI API key is not set.');135 throw new Error('01.AI API key is not set.');
136 }136 }
137137
138 if (extension_settings.caption.multimodal_api === 'groq' && !secret_state[SECRET_KEYS.GROQ]) {
139 throw new Error('Groq API key is not set.');
140 }
141
138 if (extension_settings.caption.multimodal_api === 'google' && !secret_state[SECRET_KEYS.MAKERSUITE] && !useReverseProxy) {142 if (extension_settings.caption.multimodal_api === 'google' && !secret_state[SECRET_KEYS.MAKERSUITE] && !useReverseProxy) {
139 throw new Error('Google AI Studio API key is not set.');143 throw new Error('Google AI Studio API key is not set.');
140 }144 }
public/scripts/extensions/vectors/index.js+2 -2
@@ -466,13 +466,13 @@ async function ingestDataBankAttachments(source) {
466 }466 }
467467
468 // Download and process the file468 // Download and process the file
469 file.text = await getFileAttachment(file.url);469 const fileText = await getFileAttachment(file.url);
470 console.log(`Vectors: Retrieved file ${file.name} from Data Bank`);470 console.log(`Vectors: Retrieved file ${file.name} from Data Bank`);
471 // Convert kilobytes to string length471 // Convert kilobytes to string length
472 const thresholdLength = settings.size_threshold_db * 1024;472 const thresholdLength = settings.size_threshold_db * 1024;
473 // Use chunk size from settings if file is larger than threshold473 // Use chunk size from settings if file is larger than threshold
474 const chunkSize = file.size > thresholdLength ? settings.chunk_size_db : -1;474 const chunkSize = file.size > thresholdLength ? settings.chunk_size_db : -1;
475 await vectorizeFile(file.text, file.name, collectionId, chunkSize, settings.overlap_percent_db);475 await vectorizeFile(fileText, file.name, collectionId, chunkSize, settings.overlap_percent_db);
476 }476 }
477477
478 return dataBankCollectionIds;478 return dataBankCollectionIds;
public/scripts/openai.js+4 -1
@@ -4118,7 +4118,10 @@ async function onModelChange() {
4118 if (oai_settings.max_context_unlocked) {4118 if (oai_settings.max_context_unlocked) {
4119 $('#openai_max_context').attr('max', unlocked_max);4119 $('#openai_max_context').attr('max', unlocked_max);
4120 }4120 }
4121 else if (oai_settings.groq_model.includes('llama-3.1')) {4121 else if (oai_settings.groq_model.includes('llama-3.2') && oai_settings.groq_model.includes('-preview')) {
4122 $('#openai_max_context').attr('max', max_8k);
4123 }
4124 else if (oai_settings.groq_model.includes('llama-3.2') || oai_settings.groq_model.includes('llama-3.1')) {
4122 $('#openai_max_context').attr('max', max_128k);4125 $('#openai_max_context').attr('max', max_128k);
4123 }4126 }
4124 else if (oai_settings.groq_model.includes('llama3-groq')) {4127 else if (oai_settings.groq_model.includes('llama3-groq')) {
src/endpoints/backends/chat-completions.js+6 -2
@@ -107,6 +107,7 @@ async function sendClaudeRequest(request, response) {
107 }107 }
108108
109 const requestBody = {109 const requestBody = {
110 /** @type {any} */ system: '',
110 messages: convertedPrompt.messages,111 messages: convertedPrompt.messages,
111 model: request.body.model,112 model: request.body.model,
112 max_tokens: request.body.max_tokens,113 max_tokens: request.body.max_tokens,
@@ -120,6 +121,8 @@ async function sendClaudeRequest(request, response) {
120 requestBody.system = enableSystemPromptCache121 requestBody.system = enableSystemPromptCache
121 ? [{ type: 'text', text: convertedPrompt.systemPrompt, cache_control: { type: 'ephemeral' } }]122 ? [{ type: 'text', text: convertedPrompt.systemPrompt, cache_control: { type: 'ephemeral' } }]
122 : convertedPrompt.systemPrompt;123 : convertedPrompt.systemPrompt;
124 } else {
125 delete requestBody.system;
123 }126 }
124 /*127 /*
125 if (Array.isArray(request.body.tools) && request.body.tools.length > 0) {128 if (Array.isArray(request.body.tools) && request.body.tools.length > 0) {
@@ -158,12 +161,13 @@ async function sendClaudeRequest(request, response) {
158 forwardFetchResponse(generateResponse, response);161 forwardFetchResponse(generateResponse, response);
159 } else {162 } else {
160 if (!generateResponse.ok) {163 if (!generateResponse.ok) {
161 console.log(color.red(`Claude API returned error: ${generateResponse.status} ${generateResponse.statusText}\n${await generateResponse.text()}\n${divider}`));164 const generateResponseText = await generateResponse.text();
165 console.log(color.red(`Claude API returned error: ${generateResponse.status} ${generateResponse.statusText}\n${generateResponseText}\n${divider}`));
162 return response.status(generateResponse.status).send({ error: true });166 return response.status(generateResponse.status).send({ error: true });
163 }167 }
164168
165 const generateResponseJson = await generateResponse.json();169 const generateResponseJson = await generateResponse.json();
166 const responseText = generateResponseJson.content[0].text;170 const responseText = generateResponseJson?.content?.[0]?.text || '';
167 console.log('Claude response:', generateResponseJson);171 console.log('Claude response:', generateResponseJson);
168172
169 // Wrap it back to OAI format + save the original content173 // Wrap it back to OAI format + save the original content
src/endpoints/openai.js+8 -0
@@ -55,6 +55,10 @@ router.post('/caption-image', jsonParser, async (request, response) => {
55 key = readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);55 key = readSecret(request.user.directories, SECRET_KEYS.MISTRALAI);
56 }56 }
5757
58 if (request.body.api === 'groq') {
59 key = readSecret(request.user.directories, SECRET_KEYS.GROQ);
60 }
61
58 if (!key && !request.body.reverse_proxy && ['custom', 'ooba', 'koboldcpp', 'vllm'].includes(request.body.api) === false) {62 if (!key && !request.body.reverse_proxy && ['custom', 'ooba', 'koboldcpp', 'vllm'].includes(request.body.api) === false) {
59 console.log('No key found for API', request.body.api);63 console.log('No key found for API', request.body.api);
60 return response.sendStatus(400);64 return response.sendStatus(400);
@@ -111,6 +115,10 @@ router.post('/caption-image', jsonParser, async (request, response) => {
111 apiUrl = 'https://api.01.ai/v1/chat/completions';115 apiUrl = 'https://api.01.ai/v1/chat/completions';
112 }116 }
113117
118 if (request.body.api === 'groq') {
119 apiUrl = 'https://api.groq.com/openai/v1/chat/completions';
120 }
121
114 if (request.body.api === 'mistral') {122 if (request.body.api === 'mistral') {
115 apiUrl = 'https://api.mistral.ai/v1/chat/completions';123 apiUrl = 'https://api.mistral.ai/v1/chat/completions';
116 }124 }