update model settings multi lang.
This commit is contained in:
parent
b20b4f9e19
commit
6501132d80
@ -56,7 +56,6 @@ export const getEmbeddingModel = (
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
getBatchEmbeddings: async (texts: string[]) => {
|
getBatchEmbeddings: async (texts: string[]) => {
|
||||||
console.log("use getBatchEmbeddings", texts.length)
|
|
||||||
try {
|
try {
|
||||||
if (!openai.apiKey) {
|
if (!openai.apiKey) {
|
||||||
throw new LLMAPIKeyNotSetException(
|
throw new LLMAPIKeyNotSetException(
|
||||||
|
|||||||
@ -56,7 +56,7 @@ const localeMap: { [k: string]: Partial<typeof en> } = {
|
|||||||
|
|
||||||
const locale = localeMap[moment.locale()];
|
const locale = localeMap[moment.locale()];
|
||||||
|
|
||||||
export function t(str: string): any {
|
export function t(str: string, params?: Record<string, any>): any {
|
||||||
if (!locale) {
|
if (!locale) {
|
||||||
console.error({
|
console.error({
|
||||||
plugin: "infio-copilot",
|
plugin: "infio-copilot",
|
||||||
@ -75,5 +75,12 @@ export function t(str: string): any {
|
|||||||
if (result === undefined) return str;
|
if (result === undefined) return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle parameter interpolation
|
||||||
|
if (params && typeof result === 'string') {
|
||||||
|
return result.replace(/\{([^}]+)\}/g, (match, key) => {
|
||||||
|
return params[key] !== undefined ? String(params[key]) : match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -216,8 +216,29 @@ export default {
|
|||||||
},
|
},
|
||||||
Models: {
|
Models: {
|
||||||
chatModel: 'Chat model:',
|
chatModel: 'Chat model:',
|
||||||
|
chatModelDescription: 'Model used for daily conversations and Q&A, handling most chat interactions',
|
||||||
autocompleteModel: 'Autocomplete model:',
|
autocompleteModel: 'Autocomplete model:',
|
||||||
|
autocompleteModelDescription: 'Model used for code and text autocompletion, providing intelligent writing suggestions',
|
||||||
embeddingModel: 'Embedding model:',
|
embeddingModel: 'Embedding model:',
|
||||||
|
embeddingModelDescription: 'Model used for document vectorization and semantic search, supporting RAG functionality',
|
||||||
|
},
|
||||||
|
|
||||||
|
// Model Provider Settings
|
||||||
|
ModelProvider: {
|
||||||
|
noApiKeySet: 'No API key has been set',
|
||||||
|
setApiKey: 'Set {provider} API Key',
|
||||||
|
modelSelection: 'Model Selection',
|
||||||
|
oneClickConfig: 'One-Click Config',
|
||||||
|
oneClickConfigTooltip: 'Automatically configure models to recommended models from providers with API keys set',
|
||||||
|
chatModelConfigured: 'Chat model configured automatically: {provider}/{model}',
|
||||||
|
autocompleteModelConfigured: 'Autocomplete model configured automatically: {provider}/{model}',
|
||||||
|
embeddingModelConfigured: 'Embedding model configured automatically: {provider}/{model}',
|
||||||
|
provider: 'Provider',
|
||||||
|
model: 'Model',
|
||||||
|
selectModel: 'Select model...',
|
||||||
|
searchOrEnterModelName: 'Search or enter model name...',
|
||||||
|
enterCustomModelName: 'Enter custom model name',
|
||||||
|
custom: 'Custom: ',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Model Parameters Section
|
// Model Parameters Section
|
||||||
|
|||||||
@ -224,6 +224,24 @@ export default {
|
|||||||
embeddingModelDescription: '用于文档向量化和语义搜索的模型,支持 RAG 功能',
|
embeddingModelDescription: '用于文档向量化和语义搜索的模型,支持 RAG 功能',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 模型提供商设置
|
||||||
|
ModelProvider: {
|
||||||
|
noApiKeySet: '当前未设置任何 API Key',
|
||||||
|
setApiKey: '设置 {provider} API Key',
|
||||||
|
modelSelection: '模型选择',
|
||||||
|
oneClickConfig: '一键配置',
|
||||||
|
oneClickConfigTooltip: '自动配置模型为已设置 API Key 的提供商的推荐模型',
|
||||||
|
chatModelConfigured: '已自动配置聊天模型:{provider}/{model}',
|
||||||
|
autocompleteModelConfigured: '已自动配置自动补全模型:{provider}/{model}',
|
||||||
|
embeddingModelConfigured: '已自动配置嵌入模型:{provider}/{model}',
|
||||||
|
provider: '提供商',
|
||||||
|
model: '模型',
|
||||||
|
selectModel: '选择模型...',
|
||||||
|
searchOrEnterModelName: '搜索或输入模型名称...',
|
||||||
|
enterCustomModelName: '输入自定义模型名称',
|
||||||
|
custom: '自定义: ',
|
||||||
|
},
|
||||||
|
|
||||||
// 模型参数部分
|
// 模型参数部分
|
||||||
ModelParameters: {
|
ModelParameters: {
|
||||||
title: '模型参数',
|
title: '模型参数',
|
||||||
|
|||||||
@ -82,7 +82,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
|
|
||||||
if (settedProviders.length === 0) {
|
if (settedProviders.length === 0) {
|
||||||
// 提示用户未设置任何key
|
// 提示用户未设置任何key
|
||||||
alert("当前未设置任何key");
|
alert(t("settings.ModelProvider.noApiKeySet"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,13 +104,13 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
newSettings.chatModelProvider = selectedProvider;
|
newSettings.chatModelProvider = selectedProvider;
|
||||||
newSettings.chatModelId = defaultModels.chat;
|
newSettings.chatModelId = defaultModels.chat;
|
||||||
hasUpdates = true;
|
hasUpdates = true;
|
||||||
console.log(`已自动配置聊天模型:${selectedProvider}/${defaultModels.chat}`);
|
console.log(t("settings.ModelProvider.chatModelConfigured", { provider: selectedProvider, model: defaultModels.chat }));
|
||||||
}
|
}
|
||||||
if (defaultModels.autoComplete) {
|
if (defaultModels.autoComplete) {
|
||||||
newSettings.applyModelProvider = selectedProvider;
|
newSettings.applyModelProvider = selectedProvider;
|
||||||
newSettings.applyModelId = defaultModels.autoComplete;
|
newSettings.applyModelId = defaultModels.autoComplete;
|
||||||
hasUpdates = true;
|
hasUpdates = true;
|
||||||
console.log(`已自动配置自动补全模型:${selectedProvider}/${defaultModels.autoComplete}`);
|
console.log(t("settings.ModelProvider.autocompleteModelConfigured", { provider: selectedProvider, model: defaultModels.autoComplete }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
newSettings.embeddingModelProvider = embeddingProvider;
|
newSettings.embeddingModelProvider = embeddingProvider;
|
||||||
newSettings.embeddingModelId = embeddingDefaultModels.embedding;
|
newSettings.embeddingModelId = embeddingDefaultModels.embedding;
|
||||||
hasUpdates = true;
|
hasUpdates = true;
|
||||||
console.log(`已自动配置嵌入模型:${embeddingProvider}/${embeddingDefaultModels.embedding}`);
|
console.log(t("settings.ModelProvider.embeddingModelConfigured", { provider: embeddingProvider, model: embeddingDefaultModels.embedding }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
// 生成包含链接的API Key描述
|
// 生成包含链接的API Key描述
|
||||||
const generateApiKeyDescription = (provider: ApiProvider): React.ReactNode => {
|
const generateApiKeyDescription = (provider: ApiProvider): React.ReactNode => {
|
||||||
const apiUrl = getProviderApiUrl(provider);
|
const apiUrl = getProviderApiUrl(provider);
|
||||||
const baseDescription = t("settings.ApiProvider.enterApiKeyDescription");
|
const baseDescription = String(t("settings.ApiProvider.enterApiKeyDescription"));
|
||||||
|
|
||||||
if (!apiUrl) {
|
if (!apiUrl) {
|
||||||
// 如果没有URL,直接移除占位符
|
// 如果没有URL,直接移除占位符
|
||||||
@ -253,11 +253,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
<div className="provider-config">
|
<div className="provider-config">
|
||||||
{provider !== ApiProvider.Ollama && (
|
{provider !== ApiProvider.Ollama && (
|
||||||
<ApiKeyComponent
|
<ApiKeyComponent
|
||||||
name={
|
name={t("settings.ModelProvider.setApiKey", { provider })}
|
||||||
<>
|
|
||||||
设置 <span className="provider-name-highlight">{provider}</span> API Key
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
placeholder={t("settings.ApiProvider.enterApiKey")}
|
placeholder={t("settings.ApiProvider.enterApiKey")}
|
||||||
description={generateApiKeyDescription(provider)}
|
description={generateApiKeyDescription(provider)}
|
||||||
value={providerSetting.apiKey || ''}
|
value={providerSetting.apiKey || ''}
|
||||||
@ -306,13 +302,13 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
|
|||||||
{/* 模型选择区域 */}
|
{/* 模型选择区域 */}
|
||||||
<div className="model-selection-section">
|
<div className="model-selection-section">
|
||||||
<div className="model-selection-header">
|
<div className="model-selection-header">
|
||||||
<h2 className="section-title">模型选择</h2>
|
<h2 className="section-title">{t("settings.ModelProvider.modelSelection")}</h2>
|
||||||
<button
|
<button
|
||||||
className="one-click-config-btn"
|
className="one-click-config-btn"
|
||||||
onClick={handleOneClickConfig}
|
onClick={handleOneClickConfig}
|
||||||
title="自动配置模型为已设置API Key的提供商的推荐模型"
|
title={t("settings.ModelProvider.oneClickConfigTooltip")}
|
||||||
>
|
>
|
||||||
一键配置
|
{t("settings.ModelProvider.oneClickConfig")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import * as Popover from "@radix-ui/react-popover";
|
|||||||
import Fuse, { FuseResult } from "fuse.js";
|
import Fuse, { FuseResult } from "fuse.js";
|
||||||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
|
||||||
|
import { t } from "../../lang/helpers";
|
||||||
import { ApiProvider } from "../../types/llm/model";
|
import { ApiProvider } from "../../types/llm/model";
|
||||||
import { InfioSettings } from "../../types/settings";
|
import { InfioSettings } from "../../types/settings";
|
||||||
// import { PROVIDERS } from '../constants';
|
// import { PROVIDERS } from '../constants';
|
||||||
@ -224,7 +225,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
|
|||||||
if (!exactMatch) {
|
if (!exactMatch) {
|
||||||
results.unshift({
|
results.unshift({
|
||||||
id: searchTerm,
|
id: searchTerm,
|
||||||
html: [{ text: `${modelIds.length > 0 ? '自定义: ' : ''}${searchTerm}`, isHighlighted: false }]
|
html: [{ text: `${modelIds.length > 0 ? t("settings.ModelProvider.custom") : ''}${searchTerm}`, isHighlighted: false }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,7 +269,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
|
|||||||
<div className="infio-llm-setting-item-content">
|
<div className="infio-llm-setting-item-content">
|
||||||
{/* Provider Selection - Now visible outside */}
|
{/* Provider Selection - Now visible outside */}
|
||||||
<div className="infio-llm-setting-provider-container">
|
<div className="infio-llm-setting-provider-container">
|
||||||
<label className="infio-llm-setting-provider-label">提供商</label>
|
<label className="infio-llm-setting-provider-label">{t("settings.ModelProvider.provider")}</label>
|
||||||
<select
|
<select
|
||||||
className="dropdown infio-llm-setting-provider-select"
|
className="dropdown infio-llm-setting-provider-select"
|
||||||
value={modelProvider}
|
value={modelProvider}
|
||||||
@ -287,12 +288,12 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
|
|||||||
|
|
||||||
{/* Model Selection */}
|
{/* Model Selection */}
|
||||||
<div className="infio-llm-setting-model-container">
|
<div className="infio-llm-setting-model-container">
|
||||||
<label className="infio-llm-setting-model-label">模型</label>
|
<label className="infio-llm-setting-model-label">{t("settings.ModelProvider.model")}</label>
|
||||||
<Popover.Root modal={false} open={isOpen} onOpenChange={setIsOpen}>
|
<Popover.Root modal={false} open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<Popover.Trigger asChild>
|
<Popover.Trigger asChild>
|
||||||
<button className="infio-llm-setting-model-trigger clickable-icon" type="button">
|
<button className="infio-llm-setting-model-trigger clickable-icon" type="button">
|
||||||
<span className="infio-llm-setting-model-display">
|
<span className="infio-llm-setting-model-display">
|
||||||
{modelId || "选择模型..."}
|
{modelId || t("settings.ModelProvider.selectModel")}
|
||||||
</span>
|
</span>
|
||||||
<svg
|
<svg
|
||||||
className="infio-llm-setting-model-arrow"
|
className="infio-llm-setting-model-arrow"
|
||||||
@ -322,7 +323,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="infio-llm-setting-item-search"
|
className="infio-llm-setting-item-search"
|
||||||
placeholder={modelIds.length > 0 ? "搜索或输入模型名称..." : "输入自定义模型名称"}
|
placeholder={modelIds.length > 0 ? t("settings.ModelProvider.searchOrEnterModelName") : t("settings.ModelProvider.enterCustomModelName")}
|
||||||
value={searchTerm}
|
value={searchTerm}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSearchTerm(e.target.value);
|
setSearchTerm(e.target.value);
|
||||||
@ -348,7 +349,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
|
|||||||
updateModel(modelProvider, selectedOption.id);
|
updateModel(modelProvider, selectedOption.id);
|
||||||
}
|
}
|
||||||
} else if (searchTerm.trim()) {
|
} else if (searchTerm.trim()) {
|
||||||
// 如果没有选项但有输入内容,直接使用输入内容
|
// If no options but there is input content, use the input content directly
|
||||||
updateModel(modelProvider, searchTerm.trim());
|
updateModel(modelProvider, searchTerm.trim());
|
||||||
}
|
}
|
||||||
setSearchTerm("");
|
setSearchTerm("");
|
||||||
|
|||||||
@ -147,7 +147,6 @@ export const infioDefaultModelInfo: ModelInfo = {
|
|||||||
let infioModelsCache: Record<string, ModelInfo> | null = null;
|
let infioModelsCache: Record<string, ModelInfo> | null = null;
|
||||||
|
|
||||||
async function fetchInfioModels(apiKey?: string): Promise<Record<string, ModelInfo>> {
|
async function fetchInfioModels(apiKey?: string): Promise<Record<string, ModelInfo>> {
|
||||||
console.log("fetchInfioModels apiKey", apiKey)
|
|
||||||
if (infioModelsCache) {
|
if (infioModelsCache) {
|
||||||
return infioModelsCache;
|
return infioModelsCache;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user