diff --git a/CHANGELOG.md b/CHANGELOG.md index bfb3605937e4..ce459bb57a78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,98 @@ # Changelog +### [Version 0.155.3](https://github.com/lobehub/lobe-chat/compare/v0.155.2...v0.155.3) + +Released on **2024-05-08** + +#### 💄 Styles + +- **misc**: Optimized MaxToken Slider. + +
+ +
+Improvements and Fixes + +#### Styles + +- **misc**: Optimized MaxToken Slider, closes [#2258](https://github.com/lobehub/lobe-chat/issues/2258) ([dfb892b](https://github.com/lobehub/lobe-chat/commit/dfb892b)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ +### [Version 0.155.2](https://github.com/lobehub/lobe-chat/compare/v0.155.1...v0.155.2) + +Released on **2024-05-08** + +
+ +
+Improvements and Fixes + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ +### [Version 0.155.1](https://github.com/lobehub/lobe-chat/compare/v0.155.0...v0.155.1) + +Released on **2024-05-07** + +#### 💄 Styles + +- **misc**: Improve llm list when all closed. + +
+ +
+Improvements and Fixes + +#### Styles + +- **misc**: Improve llm list when all closed, closes [#2409](https://github.com/lobehub/lobe-chat/issues/2409) ([1eb20c7](https://github.com/lobehub/lobe-chat/commit/1eb20c7)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ +## [Version 0.155.0](https://github.com/lobehub/lobe-chat/compare/v0.154.7...v0.155.0) + +Released on **2024-05-07** + +#### ✨ Features + +- **misc**: Add DataStatistics. + +
+ +
+Improvements and Fixes + +#### What's improved + +- **misc**: Add DataStatistics ([cf474bb](https://github.com/lobehub/lobe-chat/commit/cf474bb)) + +
+ +
+ +[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top) + +
+ ### [Version 0.154.7](https://github.com/lobehub/lobe-chat/compare/v0.154.6...v0.154.7) Released on **2024-05-07** diff --git a/locales/ar/common.json b/locales/ar/common.json index 99df7f245918..84cc49ef7c77 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -12,6 +12,12 @@ "copy": "نسخ", "copyFail": "فشل في النسخ", "copySuccess": "تم النسخ بنجاح", + "dataStatistics": { + "messages": "رسائل", + "sessions": "جلسات", + "today": "اليوم", + "topics": "مواضيع" + }, "defaultAgent": "مساعد افتراضي", "defaultSession": "جلسة افتراضية", "delete": "حذف", diff --git a/locales/ar/setting.json b/locales/ar/setting.json index 188a5d351458..4ad4c0cd7664 100644 --- a/locales/ar/setting.json +++ b/locales/ar/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "تكوين النموذج المخصص", "tokens": { - "title": "أقصى عدد من الرموز" + "title": "أقصى عدد من الرموز", + "unlimited": "غير محدود" }, "vision": { "extra": "سيتم تمكين قدرة تكوين تحميل الصور فقط في LobeChat من خلال هذا التكوين، مدى دعم التعرف على الصور يعتمد تمامًا على النموذج نفسه، يرجى اختبار قابلية التعرف على الصور لهذا النموذج بنفسك", diff --git a/locales/bg-BG/common.json b/locales/bg-BG/common.json index d7aa0a10d2a7..e6cc13e7b438 100644 --- a/locales/bg-BG/common.json +++ b/locales/bg-BG/common.json @@ -12,6 +12,12 @@ "copy": "Копирай", "copyFail": "Копирането не е успешно", "copySuccess": "Копирано успешно", + "dataStatistics": { + "messages": "Съобщения", + "sessions": "Сесии", + "today": "Днес", + "topics": "Теми" + }, "defaultAgent": "Агент по подразбиране", "defaultSession": "Агент по подразбиране", "delete": "Изтрий", diff --git a/locales/bg-BG/setting.json b/locales/bg-BG/setting.json index 3326ce875b36..01ab04b0e64b 100644 --- a/locales/bg-BG/setting.json +++ b/locales/bg-BG/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Конфигурация на персонализиран модел", "tokens": { - "title": "Максимален брой токени" + "title": "Максимален брой токени", + "unlimited": "неограничен" }, "vision": { "extra": "Тази конфигурация ще активира само възможността за качване на изображения в LobeChat. Възможността за разпознаване на изображения зависи изцяло от самия модел. Моля, тествайте функционалността за разпознаване на изображения на модела.", diff --git a/locales/de-DE/common.json b/locales/de-DE/common.json index 4fa2e66ed98d..d51112cccb4d 100644 --- a/locales/de-DE/common.json +++ b/locales/de-DE/common.json @@ -12,6 +12,12 @@ "copy": "Kopieren", "copyFail": "Kopieren fehlgeschlagen", "copySuccess": "Kopieren erfolgreich", + "dataStatistics": { + "messages": "Nachrichten", + "sessions": "Sitzungen", + "today": "Heute", + "topics": "Themen" + }, "defaultAgent": "Standardassistent", "defaultSession": "Standardassistent", "delete": "Löschen", diff --git a/locales/de-DE/setting.json b/locales/de-DE/setting.json index b8aba7e1764e..9b0e9016d657 100644 --- a/locales/de-DE/setting.json +++ b/locales/de-DE/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Benutzerdefinierte Modellkonfiguration", "tokens": { - "title": "Maximale Token-Anzahl" + "title": "Maximale Token-Anzahl", + "unlimited": "unbegrenzt" }, "vision": { "extra": "Diese Konfiguration aktiviert nur die Bild-Upload-Konfiguration in LobeChat. Die Unterstützung der Erkennung hängt vollständig von dem Modell selbst ab. Bitte testen Sie die Verfügbarkeit der visuellen Erkennungsfähigkeiten des Modells selbst.", diff --git a/locales/en-US/common.json b/locales/en-US/common.json index 59df757ff0e0..540b39ec6342 100644 --- a/locales/en-US/common.json +++ b/locales/en-US/common.json @@ -12,6 +12,12 @@ "copy": "Copy", "copyFail": "Copy failed", "copySuccess": "Copied successfully", + "dataStatistics": { + "messages": "Messages", + "sessions": "Assistants", + "today": "Today's New", + "topics": "Topics" + }, "defaultAgent": "Default Agent", "defaultSession": "Default Agent", "delete": "Delete", diff --git a/locales/en-US/setting.json b/locales/en-US/setting.json index 5b6bd98f7a9e..962680e31477 100644 --- a/locales/en-US/setting.json +++ b/locales/en-US/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Custom Model Configuration", "tokens": { - "title": "Maximum Token Count" + "title": "Maximum Token Count", + "unlimited": "unlimited" }, "vision": { "extra": "This configuration will only enable the image upload configuration in LobeChat. Whether recognition is supported depends entirely on the model itself. Please test the availability of visual recognition in this model on your own.", diff --git a/locales/es-ES/common.json b/locales/es-ES/common.json index ca78e29e5631..ec2005854e74 100644 --- a/locales/es-ES/common.json +++ b/locales/es-ES/common.json @@ -12,6 +12,12 @@ "copy": "Copiar", "copyFail": "Fallo al copiar", "copySuccess": "¡Copia exitosa!", + "dataStatistics": { + "messages": "Mensajes", + "sessions": "Sesiones", + "today": "Hoy", + "topics": "Temas" + }, "defaultAgent": "Asistente predeterminado", "defaultSession": "Sesión predeterminada", "delete": "Eliminar", diff --git a/locales/es-ES/setting.json b/locales/es-ES/setting.json index 9c38d8ea8c97..482aa6c1bc6f 100644 --- a/locales/es-ES/setting.json +++ b/locales/es-ES/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Configuración del modelo personalizado", "tokens": { - "title": "Número máximo de tokens" + "title": "Número máximo de tokens", + "unlimited": "ilimitado" }, "vision": { "extra": "Esta configuración solo habilitará la configuración de carga de imágenes en LobeChat. La capacidad de reconocimiento depende completamente del modelo en sí. Por favor, realiza pruebas para verificar la disponibilidad de esta capacidad en el modelo.", diff --git a/locales/fr-FR/common.json b/locales/fr-FR/common.json index c7417add28a2..f213aabb1357 100644 --- a/locales/fr-FR/common.json +++ b/locales/fr-FR/common.json @@ -12,6 +12,12 @@ "copy": "Copier", "copyFail": "Échec de la copie", "copySuccess": "Copie réussie", + "dataStatistics": { + "messages": "Messages", + "sessions": "Sessions", + "today": "Aujourd'hui", + "topics": "Sujets" + }, "defaultAgent": "Agent par défaut", "defaultSession": "Session par défaut", "delete": "Supprimer", diff --git a/locales/fr-FR/setting.json b/locales/fr-FR/setting.json index 4462a3b3a171..310ab92745ab 100644 --- a/locales/fr-FR/setting.json +++ b/locales/fr-FR/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Configuration du modèle personnalisé", "tokens": { - "title": "Nombre maximal de jetons" + "title": "Nombre maximal de jetons", + "unlimited": "illimité" }, "vision": { "extra": "Cette configuration activera uniquement la configuration de téléchargement d'images dans LobeChat. La prise en charge de la reconnaissance dépend entièrement du modèle lui-même. Veuillez tester par vous-même la disponibilité de la capacité de reconnaissance visuelle de ce modèle.", diff --git a/locales/it-IT/common.json b/locales/it-IT/common.json index f202f8eae5f9..e5803e646d6a 100644 --- a/locales/it-IT/common.json +++ b/locales/it-IT/common.json @@ -12,6 +12,12 @@ "copy": "Copia", "copyFail": "Copia non riuscita", "copySuccess": "Copia riuscita", + "dataStatistics": { + "messages": "Messaggi", + "sessions": "Sessioni", + "today": "Oggi", + "topics": "Argomenti" + }, "defaultAgent": "Assistente predefinito", "defaultSession": "Sessione predefinita", "delete": "Elimina", diff --git a/locales/it-IT/setting.json b/locales/it-IT/setting.json index 4479c0969545..e4ae685bbef5 100644 --- a/locales/it-IT/setting.json +++ b/locales/it-IT/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Configurazione del modello personalizzato", "tokens": { - "title": "Numero massimo di token" + "title": "Numero massimo di token", + "unlimited": "illimitato" }, "vision": { "extra": "Questa configurazione abiliterà solo la funzionalità di caricamento delle immagini in LobeChat. La reale capacità di riconoscimento dipende interamente dal modello stesso, si consiglia di testare autonomamente la disponibilità di questa funzionalità nel modello.", diff --git a/locales/ja-JP/common.json b/locales/ja-JP/common.json index ee0a5635cd39..2d5e7dda93d8 100644 --- a/locales/ja-JP/common.json +++ b/locales/ja-JP/common.json @@ -12,6 +12,12 @@ "copy": "コピー", "copyFail": "コピーに失敗しました", "copySuccess": "コピーが成功しました", + "dataStatistics": { + "messages": "メッセージ", + "sessions": "セッション", + "today": "今日の追加", + "topics": "トピック" + }, "defaultAgent": "デフォルトエージェント", "defaultSession": "デフォルトセッション", "delete": "削除", diff --git a/locales/ja-JP/setting.json b/locales/ja-JP/setting.json index bd16d9e9b62c..77b54358fe1b 100644 --- a/locales/ja-JP/setting.json +++ b/locales/ja-JP/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "カスタムモデルの設定", "tokens": { - "title": "最大トークン数" + "title": "最大トークン数", + "unlimited": "無制限" }, "vision": { "extra": "この設定は LobeChat での画像アップロード構成のみを有効にします。認識のサポートは完全にモデル自体に依存するため、モデルの視覚認識機能の可用性を自己でテストしてください", diff --git a/locales/ko-KR/common.json b/locales/ko-KR/common.json index 21cd1ef4dc3b..1bba196c00e1 100644 --- a/locales/ko-KR/common.json +++ b/locales/ko-KR/common.json @@ -12,6 +12,12 @@ "copy": "복사", "copyFail": "복사 실패", "copySuccess": "복사 성공", + "dataStatistics": { + "messages": "메시지", + "sessions": "세션", + "today": "오늘", + "topics": "주제" + }, "defaultAgent": "기본 에이전트", "defaultSession": "기본 세션", "delete": "삭제", diff --git a/locales/ko-KR/setting.json b/locales/ko-KR/setting.json index de24e392a164..3f1ea2060e25 100644 --- a/locales/ko-KR/setting.json +++ b/locales/ko-KR/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "사용자 정의 모델 구성", "tokens": { - "title": "최대 토큰 수" + "title": "최대 토큰 수", + "unlimited": "제한 없는" }, "vision": { "extra": "이 구성은 LobeChat에서 이미지 업로드 구성만 활성화하며, 인식 지원 여부는 모델 자체에 따라 달라집니다. 모델의 시각 인식 기능을 테스트해보세요", diff --git a/locales/nl-NL/common.json b/locales/nl-NL/common.json index d723fe9eb29a..18fce3d33b58 100644 --- a/locales/nl-NL/common.json +++ b/locales/nl-NL/common.json @@ -12,6 +12,12 @@ "copy": "Kopiëren", "copyFail": "Kopiëren mislukt", "copySuccess": "Kopiëren gelukt", + "dataStatistics": { + "messages": "Berichten", + "sessions": "Sessies", + "today": "Vandaag", + "topics": "Onderwerpen" + }, "defaultAgent": "Standaard assistent", "defaultSession": "Standaard assistent", "delete": "Verwijderen", diff --git a/locales/nl-NL/setting.json b/locales/nl-NL/setting.json index fed1c4a904c4..a7212965229b 100644 --- a/locales/nl-NL/setting.json +++ b/locales/nl-NL/setting.json @@ -58,30 +58,31 @@ }, "files": { "extra": "Currently, the file upload implementation in LobeChat is just a temporary solution and is for self-exploration only. Please wait for the full file upload capability in the future.", - "title": "Support File Upload" + "title": "Ondersteuning voor het uploaden van bestanden" }, "functionCall": { - "extra": "This configuration will only enable the function call capability in LobeChat. Whether function calls are supported depends entirely on the model itself. Please test the availability of function calls of this model on your own.", - "title": "Support Function Call" + "extra": "Deze configuratie schakelt alleen de functieaanroepmogelijkheid in LobeChat in. Of functieaanroepen worden ondersteund, hangt volledig af van het model zelf. Test zelf de beschikbaarheid van functieaanroepen van dit model.", + "title": "Ondersteuningsfunctie Oproep" }, "id": { - "extra": "Will be displayed as the model tag", - "placeholder": "Please enter the model ID, for example gpt-4-turbo-preview or claude-2.1", + "extra": "Wordt weergegeven als de modeltag", + "placeholder": "Voer de model ID in, bijvoorbeeld gpt-4-turbo-preview of claude-2.1", "title": "Model ID" }, - "modalTitle": "Custom Model Configuration", + "modalTitle": "Aangepaste modelconfiguratie", "tokens": { - "title": "Maximum Token Count" + "title": "Maximaal tokenaantal", + "unlimited": "onbeperkt" }, "vision": { - "extra": "This configuration will only enable the image upload feature in LobeChat. Whether image recognition is supported depends entirely on the model itself. Please test the availability of visual recognition capability of this model on your own.", - "title": "Support Visual Recognition" + "extra": "Deze configuratie schakelt alleen de configuratie voor het uploaden van afbeeldingen in LobeChat in. Of herkenning wordt ondersteund, hangt volledig af van het model zelf. Test zelf de beschikbaarheid van visuele herkenning in dit model.", + "title": "Ondersteuning van visuele herkenning" } } }, "fetchOnClient": { - "desc": "使用客户端请求模式将直接从浏览器发起会话请求,可提升响应速度", - "title": "使用客户端请求模式" + "desc": "De ophaalmodus aan de clientzijde initieert sessieverzoeken rechtstreeks vanuit de browser, waardoor de reactiesnelheid wordt verbeterd.", + "title": "Gebruik de ophaalmodus aan de clientzijde" }, "fetcher": { "fetch": "Haal model lijst op", diff --git a/locales/pl-PL/common.json b/locales/pl-PL/common.json index 4236ed957e4b..18270eeed8c9 100644 --- a/locales/pl-PL/common.json +++ b/locales/pl-PL/common.json @@ -12,6 +12,12 @@ "copy": "Kopiuj", "copyFail": "Nie udało się skopiować", "copySuccess": "Skopiowano pomyślnie", + "dataStatistics": { + "messages": "Wiadomości", + "sessions": "Sesje", + "today": "Dzisiaj", + "topics": "Tematy" + }, "defaultAgent": "Domyślny asystent", "defaultSession": "Domyślna sesja", "delete": "Usuń", diff --git a/locales/pl-PL/setting.json b/locales/pl-PL/setting.json index 582be486551f..4253b0df6b9b 100644 --- a/locales/pl-PL/setting.json +++ b/locales/pl-PL/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Konfiguracja niestandardowego modelu", "tokens": { - "title": "Maksymalna liczba tokenów" + "title": "Maksymalna liczba tokenów", + "unlimited": "Nieograniczony" }, "vision": { "extra": "Ta konfiguracja aktywuje tylko możliwość przesyłania obrazów w LobeChat. Możliwość rozpoznawania zależy wyłącznie od modelu. Proszę przetestować dostępność rozpoznawania wizyjnego tego modelu", diff --git a/locales/pt-BR/common.json b/locales/pt-BR/common.json index 67304744ac55..166775a3f83b 100644 --- a/locales/pt-BR/common.json +++ b/locales/pt-BR/common.json @@ -12,6 +12,12 @@ "copy": "Copiar", "copyFail": "Falha ao copiar", "copySuccess": "Cópia bem-sucedida", + "dataStatistics": { + "messages": "Mensagens", + "sessions": "Sessões", + "today": "Hoje", + "topics": "Tópicos" + }, "defaultAgent": "Assistente padrão", "defaultSession": "Sessão padrão", "delete": "Excluir", diff --git a/locales/pt-BR/setting.json b/locales/pt-BR/setting.json index de2142df7c51..d8e61d59647b 100644 --- a/locales/pt-BR/setting.json +++ b/locales/pt-BR/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Configuração de Modelo Personalizado", "tokens": { - "title": "Número Máximo de Tokens" + "title": "Número Máximo de Tokens", + "unlimited": "ilimitado" }, "vision": { "extra": "Esta configuração ativará apenas a configuração de upload de imagens no LobeChat. A capacidade de reconhecimento depende inteiramente do modelo em si. Por favor, teste a disponibilidade da capacidade de reconhecimento visual deste modelo.", diff --git a/locales/ru-RU/common.json b/locales/ru-RU/common.json index cbaa801031ce..4a897c4bf17d 100644 --- a/locales/ru-RU/common.json +++ b/locales/ru-RU/common.json @@ -12,6 +12,12 @@ "copy": "Копировать", "copyFail": "Не удалось скопировать", "copySuccess": "Успешно скопировано", + "dataStatistics": { + "messages": "Сообщения", + "sessions": "Сессии", + "today": "Сегодня", + "topics": "Темы" + }, "defaultAgent": "Пользовательский агент", "defaultSession": "Пользовательский агент", "delete": "Удалить", diff --git a/locales/ru-RU/setting.json b/locales/ru-RU/setting.json index 2adb09c57d63..8708dafb83d8 100644 --- a/locales/ru-RU/setting.json +++ b/locales/ru-RU/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Настройка пользовательской модели", "tokens": { - "title": "Максимальное количество токенов" + "title": "Максимальное количество токенов", + "unlimited": "неограниченный" }, "vision": { "extra": "Эта настройка активирует только конфигурацию загрузки изображений в LobeChat. Поддержка распознавания полностью зависит от самой модели, пожалуйста, протестируйте доступность распознавания изображений этой модели самостоятельно", diff --git a/locales/tr-TR/common.json b/locales/tr-TR/common.json index 638b20cadf1c..b9be9e374623 100644 --- a/locales/tr-TR/common.json +++ b/locales/tr-TR/common.json @@ -12,6 +12,12 @@ "copy": "Kopyala", "copyFail": "Kopyalama başarısız oldu", "copySuccess": "Kopyalama Başarılı", + "dataStatistics": { + "messages": "Mesajlar", + "sessions": "Oturumlar", + "today": "Bugün", + "topics": "Konular" + }, "defaultAgent": "Varsayılan Asistan", "defaultSession": "Varsayılan Asistan", "delete": "Sil", diff --git a/locales/tr-TR/setting.json b/locales/tr-TR/setting.json index 18b2ba254645..9d170c515495 100644 --- a/locales/tr-TR/setting.json +++ b/locales/tr-TR/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Özel Model Yapılandırması", "tokens": { - "title": "Maksimum token sayısı" + "title": "Maksimum token sayısı", + "unlimited": "Sınırsız" }, "vision": { "extra": "Bu yapılandırma yalnızca LobeChat'teki görüntü yükleme yapılandırmasını etkinleştirir, tanıma desteğinin olup olmadığı tamamen modelin kendisine bağlıdır, bu modelin görüntü tanıma yeteneğini test etmek size kalmıştır", diff --git a/locales/vi-VN/common.json b/locales/vi-VN/common.json index c959b78fff04..6033397b35f8 100644 --- a/locales/vi-VN/common.json +++ b/locales/vi-VN/common.json @@ -12,6 +12,12 @@ "copy": "Sao chép", "copyFail": "Sao chép thất bại", "copySuccess": "Sao chép thành công", + "dataStatistics": { + "messages": "Tin nhắn", + "sessions": "Phiên làm việc", + "today": "Hôm nay", + "topics": "Chủ đề" + }, "defaultAgent": "Trợ lý mặc định", "defaultSession": "Phiên mặc định", "delete": "Xóa", diff --git a/locales/vi-VN/setting.json b/locales/vi-VN/setting.json index cdd9a17fc3be..de4e6ddbccf5 100644 --- a/locales/vi-VN/setting.json +++ b/locales/vi-VN/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "Cấu hình mô hình tùy chỉnh", "tokens": { - "title": "Số lượng token tối đa" + "title": "Số lượng token tối đa", + "unlimited": "vô hạn" }, "vision": { "extra": "Cấu hình này chỉ mở khả năng tải lên hình ảnh trong LobeChat, việc hỗ trợ nhận diện hoàn toàn phụ thuộc vào mô hình chính mình, hãy tự kiểm tra tính khả dụng của khả năng nhận diện hình ảnh của mô hình", diff --git a/locales/zh-CN/common.json b/locales/zh-CN/common.json index 8d6057937916..49cc822bfb32 100644 --- a/locales/zh-CN/common.json +++ b/locales/zh-CN/common.json @@ -12,6 +12,12 @@ "copy": "复制", "copyFail": "复制失败", "copySuccess": "复制成功", + "dataStatistics": { + "messages": "消息", + "sessions": "助手", + "today": "今日新增", + "topics": "话题" + }, "defaultAgent": "自定义助手", "defaultSession": "自定义助手", "delete": "删除", diff --git a/locales/zh-CN/setting.json b/locales/zh-CN/setting.json index 5a9e5dd56cbe..fbe3fc79ef9c 100644 --- a/locales/zh-CN/setting.json +++ b/locales/zh-CN/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "自定义模型配置", "tokens": { - "title": "最大 token 数" + "title": "最大 token 数", + "unlimited": "无限制" }, "vision": { "extra": "此配置将仅开启 LobeChat 中的图片上传配置,是否支持识别完全取决于模型本身,请自行测试该模型的视觉识别能力可用性", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index b0d561ad60c5..5e728b070408 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -12,6 +12,12 @@ "copy": "複製", "copyFail": "複製失敗", "copySuccess": "複製成功", + "dataStatistics": { + "messages": "消息", + "sessions": "助手", + "today": "今日新增", + "topics": "話題" + }, "defaultAgent": "預設助手", "defaultSession": "預設助手", "delete": "刪除", diff --git a/locales/zh-TW/setting.json b/locales/zh-TW/setting.json index acad5e84b8d6..2e366c4e22c5 100644 --- a/locales/zh-TW/setting.json +++ b/locales/zh-TW/setting.json @@ -71,7 +71,8 @@ }, "modalTitle": "自定義模型配置", "tokens": { - "title": "最大 token 數" + "title": "最大 token 數", + "unlimited": "無限制" }, "vision": { "extra": "此配置將僅開啟 LobeChat 中的圖片上傳配置,是否支持識別完全取決於模型本身,請自行測試該模型的視覺識別能力可用性", diff --git a/package.json b/package.json index f952ba46a610..774148d5546b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@lobehub/chat", - "version": "0.154.7", + "version": "0.155.3", "description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.", "keywords": [ "framework", diff --git a/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx b/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx index 4667cca9bf24..a0d733b300fb 100644 --- a/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx +++ b/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx @@ -4,13 +4,12 @@ import { PropsWithChildren, memo } from 'react'; import { Flexbox } from 'react-layout-kit'; import UserAvatar from '@/features/User/UserAvatar'; -import UserInfo from '@/features/User/UserInfo'; import { useStyles } from './style'; export const AVATAR_SIZE = 80; -const AvatarBanner = memo(() => { +const AvatarBanner = memo(({ children }) => { const { styles } = useStyles(); return ( @@ -20,7 +19,7 @@ const AvatarBanner = memo(() => { - + {children} ); }); diff --git a/src/app/(main)/(mobile)/me/loading.tsx b/src/app/(main)/(mobile)/me/loading.tsx index 48dd598b1de4..eacbe24611ed 100644 --- a/src/app/(main)/(mobile)/me/loading.tsx +++ b/src/app/(main)/(mobile)/me/loading.tsx @@ -4,6 +4,7 @@ import { Skeleton } from 'antd'; import { memo } from 'react'; import { Flexbox } from 'react-layout-kit'; +import Divider from '@/components/Cell/Divider'; import SkeletonLoading from '@/components/SkeletonLoading'; import { useStyles } from './features/style'; @@ -22,9 +23,25 @@ const Loading = memo(() => { paddingInline={12} > - + - + + + + + + + + + ); }); diff --git a/src/app/(main)/(mobile)/me/page.tsx b/src/app/(main)/(mobile)/me/page.tsx index 783d4fc24773..74fc75fc6fa8 100644 --- a/src/app/(main)/(mobile)/me/page.tsx +++ b/src/app/(main)/(mobile)/me/page.tsx @@ -3,6 +3,8 @@ import { Center } from 'react-layout-kit'; import BrandWatermark from '@/components/BrandWatermark'; import Divider from '@/components/Cell/Divider'; +import DataStatistics from '@/features/User/DataStatistics'; +import UserInfo from '@/features/User/UserInfo'; import { isMobileDevice } from '@/utils/responsive'; import AvatarBanner from './features/AvatarBanner'; @@ -16,7 +18,10 @@ const Page = () => { return ( <> - + + + + diff --git a/src/app/(main)/settings/llm/components/ProviderModelList/MaxTokenSlider.tsx b/src/app/(main)/settings/llm/components/ProviderModelList/MaxTokenSlider.tsx index 628ddbc66f88..3094f2ab9a97 100644 --- a/src/app/(main)/settings/llm/components/ProviderModelList/MaxTokenSlider.tsx +++ b/src/app/(main)/settings/llm/components/ProviderModelList/MaxTokenSlider.tsx @@ -1,23 +1,17 @@ -import { InputNumber, Slider, SliderSingleProps } from 'antd'; -import { memo } from 'react'; +import { InputNumber, Slider } from 'antd'; +import { memo, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; import { Flexbox } from 'react-layout-kit'; import useMergeState from 'use-merge-value'; +import { useServerConfigStore } from '@/store/serverConfig'; +import { serverConfigSelectors } from '@/store/serverConfig/selectors'; + +const Kibi = 1024; + const exponent = (num: number) => Math.log2(num); const getRealValue = (num: number) => Math.round(Math.pow(2, num)); - -const marks: SliderSingleProps['marks'] = { - [exponent(1)]: '1k', - [exponent(2)]: '2k', - [exponent(4)]: '4k', - [exponent(8)]: '8k', - [exponent(16)]: '16k', - [exponent(32)]: '32k', - [exponent(64)]: '64k', - [exponent(128)]: '128k', - [exponent(200)]: '200k', - [exponent(1000)]: '1M', -}; +const powerKibi = (num: number) => Math.round(Math.pow(2, num) * Kibi); interface MaxTokenSliderProps { defaultValue?: number; @@ -26,6 +20,8 @@ interface MaxTokenSliderProps { } const MaxTokenSlider = memo(({ value, onChange, defaultValue }) => { + const { t } = useTranslation('setting'); + const [token, setTokens] = useMergeState(0, { defaultValue, onChange, @@ -33,39 +29,57 @@ const MaxTokenSlider = memo(({ value, onChange, defaultValu }); const [powValue, setPowValue] = useMergeState(0, { - defaultValue: exponent(typeof defaultValue === 'undefined' ? 0 : defaultValue / 1000), - value: exponent(typeof value === 'undefined' ? 0 : value / 1000), + defaultValue: exponent(typeof defaultValue === 'undefined' ? 0 : defaultValue / 1024), + value: exponent(typeof value === 'undefined' ? 0 : value / Kibi), }); const updateWithPowValue = (value: number) => { setPowValue(value); - setTokens(getRealValue(value) * 1024); + setTokens(getRealValue(value) === 1 ? 0 : powerKibi(value)); }; + const updateWithRealValue = (value: number) => { - setTokens(value); + setTokens(Math.round(value)); - setPowValue(exponent(value / 1024)); + setPowValue(exponent(value / Kibi)); }; + const isMobile = useServerConfigStore(serverConfigSelectors.isMobile); + + const marks = useMemo(() => { + return { + [exponent(1)]: '0', + [exponent(2)]: isMobile ? '2' : '2K', // 2 Kibi = 2048 + [exponent(4)]: isMobile ? '4' : '4K', + [exponent(8)]: isMobile ? '8' : '8K', + [exponent(16)]: isMobile ? '16' : '16K', + [exponent(32)]: isMobile ? '32' : '32K', + [exponent(64)]: isMobile ? '64' : '64K', + [exponent((128 / Kibi) * 1000)]: ' ', // hide tick mark + [exponent((200 / Kibi) * 1000)]: isMobile ? '200' : '200k', // 200,000 + [exponent(Kibi)]: isMobile ? '1024' : '1M', + }; + }, [isMobile]); + return ( { if (typeof x === 'undefined') return; + if (x === 0) return t('llm.customModelCards.modelConfig.tokens.unlimited'); - const value = getRealValue(x); - - if (value < 1000) return value.toFixed(0) + 'K'; - - return (value / 1000).toFixed(0) + 'M'; + let value = getRealValue(x); + if (value < 125) return value.toFixed(0) + 'K'; + else if (value < Kibi) return ((value * Kibi) / 1000).toFixed(0) + 'k'; + return (value / Kibi).toFixed(0) + 'M'; }, }} value={powValue} @@ -73,12 +87,13 @@ const MaxTokenSlider = memo(({ value, onChange, defaultValu
{ - if (!e) return; + if (!e && e !== 0) return; updateWithRealValue(e); }} - step={1024} + step={2 * Kibi} value={token} />
diff --git a/src/components/ModelSelect/index.tsx b/src/components/ModelSelect/index.tsx index addaa0acd469..5b8799711851 100644 --- a/src/components/ModelSelect/index.tsx +++ b/src/components/ModelSelect/index.tsx @@ -1,6 +1,6 @@ import { Icon, Tooltip } from '@lobehub/ui'; import { createStyles } from 'antd-style'; -import { LucideEye, LucidePaperclip, ToyBrick } from 'lucide-react'; +import { Infinity, LucideEye, LucidePaperclip, ToyBrick } from 'lucide-react'; import numeral from 'numeral'; import { rgba } from 'polished'; import { memo } from 'react'; @@ -57,10 +57,14 @@ const useStyles = createStyles(({ css, token }) => ({ `, })); const formatTokenNumber = (num: number): string => { - if (num < 1000) return '1K'; - const kiloToken = Math.floor(num / 1000); + if (num > 0 && num < 1024) return '1K'; + + let kiloToken = Math.floor(num / 1024); + if (num >= 128_000 && num < 1_024_000) { + kiloToken = Math.floor(num / 1000); + } return kiloToken < 1000 ? `${kiloToken}K` : `${Math.floor(kiloToken / 1000)}M`; -} +}; interface ModelInfoTagsProps extends ChatModelCard { directionReverse?: boolean; @@ -83,7 +87,7 @@ export const ModelInfoTags = memo( )} {model.vision && ( -
+
@@ -94,20 +98,26 @@ export const ModelInfoTags = memo( placement={placement} title={t('ModelSelect.featureTag.functionCall')} > -
+
)} - {model.tokens && ( + {model.tokens !== undefined && ( -
{formatTokenNumber(model.tokens)}
+
+ {model.tokens === 0 ? ( + + ) : ( + formatTokenNumber(model.tokens) + )} +
)} {/*{model.isCustom && (*/} diff --git a/src/database/client/core/model.ts b/src/database/client/core/model.ts index 100391797ef7..eb2d95509f10 100644 --- a/src/database/client/core/model.ts +++ b/src/database/client/core/model.ts @@ -106,7 +106,7 @@ export class BaseModel ({ + card: css` + padding: 6px 8px; + background: ${token.colorFillTertiary}; + border-radius: ${token.borderRadius}px; + `, + count: css` + font-size: 16px; + font-weight: bold; + line-height: 1.2; + `, + title: css` + font-size: 12px; + line-height: 1.2; + color: ${token.colorTextDescription}; + `, + today: css` + font-size: 12px; + `, +})); + +const formatNumber = (num: any) => { + if (!isNumber(num)) return num; + // 使用Intl.NumberFormat来添加千分号 + const formattedWithComma = new Intl.NumberFormat('en-US').format(num); + + // 格式化为 K 或 M + if (num >= 10_000_000) { + return (num / 1_000_000).toFixed(1) + 'M'; + } else if (num >= 10_000) { + return (num / 1000).toFixed(1) + 'K'; + } else if (num === 0) { + return 0; + } else { + return formattedWithComma; + } +}; + +const DataStatistics = memo>(({ style, ...rest }) => { + // sessions + const { data: sessions, isLoading: sessionsLoading } = useSWR( + 'count-sessions', + sessionService.countSessions, + ); + // topics + const { data: topics, isLoading: topicsLoading } = useSWR( + 'count-topics', + topicService.countTopics, + ); + // messages + const { data: messages, isLoading: messagesLoading } = useSWR( + 'count-messages', + messageService.countMessages, + ); + const { data: messagesToday } = useSWR('today-messages', messageService.countTodayMessages); + + const { styles, theme } = useStyles(); + const { t } = useTranslation('common'); + + const loading = useMemo(() => , []); + + const items = [ + { + count: sessionsLoading ? loading : sessions, + key: 'sessions', + title: t('dataStatistics.sessions'), + }, + { + count: topicsLoading ? loading : topics, + key: 'topics', + title: t('dataStatistics.topics'), + }, + { + count: messagesLoading ? loading : messages, + countToady: messagesToday, + key: 'messages', + title: t('dataStatistics.messages'), + }, + ]; + + return ( + + {items.map((item) => { + if (item.key === 'messages') { + const showBadge = Boolean(item.countToady && item.countToady > 0); + return ( + + +
{formatNumber(item.count)}
+
{item.title}
+
+ {showBadge && ( + + + + )} +
+ ); + } + + return ( + + +
{formatNumber(item.count)}
+
+
{item.title}
+
+ ); + })} +
+ ); +}); + +export default DataStatistics; diff --git a/src/features/User/UserPanel/PanelContent.tsx b/src/features/User/UserPanel/PanelContent.tsx index b84f9206db98..0ee23309d413 100644 --- a/src/features/User/UserPanel/PanelContent.tsx +++ b/src/features/User/UserPanel/PanelContent.tsx @@ -8,6 +8,7 @@ import { enableAuth } from '@/const/auth'; import { useUserStore } from '@/store/user'; import { authSelectors } from '@/store/user/selectors'; +import DataStatistics from '../DataStatistics'; import UserInfo from '../UserInfo'; import UserLoginOrSignup from '../UserLoginOrSignup'; import LangButton from './LangButton'; @@ -50,6 +51,7 @@ const PanelContent = memo<{ closePopover: () => void }>(({ closePopover }) => { ) : ( )} + dayjs(item.createdAt).format('YYYY-MM-DD') === dayjs().format('YYYY-MM-DD'), + ).length; + } + async getAllMessagesInSession(sessionId: string) { return MessageModel.queryBySessionId(sessionId); } diff --git a/src/services/session/client.ts b/src/services/session/client.ts index bc7e2f5f4d2a..8a083a9bd812 100644 --- a/src/services/session/client.ts +++ b/src/services/session/client.ts @@ -79,6 +79,7 @@ export class ClientService implements ISessionService { async countSessions() { return SessionModel.count(); } + async hasSessions() { return (await this.countSessions()) !== 0; } diff --git a/src/services/topic/client.test.ts b/src/services/topic/client.test.ts index 53df886a6f3d..9c2eadfb7bd0 100644 --- a/src/services/topic/client.test.ts +++ b/src/services/topic/client.test.ts @@ -1,5 +1,6 @@ import { Mock, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'; +import { SessionModel } from '@/database/client/models/session'; import { CreateTopicParams, TopicModel } from '@/database/client/models/topic'; import { ChatTopic } from '@/types/topic'; @@ -13,6 +14,7 @@ vi.mock('@/database/client/models/topic', () => { create: vi.fn(), query: vi.fn(), delete: vi.fn(), + count: vi.fn(), batchDeleteBySessionId: vi.fn(), batchDelete: vi.fn(), clearTable: vi.fn(), @@ -214,4 +216,30 @@ describe('TopicService', () => { expect(result).toBe(mockTopics); }); }); + + describe('countTopics', () => { + it('should return false if no topics exist', async () => { + // Setup + (TopicModel.count as Mock).mockResolvedValue(0); + + // Execute + const result = await topicService.countTopics(); + + // Assert + expect(TopicModel.count).toHaveBeenCalled(); + expect(result).toBe(0); + }); + + it('should return true if topics exist', async () => { + // Setup + (TopicModel.count as Mock).mockResolvedValue(1); + + // Execute + const result = await topicService.countTopics(); + + // Assert + expect(TopicModel.count).toHaveBeenCalled(); + expect(result).toBe(1); + }); + }); }); diff --git a/src/services/topic/client.ts b/src/services/topic/client.ts index e93a08d7f9a4..1be53520ed17 100644 --- a/src/services/topic/client.ts +++ b/src/services/topic/client.ts @@ -34,6 +34,10 @@ export class ClientService implements ITopicService { return TopicModel.queryAll(); } + async countTopics() { + return TopicModel.count(); + } + async updateTopicFavorite(id: string, favorite?: boolean) { return this.updateTopic(id, { favorite }); }