improvements

This commit is contained in:
Andrew Pareles 2025-02-24 06:23:24 -08:00
parent 5c047b78f3
commit 4a43b628d4
6 changed files with 77 additions and 53 deletions

View file

@ -5,7 +5,7 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { InputBox } from '../../../../../../../base/browser/ui/inputbox/inputBox.js'
import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidModelInfo, globalSettingNames, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, defaultProviderSettings, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled } from '../../../../common/voidSettingsTypes.js'
import { ProviderName, SettingName, displayInfoOfSettingName, providerNames, VoidModelInfo, globalSettingNames, customSettingNamesOfProvider, RefreshableProviderName, refreshableProviderNames, displayInfoOfProviderName, defaultProviderSettings, nonlocalProviderNames, localProviderNames, GlobalSettingName, featureNames, displayInfoOfFeatureName, isProviderNameDisabled, FeatureName } from '../../../../common/voidSettingsTypes.js'
import ErrorBoundary from '../sidebar-tsx/ErrorBoundary.js'
import { VoidButton, VoidCheckBox, VoidCustomDropdownBox, VoidInputBox, VoidInputBox2, VoidSwitch } from '../util/inputs.js'
import { useAccessor, useIsDark, useRefreshModelListener, useRefreshModelState, useSettingsState } from '../util/services.js'
@ -368,15 +368,15 @@ export const AutoRefreshToggle = () => {
// right now this is just `enabled_autoRefreshModels`
const enabled = voidSettingsState.globalSettings[settingName]
return <SubtleButton
onClick={() => {
voidSettingsService.setGlobalSetting(settingName, !enabled)
metricsService.capture('Click', { action: 'Autorefresh Toggle', settingName, enabled: !enabled })
}}
text={`Automatically detect local providers and models (${refreshableProviderNames.map(providerName => displayInfoOfProviderName(providerName).title).join(', ')}).`}
icon={enabled ? <Check className='stroke-green-500 size-3' /> : <X className='stroke-red-500 size-3' />}
disabled={false}
/>
return <SubtleButton
onClick={() => {
voidSettingsService.setGlobalSetting(settingName, !enabled)
metricsService.capture('Click', { action: 'Autorefresh Toggle', settingName, enabled: !enabled })
}}
text={`Automatically detect local providers and models (${refreshableProviderNames.map(providerName => displayInfoOfProviderName(providerName).title).join(', ')}).`}
icon={enabled ? <Check className='stroke-green-500 size-3' /> : <X className='stroke-red-500 size-3' />}
disabled={false}
/>
}
@ -401,7 +401,7 @@ export const FeaturesTab = () => {
<ErrorBoundary>
<AutoRefreshToggle />
<RefreshableModels />
<div className='py-2'/>
<div className='py-2' />
<ModelDump />
<AddModelMenuFull />
</ErrorBoundary>
@ -437,12 +437,13 @@ export const FeaturesTab = () => {
<h2 className={`text-3xl mb-2 mt-12`}>Feature Options</h2>
<ErrorBoundary>
{featureNames.map(featureName =>
<div key={featureName}
className='mb-2'
>
<h4 className={`text-void-fg-3`}>{displayInfoOfFeatureName(featureName)}</h4>
<ModelDropdown featureName={featureName} />
</div>
(['Ctrl+L', 'Ctrl+K'] as FeatureName[]).includes(featureName) ? null :
<div key={featureName}
className='mb-2'
>
<h4 className={`text-void-fg-3`}>{displayInfoOfFeatureName(featureName)}</h4>
<ModelDropdown featureName={featureName} />
</div>
)}
</ErrorBoundary>

View file

@ -55,7 +55,7 @@ export const voidTools = {
query: { type: 'string', description: undefined },
...paginationHelper.param,
},
required: ['query']
required: ['query'],
},
search: {
@ -305,6 +305,8 @@ export class ToolsService implements IToolsService {
return { queryStr, uris, hasNextPage }
},
search: async (s: string) => {
console.log('search')
const o = validateJSON(s)

View file

@ -63,7 +63,30 @@ export interface IVoidSettingsService {
const _updatedValidatedState = (state: Omit<VoidSettingsState, '_modelOptions'>) => {
const _updatedModelsAfterDefaultModelsChange = (defaultModelNames: string[], options: { existingModels: VoidModelInfo[] }) => {
const { existingModels } = options
const existingModelsMap: Record<string, VoidModelInfo> = {}
for (const existingModel of existingModels) {
existingModelsMap[existingModel.modelName] = existingModel
}
const newDefaultModels = defaultModelNames.map((modelName, i) => ({
modelName,
isDefault: true,
isAutodetected: true,
isHidden: !!existingModelsMap[modelName]?.isHidden,
}))
return [
...newDefaultModels, // swap out all the default models for the new default models
...existingModels.filter(m => !m.isDefault), // keep any non-default (custom) models
]
}
const _validatedState = (state: Omit<VoidSettingsState, '_modelOptions'>) => {
let newSettingsOfProvider = state.settingsOfProvider
@ -201,7 +224,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
modelSelectionOfFeature: newModelSelectionOfFeature,
}
this.state = _updatedValidatedState(readS)
this.state = _validatedState(readS)
resolver()
this._onDidChangeState.fire()
@ -248,7 +271,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
globalSettings: newGlobalSettings,
}
this.state = _updatedValidatedState(newState)
this.state = _validatedState(newState)
await this._storeState()
this._onDidChangeState.fire()
@ -290,27 +313,6 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
}
private _updatedModelsAfterAutodetection = (defaultModelNames: string[], options: { existingModels: VoidModelInfo[] }) => {
const { existingModels } = options
const existingModelsMap: Record<string, VoidModelInfo> = {}
for (const existingModel of existingModels) {
existingModelsMap[existingModel.modelName] = existingModel
}
const newDefaultModels = defaultModelNames.map((modelName, i) => ({
modelName,
isDefault: true,
isAutodetected: true,
isHidden: !!existingModelsMap[modelName]?.isHidden,
}))
return [
...newDefaultModels, // swap out all the default models for the new default models
...existingModels.filter(m => !m.isDefault), // keep any non-default (custom) models
]
}
setAutodetectedModels(providerName: ProviderName, autodetectedModelNames: string[], logging: object) {
@ -318,7 +320,7 @@ class VoidSettingsService extends Disposable implements IVoidSettingsService {
const { models } = this.state.settingsOfProvider[providerName]
const oldModelNames = models.map(m => m.modelName)
const newModels = this._updatedModelsAfterAutodetection(autodetectedModelNames, { existingModels: models })
const newModels = _updatedModelsAfterDefaultModelsChange(autodetectedModelNames, { existingModels: models })
this.setSettingOfProvider(providerName, 'models', newModels)
// if the models changed, log it

View file

@ -83,7 +83,7 @@ export const defaultModelsOfProvider = {
'anthropic/claude-3.5-sonnet',
'deepseek/deepseek-r1',
'mistralai/codestral-2501',
'qwen/qwen2.5-vl-72b-instruct:free',
'qwen/qwen-2.5-coder-32b-instruct',
],
groq: [ // https://console.groq.com/docs/models
'llama-3.3-70b-versatile',

View file

@ -429,7 +429,7 @@ const extensiveModelFallback: ProviderSettings['modelOptionsFallback'] = (modelN
if (modelName.includes('deepseek-r1') || modelName.includes('deepseek-reasoner')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat.deepseekR1, contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('deepseek')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat.deepseekCoderV2, contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('llama3')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat.llama3, contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('qwen2.5-coder')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat['qwen2.5coder'], contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('qwen') && modelName.includes('2.5') && modelName.includes('coder')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat['qwen2.5coder'], contextWindow: 32_000, maxOutputTokens: 4_096, })
if (modelName.includes('codestral')) return toFallback({ ...openSourceModelDefaultOptionsAssumingOAICompat.codestral, contextWindow: 32_000, maxOutputTokens: 4_096, })
if (/\bo1\b/.test(modelName) || /\bo3\b/.test(modelName)) return toFallback(openAIModelOptions['o1'])
return toFallback(modelOptionDefaults)
@ -482,6 +482,15 @@ const openRouterModelOptions = {
supportsTools: 'openai-style',
supportsReasoningOutput: false,
},
'qwen/qwen-2.5-coder-32b-instruct': {
...openSourceModelDefaultOptionsAssumingOAICompat['qwen2.5coder'],
contextWindow: 33_000,
maxOutputTokens: null,
supportsTools: false, // openrouter qwen doesn't seem to support tools...?
cost: { input: 0.07, output: 0.16 },
}
} as const satisfies { [s: string]: ModelOptions }
const openRouterSettings: ProviderSettings = {
@ -520,7 +529,7 @@ const modelSettingsOfProvider: ModelSettingsOfProvider = {
export const modelOptionsOfProvider = (providerName: ProviderName, modelName: string): ModelOptions & { modelName: string } => {
export const getModelCapabilities = (providerName: ProviderName, modelName: string): ModelOptions & { modelName: string } => {
const { modelOptions, modelOptionsFallback } = modelSettingsOfProvider[providerName]
if (modelName in modelOptions) return { modelName, ...modelOptions[modelName] }
const result = modelOptionsFallback(modelName)
@ -629,7 +638,15 @@ const newOpenAICompatibleSDK = ({ settingsOfProvider, providerName, includeInPay
const _sendOpenAICompatibleFIM = ({ messages: messages_, onFinalMessage, onError, settingsOfProvider, modelName: modelName_, _setAborter, providerName, aiInstructions, }: SendFIMParams_Internal) => {
const { modelName } = modelOptionsOfProvider(providerName, modelName_)
const { modelName, supportsFIM } = getModelCapabilities(providerName, modelName_)
if (!supportsFIM) {
if (modelName === modelName_)
onFinalMessage({ fullText: `Model ${modelName} does not support FIM.` })
else
onFinalMessage({ fullText: `Model ${modelName_} (${modelName}) does not support FIM.` })
return
}
const messages = prepareFIMMessage({ messages: messages_, aiInstructions, })
const openai = newOpenAICompatibleSDK({ providerName, settingsOfProvider })
@ -661,7 +678,7 @@ const _sendOpenAICompatibleChat = ({ messages: messages_, onText, onFinalMessage
supportsSystemMessage,
supportsTools,
maxOutputTokens,
} = modelOptionsOfProvider(providerName, modelName_)
} = getModelCapabilities(providerName, modelName_)
const { messages } = prepareMessages({ messages: messages_, aiInstructions, supportsSystemMessage, supportsTools, })
const tools = (supportsTools && ((tools_?.length ?? 0) !== 0)) ? tools_?.map(tool => toOpenAICompatibleTool(tool)) : undefined
@ -777,7 +794,7 @@ const sendAnthropicChat = ({ messages: messages_, onText, providerName, onFinalM
supportsSystemMessage,
supportsTools,
maxOutputTokens,
} = modelOptionsOfProvider(providerName, modelName_)
} = getModelCapabilities(providerName, modelName_)
const { messages, separateSystemMessageStr } = prepareMessages({ messages: messages_, aiInstructions, supportsSystemMessage, supportsTools, })

View file

@ -335,14 +335,16 @@ export const prepareFIMMessage = ({
}) => {
let prefix = `\
## You are a helpful coding assistant that performs autocomplete.
${!aiInstructions ? '' : `\
## Instructions:
${aiInstructions.split('\n').map(line => `##${line}`).join('\n')}`}
// Instructions:
// Do not output an explanation. Try to avoid outputting comments. Only output the middle code.
${aiInstructions.split('\n').map(line => `//${line}`).join('\n')}`}
${messages.prefix}`
const suffix = messages.suffix
const stopTokens = messages.stopTokens
return { prefix, suffix, stopTokens, maxTokens: 300 } as const
const ret = { prefix, suffix, stopTokens, maxTokens: 300 } as const
console.log('ret', ret)
return ret
}