Merge pull request #1 from jcommaret/fix-pb

Fix pb
This commit is contained in:
Jérôme Commaret 2025-03-09 05:35:38 +01:00 committed by GitHub
commit 7b665d05cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 142 additions and 28 deletions

8
package-lock.json generated
View file

@ -15,7 +15,7 @@
"@google/generative-ai": "^0.22.0",
"@microsoft/1ds-core-js": "^3.2.13",
"@microsoft/1ds-post-js": "^3.2.13",
"@mistralai/mistralai": "^1.5.0",
"@mistralai/mistralai": "^1.5.1",
"@parcel/watcher": "2.5.1",
"@types/semver": "^7.5.8",
"@vscode/deviceid": "^0.1.1",
@ -2540,9 +2540,9 @@
"integrity": "sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ=="
},
"node_modules/@mistralai/mistralai": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.5.0.tgz",
"integrity": "sha512-AIn8pwAwA/fDvEUvmkt+40zH1ZmfaG3Q7oUWl17GUEC1tU7ZPwYz8Cv9P59lyS1SisHdDSu81oknO7f1ywkz8Q==",
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.5.1.tgz",
"integrity": "sha512-Ie0EH4dAO11MEXR5N2kS2cgr+ycTWvqN/yP9bKrtmUEqjdcF4i7DLxtrFMUw5l2dOPhrkX93G4SziFiATPWu2w==",
"dependencies": {
"zod-to-json-schema": "^3.24.1"
},

View file

@ -76,7 +76,7 @@
"@google/generative-ai": "^0.22.0",
"@microsoft/1ds-core-js": "^3.2.13",
"@microsoft/1ds-post-js": "^3.2.13",
"@mistralai/mistralai": "^1.5.0",
"@mistralai/mistralai": "^1.5.1",
"@parcel/watcher": "2.5.1",
"@types/semver": "^7.5.8",
"@vscode/deviceid": "^0.1.1",

View file

@ -51,13 +51,9 @@ export const defaultModelsOfProvider = {
'llama-3.1-8b-instant',
// 'qwen-2.5-coder-32b', // preview mode (experimental)
],
// not supporting mistral right now- it's last on Void usage, and a huge pain to set up since it's nonstandard (it supports codestral FIM but it's on v1/fim/completions, etc)
// mistral: [ // https://docs.mistral.ai/getting-started/models/models_overview/
// 'codestral-latest',
// 'mistral-large-latest',
// 'ministral-3b-latest',
// 'ministral-8b-latest',
// ],
mistral: [ // https://docs.mistral.ai/getting-started/models/models_overview/
'codestral-latest'
],
openAICompatible: [], // fallback
} as const satisfies Record<ProviderName, string[]>
@ -135,12 +131,6 @@ const openSourceModelOptions_assumingOAICompat = {
supportsTools: false,
supportsReasoning: false,
},
'codestral': {
supportsFIM: true,
supportsSystemMessage: 'system-role',
supportsTools: 'openai-style',
supportsReasoning: false,
},
// llama
'llama3': {
supportsFIM: false,
@ -179,6 +169,12 @@ const openSourceModelOptions_assumingOAICompat = {
supportsTools: 'openai-style',
supportsReasoning: { canToggleReasoning: false, canIOReasoning: true, openSourceThinkTags: ['<think>', '</think>'] },
},
'mistral-large-latest': {
supportsFIM: false,
supportsSystemMessage: 'system-role',
supportsTools: 'openai-style',
supportsReasoning: false,
},
// FIM only
'starcoder2': {
supportsFIM: true,
@ -186,6 +182,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,
@ -214,7 +217,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, })
if (modelName.includes('codestral')) return toFallback({ ...openSourceModelOptions_assumingOAICompat.codestral, contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('mistral-large-latest')) return toFallback({ ...openSourceModelOptions_assumingOAICompat['mistral-large-latest'], contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('codestral-latest')) return toFallback(mistralModelOptions['codestral-latest'])
if (/\bo1\b/.test(modelName) || /\bo3\b/.test(modelName)) return toFallback(openAIModelOptions['o1'])
return toFallback(modelOptionsDefaults)
}
@ -354,6 +358,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': {
@ -555,13 +586,20 @@ const openRouterModelOptions_assumingOpenAICompat = {
supportsReasoning: false,
},
'mistralai/codestral-2501': {
...openSourceModelOptions_assumingOAICompat.codestral,
...openSourceModelOptions_assumingOAICompat['codestral-latest'],
contextWindow: 256_000,
maxOutputTokens: null,
cost: { input: 0.3, output: 0.9 },
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,
@ -590,6 +628,12 @@ const openRouterSettings: ProviderSettings = {
}
const mistralSettings: ProviderSettings = {
...openSourceModelOptions_assumingOAICompat.mistral,
modelOptions: {},
modelOptionsFallback: (modelName) => extensiveModelFallback(modelName),
}
// ---------------- model settings of everything above ----------------
@ -599,7 +643,7 @@ const modelSettingsOfProvider: { [providerName in ProviderName]: ProviderSetting
anthropic: anthropicSettings,
xAI: xAISettings,
gemini: geminiSettings,
mistral: mistralSettings,
// open source models
deepseek: deepseekSettings,
groq: groqSettings,

View file

@ -43,6 +43,9 @@ export const defaultProviderSettings = {
xAI: {
apiKey: ''
},
mistral: {
apiKey: ''
},
} as const
@ -144,6 +147,11 @@ export const displayInfoOfProviderName = (providerName: ProviderName): DisplayIn
title: 'Grok (xAI)',
}
}
else if (providerName === 'mistral') {
return {
title: 'Mistral.ai API',
}
}
throw new Error(`descOfProviderName: Unknown provider name: "${providerName}"`)
@ -170,7 +178,8 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
providerName === 'groq' ? 'gsk_key...' :
providerName === 'openAICompatible' ? 'sk-key...' :
providerName === 'xAI' ? 'xai-key...' :
'',
providerName === 'mistral' ? 'key...' :
'',
subTextMd: providerName === 'anthropic' ? 'Get your [API Key here](https://console.anthropic.com/settings/keys).' :
providerName === 'openAI' ? 'Get your [API Key here](https://platform.openai.com/api-keys).' :
@ -179,8 +188,9 @@ export const displayInfoOfSettingName = (providerName: ProviderName, settingName
providerName === 'gemini' ? 'Get your [API Key here](https://aistudio.google.com/apikey).' :
providerName === 'groq' ? 'Get your [API Key here](https://console.groq.com/keys).' :
providerName === 'xAI' ? 'Get your [API Key here](https://console.x.ai).' :
providerName === 'openAICompatible' ? undefined :
'',
providerName === 'mistral' ? 'Get your [API Key here](https://console.mistral.ai/api-keys).' :
providerName === 'openAICompatible' ? undefined :
'',
isPasswordField: true,
}
}
@ -300,6 +310,12 @@ export const defaultSettingsOfProvider: SettingsOfProvider = {
...modelInfoOfDefaultModelNames(defaultModelsOfProvider.vLLM),
_didFillInProviderSettings: undefined,
},
mistral: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.mistral,
...modelInfoOfDefaultModelNames(defaultModelsOfProvider.mistral),
_didFillInProviderSettings: undefined,
},
}

View file

@ -7,6 +7,11 @@ import Anthropic from '@anthropic-ai/sdk';
import { Ollama } from 'ollama';
import OpenAI, { ClientOptions } from 'openai';
/* Mistral standalone Fim endpoint */
import { MistralCore } from "@mistralai/mistralai/core.js";
import { fimComplete } from "@mistralai/mistralai/funcs/fimComplete.js";
/* End Mistral standalone Fim endpoint */
import { Model as OpenAIModel } from 'openai/resources/models.js';
import { extractReasoningOnFinalMessage, extractReasoningOnTextWrapper } from '../../browser/helpers/extractCodeFromResult.js';
import { LLMChatMessage, LLMFIMMessage, ModelListParams, OllamaModelResponse, OnError, OnFinalMessage, OnText } from '../../common/sendLLMMessageTypes.js';
@ -112,6 +117,10 @@ const newOpenAICompatibleSDK = ({ settingsOfProvider, providerName, includeInPay
const thisConfig = settingsOfProvider[providerName]
return new OpenAI({ baseURL: 'https://api.x.ai/v1', apiKey: thisConfig.apiKey, ...commonPayloadOpts })
}
else if (providerName === 'mistral') {
const thisConfig = settingsOfProvider[providerName]
return new OpenAI({ baseURL: 'https://api.mistral.ai/v1', apiKey: thisConfig.apiKey, ...commonPayloadOpts })
}
else throw new Error(`Void providerName was invalid: ${providerName}.`)
}
@ -139,6 +148,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 });
})
@ -149,7 +159,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, tools: tools_ }: SendChatParams_Internal) => {
const {
@ -530,6 +582,11 @@ export const sendLLMMessageToProviderImplementation = {
sendFIM: null,
list: null,
},
mistral: {
sendChat: (params) => _sendOpenAICompatibleChat(params),
sendFIM: (params) => _sendMistralFIM(params),
list: null
},
} satisfies CallFnOfProvider
@ -542,10 +599,7 @@ 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
<fimbegin>{{ .Prompt }}<fimhole>{{ .Suffix }}<fimend>
{{ .Prompt }}
starcoder2 https://ollama.com/library/starcoder2/blobs/3b190e68fefe
<file_sep>