mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for model filters, group alias settings, and hub columns
This commit is contained in:
parent
625feb0ab7
commit
4018f9a836
5 changed files with 134 additions and 50 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect, useMemo, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Card, Text } from "@tremor/react";
|
||||
|
||||
interface ModelGroupInfo {
|
||||
|
|
@ -32,6 +33,7 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
showFiltersCard = true,
|
||||
className = "",
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [searchTerm, setSearchTerm] = useState<string>("");
|
||||
const [selectedProvider, setSelectedProvider] = useState<string>("");
|
||||
const [selectedMode, setSelectedMode] = useState<string>("");
|
||||
|
|
@ -132,24 +134,24 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
const filtersContent = (
|
||||
<div className="flex flex-wrap gap-4 items-center">
|
||||
<div>
|
||||
<Text className="text-sm font-medium mb-2">Search Models:</Text>
|
||||
<Text className="text-sm font-medium mb-2">{t("modelFilters.searchModels")}</Text>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search model names..."
|
||||
placeholder={t("modelFilters.searchPlaceholder")}
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="border rounded px-3 py-2 w-64 h-10 text-sm"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="text-sm font-medium mb-2">Provider:</Text>
|
||||
<Text className="text-sm font-medium mb-2">{t("modelFilters.provider")}</Text>
|
||||
<select
|
||||
value={selectedProvider}
|
||||
onChange={(e) => setSelectedProvider(e.target.value)}
|
||||
className="border rounded px-3 py-2 text-sm text-gray-600 w-40 h-10"
|
||||
>
|
||||
<option value="" className="text-sm text-gray-600">
|
||||
All Providers
|
||||
{t("modelFilters.allProviders")}
|
||||
</option>
|
||||
{modelHubData &&
|
||||
getUniqueProviders(modelHubData).map((provider) => (
|
||||
|
|
@ -160,14 +162,14 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="text-sm font-medium mb-2">Mode:</Text>
|
||||
<Text className="text-sm font-medium mb-2">{t("modelFilters.mode")}</Text>
|
||||
<select
|
||||
value={selectedMode}
|
||||
onChange={(e) => setSelectedMode(e.target.value)}
|
||||
className="border rounded px-3 py-2 text-sm text-gray-600 w-32 h-10"
|
||||
>
|
||||
<option value="" className="text-sm text-gray-600">
|
||||
All Modes
|
||||
{t("modelFilters.allModes")}
|
||||
</option>
|
||||
{modelHubData &&
|
||||
getUniqueModes(modelHubData).map((mode) => (
|
||||
|
|
@ -178,14 +180,14 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="text-sm font-medium mb-2">Features:</Text>
|
||||
<Text className="text-sm font-medium mb-2">{t("modelFilters.features")}</Text>
|
||||
<select
|
||||
value={selectedFeature}
|
||||
onChange={(e) => setSelectedFeature(e.target.value)}
|
||||
className="border rounded px-3 py-2 text-sm text-gray-600 w-48 h-10"
|
||||
>
|
||||
<option value="" className="text-sm text-gray-600">
|
||||
All Features
|
||||
{t("modelFilters.allFeatures")}
|
||||
</option>
|
||||
{modelHubData &&
|
||||
getUniqueFeatures(modelHubData).map((feature) => (
|
||||
|
|
@ -203,7 +205,7 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
onClick={resetFilters}
|
||||
className="text-blue-600 hover:text-blue-800 text-sm underline h-10 flex items-center"
|
||||
>
|
||||
Clear Filters
|
||||
{t("common.clear")} {t("modelFilters.filtersLabel")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { PlusCircleIcon, PencilIcon, TrashIcon, ChevronDownIcon, ChevronRightIcon } from "@heroicons/react/outline";
|
||||
import { setCallbacksCall } from "./networking";
|
||||
import { Card, Title, Text, Table, TableHead, TableHeaderCell, TableBody, TableRow, TableCell } from "@tremor/react";
|
||||
|
|
@ -23,6 +24,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
initialModelGroupAlias = {},
|
||||
onAliasUpdate,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [aliases, setAliases] = useState<AliasItem[]>([]);
|
||||
const [newAlias, setNewAlias] = useState({ aliasName: "", targetModelGroup: "" });
|
||||
const [editingAlias, setEditingAlias] = useState<AliasItem | null>(null);
|
||||
|
|
@ -67,20 +69,20 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
return true;
|
||||
} catch (error) {
|
||||
console.error("Failed to save model group alias settings:", error);
|
||||
NotificationsManager.fromBackend("Failed to save model group alias settings");
|
||||
NotificationsManager.fromBackend(t("modelGroupAliasSettings.saveFailed"));
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddAlias = async () => {
|
||||
if (!newAlias.aliasName || !newAlias.targetModelGroup) {
|
||||
NotificationsManager.fromBackend("Please provide both alias name and target model group");
|
||||
NotificationsManager.fromBackend(t("modelGroupAliasSettings.bothRequired"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate alias names
|
||||
if (aliases.some((alias) => alias.aliasName === newAlias.aliasName)) {
|
||||
NotificationsManager.fromBackend("An alias with this name already exists");
|
||||
NotificationsManager.fromBackend(t("modelGroupAliasSettings.duplicateAlias"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +97,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
if (await saveAliasesToBackend(updatedAliases)) {
|
||||
setAliases(updatedAliases);
|
||||
setNewAlias({ aliasName: "", targetModelGroup: "" });
|
||||
NotificationsManager.success("Alias added successfully");
|
||||
NotificationsManager.success(t("modelGroupAliasSettings.addSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -107,13 +109,13 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
if (!editingAlias) return;
|
||||
|
||||
if (!editingAlias.aliasName || !editingAlias.targetModelGroup) {
|
||||
NotificationsManager.fromBackend("Please provide both alias name and target model group");
|
||||
NotificationsManager.fromBackend(t("modelGroupAliasSettings.bothRequired"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicate alias names (excluding current alias)
|
||||
if (aliases.some((alias) => alias.id !== editingAlias.id && alias.aliasName === editingAlias.aliasName)) {
|
||||
NotificationsManager.fromBackend("An alias with this name already exists");
|
||||
NotificationsManager.fromBackend(t("modelGroupAliasSettings.duplicateAlias"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +124,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
if (await saveAliasesToBackend(updatedAliases)) {
|
||||
setAliases(updatedAliases);
|
||||
setEditingAlias(null);
|
||||
NotificationsManager.success("Alias updated successfully");
|
||||
NotificationsManager.success(t("modelGroupAliasSettings.updateSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -135,7 +137,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
|
||||
if (await saveAliasesToBackend(updatedAliases)) {
|
||||
setAliases(updatedAliases);
|
||||
NotificationsManager.success("Alias deleted successfully");
|
||||
NotificationsManager.success(t("modelGroupAliasSettings.deleteSuccess"));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -152,11 +154,8 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
<Card className="mb-6">
|
||||
<div className="flex items-center justify-between cursor-pointer" onClick={() => setIsExpanded(!isExpanded)}>
|
||||
<div className="flex flex-col">
|
||||
<Title className="mb-0">Model Group Alias Settings</Title>
|
||||
<p className="text-sm text-gray-500">
|
||||
Create aliases for your model groups to simplify API calls. For example, you can create an alias
|
||||
'gpt-4o' that points to 'gpt-4o-mini-openai' model group.
|
||||
</p>
|
||||
<Title className="mb-0">{t("modelGroupAliasSettings.title")}</Title>
|
||||
<p className="text-sm text-gray-500">{t("modelGroupAliasSettings.description")}</p>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
{isExpanded ? (
|
||||
|
|
@ -170,10 +169,10 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
{isExpanded && (
|
||||
<div className="mt-4">
|
||||
<div className="mb-6">
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">Add New Alias</Text>
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">{t("modelGroupAliasSettings.addNewAlias")}</Text>
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-xs text-gray-500 mb-1">Alias Name</label>
|
||||
<label className="block text-xs text-gray-500 mb-1">{t("modelGroupAliasSettings.aliasName")}</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newAlias.aliasName}
|
||||
|
|
@ -188,7 +187,9 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-xs text-gray-500 mb-1">Target Model Group</label>
|
||||
<label className="block text-xs text-gray-500 mb-1">
|
||||
{t("modelGroupAliasSettings.targetModelGroup")}
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newAlias.targetModelGroup}
|
||||
|
|
@ -209,21 +210,23 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
className={`flex items-center px-4 py-2 rounded-md text-sm ${!newAlias.aliasName || !newAlias.targetModelGroup ? "bg-gray-300 text-gray-500 cursor-not-allowed" : "bg-green-600 text-white hover:bg-green-700"}`}
|
||||
>
|
||||
<PlusCircleIcon className="w-4 h-4 mr-1" />
|
||||
Add Alias
|
||||
{t("modelGroupAliasSettings.addAlias")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">Manage Existing Aliases</Text>
|
||||
<Text className="text-sm font-medium text-gray-700 mb-2">{t("modelGroupAliasSettings.manageExisting")}</Text>
|
||||
<div className="rounded-lg custom-border relative mb-6">
|
||||
<div className="overflow-x-auto">
|
||||
<Table className="[&_td]:py-0.5 [&_th]:py-1">
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell className="py-1 h-8">Alias Name</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">Target Model Group</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">Actions</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">{t("modelGroupAliasSettings.aliasName")}</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">
|
||||
{t("modelGroupAliasSettings.targetModelGroup")}
|
||||
</TableHeaderCell>
|
||||
<TableHeaderCell className="py-1 h-8">{t("common.actions")}</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
|
@ -263,13 +266,13 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
onClick={handleUpdateAlias}
|
||||
className="text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100"
|
||||
>
|
||||
Save
|
||||
{t("common.save")}
|
||||
</button>
|
||||
<button
|
||||
onClick={handleCancelEdit}
|
||||
className="text-xs bg-gray-50 text-gray-600 px-2 py-1 rounded hover:bg-gray-100"
|
||||
>
|
||||
Cancel
|
||||
{t("common.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
|
@ -301,7 +304,7 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
{aliases.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell colSpan={3} className="py-0.5 text-sm text-gray-500 text-center">
|
||||
No aliases added yet. Add a new alias above.
|
||||
{t("modelGroupAliasSettings.noAliases")}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
|
@ -312,10 +315,8 @@ const ModelGroupAliasSettings: React.FC<ModelGroupAliasSettingsProps> = ({
|
|||
|
||||
{/* Configuration Example */}
|
||||
<Card>
|
||||
<Title className="mb-4">Configuration Example</Title>
|
||||
<Text className="text-gray-600 mb-4">
|
||||
Here's how your current aliases would look in the config.yaml:
|
||||
</Text>
|
||||
<Title className="mb-4">{t("modelGroupAliasSettings.configExample")}</Title>
|
||||
<Text className="text-gray-600 mb-4">{t("modelGroupAliasSettings.configExampleDesc")}</Text>
|
||||
<div className="bg-gray-100 rounded-lg p-4 font-mono text-sm">
|
||||
<div className="text-gray-700">
|
||||
router_settings:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { ColumnDef } from "@tanstack/react-table";
|
|||
import { Button, Badge, Text } from "@tremor/react";
|
||||
import { Tooltip, Tag } from "antd";
|
||||
import { CopyOutlined, InfoCircleOutlined } from "@ant-design/icons";
|
||||
import i18n from "@/lib/i18n";
|
||||
|
||||
interface ModelHubData {
|
||||
model_group: string;
|
||||
|
|
@ -55,7 +56,7 @@ export const modelHubColumns = (
|
|||
): ColumnDef<ModelHubData>[] => {
|
||||
const allColumns: ColumnDef<ModelHubData>[] = [
|
||||
{
|
||||
header: "Public Model Name",
|
||||
header: i18n.t("modelHubTableColumns.publicModelName"),
|
||||
accessorKey: "model_group",
|
||||
enableSorting: true,
|
||||
sortingFn: "alphanumeric",
|
||||
|
|
@ -66,7 +67,7 @@ export const modelHubColumns = (
|
|||
<div className="space-y-1">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Text className="font-medium text-sm">{model.model_group}</Text>
|
||||
<Tooltip title="Copy model name">
|
||||
<Tooltip title={i18n.t("modelHubTableColumns.copyModelName")}>
|
||||
<CopyOutlined
|
||||
onClick={() => copyToClipboard(model.model_group)}
|
||||
className="cursor-pointer text-gray-500 hover:text-blue-500 text-xs"
|
||||
|
|
@ -82,7 +83,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Provider",
|
||||
header: i18n.t("modelHubTableColumns.provider"),
|
||||
accessorKey: "providers",
|
||||
enableSorting: true,
|
||||
sortingFn: (rowA, rowB) => {
|
||||
|
|
@ -109,7 +110,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Mode",
|
||||
header: i18n.t("modelHubTableColumns.mode"),
|
||||
accessorKey: "mode",
|
||||
enableSorting: true,
|
||||
sortingFn: "alphanumeric",
|
||||
|
|
@ -129,7 +130,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Tokens",
|
||||
header: i18n.t("modelHubTableColumns.tokens"),
|
||||
accessorKey: "max_input_tokens",
|
||||
enableSorting: true,
|
||||
sortingFn: (rowA, rowB) => {
|
||||
|
|
@ -154,7 +155,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Cost/1M",
|
||||
header: i18n.t("modelHubTableColumns.costPerMillion"),
|
||||
accessorKey: "input_cost_per_token",
|
||||
enableSorting: true,
|
||||
sortingFn: (rowA, rowB) => {
|
||||
|
|
@ -176,7 +177,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Features",
|
||||
header: i18n.t("modelHubTableColumns.features"),
|
||||
accessorKey: "capabilities",
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => {
|
||||
|
|
@ -200,7 +201,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Public",
|
||||
header: i18n.t("modelHubTableColumns.public"),
|
||||
accessorKey: "is_public_model_group",
|
||||
enableSorting: true,
|
||||
sortingFn: (rowA, rowB) => {
|
||||
|
|
@ -213,11 +214,11 @@ export const modelHubColumns = (
|
|||
|
||||
return model.is_public_model_group === true ? (
|
||||
<Badge color="green" size="xs">
|
||||
Yes
|
||||
{i18n.t("common.yes")}
|
||||
</Badge>
|
||||
) : (
|
||||
<Badge color="gray" size="xs">
|
||||
No
|
||||
{i18n.t("common.no")}
|
||||
</Badge>
|
||||
);
|
||||
},
|
||||
|
|
@ -226,7 +227,7 @@ export const modelHubColumns = (
|
|||
},
|
||||
},
|
||||
{
|
||||
header: "Details",
|
||||
header: i18n.t("common.details"),
|
||||
id: "details",
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => {
|
||||
|
|
@ -234,8 +235,8 @@ export const modelHubColumns = (
|
|||
|
||||
return (
|
||||
<Button size="xs" variant="secondary" onClick={() => showModal(model)} icon={InfoCircleOutlined}>
|
||||
<span className="hidden lg:inline">Details</span>
|
||||
<span className="lg:hidden">Info</span>
|
||||
<span className="hidden lg:inline">{i18n.t("common.details")}</span>
|
||||
<span className="lg:hidden">{i18n.t("modelHubTableColumns.infoShort")}</span>
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,46 @@
|
|||
"allTools": "All tools",
|
||||
"infoShort": "Info"
|
||||
},
|
||||
"modelFilters": {
|
||||
"searchModels": "Search Models:",
|
||||
"searchPlaceholder": "Search model names...",
|
||||
"provider": "Provider:",
|
||||
"allProviders": "All Providers",
|
||||
"mode": "Mode:",
|
||||
"allModes": "All Modes",
|
||||
"features": "Features:",
|
||||
"allFeatures": "All Features",
|
||||
"filtersLabel": "Filters"
|
||||
},
|
||||
"modelGroupAliasSettings": {
|
||||
"title": "Model Group Alias Settings",
|
||||
"description": "Create aliases for your model groups to simplify API calls. For example, you can create an alias 'gpt-4o' that points to 'gpt-4o-mini-openai' model group.",
|
||||
"addNewAlias": "Add New Alias",
|
||||
"aliasName": "Alias Name",
|
||||
"targetModelGroup": "Target Model Group",
|
||||
"addAlias": "Add Alias",
|
||||
"manageExisting": "Manage Existing Aliases",
|
||||
"noAliases": "No aliases added yet. Add a new alias above.",
|
||||
"configExample": "Configuration Example",
|
||||
"configExampleDesc": "Here's how your current aliases would look in the config.yaml:",
|
||||
"bothRequired": "Please provide both alias name and target model group",
|
||||
"duplicateAlias": "An alias with this name already exists",
|
||||
"saveFailed": "Failed to save model group alias settings",
|
||||
"addSuccess": "Alias added successfully",
|
||||
"updateSuccess": "Alias updated successfully",
|
||||
"deleteSuccess": "Alias deleted successfully"
|
||||
},
|
||||
"modelHubTableColumns": {
|
||||
"publicModelName": "Public Model Name",
|
||||
"copyModelName": "Copy model name",
|
||||
"provider": "Provider",
|
||||
"mode": "Mode",
|
||||
"tokens": "Tokens",
|
||||
"costPerMillion": "Cost/1M",
|
||||
"features": "Features",
|
||||
"public": "Public",
|
||||
"infoShort": "Info"
|
||||
},
|
||||
"common": {
|
||||
"save": "Save",
|
||||
"cancel": "Cancel",
|
||||
|
|
|
|||
|
|
@ -1259,6 +1259,46 @@
|
|||
"allTools": "所有工具",
|
||||
"infoShort": "详情"
|
||||
},
|
||||
"modelFilters": {
|
||||
"searchModels": "搜索模型:",
|
||||
"searchPlaceholder": "搜索模型名称...",
|
||||
"provider": "提供商:",
|
||||
"allProviders": "所有提供商",
|
||||
"mode": "模式:",
|
||||
"allModes": "所有模式",
|
||||
"features": "功能:",
|
||||
"allFeatures": "所有功能",
|
||||
"filtersLabel": "筛选"
|
||||
},
|
||||
"modelGroupAliasSettings": {
|
||||
"title": "模型组别名设置",
|
||||
"description": "为您的模型组创建别名以简化 API 调用。例如,您可以创建别名 'gpt-4o' 指向 'gpt-4o-mini-openai' 模型组。",
|
||||
"addNewAlias": "添加新别名",
|
||||
"aliasName": "别名名称",
|
||||
"targetModelGroup": "目标模型组",
|
||||
"addAlias": "添加别名",
|
||||
"manageExisting": "管理现有别名",
|
||||
"noAliases": "暂无别名。请在上方添加新别名。",
|
||||
"configExample": "配置示例",
|
||||
"configExampleDesc": "以下是您当前别名在 config.yaml 中的样子:",
|
||||
"bothRequired": "请同时提供别名名称和目标模型组",
|
||||
"duplicateAlias": "同名别名已存在",
|
||||
"saveFailed": "保存模型组别名设置失败",
|
||||
"addSuccess": "别名添加成功",
|
||||
"updateSuccess": "别名更新成功",
|
||||
"deleteSuccess": "别名删除成功"
|
||||
},
|
||||
"modelHubTableColumns": {
|
||||
"publicModelName": "公开模型名称",
|
||||
"copyModelName": "复制模型名称",
|
||||
"provider": "提供商",
|
||||
"mode": "模式",
|
||||
"tokens": "Token",
|
||||
"costPerMillion": "费用/百万",
|
||||
"features": "功能",
|
||||
"public": "公开",
|
||||
"infoShort": "详情"
|
||||
},
|
||||
"common": {
|
||||
"save": "保存",
|
||||
"cancel": "取消",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue