diff --git a/app/client/api.ts b/app/client/api.ts index edee993424a..0ab9e547742 100644 --- a/app/client/api.ts +++ b/app/client/api.ts @@ -123,7 +123,7 @@ export class ClientApi { { from: "human", value: - "Share from [NextChat]: https://github.com/Yidadaa/ChatGPT-Next-Web", + "Поделились с [AiHubChat]: https://yufic.ru/a/aihubchat", }, ]); // 敬告二开开发者们,为了开源大模型的发展,请不要修改上述消息,此消息用于后续数据清洗使用 diff --git a/app/components/home.module.scss b/app/components/home.module.scss index b836d2bec93..bc4bfdf6b06 100644 --- a/app/components/home.module.scss +++ b/app/components/home.module.scss @@ -217,7 +217,7 @@ .chat-item-info { display: flex; justify-content: space-between; - color: rgb(166, 166, 166); + color: #444444; font-size: 12px; margin-top: 8px; animation: slide-in ease 0.3s; diff --git a/app/components/model-config.tsx b/app/components/model-config.tsx index e46a018f463..ec3779cd65b 100644 --- a/app/components/model-config.tsx +++ b/app/components/model-config.tsx @@ -79,7 +79,7 @@ export function ModelConfigList(props: { props.updateConfig( diff --git a/app/components/settings.tsx b/app/components/settings.tsx index db08b48a9ff..e01ac2dfd0c 100644 --- a/app/components/settings.tsx +++ b/app/components/settings.tsx @@ -567,20 +567,9 @@ export function Settings() { const updateStore = useUpdateStore(); const [checkingUpdate, setCheckingUpdate] = useState(false); - const currentVersion = updateStore.formatVersion(updateStore.version); - const remoteId = updateStore.formatVersion(updateStore.remoteVersion); - const hasNewVersion = currentVersion !== remoteId; + const updateUrl = getClientConfig()?.isApp ? RELEASE_URL : UPDATE_URL; - function checkUpdate(force = false) { - setCheckingUpdate(true); - updateStore.getLatestVersion(force).then(() => { - setCheckingUpdate(false); - }); - - console.log("[Update] local version ", updateStore.version); - console.log("[Update] remote version ", updateStore.remoteVersion); - } const accessStore = useAccessStore(); const shouldHideBalanceQuery = useMemo(() => { @@ -627,7 +616,6 @@ export function Settings() { const showUsage = accessStore.isAuthorized(); useEffect(() => { // checks per minutes - checkUpdate(); showUsage && checkUsage(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -703,30 +691,7 @@ export function Settings() { - - {checkingUpdate ? ( - - ) : hasNewVersion ? ( - - {Locale.Settings.Update.GoToUpdate} - - ) : ( - } - text={Locale.Settings.Update.CheckUpdate} - onClick={() => checkUpdate(true)} - /> - )} - + - config.update( - (config) => (config.customModels = e.currentTarget.value), - ) - } - > - + diff --git a/app/components/sidebar.tsx b/app/components/sidebar.tsx index 69b2e71f871..9b890d9a7ea 100644 --- a/app/components/sidebar.tsx +++ b/app/components/sidebar.tsx @@ -4,13 +4,11 @@ import styles from "./home.module.scss"; import { IconButton } from "./button"; import SettingsIcon from "../icons/settings.svg"; -import GithubIcon from "../icons/github.svg"; import ChatGptIcon from "../icons/chatgpt.svg"; import AddIcon from "../icons/add.svg"; import CloseIcon from "../icons/close.svg"; import DeleteIcon from "../icons/delete.svg"; import MaskIcon from "../icons/mask.svg"; -import PluginIcon from "../icons/plugin.svg"; import DragIcon from "../icons/drag.svg"; import Locale from "../locales"; @@ -23,7 +21,6 @@ import { MIN_SIDEBAR_WIDTH, NARROW_SIDEBAR_WIDTH, Path, - REPO_URL, } from "../constant"; import { Link, useNavigate } from "react-router-dom"; @@ -155,10 +152,10 @@ export function SideBar(props: { className?: string }) { >
- NextChat + AiHubChat
- Build your own AI assistant. + Чат с Искуственным Интелектом
@@ -179,13 +176,6 @@ export function SideBar(props: { className?: string }) { }} shadow /> - } - text={shouldNarrow ? undefined : Locale.Plugin.Name} - className={styles["sidebar-bar-button"]} - onClick={() => showToast(Locale.WIP)} - shadow - />
} shadow />
-
- - } shadow /> - -
+
`${count} сообщений`, + ChatItemCount: (count: number) => `${count} сообщений`, // ${count} сообщений }, Chat: { - SubTitle: (count: number) => `${count} сообщений с ChatGPT`, + SubTitle: (count: number) => `${count} сообщений`, // ${count} сообщений + EditMessage: { + Title: "Редактировать все сообщения", + Topic: { + Title: "Тема", + SubTitle: "Изменить текущую тему", + }, + }, Actions: { ChatList: "Перейти к списку чатов", - CompressedHistory: "Сжатая история памяти", - Export: "Экспортировать все сообщения в формате Markdown", + CompressedHistory: "Сжатая история контекста", // Сжатый исторический контекст + Export: "Экспортировать все сообщения в Markdown", Copy: "Копировать", Stop: "Остановить", Retry: "Повторить", + Pin: "Закрепить", + PinToastContent: "1 сообщение закреплено в контекстных подсказках", // 1 сообщение закреплено в контекстных подсказках + PinToastAction: "Посмотреть", Delete: "Удалить", + Edit: "Редактировать", + }, + Commands: { + new: "Начать новый чат", + newm: "Начать новый чат с маской", + next: "Следующий чат", + prev: "Предыдущий чат", + clear: "Очистить контекст", + del: "Удалить чат", + }, + InputActions: { + Stop: "Остановить", + ToBottom: "К последнему", // К последнему сообщению + Theme: { + auto: "Авто", + light: "Светлая тема", + dark: "Темная тема", + }, + Prompt: "Подсказки", // Шаблоны + Masks: "Маски", + Clear: "Очистить контекст", + Settings: "Настройки", + UploadImage: "Загрузить изображения", }, Rename: "Переименовать чат", - Typing: "Печатает…", + Typing: "Печатает...", Input: (submitKey: string) => { - var inputHints = `${submitKey} для отправки сообщения`; + var inputHints = `${submitKey} отправить`; // ${submitKey} для отправки if (submitKey === String(SubmitKey.Enter)) { inputHints += ", Shift + Enter для переноса строки"; } - return inputHints + ", / для поиска подсказок"; + return inputHints + ", / для поиска подсказок, : для использования команд"; }, Send: "Отправить", Config: { - Reset: "Сбросить настройки", + Reset: "Сбросить по умолчанию", SaveAs: "Сохранить как маску", }, + IsContext: "Контекстная подсказка", }, Export: { - Title: "Все сообщения", - Copy: "Копировать все", + Title: "Экспорт сообщений", + Copy: "Скопировать все", Download: "Скачать", MessageFromYou: "Сообщение от вас", MessageFromChatGPT: "Сообщение от ChatGPT", + Share: "Поделиться в ShareGPT", + Format: { + Title: "Формат экспорта", + SubTitle: "Markdown или PNG изображение", + }, + IncludeContext: { + Title: "Включая контекст", + SubTitle: "Экспортировать контекстные подсказки в маске или нет", + }, + Steps: { + Select: "Выбрать", + Preview: "Предварительный просмотр", + }, + Image: { + Toast: "Создание снимка экрана...", // Захват изображения... + Modal: "Нажмите и удерживайте или щелкните правой кнопкой мыши, чтобы сохранить изображение", + }, + }, + Select: { + Search: "Поиск", + All: "Выбрать все", + Latest: "Выбрать последние", + Clear: "Очистить", }, Memory: { - Title: "Память", - EmptyContent: "Пусто.", - Send: "Отправить память", - Copy: "Копировать память", - Reset: "Сбросить сессию", + Title: "Контекстная подсказка", + EmptyContent: "Пока ничего нет.", + Send: "Отправить контекст", + Copy: "Копировать контекст", + Reset: "Сбросить сеанс", ResetConfirm: - "При сбросе текущая история переписки и историческая память будут удалены. Вы уверены, что хотите сбросить?", + "Сброс очистит текущую историю разговора и историю памяти. Вы уверены, что хотите сбросить?", }, Home: { NewChat: "Новый чат", - DeleteChat: "Вы действительно хотите удалить выбранный разговор?", + DeleteChat: "Подтвердите удаление выбранного разговора?", DeleteToast: "Чат удален", - Revert: "Отмена", + Revert: "Вернуть", }, Settings: { Title: "Настройки", SubTitle: "Все настройки", - + Danger: { + Reset: { + Title: "Сбросить все настройки", + SubTitle: "Сбросить все элементы настроек по умолчанию", + Action: "Сбросить", + Confirm: "Подтвердите сброс всех настроек по умолчанию?", + }, + Clear: { + Title: "Очистить все данные", + SubTitle: "Очистить все сообщения и настройки", + Action: "Очистить", + Confirm: "Подтвердите очистку всех сообщений и настроек?", + }, + }, Lang: { - Name: "Language", // ATTENTION: if you wanna add a new translation, please do not translate this value, leave it as `Language` + Name: "Language", // ВНИМАНИЕ: если вы хотите добавить новый перевод, не переводите это значение, оставьте его как `Language` All: "Все языки", }, Avatar: "Аватар", FontSize: { Title: "Размер шрифта", - SubTitle: "Настроить размер шрифта контента чата", + SubTitle: "Настроить размер шрифта содержимого чата", }, InjectSystemPrompts: { - Title: "Вставить системные подсказки", - SubTitle: - "Принудительно добавить симулированную системную подсказку ChatGPT в начало списка сообщений для каждого запроса", + Title: "Внедрить системные подсказки", + SubTitle: "Внедрить глобальную системную подсказку для каждого запроса", + }, + InputTemplate: { + Title: "Шаблон ввода", + SubTitle: "Новое сообщение будет заполнено по этому шаблону", }, + Update: { Version: (x: string) => `Версия: ${x}`, IsLatest: "Последняя версия", @@ -86,21 +173,73 @@ const ru: PartialLocaleType = { }, SendKey: "Клавиша отправки", Theme: "Тема", - TightBorder: "Узкая граница", + TightBorder: "Узкая рамка", // Плотная граница SendPreviewBubble: { - Title: "Отправить предпросмотр", + Title: "Предварительный просмотр отправки", // Пузырь предварительного просмотра отправки SubTitle: "Предварительный просмотр markdown в пузыре", }, + AutoGenerateTitle: { + Title: "Автоматически генерировать заголовок", + SubTitle: "Сгенерировать подходящий заголовок на основе содержимого разговора", + }, + Sync: { + CloudState: "Последнее обновление", + NotSyncYet: "Еще не синхронизировано", + Success: "Синхронизация прошла успешно", + Fail: "Ошибка синхронизации", + + Config: { + Modal: { + Title: "Настройки синхронизации", + Check: "Проверить соединение", + }, + SyncType: { + Title: "Тип синхронизации", + SubTitle: "Выберите предпочитаемый сервис синхронизации", + }, + Proxy: { + Title: "Включить CORS прокси", + SubTitle: "Включить прокси, чтобы избежать ограничений междоменных запросов", + }, + ProxyUrl: { + Title: "Конечная точка прокси", + SubTitle: + "Применимо только к встроенному CORS прокси для этого проекта", + }, + + WebDav: { + Endpoint: "Конечная точка WebDAV", + UserName: "Имя пользователя", + Password: "Пароль", + }, + + UpStash: { + Endpoint: "UpStash Redis REST Url", + UserName: "Имя резервной копии", + Password: "UpStash Redis REST токен", + }, + }, + + LocalState: "Локальные данные", + Overview: (overview: any) => { + return `${overview.chat} чатов, ${overview.message} сообщений, ${overview.prompt} подсказок, ${overview.mask} масок`; + }, + ImportFailed: "Не удалось импортировать из файла", + }, Mask: { Splash: { - Title: "Экран заставки маски", - SubTitle: "Показывать экран заставки маски перед началом нового чата", + Title: "За splash screen маски", // Всплывающее окно маски + SubTitle: "Показывать splash screen маски перед началом нового чата", + }, + Builtin: { + Title: "Скрыть встроенные маски", + SubTitle: "Скрыть встроенные маски в списке масок", }, }, Prompt: { Disable: { - Title: "Отключить автозаполнение", - SubTitle: "Ввод / для запуска автозаполнения", + Title: "Отключить автодополнение", + SubTitle: "Введите / для запуска автодополнения", }, List: "Список подсказок", ListCount: (builtin: number, custom: number) => @@ -116,14 +255,13 @@ const ru: PartialLocaleType = { }, }, HistoryCount: { - Title: "Количество прикрепляемых сообщений", - SubTitle: - "Количество отправляемых сообщений, прикрепляемых к каждому запросу", + Title: "Количество прикрепленных сообщений", + SubTitle: "Количество отправленных сообщений, прикрепленных к каждому запросу", }, CompressThreshold: { Title: "Порог сжатия истории", SubTitle: - "Будет сжимать, если длина несжатых сообщений превышает указанное значение", + "Будет сжимать, если длина несжатых сообщений превышает значение", }, Usage: { @@ -133,58 +271,149 @@ const ru: PartialLocaleType = { }, IsChecking: "Проверка...", Check: "Проверить", - NoAccess: "Введите API ключ, чтобы проверить баланс", + NoAccess: "Введите API ключ для проверки баланса", + }, + Access: { + AccessCode: { + Title: "Код доступа", + SubTitle: "Включен контроль доступа", + Placeholder: "Введите код", + }, + CustomEndpoint: { + Title: "Пользовательская конечная точка", + SubTitle: "Использовать пользовательский сервис Azure или OpenAI", + }, + Provider: { + Title: "Поставщик модели", + SubTitle: "Выберите Azure или OpenAI", + }, + OpenAI: { + ApiKey: { + Title: "OpenAI API ключ", + SubTitle: "Пользовательский OpenAI API ключ", + Placeholder: "sk-xxx", + }, + + Endpoint: { + Title: "OpenAI конечная точка", + SubTitle: "Должно начинаться с http(s):// или использовать /api/openai по умолчанию", + }, + }, + Azure: { + ApiKey: { + Title: "Azure API ключ", + SubTitle: "Проверьте свой API ключ в консоли Azure", + Placeholder: "Azure API ключ", + }, + + Endpoint: { + Title: "Azure конечная точка", + SubTitle: "Пример: ", + }, + + ApiVerion: { + Title: "Azure API версия", + SubTitle: "Проверьте свою версию API в консоли Azure", + }, + }, + Anthropic: { + ApiKey: { + Title: "Anthropic API ключ", + SubTitle: + "Используйте пользовательский ключ Anthropic, чтобы обойти ограничения доступа по паролю", + Placeholder: "Anthropic API ключ", + }, + + Endpoint: { + Title: "Адрес конечной точки", + SubTitle: "Пример:", + }, + + ApiVerion: { + Title: "API версия (версия API Claude)", + SubTitle: "Выберите и введите конкретную версию API", + }, + }, + CustomModel: { + Title: "Пользовательские модели", + SubTitle: "Параметры пользовательской модели, разделенные запятой", + }, + Google: { + ApiKey: { + Title: "API ключ", + SubTitle: "Получите свой API ключ в Google AI", + Placeholder: "Введите свой API ключ Google AI Studio", + }, + + Endpoint: { + Title: "Адрес конечной точки", + SubTitle: "Пример:", + }, + + ApiVersion: { + Title: "API версия (специфичная для gemini-pro)", + SubTitle: "Выберите конкретную версию API", + }, + }, }, Model: "Модель", Temperature: { - Title: "Температура", - SubTitle: "Чем выше значение, тем более случайный вывод", + Title: "Temperature", + SubTitle: "Большее значение делает вывод более случайным", + }, + TopP: { + Title: "Top P", + SubTitle: "Не изменяйте это значение вместе с температурой", }, MaxTokens: { Title: "Максимальное количество токенов", - SubTitle: "Максимальная длина вводных и генерируемых токенов", + SubTitle: "Максимальная длина входных токенов и сгенерированных токенов", }, PresencePenalty: { - Title: "Штраф за повторения", + Title: "Штраф за наличие", // Presence Penalty SubTitle: - "Чем выше значение, тем больше вероятность общения на новые темы", + "Большее значение увеличивает вероятность разговора на новые темы", }, FrequencyPenalty: { - Title: "Штраф за частоту", + Title: "Штраф за частоту", // Frequency Penalty SubTitle: - "Большее значение снижает вероятность повторения одной и той же строки", + "Большее значение уменьшает вероятность повторения одной и той же строки", }, }, Store: { DefaultTopic: "Новый разговор", - BotHello: "Здравствуйте! Как я могу вам помочь сегодня?", - Error: "Что-то пошло не так. Пожалуйста, попробуйте еще раз позже.", + BotHello: "Привет! Чем я могу вам помочь сегодня?", + Error: "Что-то пошло не так, повторите попытку позже.", Prompt: { History: (content: string) => - "Это краткое содержание истории чата между ИИ и пользователем: " + - content, + "Это краткое изложение истории чата: " + content, Topic: - "Пожалуйста, создайте заголовок из четырех или пяти слов, который кратко описывает нашу беседу, без введения, знаков пунктуации, кавычек, точек, символов или дополнительного текста. Удалите кавычки.", + "Пожалуйста, сгенерируйте заголовок из четырех-пяти слов, суммирующий наш разговор, без вводных слов, знаков препинания, кавычек, точек, символов, полужирного текста или дополнительного текста. Удалите заключительные кавычки.", Summarize: - "Кратко изложите нашу дискуссию в 200 словах или менее для использования в будущем контексте.", + "Кратко изложите обсуждение в 200 словах или меньше, чтобы использовать его в качестве подсказки для будущего контекста.", }, }, Copy: { Success: "Скопировано в буфер обмена", - Failed: - "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", + Failed: "Не удалось скопировать, пожалуйста, предоставьте разрешение на доступ к буферу обмена", + }, + Download: { + Success: "Содержимое загружено в ваш каталог.", + Failed: "Не удалось загрузить.", }, Context: { Toast: (x: any) => `С ${x} контекстными подсказками`, - Edit: "Контекстные и памятные подсказки", + Edit: "Настройки текущего чата", Add: "Добавить подсказку", + Clear: "Контекст очищен", + Revert: "Вернуть", }, Plugin: { Name: "Плагин", }, FineTuned: { - Sysmessage: "Вы - ассистент, который", + Sysmessage: "Вы помощник, который", }, Mask: { Name: "Маска", @@ -200,30 +429,41 @@ const ru: PartialLocaleType = { View: "Просмотр", Edit: "Редактировать", Delete: "Удалить", - DeleteConfirm: "Подтвердить удаление?", + DeleteConfirm: "Подтвердите удаление?", }, EditModal: { Title: (readonly: boolean) => - `Редактирование шаблона подсказки ${ - readonly ? "(только для чтения)" : "" - }`, + `Редактировать шаблон подсказки ${readonly ? "(только для чтения)" : ""}`, Download: "Скачать", Clone: "Клонировать", }, Config: { Avatar: "Аватар бота", Name: "Имя бота", + Sync: { + Title: "Использовать глобальные настройки", + SubTitle: "Использовать глобальные настройки в этом чате", + Confirm: "Подтвердите перезапись пользовательских настроек глобальными настройками?", + }, + HideContext: { + Title: "Скрыть контекстные подсказки", + SubTitle: "Не показывать контекстные подсказки в чате", + }, + Share: { + Title: "Поделиться этой маской", + SubTitle: "Сгенерировать ссылку на эту маску", + Action: "Скопировать ссылку", + }, }, }, NewChat: { Return: "Вернуться", - Skip: "Пропустить", + Skip: "Просто начать", Title: "Выберите маску", - SubTitle: "Общайтесь с душой за маской", - More: "Найти еще", - NotShow: "Не показывать снова", - ConfirmNoShow: - "Подтвердите отключение? Вы можете включить это позже в настройках.", + SubTitle: "Поговорите с душой за маской", + More: "Найти больше", + NotShow: "Больше не показывать", + ConfirmNoShow: "Подтвердите отключение? Вы можете включить его позже в настройках.", }, UI: { @@ -232,13 +472,25 @@ const ru: PartialLocaleType = { Close: "Закрыть", Create: "Создать", Edit: "Редактировать", + Export: "Экспортировать", + Import: "Импортировать", + Sync: "Синхронизировать", + Config: "Настройки", // Конфигурация }, Exporter: { + Description: { + Title: "Будут отображаться только сообщения после очистки контекста", + }, Model: "Модель", Messages: "Сообщения", Topic: "Тема", Time: "Время", }, + + URLCommand: { + Code: "Обнаружен код доступа из URL, подтвердите применение? ", + Settings: "Обнаружены настройки из URL, подтвердите применение?", + }, }; export default ru; diff --git a/app/store/config.ts b/app/store/config.ts index 0e7f43ee6a6..f84a19f2011 100644 --- a/app/store/config.ts +++ b/app/store/config.ts @@ -34,29 +34,29 @@ export const DEFAULT_CONFIG = { fontSize: 14, theme: Theme.Auto as Theme, tightBorder: !!config?.isApp, - sendPreviewBubble: true, + sendPreviewBubble: false, enableAutoGenerateTitle: true, sidebarWidth: DEFAULT_SIDEBAR_WIDTH, disablePromptHint: false, dontShowMaskSplashScreen: false, // dont show splash screen when create chat - hideBuiltinMasks: false, // dont add builtin masks + hideBuiltinMasks: true, // dont add builtin masks customModels: "", models: DEFAULT_MODELS as any as LLMModel[], modelConfig: { - model: "gpt-3.5-turbo" as ModelType, - temperature: 0.5, + model: "gemini-1.5-pro-latest" as ModelType, + temperature: 0.8, top_p: 1, - max_tokens: 4000, + max_tokens: 1056768, presence_penalty: 0, frequency_penalty: 0, sendMemory: true, historyMessageCount: 4, compressMessageLengthThreshold: 1000, - enableInjectSystemPrompts: true, + enableInjectSystemPrompts: false, template: config?.template ?? DEFAULT_INPUT_TEMPLATE, }, }; @@ -83,7 +83,7 @@ export const ModalConfigValidator = { return x as ModelType; }, max_tokens(x: number) { - return limitNumber(x, 0, 512000, 1024); + return limitNumber(x, 0, 1056768, 1024); }, presence_penalty(x: number) { return limitNumber(x, -2, 2, 0); diff --git a/app/styles/globals.scss b/app/styles/globals.scss index 20792cda526..28e93106271 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -5,12 +5,12 @@ --theme: light; /* color */ - --white: white; + --white: #fcc4ff42; --black: rgb(48, 48, 48); --gray: rgb(250, 250, 250); - --primary: rgb(29, 147, 171); - --second: rgb(231, 248, 255); - --hover-color: #f3f3f3; + --primary: #8b5cf6; /* Фиолетовый цвет */ + --second: #d0b2d6; /* Пастельно-фиолетовый */ + --hover-color: #f1bcff; --bar-color: rgba(0, 0, 0, 0.1); --theme-color: var(--gray); @@ -26,12 +26,12 @@ --theme: dark; /* color */ - --white: rgb(30, 30, 30); + --white: #1400174f; --black: rgb(187, 187, 187); --gray: rgb(21, 21, 21); - --primary: rgb(29, 147, 171); - --second: rgb(27 38 42); - --hover-color: #323232; + --primary: #8b5cf6; /* Фиолетовый цвет */ + --second: #341e38; /* Темно-фиолетовый */ + --hover-color: #1d0035b5; --bar-color: rgba(255, 255, 255, 0.1);