mirror of
https://github.com/EthanMarti/infio-copilot.git
synced 2026-01-16 08:21:55 +00:00
添加本地提供者支持,包括本地嵌入模型的描述、特性和设置,更新相关类型和API函数以支持新模型。
This commit is contained in:
parent
8b3babc28e
commit
bed96a5233
@ -257,6 +257,11 @@ export default {
|
||||
searchOrEnterModelName: 'Search or enter model name...',
|
||||
enterCustomModelName: 'Enter custom model name',
|
||||
custom: 'Custom: ',
|
||||
localProviderDescription: 'Local embedding models run on your device using WASM technology, providing privacy and offline capability.',
|
||||
localProviderFeature0: 'Currently only supports embedding models',
|
||||
localProviderFeature1: 'Complete privacy - data never leaves your device',
|
||||
localProviderFeature2: 'No API costs - runs entirely locally',
|
||||
localProviderFeature3: 'Offline capability - works without internet connection',
|
||||
testConnection: {
|
||||
testApiConnection: 'Test API Connection',
|
||||
testingConnection: 'Testing connection...',
|
||||
|
||||
@ -259,6 +259,11 @@ export default {
|
||||
searchOrEnterModelName: '搜索或输入模型名称...',
|
||||
enterCustomModelName: '输入自定义模型名称',
|
||||
custom: '自定义: ',
|
||||
localProviderDescription: '本地嵌入模型使用 WASM 技术在您的设备上运行,提供隐私保护和离线功能。',
|
||||
localProviderFeature0: '目前仅支持嵌入模型',
|
||||
localProviderFeature1: '完全隐私 - 数据不会离开您的设备',
|
||||
localProviderFeature2: '无 API 费用 - 完全本地运行',
|
||||
localProviderFeature3: '离线功能 - 无需网络连接即可工作',
|
||||
testConnection: {
|
||||
testApiConnection: '测试 API 连接',
|
||||
testingConnection: '正在测试连接...',
|
||||
|
||||
@ -4,7 +4,10 @@ import { t } from '../../lang/helpers';
|
||||
import InfioPlugin from "../../main";
|
||||
import { ApiProvider } from '../../types/llm/model';
|
||||
import { InfioSettings } from '../../types/settings';
|
||||
import { GetAllProviders, GetDefaultModelId, GetEmbeddingProviders } from '../../utils/api';
|
||||
import {
|
||||
GetAllProviders, GetDefaultModelId, GetEmbeddingProviders,
|
||||
localProviderDefaultEmbeddingModelId
|
||||
} from '../../utils/api';
|
||||
import { getProviderApiUrl } from '../../utils/provider-urls';
|
||||
|
||||
import { ApiKeyComponent, CustomUrlComponent } from './FormComponents';
|
||||
@ -27,7 +30,8 @@ type ProviderSettingKey =
|
||||
| 'groqProvider'
|
||||
| 'grokProvider'
|
||||
| 'ollamaProvider'
|
||||
| 'openaicompatibleProvider';
|
||||
| 'openaicompatibleProvider'
|
||||
| 'localproviderProvider';
|
||||
|
||||
const keyMap: Record<ApiProvider, ProviderSettingKey> = {
|
||||
'Infio': 'infioProvider',
|
||||
@ -42,6 +46,7 @@ const keyMap: Record<ApiProvider, ProviderSettingKey> = {
|
||||
'Grok': 'grokProvider',
|
||||
'Ollama': 'ollamaProvider',
|
||||
'OpenAICompatible': 'openaicompatibleProvider',
|
||||
'LocalProvider': 'localproviderProvider',
|
||||
};
|
||||
|
||||
export const getProviderSettingKey = (provider: ApiProvider): ProviderSettingKey => {
|
||||
@ -124,6 +129,11 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
hasUpdates = true;
|
||||
console.debug(t("settings.ModelProvider.embeddingModelConfigured", { provider: embeddingProvider, model: embeddingDefaultModels.embedding }));
|
||||
}
|
||||
} else { // use local provider
|
||||
newSettings.embeddingModelProvider = ApiProvider.LocalProvider;
|
||||
newSettings.embeddingModelId = localProviderDefaultEmbeddingModelId;
|
||||
hasUpdates = true;
|
||||
console.debug(t("settings.ModelProvider.embeddingModelConfigured", { provider: ApiProvider.LocalProvider, model: localProviderDefaultEmbeddingModelId }));
|
||||
}
|
||||
|
||||
// 一次性更新所有设置
|
||||
@ -294,12 +304,12 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
const providerSettingKey = getProviderSettingKey(provider);
|
||||
const providerSettings = settings[providerSettingKey] || {};
|
||||
const currentModels = providerSettings.models || [];
|
||||
|
||||
|
||||
// 如果是自定义模型且不在列表中,则添加
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
: currentModels;
|
||||
|
||||
|
||||
handleSettingsUpdate({
|
||||
...settings,
|
||||
chatModelProvider: provider,
|
||||
@ -316,12 +326,12 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
const providerSettingKey = getProviderSettingKey(provider);
|
||||
const providerSettings = settings[providerSettingKey] || {};
|
||||
const currentModels = providerSettings.models || [];
|
||||
|
||||
|
||||
// 如果是自定义模型且不在列表中,则添加
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
: currentModels;
|
||||
|
||||
|
||||
handleSettingsUpdate({
|
||||
...settings,
|
||||
applyModelProvider: provider,
|
||||
@ -338,12 +348,12 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
const providerSettingKey = getProviderSettingKey(provider);
|
||||
const providerSettings = settings[providerSettingKey] || {};
|
||||
const currentModels = providerSettings.models || [];
|
||||
|
||||
|
||||
// 如果是自定义模型且不在列表中,则添加
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
const updatedModels = isCustom && !currentModels.includes(modelId)
|
||||
? [...currentModels, modelId]
|
||||
: currentModels;
|
||||
|
||||
|
||||
handleSettingsUpdate({
|
||||
...settings,
|
||||
embeddingModelProvider: provider,
|
||||
@ -392,25 +402,43 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
|
||||
return (
|
||||
<div className="provider-config">
|
||||
{provider !== ApiProvider.Ollama && (
|
||||
<ApiKeyComponent
|
||||
name={t("settings.ModelProvider.setApiKey", { provider })}
|
||||
placeholder={t("settings.ApiProvider.enterApiKey")}
|
||||
description={generateApiKeyDescription(provider)}
|
||||
value={providerSetting.apiKey || ''}
|
||||
onChange={(value) => updateProviderApiKey(provider, value)}
|
||||
onTest={() => testApiConnection(provider)}
|
||||
/>
|
||||
)}
|
||||
{provider === ApiProvider.LocalProvider ? (
|
||||
<div className="local-provider-info">
|
||||
<p className="local-provider-description">
|
||||
{t("settings.ModelProvider.localProviderDescription")}
|
||||
</p>
|
||||
<div className="local-provider-features">
|
||||
<ul>
|
||||
<li>• {t("settings.ModelProvider.localProviderFeature0")}</li>
|
||||
<li>• {t("settings.ModelProvider.localProviderFeature1")}</li>
|
||||
<li>• {t("settings.ModelProvider.localProviderFeature2")}</li>
|
||||
<li>• {t("settings.ModelProvider.localProviderFeature3")}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{provider !== ApiProvider.Ollama && (
|
||||
<ApiKeyComponent
|
||||
name={t("settings.ModelProvider.setApiKey", { provider })}
|
||||
placeholder={t("settings.ApiProvider.enterApiKey")}
|
||||
description={generateApiKeyDescription(provider)}
|
||||
value={providerSetting.apiKey || ''}
|
||||
onChange={(value) => updateProviderApiKey(provider, value)}
|
||||
onTest={() => testApiConnection(provider)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<CustomUrlComponent
|
||||
name={t("settings.ApiProvider.useCustomBaseUrl")}
|
||||
placeholder={t("settings.ApiProvider.enterCustomUrl")}
|
||||
useCustomUrl={providerSetting.useCustomUrl || false}
|
||||
baseUrl={providerSetting.baseUrl || ''}
|
||||
onToggleCustomUrl={(value) => updateProviderUseCustomUrl(provider, value)}
|
||||
onChangeBaseUrl={(value) => updateProviderBaseUrl(provider, value)}
|
||||
/>
|
||||
<CustomUrlComponent
|
||||
name={t("settings.ApiProvider.useCustomBaseUrl")}
|
||||
placeholder={t("settings.ApiProvider.enterCustomUrl")}
|
||||
useCustomUrl={providerSetting.useCustomUrl || false}
|
||||
baseUrl={providerSetting.baseUrl || ''}
|
||||
onToggleCustomUrl={(value) => updateProviderUseCustomUrl(provider, value)}
|
||||
onChangeBaseUrl={(value) => updateProviderBaseUrl(provider, value)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -684,6 +712,43 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
||||
background: var(--background-primary-alt);
|
||||
border-color: var(--background-modifier-border-hover);
|
||||
}
|
||||
|
||||
/* LocalProvider 特殊样式 */
|
||||
.local-provider-info {
|
||||
padding: var(--size-4-3);
|
||||
background: var(--background-secondary);
|
||||
border-radius: var(--radius-m);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
.local-provider-description {
|
||||
color: var(--text-normal);
|
||||
font-size: var(--font-ui-medium);
|
||||
margin-bottom: var(--size-4-2);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.local-provider-features {
|
||||
margin-top: var(--size-4-2);
|
||||
}
|
||||
|
||||
.local-provider-features ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.local-provider-features li {
|
||||
padding: var(--size-2-1) 0;
|
||||
font-size: var(--font-ui-small);
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.theme-dark .local-provider-info {
|
||||
background: var(--background-secondary-alt);
|
||||
border-color: var(--background-modifier-border-hover);
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
@ -11,6 +11,7 @@ export enum ApiProvider {
|
||||
Grok = "Grok",
|
||||
Ollama = "Ollama",
|
||||
OpenAICompatible = "OpenAICompatible",
|
||||
LocalProvider = "LocalProvider",
|
||||
}
|
||||
|
||||
export type LLMModel = {
|
||||
|
||||
@ -183,6 +183,20 @@ const GrokProviderSchema = z.object({
|
||||
models: []
|
||||
})
|
||||
|
||||
const LocalProviderSchema = z.object({
|
||||
name: z.literal('LocalProvider'),
|
||||
apiKey: z.string().catch(''),
|
||||
baseUrl: z.string().catch(''),
|
||||
useCustomUrl: z.boolean().catch(false),
|
||||
models: z.array(z.string()).catch([])
|
||||
}).catch({
|
||||
name: 'LocalProvider',
|
||||
apiKey: '',
|
||||
baseUrl: '',
|
||||
useCustomUrl: false,
|
||||
models: []
|
||||
})
|
||||
|
||||
const ollamaModelSchema = z.object({
|
||||
baseUrl: z.string().catch(''),
|
||||
model: z.string().catch(''),
|
||||
@ -255,6 +269,7 @@ export const InfioSettingsSchema = z.object({
|
||||
groqProvider: GroqProviderSchema,
|
||||
grokProvider: GrokProviderSchema,
|
||||
openaicompatibleProvider: OpenAICompatibleProviderSchema,
|
||||
localproviderProvider: LocalProviderSchema,
|
||||
|
||||
// MCP Servers
|
||||
mcpEnabled: z.boolean().catch(false),
|
||||
|
||||
@ -1635,6 +1635,24 @@ export const grokModels = {
|
||||
}
|
||||
} as const satisfies Record<string, ModelInfo>
|
||||
|
||||
// LocalProvider (本地嵌入模型)
|
||||
export const localProviderDefaultModelId = null // this is not supported for chat/autocomplete
|
||||
export const localProviderDefaultAutoCompleteModelId = null // this is not supported for chat/autocomplete
|
||||
export const localProviderDefaultEmbeddingModelId: keyof typeof localProviderEmbeddingModels = "Xenova/all-MiniLM-L6-v2"
|
||||
|
||||
export const localProviderEmbeddingModels = {
|
||||
'Xenova/all-MiniLM-L6-v2': { dimensions: 384, description: 'All-MiniLM-L6-v2 (推荐,轻量级)' },
|
||||
'Xenova/bge-small-en-v1.5': { dimensions: 384, description: 'BGE-small-en-v1.5' },
|
||||
'Xenova/bge-base-en-v1.5': { dimensions: 768, description: 'BGE-base-en-v1.5 (更高质量)' },
|
||||
'Xenova/jina-embeddings-v2-base-zh': { dimensions: 768, description: 'Jina-v2-base-zh (中英双语)' },
|
||||
'Xenova/jina-embeddings-v2-small-en': { dimensions: 512, description: 'Jina-v2-small-en' },
|
||||
'Xenova/multilingual-e5-small': { dimensions: 384, description: 'E5-small (多语言)' },
|
||||
'Xenova/multilingual-e5-base': { dimensions: 768, description: 'E5-base (多语言,更高质量)' },
|
||||
'Xenova/gte-small': { dimensions: 384, description: 'GTE-small' },
|
||||
'Xenova/e5-small-v2': { dimensions: 384, description: 'E5-small-v2' },
|
||||
'Xenova/e5-base-v2': { dimensions: 768, description: 'E5-base-v2 (更高质量)' }
|
||||
} as const satisfies Record<string, EmbeddingModelInfo>
|
||||
|
||||
/// helper functions
|
||||
// get all providers, used for the provider dropdown
|
||||
export const GetAllProviders = (): ApiProvider[] => {
|
||||
@ -1651,6 +1669,7 @@ export const GetAllProviders = (): ApiProvider[] => {
|
||||
ApiProvider.Groq,
|
||||
ApiProvider.Ollama,
|
||||
ApiProvider.OpenAICompatible,
|
||||
ApiProvider.LocalProvider,
|
||||
]
|
||||
}
|
||||
|
||||
@ -1663,6 +1682,7 @@ export const GetEmbeddingProviders = (): ApiProvider[] => {
|
||||
ApiProvider.SiliconFlow,
|
||||
ApiProvider.OpenAICompatible,
|
||||
ApiProvider.Ollama,
|
||||
ApiProvider.LocalProvider,
|
||||
]
|
||||
}
|
||||
|
||||
@ -1695,6 +1715,8 @@ export const GetProviderModels = async (provider: ApiProvider, settings?: InfioS
|
||||
return {}
|
||||
case ApiProvider.OpenAICompatible:
|
||||
return {}
|
||||
case ApiProvider.LocalProvider:
|
||||
return {}
|
||||
default:
|
||||
return {}
|
||||
}
|
||||
@ -1729,6 +1751,8 @@ export const GetProviderModelsWithSettings = async (provider: ApiProvider, setti
|
||||
return {}
|
||||
case ApiProvider.OpenAICompatible:
|
||||
return {}
|
||||
case ApiProvider.LocalProvider:
|
||||
return {} // LocalProvider only supports embedding models
|
||||
default:
|
||||
return {}
|
||||
}
|
||||
@ -1755,6 +1779,8 @@ export const GetEmbeddingProviderModels = (provider: ApiProvider): Record<string
|
||||
return openAINativeEmbeddingModels;
|
||||
case ApiProvider.AlibabaQwen:
|
||||
return qwenEmbeddingModels;
|
||||
case ApiProvider.LocalProvider:
|
||||
return localProviderEmbeddingModels;
|
||||
default:
|
||||
return {}
|
||||
}
|
||||
@ -1832,6 +1858,12 @@ export const GetDefaultModelId = (provider: ApiProvider): { chat: string, autoCo
|
||||
"autoComplete": grokDefaultAutoCompleteModelId,
|
||||
"embedding": grokDefaultEmbeddingModelId,
|
||||
}
|
||||
case ApiProvider.LocalProvider:
|
||||
return {
|
||||
"chat": localProviderDefaultModelId,
|
||||
"autoComplete": localProviderDefaultAutoCompleteModelId,
|
||||
"embedding": localProviderDefaultEmbeddingModelId,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
"chat": null,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user