diff --git a/src/vs/workbench/contrib/void/common/modelCapabilities.ts b/src/vs/workbench/contrib/void/common/modelCapabilities.ts index 7bffa921..fe8e8b5d 100644 --- a/src/vs/workbench/contrib/void/common/modelCapabilities.ts +++ b/src/vs/workbench/contrib/void/common/modelCapabilities.ts @@ -209,6 +209,12 @@ const openSourceModelOptions_assumingOAICompat = { supportsTools: 'openai-style', supportsReasoning: { canToggleReasoning: false, canIOReasoning: true, openSourceThinkTags: ['', ''] }, }, + 'mistral-large-latest': { + supportsFIM: false, + supportsSystemMessage: 'system-role', + supportsTools: 'openai-style', + supportsReasoning: false, + }, // FIM only 'starcoder2': { supportsFIM: true, @@ -216,6 +222,13 @@ const openSourceModelOptions_assumingOAICompat = { supportsTools: false, supportsReasoning: false, }, + // Mistral + 'codestral-latest': { + supportsFIM: true, + supportsSystemMessage: 'system-role', + supportsTools: 'openai-style', + supportsReasoning: false, + }, 'codegemma:2b': { supportsFIM: true, supportsSystemMessage: false, @@ -242,11 +255,8 @@ const extensiveModelFallback: ProviderSettings['modelOptionsFallback'] = (modelN if (modelName.includes('deepseek')) return toFallback({ ...openSourceModelOptions_assumingOAICompat.deepseekCoderV2, contextWindow: 32_000, maxOutputTokens: 4_096, }) if (modelName.includes('llama3')) return toFallback({ ...openSourceModelOptions_assumingOAICompat.llama3, contextWindow: 32_000, maxOutputTokens: 4_096, }) if (modelName.includes('qwen') && modelName.includes('2.5') && modelName.includes('coder')) return toFallback({ ...openSourceModelOptions_assumingOAICompat['qwen2.5coder'], contextWindow: 32_000, maxOutputTokens: 4_096, }) - - /* Mistral Options fallback for Mistral and others providers keeping the code relatively clean for all models */ if (modelName.includes('mistral')) return toFallback({ ...openSourceModelOptions_assumingOAICompat['mistral-large-latest'] }) if (modelName.includes('codestral')) return toFallback({ ...openSourceModelOptions_assumingOAICompat['codestral-latest'] }) - if (/\bo1\b/.test(modelName) || /\bo3\b/.test(modelName)) return toFallback(openAIModelOptions['o1']) return toFallback(modelOptionsDefaults) } @@ -381,6 +391,33 @@ const openAISettings: ProviderSettings = { } } +const mistralModelOptions = { + 'codestral-latest': { + contextWindow: 32_000, + maxOutputTokens: 4_096, + cost: { input: 0.00, output: 0.00 }, + supportsFIM: true, + supportsSystemMessage: 'system-role', + supportsTools: 'openai-style', + supportsReasoning: false, + }, + 'mistral-large-latest': { + contextWindow: 32_000, + maxOutputTokens: 4_096, + cost: { input: 0.00, output: 0.00 }, + supportsFIM: false, + supportsSystemMessage: 'system-role', + supportsTools: 'openai-style', + supportsReasoning: false, + } +} as const satisfies { [s: string]: ModelOptions } + + + + + + + // ---------------- XAI ---------------- const xAIModelOptions = { 'grok-2': { @@ -589,6 +626,13 @@ const openRouterModelOptions_assumingOpenAICompat = { supportsTools: 'openai-style', supportsReasoning: false, }, + 'mistralai/mistral-large-latest': { + ...openSourceModelOptions_assumingOAICompat['mistral-large-latest'], + contextWindow: 256_000, + maxOutputTokens: null, + cost: { input: 0.3, output: 0.9 }, + }, + 'qwen/qwen-2.5-coder-32b-instruct': { ...openSourceModelOptions_assumingOAICompat['qwen2.5coder'], contextWindow: 33_000, @@ -616,6 +660,7 @@ const openRouterSettings: ProviderSettings = { modelOptionsFallback: (modelName) => extensiveModelFallback(modelName), } + // ---------------- model settings of everything above ---------------- const modelSettingsOfProvider: { [providerName in ProviderName]: ProviderSettings } = { @@ -623,7 +668,7 @@ const modelSettingsOfProvider: { [providerName in ProviderName]: ProviderSetting anthropic: anthropicSettings, xAI: xAISettings, gemini: geminiSettings, - + mistral: mistralSettings, // open source models deepseek: deepseekSettings, groq: groqSettings, diff --git a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts index 79d2204b..0f3e50e6 100644 --- a/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts +++ b/src/vs/workbench/contrib/void/common/voidSettingsTypes.ts @@ -316,6 +316,12 @@ export const defaultSettingsOfProvider: SettingsOfProvider = { ...modelInfoOfDefaultModelNames(defaultModelsOfProvider.vLLM), _didFillInProviderSettings: undefined, }, + mistral: { // aggregator + ...defaultCustomSettings, + ...defaultProviderSettings.mistral, + ...modelInfoOfDefaultModelNames(defaultModelsOfProvider.mistral), + _didFillInProviderSettings: undefined, + }, } diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 8694795a..24afe0c5 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -143,6 +143,7 @@ const _sendOpenAICompatibleFIM = ({ messages: messages_, onFinalMessage, onError max_tokens: messages.maxTokens, }) .then(async response => { + const fullText = response.choices[0]?.text onFinalMessage({ fullText, fullReasoning: '', anthropicReasoning: null }); }) @@ -153,7 +154,49 @@ const _sendOpenAICompatibleFIM = ({ messages: messages_, onFinalMessage, onError } +const _sendMistralFIM = ({ messages: messages_, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions }: SendFIMParams_Internal) => { + const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_) + if (!supportsFIM) { + if (modelName === modelName_) + onError({ message: `Model ${modelName} does not support FIM.`, fullError: null }) + else + onError({ message: `Model ${modelName_} (${modelName}) does not support FIM.`, fullError: null }) + return + } + const messages = prepareFIMMessage({ messages: messages_, aiInstructions }) + const mistral = new MistralCore({ apiKey: settingsOfProvider.mistral.apiKey }) + + // DEBUG : request params + // console.log('🔍 Sending FIM request with params:', { + // model: modelName, + // promptLength: messages.prefix.length, + // suffixLength: messages.suffix.length, + // stream: false, + // maxTokens: messages.maxTokens + //}); + + fimComplete( + mistral, { + model: modelName, + prompt: messages.prefix, + suffix: messages.suffix, + stream: false, + topP: 1, + maxTokens: messages.maxTokens, + stop: messages.stopTokens + }, + ) + .then(async response => { + const fullText = response.choices[0]?.text || ''; + onFinalMessage({ fullText, }); + // console.log('✅ Réponse FIM reçue:', fullText); + + }) + .catch(error => { + onError({ message: error + '', fullError: error }); + }) +} const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, modelSelectionOptions, tools: tools_ }: SendChatParams_Internal) => { const { @@ -575,30 +618,4 @@ export const sendLLMMessageToProviderImplementation = { sendFIM: (params) => sendMistralFIM(params), list: null, }, -} satisfies CallFnOfProvider - - - - -/* -FIM info (this may be useful in the future with vLLM, but in most cases the only way to use FIM is if the provider explicitly supports it): - -qwen2.5-coder https://ollama.com/library/qwen2.5-coder/blobs/e94a8ecb9327 -<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|> - -codestral https://ollama.com/library/codestral/blobs/51707752a87c -[SUFFIX]{{ .Suffix }}[PREFIX] {{ .Prompt }} - -deepseek-coder-v2 https://ollama.com/library/deepseek-coder-v2/blobs/22091531faf0 -{{ .Prompt }} - -starcoder2 https://ollama.com/library/starcoder2/blobs/3b190e68fefe - - -{{ .Prompt }}{{ .Suffix }} -<|end_of_text|> - -codegemma https://ollama.com/library/codegemma:2b/blobs/48d9a8140749 -<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|> - -*/ +} satisfies CallFnOfProvider \ No newline at end of file