mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for playground compare UI
This commit is contained in:
parent
a4b623ba37
commit
e1d3ea9aa5
7 changed files with 158 additions and 33 deletions
|
|
@ -4,6 +4,7 @@ import NotificationsManager from "@/components/molecules/notifications_manager";
|
|||
import { ClearOutlined, DeleteOutlined, FilePdfOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { Button, Input, Select, Tooltip } from "antd";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import ChatImageUpload from "../chat_ui/ChatImageUpload";
|
||||
import { createChatDisplayMessage, createChatMultimodalMessage } from "../chat_ui/ChatImageUtils";
|
||||
|
|
@ -53,6 +54,7 @@ const GENERIC_FOLLOW_UPS = [
|
|||
const SUGGESTED_PROMPTS = ["Write me a poem", "Explain quantum computing", "Draft a polite email requesting a meeting"];
|
||||
const DEFAULT_ENDPOINT = EndpointId.CHAT_COMPLETIONS;
|
||||
export default function CompareUI({ accessToken, disabledPersonalKeyCreation }: CompareUIProps) {
|
||||
const { t } = useTranslation();
|
||||
const [comparisons, setComparisons] = useState<ComparisonInstance[]>([
|
||||
{
|
||||
id: "1",
|
||||
|
|
@ -483,7 +485,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
return;
|
||||
}
|
||||
if (!effectiveApiKey) {
|
||||
NotificationsManager.fromBackend("Please provide a Virtual Key or select Current UI Session");
|
||||
NotificationsManager.fromBackend(t("playground.compareUi.provideVirtualKey"));
|
||||
return;
|
||||
}
|
||||
const targetComparisons = comparisons;
|
||||
|
|
@ -643,13 +645,13 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
messages[messages.length - 1] = {
|
||||
...last,
|
||||
content: assistantContent
|
||||
? `${assistantContent}\nError fetching response: ${errorMessage}`
|
||||
: `Error fetching response: ${errorMessage}`,
|
||||
? `${assistantContent}\n${t("playground.compareUi.errorFetchingResponse", { errorMessage })}`
|
||||
: t("playground.compareUi.errorFetchingResponse", { errorMessage }),
|
||||
};
|
||||
} else {
|
||||
messages.push({
|
||||
role: "assistant",
|
||||
content: `Error fetching response: ${errorMessage}`,
|
||||
content: t("playground.compareUi.errorFetchingResponse", { errorMessage }),
|
||||
});
|
||||
}
|
||||
return {
|
||||
|
|
@ -693,7 +695,9 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
<div className="border-b px-4 py-2">
|
||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-gray-600">Virtual Key Source</span>
|
||||
<span className="text-sm font-medium text-gray-600">
|
||||
{t("playground.compareUi.virtualKeySourceLabel")}
|
||||
</span>
|
||||
<Select
|
||||
value={apiKeySource}
|
||||
onChange={(value) => setApiKeySource(value as "session" | "custom")}
|
||||
|
|
@ -701,21 +705,21 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
className="w-48"
|
||||
>
|
||||
<Select.Option value="session" disabled={!canUseSessionKey}>
|
||||
Current UI Session
|
||||
{t("playground.compareUi.currentUiSession")}
|
||||
</Select.Option>
|
||||
<Select.Option value="custom">Virtual Key</Select.Option>
|
||||
<Select.Option value="custom">{t("playground.compareUi.virtualKeyOption")}</Select.Option>
|
||||
</Select>
|
||||
{apiKeySource === "custom" && (
|
||||
<Input.Password
|
||||
value={customApiKey}
|
||||
onChange={(event) => setCustomApiKey(event.target.value)}
|
||||
placeholder="Enter Virtual Key"
|
||||
placeholder={t("playground.compareUi.enterVirtualKeyPlaceholder")}
|
||||
className="w-56"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm font-medium text-gray-600">Endpoint</span>
|
||||
<span className="text-sm font-medium text-gray-600">{t("playground.compareUi.endpointLabel")}</span>
|
||||
<Select
|
||||
value={selectedEndpoint}
|
||||
onChange={(value) => setSelectedEndpoint(value as EndpointIdType)}
|
||||
|
|
@ -730,15 +734,17 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Button onClick={clearAllChats} disabled={!hasMessages} icon={<ClearOutlined />}>
|
||||
Clear All Chats
|
||||
{t("playground.compareUi.clearAllChats")}
|
||||
</Button>
|
||||
<Tooltip
|
||||
title={
|
||||
comparisons.length >= maxComparisons ? "Compare up to 3 models at a time" : "Add another comparison"
|
||||
comparisons.length >= maxComparisons
|
||||
? t("playground.compareUi.compareUpToThreeModels")
|
||||
: t("playground.compareUi.addAnotherComparison")
|
||||
}
|
||||
>
|
||||
<Button onClick={addComparison} disabled={comparisons.length >= maxComparisons} icon={<PlusOutlined />}>
|
||||
Add Comparison
|
||||
{t("playground.compareUi.addComparison")}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
@ -770,7 +776,7 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
<div className="border border-gray-200 shadow-lg rounded-xl bg-white p-4">
|
||||
<div className="flex items-center justify-between gap-4 mb-3 min-h-8">
|
||||
{hasAttachment ? (
|
||||
<span className="text-sm text-gray-500">Attachment ready to send</span>
|
||||
<span className="text-sm text-gray-500">{t("playground.compareUi.attachmentReadyToSend")}</span>
|
||||
) : showSuggestedPrompts ? (
|
||||
<div className="flex items-center gap-2 overflow-x-auto">
|
||||
{SUGGESTED_PROMPTS.map((prompt) => (
|
||||
|
|
@ -817,14 +823,16 @@ export default function CompareUI({ accessToken, disabledPersonalKeyCreation }:
|
|||
) : (
|
||||
<img
|
||||
src={uploadedFilePreviewUrl || ""}
|
||||
alt="Upload preview"
|
||||
alt={t("playground.compareUi.uploadPreviewAlt")}
|
||||
className="w-10 h-10 rounded-md border border-gray-200 object-cover"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-medium text-gray-900 truncate">{uploadedFile.name}</div>
|
||||
<div className="text-xs text-gray-500">{isUploadedFilePdf ? "PDF" : "Image"}</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
{isUploadedFilePdf ? t("playground.compareUi.pdfLabel") : t("playground.compareUi.imageLabel")}
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
className="flex items-center justify-center w-6 h-6 text-gray-400 hover:text-gray-600 hover:bg-gray-200 rounded-full transition-colors"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Settings, X } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ComparisonInstance } from "../CompareUI";
|
||||
import { MessageDisplay } from "./MessageDisplay";
|
||||
import { UnifiedSelector } from "./UnifiedSelector";
|
||||
|
|
@ -32,6 +33,7 @@ export function ComparisonPanel({
|
|||
endpointConfig,
|
||||
apiKey,
|
||||
}: ComparisonPanelProps) {
|
||||
const { t } = useTranslation();
|
||||
const isA2AMode = isAgentEndpoint(endpointConfig.id);
|
||||
const currentSelection = getComparisonSelection(comparison, endpointConfig.id);
|
||||
const [popoverVisible, setPopoverVisible] = useState(false);
|
||||
|
|
@ -104,7 +106,7 @@ export function ComparisonPanel({
|
|||
{/* Sync Checkbox */}
|
||||
<div className="flex items-center gap-2">
|
||||
<Checkbox checked={comparison.applyAcrossModels} onChange={(e) => handleSyncChange(e.target.checked)}>
|
||||
<span className="text-xs font-medium">Sync Settings Across Models</span>
|
||||
<span className="text-xs font-medium">{t("playground.comparisonPanel.syncSettingsAcrossModels")}</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
|
|
@ -112,10 +114,14 @@ export function ComparisonPanel({
|
|||
|
||||
{/* General Settings */}
|
||||
<div>
|
||||
<h4 className="text-xs font-semibold text-gray-700 mb-1.5 uppercase tracking-wide">General Settings</h4>
|
||||
<h4 className="text-xs font-semibold text-gray-700 mb-1.5 uppercase tracking-wide">
|
||||
{t("playground.comparisonPanel.generalSettings")}
|
||||
</h4>
|
||||
<div className="space-y-2">
|
||||
<div>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">Tags</label>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">
|
||||
{t("playground.comparisonPanel.tagsLabel")}
|
||||
</label>
|
||||
<TagSelector
|
||||
value={comparison.tags}
|
||||
onChange={(value) => handleSettingChange("tags", value)}
|
||||
|
|
@ -123,7 +129,9 @@ export function ComparisonPanel({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">Vector Stores</label>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">
|
||||
{t("playground.comparisonPanel.vectorStoresLabel")}
|
||||
</label>
|
||||
<VectorStoreSelector
|
||||
value={comparison.vectorStores}
|
||||
onChange={(value) => handleSettingChange("vectorStores", value)}
|
||||
|
|
@ -131,7 +139,9 @@ export function ComparisonPanel({
|
|||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">Guardrails</label>
|
||||
<label className="text-xs font-medium text-gray-600 block mb-0.5">
|
||||
{t("playground.comparisonPanel.guardrailsLabel")}
|
||||
</label>
|
||||
<GuardrailSelector
|
||||
value={comparison.guardrails}
|
||||
onChange={(value) => handleSettingChange("guardrails", value)}
|
||||
|
|
@ -142,20 +152,24 @@ export function ComparisonPanel({
|
|||
</div>
|
||||
{/* Advanced Settings */}
|
||||
<div>
|
||||
<h4 className="text-xs font-semibold text-gray-700 mb-1.5 uppercase tracking-wide">Advanced Settings</h4>
|
||||
<h4 className="text-xs font-semibold text-gray-700 mb-1.5 uppercase tracking-wide">
|
||||
{t("playground.comparisonPanel.advancedSettings")}
|
||||
</h4>
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center gap-2 pb-1">
|
||||
<Checkbox
|
||||
checked={comparison.useAdvancedParams}
|
||||
onChange={(e) => handleAdvancedParamsChange(e.target.checked)}
|
||||
>
|
||||
<span className="text-sm font-medium">Use Advanced Parameters</span>
|
||||
<span className="text-sm font-medium">{t("playground.comparisonPanel.useAdvancedParameters")}</span>
|
||||
</Checkbox>
|
||||
</div>
|
||||
<div className="space-y-2 transition-opacity duration-200" style={{ opacity: disabledOpacity }}>
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<label className={`text-xs font-medium ${disabledTextColor}`}>Temperature</label>
|
||||
<label className={`text-xs font-medium ${disabledTextColor}`}>
|
||||
{t("playground.comparisonPanel.temperatureLabel")}
|
||||
</label>
|
||||
<span className={`text-xs ${disabledTextColor}`}>{comparison.temperature.toFixed(2)}</span>
|
||||
</div>
|
||||
<Slider
|
||||
|
|
@ -173,7 +187,9 @@ export function ComparisonPanel({
|
|||
</div>
|
||||
<div>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<label className={`text-xs font-medium ${disabledTextColor}`}>Max Tokens</label>
|
||||
<label className={`text-xs font-medium ${disabledTextColor}`}>
|
||||
{t("playground.comparisonPanel.maxTokensLabel")}
|
||||
</label>
|
||||
<span className={`text-xs ${disabledTextColor}`}>{comparison.maxTokens}</span>
|
||||
</div>
|
||||
<Slider
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Bot, Loader2, UserRound } from "lucide-react";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||
import { coy } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||
|
|
@ -15,6 +16,8 @@ interface MessageDisplayProps {
|
|||
}
|
||||
|
||||
export function MessageDisplay({ messages, isLoading }: MessageDisplayProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (messages.length === 0) {
|
||||
return <div className="h-full" />;
|
||||
}
|
||||
|
|
@ -101,7 +104,7 @@ export function MessageDisplay({ messages, isLoading }: MessageDisplayProps) {
|
|||
<div className="flex flex-col gap-6 min-w-0 w-full p-4">
|
||||
{conversationBlocks.map((block, blockIndex) => {
|
||||
const assistantMessage = block.assistant;
|
||||
const displayModel = assistantMessage?.model || "Assistant";
|
||||
const displayModel = assistantMessage?.model || t("playground.messageDisplay.assistantFallback");
|
||||
return (
|
||||
<div key={blockIndex} className="space-y-4">
|
||||
{block.user && (
|
||||
|
|
@ -110,7 +113,7 @@ export function MessageDisplay({ messages, isLoading }: MessageDisplayProps) {
|
|||
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-blue-100 text-blue-600">
|
||||
<UserRound size={16} />
|
||||
</div>
|
||||
<div className="text-sm font-semibold text-gray-700">You</div>
|
||||
<div className="text-sm font-semibold text-gray-700">{t("playground.messageDisplay.youLabel")}</div>
|
||||
</div>
|
||||
{renderMessageBody(block.user)}
|
||||
</div>
|
||||
|
|
@ -152,10 +155,10 @@ export function MessageDisplay({ messages, isLoading }: MessageDisplayProps) {
|
|||
) : isLoading && blockIndex === conversationBlocks.length - 1 ? (
|
||||
<div className="flex items-center gap-2 text-sm text-gray-500">
|
||||
<Loader2 size={18} className="animate-spin" />
|
||||
<span>Generating response...</span>
|
||||
<span>{t("playground.messageDisplay.generatingResponse")}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm text-gray-500">Waiting for a response...</div>
|
||||
<div className="text-sm text-gray-500">{t("playground.messageDisplay.waitingForResponse")}</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -163,7 +166,7 @@ export function MessageDisplay({ messages, isLoading }: MessageDisplayProps) {
|
|||
{isLoading && conversationBlocks.length === 0 && (
|
||||
<div className="flex items-center gap-2 text-gray-500">
|
||||
<Loader2 size={18} className="animate-spin" />
|
||||
<span>Generating response...</span>
|
||||
<span>{t("playground.messageDisplay.generatingResponse")}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { Input, Button } from "antd";
|
||||
import { ArrowUpOutlined } from "@ant-design/icons";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const { TextArea } = Input;
|
||||
|
||||
|
|
@ -14,6 +15,7 @@ interface MessageInputProps {
|
|||
}
|
||||
|
||||
export function MessageInput({ value, onChange, onSend, disabled, hasAttachment, uploadComponent }: MessageInputProps) {
|
||||
const { t } = useTranslation();
|
||||
const canSend = !disabled && (value.trim().length > 0 || Boolean(hasAttachment));
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
||||
|
|
@ -33,7 +35,7 @@ export function MessageInput({ value, onChange, onSend, disabled, hasAttachment,
|
|||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Type your message... (Shift+Enter for new line)"
|
||||
placeholder={t("playground.messageInput.placeholder")}
|
||||
disabled={disabled}
|
||||
className="flex-1"
|
||||
autoSize={{ minRows: 1, maxRows: 4 }}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useMemo, useState } from "react";
|
||||
import { Select } from "antd";
|
||||
import { TextInput } from "@tremor/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
interface ModelSelectorProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
|
|
@ -9,6 +10,7 @@ interface ModelSelectorProps {
|
|||
disabled?: boolean;
|
||||
}
|
||||
export function ModelSelector({ value, onChange, models, loading, disabled }: ModelSelectorProps) {
|
||||
const { t } = useTranslation();
|
||||
const [isAddingCustom, setIsAddingCustom] = useState(false);
|
||||
const [customValue, setCustomValue] = useState("");
|
||||
|
||||
|
|
@ -55,7 +57,11 @@ export function ModelSelector({ value, onChange, models, loading, disabled }: Mo
|
|||
onChange={handleSelectChange}
|
||||
disabled={disabled}
|
||||
loading={loading}
|
||||
placeholder={loading ? "Loading models..." : "Select a model"}
|
||||
placeholder={
|
||||
loading
|
||||
? t("playground.compareModelSelector.loadingModels")
|
||||
: t("playground.compareModelSelector.selectModel")
|
||||
}
|
||||
className="w-full rounded-md"
|
||||
showSearch
|
||||
optionFilterProp="children"
|
||||
|
|
@ -65,12 +71,12 @@ export function ModelSelector({ value, onChange, models, loading, disabled }: Mo
|
|||
{model}
|
||||
</Select.Option>
|
||||
))}
|
||||
<Select.Option value="__custom__">+ Add custom model</Select.Option>
|
||||
<Select.Option value="__custom__">{t("playground.compareModelSelector.addCustomModel")}</Select.Option>
|
||||
</Select>
|
||||
{isAddingCustom && (
|
||||
<TextInput
|
||||
className="mt-2"
|
||||
placeholder="Custom Model Name (Enter to add)"
|
||||
placeholder={t("playground.compareModelSelector.customModelPlaceholder")}
|
||||
value={customValue}
|
||||
onValueChange={setCustomValue}
|
||||
onKeyDown={(event) => {
|
||||
|
|
|
|||
|
|
@ -4061,5 +4061,50 @@
|
|||
"uiSessionActiveDesc": "UI session active - context maintained client-side",
|
||||
"copyTooltipTitle": "Copy response ID to continue session:"
|
||||
}
|
||||
},
|
||||
"playground": {
|
||||
"compareUi": {
|
||||
"virtualKeySourceLabel": "Virtual Key Source",
|
||||
"currentUiSession": "Current UI Session",
|
||||
"virtualKeyOption": "Virtual Key",
|
||||
"enterVirtualKeyPlaceholder": "Enter Virtual Key",
|
||||
"endpointLabel": "Endpoint",
|
||||
"clearAllChats": "Clear All Chats",
|
||||
"compareUpToThreeModels": "Compare up to 3 models at a time",
|
||||
"addAnotherComparison": "Add another comparison",
|
||||
"addComparison": "Add Comparison",
|
||||
"attachmentReadyToSend": "Attachment ready to send",
|
||||
"uploadPreviewAlt": "Upload preview",
|
||||
"pdfLabel": "PDF",
|
||||
"imageLabel": "Image",
|
||||
"errorFetchingResponse": "Error fetching response: {{errorMessage}}",
|
||||
"provideVirtualKey": "Please provide a Virtual Key or select Current UI Session"
|
||||
},
|
||||
"comparisonPanel": {
|
||||
"syncSettingsAcrossModels": "Sync Settings Across Models",
|
||||
"generalSettings": "General Settings",
|
||||
"tagsLabel": "Tags",
|
||||
"vectorStoresLabel": "Vector Stores",
|
||||
"guardrailsLabel": "Guardrails",
|
||||
"advancedSettings": "Advanced Settings",
|
||||
"useAdvancedParameters": "Use Advanced Parameters",
|
||||
"temperatureLabel": "Temperature",
|
||||
"maxTokensLabel": "Max Tokens"
|
||||
},
|
||||
"messageDisplay": {
|
||||
"youLabel": "You",
|
||||
"generatingResponse": "Generating response...",
|
||||
"waitingForResponse": "Waiting for a response...",
|
||||
"assistantFallback": "Assistant"
|
||||
},
|
||||
"messageInput": {
|
||||
"placeholder": "Type your message... (Shift+Enter for new line)"
|
||||
},
|
||||
"compareModelSelector": {
|
||||
"loadingModels": "Loading models...",
|
||||
"selectModel": "Select a model",
|
||||
"addCustomModel": "+ Add custom model",
|
||||
"customModelPlaceholder": "Custom Model Name (Enter to add)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4061,5 +4061,50 @@
|
|||
"uiSessionActiveDesc": "UI 会话活跃 - 上下文在客户端维护",
|
||||
"copyTooltipTitle": "复制响应 ID 以继续会话:"
|
||||
}
|
||||
},
|
||||
"playground": {
|
||||
"compareUi": {
|
||||
"virtualKeySourceLabel": "虚拟密钥来源",
|
||||
"currentUiSession": "当前 UI 会话",
|
||||
"virtualKeyOption": "虚拟密钥",
|
||||
"enterVirtualKeyPlaceholder": "输入虚拟密钥",
|
||||
"endpointLabel": "端点",
|
||||
"clearAllChats": "清空所有对话",
|
||||
"compareUpToThreeModels": "最多同时对比 3 个模型",
|
||||
"addAnotherComparison": "添加新对比项",
|
||||
"addComparison": "添加对比",
|
||||
"attachmentReadyToSend": "附件已准备好发送",
|
||||
"uploadPreviewAlt": "上传预览",
|
||||
"pdfLabel": "PDF",
|
||||
"imageLabel": "图片",
|
||||
"errorFetchingResponse": "获取响应失败:{{errorMessage}}",
|
||||
"provideVirtualKey": "请提供虚拟密钥或选择当前 UI 会话"
|
||||
},
|
||||
"comparisonPanel": {
|
||||
"syncSettingsAcrossModels": "跨模型同步设置",
|
||||
"generalSettings": "常规设置",
|
||||
"tagsLabel": "标签",
|
||||
"vectorStoresLabel": "向量存储",
|
||||
"guardrailsLabel": "护栏",
|
||||
"advancedSettings": "高级设置",
|
||||
"useAdvancedParameters": "使用高级参数",
|
||||
"temperatureLabel": "Temperature",
|
||||
"maxTokensLabel": "最大 Token 数"
|
||||
},
|
||||
"messageDisplay": {
|
||||
"youLabel": "你",
|
||||
"generatingResponse": "正在生成响应...",
|
||||
"waitingForResponse": "等待响应...",
|
||||
"assistantFallback": "Assistant"
|
||||
},
|
||||
"messageInput": {
|
||||
"placeholder": "输入消息...(Shift+Enter 换行)"
|
||||
},
|
||||
"compareModelSelector": {
|
||||
"loadingModels": "加载模型中...",
|
||||
"selectModel": "选择模型",
|
||||
"addCustomModel": "+ 添加自定义模型",
|
||||
"customModelPlaceholder": "自定义模型名称(回车确认)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue