Merge pull request #3 from jcommaret/feat_mistral-199

Feat mistral 199
This commit is contained in:
Jérôme Commaret 2025-03-14 23:23:15 +01:00 committed by GitHub
commit 00e57dd1bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 99 additions and 60 deletions

View file

@ -52,7 +52,12 @@ export const defaultModelsOfProvider = {
// 'qwen-2.5-coder-32b', // preview mode (experimental)
],
mistral: [ // https://docs.mistral.ai/getting-started/models/models_overview/
'codestral-latest'
'codestral-latest',
'open-codestral-mamba',
'mistral-small-latest',
'mistral-large-latest',
'ministral-3b-latest',
'ministral-8b-latest',
],
openAICompatible: [], // fallback
} as const satisfies Record<ProviderName, string[]>
@ -117,6 +122,41 @@ const modelOptionsDefaults: ModelOptions = {
supportsReasoning: false,
}
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,
},
'open-codestral-mamba': {
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 }
const mistralSettings: ProviderSettings = {
...mistralModelOptions,
modelOptions: {},
modelOptionsFallback: (modelName) => extensiveModelFallback(modelName),
}
const openSourceModelOptions_assumingOAICompat = {
'deepseekR1': {
@ -195,11 +235,9 @@ const openSourceModelOptions_assumingOAICompat = {
supportsTools: false,
supportsReasoning: false,
},
...mistralModelOptions,
} as const satisfies { [s: string]: Partial<ModelOptions> }
const extensiveModelFallback: ProviderSettings['modelOptionsFallback'] = (modelName) => {
const toFallback = (opts: Omit<ModelOptions, 'cost'>): ModelOptions & { modelName: string } => {
return {
@ -217,17 +255,12 @@ 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('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 (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)
}
// ---------------- ANTHROPIC ----------------
const anthropicModelOptions = {
'claude-3-7-sonnet-20250219': { // https://docs.anthropic.com/en/docs/about-claude/models/all-models#model-comparison-table
@ -628,14 +661,6 @@ const openRouterSettings: ProviderSettings = {
}
const mistralSettings: ProviderSettings = {
...openSourceModelOptions_assumingOAICompat.mistral,
modelOptions: {},
modelOptionsFallback: (modelName) => extensiveModelFallback(modelName),
}
// ---------------- model settings of everything above ----------------
const modelSettingsOfProvider: { [providerName in ProviderName]: ProviderSettings } = {
@ -653,7 +678,7 @@ const modelSettingsOfProvider: { [providerName in ProviderName]: ProviderSetting
vLLM: vLLMSettings,
ollama: ollamaSettings,
openAICompatible: openaiCompatible,
mistral: mistralSettings,
// googleVertex: {},
// microsoftAzure: {},
} as const

View file

@ -298,6 +298,12 @@ export const defaultSettingsOfProvider: SettingsOfProvider = {
...modelInfoOfDefaultModelNames(defaultModelsOfProvider.openAICompatible),
_didFillInProviderSettings: undefined,
},
mistral: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.mistral,
...modelInfoOfDefaultModelNames(defaultModelsOfProvider.mistral),
_didFillInProviderSettings: undefined,
},
ollama: { // aggregator
...defaultCustomSettings,
...defaultProviderSettings.ollama,

View file

@ -6,13 +6,8 @@
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 '../../common/helpers/extractCodeFromResult.js';
import { LLMChatMessage, LLMFIMMessage, ModelListParams, OllamaModelResponse, OnError, OnFinalMessage, OnText } from '../../common/sendLLMMessageTypes.js';
import { defaultProviderSettings, displayInfoOfProviderName, ModelSelectionOptions, ProviderName, SettingsOfProvider } from '../../common/voidSettingsTypes.js';
@ -126,7 +121,7 @@ const newOpenAICompatibleSDK = ({ settingsOfProvider, providerName, includeInPay
}
const _sendOpenAICompatibleFIM = ({ messages: messages_, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, }: SendFIMParams_Internal) => {
const _sendOpenAICompatibleFIM = ({ messages: messages_, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, modelSelectionOptions, }: SendFIMParams_Internal) => {
const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_)
if (!supportsFIM) {
if (modelName === modelName_)
@ -203,7 +198,7 @@ const _sendMistralFIM = ({ messages: messages_, onFinalMessage, onError, setting
})
}
const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, tools: tools_ }: SendChatParams_Internal) => {
const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, modelSelectionOptions, tools: tools_ }: SendChatParams_Internal) => {
const {
modelName,
supportsReasoning,
@ -516,6 +511,47 @@ const sendOllamaFIM = ({ messages: messages_, onFinalMessage, onError, settingsO
})
}
//////// MISTRAL ////////
const sendMistralChat = ({ messages: messages_, onText, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, modelSelectionOptions }: SendChatParams_Internal) => {
_sendOpenAICompatibleChat({
messages: messages_,
onText,
onFinalMessage,
onError,
settingsOfProvider,
modelName: modelName_,
_setAborter,
providerName,
aiInstructions,
modelSelectionOptions
});
}
const sendMistralFIM = ({ messages: messages_, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, modelSelectionOptions }: 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
}
prepareFIMMessage({ messages: messages_, aiInstructions })
_sendOpenAICompatibleFIM({
messages: messages_,
onFinalMessage,
onError,
settingsOfProvider,
modelName: modelName_,
_setAborter,
providerName,
aiInstructions,
modelSelectionOptions,
onText: () => { }
});
}
type CallFnOfProvider = {
@ -547,11 +583,6 @@ export const sendLLMMessageToProviderImplementation = {
sendFIM: null,
list: null,
},
// mistral: {
// sendChat: , // TODO
// sendFIM: , // TODO // https://docs.mistral.ai/api/#tag/fim
// list: null,
// },
ollama: {
sendChat: (params) => _sendOpenAICompatibleChat(params),
sendFIM: sendOllamaFIM,
@ -583,31 +614,8 @@ export const sendLLMMessageToProviderImplementation = {
list: null,
},
mistral: {
sendChat: (params) => _sendOpenAICompatibleChat(params),
sendFIM: (params) => _sendMistralFIM(params),
list: null
sendChat: (params) => sendMistralChat(params),
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
{{ .Prompt }}
starcoder2 https://ollama.com/library/starcoder2/blobs/3b190e68fefe
<file_sep>
<fim_prefix>
{{ .Prompt }}<fim_suffix>{{ .Suffix }}<fim_middle>
<|end_of_text|>
codegemma https://ollama.com/library/codegemma:2b/blobs/48d9a8140749
<|fim_prefix|>{{ .Prompt }}<|fim_suffix|>{{ .Suffix }}<|fim_middle|>
*/
} satisfies CallFnOfProvider