@lobehub/chat 1.22.14 → 1.22.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,8 +47,8 @@
47
47
  "ERNIE-4.0-8K-Preview": {
48
48
  "description": "百度自研的旗艦級超大規模語言模型,相較ERNIE 3.5實現了模型能力全面升級,廣泛適用於各領域複雜任務場景;支持自動對接百度搜索插件,保障問答信息時效。"
49
49
  },
50
- "ERNIE-4.0-Turbo-8K": {
51
- "description": "百度自研的旗艦級超大規模語言模型,綜合效果表現出色,廣泛適用於各領域複雜任務場景;支持自動對接百度搜索插件,保障問答信息時效。相較於ERNIE 4.0在性能表現上更優秀。"
50
+ "ERNIE-4.0-Turbo-8K-Latest": {
51
+ "description": "百度自研的旗艦級超大規模大語言模型,綜合效果表現優異,廣泛適用於各領域複雜任務場景;支持自動對接百度搜索插件,保障問答信息時效。相較於 ERNIE 4.0 在性能表現上更為優秀。"
52
52
  },
53
53
  "ERNIE-4.0-Turbo-8K-Preview": {
54
54
  "description": "百度自研的旗艦級超大規模語言模型,綜合效果表現出色,廣泛適用於各領域複雜任務場景;支持自動對接百度搜索插件,保障問答信息時效。相較於ERNIE 4.0在性能表現上更優秀。"
@@ -80,8 +80,11 @@
80
80
  "NousResearch/Nous-Hermes-2-Yi-34B": {
81
81
  "description": "Nous Hermes-2 Yi (34B) 提供優化的語言輸出和多樣化的應用可能。"
82
82
  },
83
- "Phi-3-5-mini-instruct": {
84
- "description": "Phi-3-mini模型的更新版本。"
83
+ "OpenGVLab/InternVL2-26B": {
84
+ "description": "InternVL2在各種視覺語言任務上展現出了卓越的性能,包括文檔和圖表理解、場景文本理解、OCR、科學和數學問題解決等。"
85
+ },
86
+ "OpenGVLab/InternVL2-Llama3-76B": {
87
+ "description": "InternVL2在各種視覺語言任務上展現出了卓越的性能,包括文檔和圖表理解、場景文本理解、OCR、科學和數學問題解決等。"
85
88
  },
86
89
  "Phi-3-medium-128k-instruct": {
87
90
  "description": "相同的Phi-3-medium模型,但具有更大的上下文大小,適用於RAG或少量提示。"
@@ -101,9 +104,21 @@
101
104
  "Phi-3-small-8k-instruct": {
102
105
  "description": "一個7B參數模型,質量優於Phi-3-mini,專注於高質量、推理密集型數據。"
103
106
  },
107
+ "Phi-3.5-mini-instruct": {
108
+ "description": "Phi-3-mini模型的更新版。"
109
+ },
110
+ "Phi-3.5-vision-instrust": {
111
+ "description": "Phi-3-vision模型的更新版。"
112
+ },
104
113
  "Pro-128k": {
105
114
  "description": "Spark Pro-128K 配置了特大上下文處理能力,能夠處理多達128K的上下文信息,特別適合需通篇分析和長期邏輯關聯處理的長文內容,可在複雜文本溝通中提供流暢一致的邏輯與多樣的引用支持。"
106
115
  },
116
+ "Pro/OpenGVLab/InternVL2-8B": {
117
+ "description": "InternVL2在各種視覺語言任務上展現出了卓越的性能,包括文檔和圖表理解、場景文本理解、OCR、科學和數學問題解決等。"
118
+ },
119
+ "Pro/Qwen/Qwen2-VL-7B-Instruct": {
120
+ "description": "Qwen2-VL 是 Qwen-VL 模型的最新迭代版本,在視覺理解基準測試中達到了最先進的性能。"
121
+ },
107
122
  "Qwen/Qwen1.5-110B-Chat": {
108
123
  "description": "作為 Qwen2 的測試版,Qwen1.5 使用大規模數據實現了更精確的對話功能。"
109
124
  },
@@ -113,18 +128,27 @@
113
128
  "Qwen/Qwen2-72B-Instruct": {
114
129
  "description": "Qwen2 是先進的通用語言模型,支持多種指令類型。"
115
130
  },
131
+ "Qwen/Qwen2-VL-72B-Instruct": {
132
+ "description": "Qwen2-VL 是 Qwen-VL 模型的最新迭代版本,在視覺理解基準測試中達到了最先進的性能。"
133
+ },
116
134
  "Qwen/Qwen2.5-14B-Instruct": {
117
135
  "description": "Qwen2.5是全新的大型語言模型系列,旨在優化指令式任務的處理。"
118
136
  },
119
137
  "Qwen/Qwen2.5-32B-Instruct": {
120
138
  "description": "Qwen2.5是全新的大型語言模型系列,旨在優化指令式任務的處理。"
121
139
  },
122
- "Qwen/Qwen2.5-72B-Instruct": {
123
- "description": "Qwen2.5是全新的大型語言模型系列,具有更強的理解和生成能力。"
140
+ "Qwen/Qwen2.5-72B-Instruct-128K": {
141
+ "description": "Qwen2.5 是全新的大型語言模型系列,具有更強的理解和生成能力。"
142
+ },
143
+ "Qwen/Qwen2.5-72B-Instruct-Turbo": {
144
+ "description": "Qwen2.5 是全新的大型語言模型系列,旨在優化指令式任務的處理。"
124
145
  },
125
146
  "Qwen/Qwen2.5-7B-Instruct": {
126
147
  "description": "Qwen2.5是全新的大型語言模型系列,旨在優化指令式任務的處理。"
127
148
  },
149
+ "Qwen/Qwen2.5-7B-Instruct-Turbo": {
150
+ "description": "Qwen2.5 是全新的大型語言模型系列,旨在優化指令式任務的處理。"
151
+ },
128
152
  "Qwen/Qwen2.5-Coder-7B-Instruct": {
129
153
  "description": "Qwen2.5-Coder專注於代碼編寫。"
130
154
  },
@@ -158,9 +182,6 @@
158
182
  "accounts/fireworks/models/firellava-13b": {
159
183
  "description": "fireworks-ai/FireLLaVA-13b 是一款視覺語言模型,可以同時接收圖像和文本輸入,經過高質量數據訓練,適合多模態任務。"
160
184
  },
161
- "accounts/fireworks/models/gemma2-9b-it": {
162
- "description": "Gemma 2 9B 指令模型,基於之前的 Google 技術,適合回答問題、總結和推理等多種文本生成任務。"
163
- },
164
185
  "accounts/fireworks/models/llama-v3-70b-instruct": {
165
186
  "description": "Llama 3 70B 指令模型,專為多語言對話和自然語言理解優化,性能優於多數競爭模型。"
166
187
  },
@@ -182,6 +203,18 @@
182
203
  "accounts/fireworks/models/llama-v3p1-8b-instruct": {
183
204
  "description": "Llama 3.1 8B 指令模型,專為多語言對話優化,能夠在常見行業基準上超越多數開源及閉源模型。"
184
205
  },
206
+ "accounts/fireworks/models/llama-v3p2-11b-vision-instruct": {
207
+ "description": "Meta的11B參數指令調整圖像推理模型。該模型針對視覺識別、圖像推理、圖像描述和回答關於圖像的一般性問題進行了優化。該模型能夠理解視覺數據,如圖表和圖形,並通過生成文本描述圖像細節來弥合視覺與語言之間的差距。"
208
+ },
209
+ "accounts/fireworks/models/llama-v3p2-1b-instruct": {
210
+ "description": "Llama 3.2 1B 指令模型是Meta推出的一款輕量級多語言模型。該模型旨在提高效率,與更大型的模型相比,在延遲和成本方面提供了顯著的改進。該模型的示例用例包括檢索和摘要。"
211
+ },
212
+ "accounts/fireworks/models/llama-v3p2-3b-instruct": {
213
+ "description": "Llama 3.2 3B 指令模型是Meta推出的一款輕量級多語言模型。該模型旨在提高效率,與更大型的模型相比,在延遲和成本方面提供了顯著的改進。該模型的示例用例包括查詢和提示重寫以及寫作輔助。"
214
+ },
215
+ "accounts/fireworks/models/llama-v3p2-90b-vision-instruct": {
216
+ "description": "Meta的90B參數指令調整圖像推理模型。該模型針對視覺識別、圖像推理、圖像描述和回答關於圖像的一般性問題進行了優化。該模型能夠理解視覺數據,如圖表和圖形,並通過生成文本描述圖像細節來弥合視覺與語言之間的差距。"
217
+ },
185
218
  "accounts/fireworks/models/mixtral-8x22b-instruct": {
186
219
  "description": "Mixtral MoE 8x22B 指令模型,大規模參數和多專家架構,全方位支持複雜任務的高效處理。"
187
220
  },
@@ -197,6 +230,9 @@
197
230
  "accounts/fireworks/models/phi-3-vision-128k-instruct": {
198
231
  "description": "Phi 3 Vision 指令模型,輕量級多模態模型,能夠處理複雜的視覺和文本信息,具備較強的推理能力。"
199
232
  },
233
+ "accounts/fireworks/models/qwen2p5-72b-instruct": {
234
+ "description": "Qwen2.5 是由阿里雲 Qwen 團隊開發的一系列僅包含解碼器的語言模型。這些模型提供不同的大小,包括 0.5B、1.5B、3B、7B、14B、32B 和 72B,並且有基礎版(base)和指令版(instruct)兩種變體。"
235
+ },
200
236
  "accounts/fireworks/models/starcoder-16b": {
201
237
  "description": "StarCoder 15.5B 模型,支持高級編程任務,多語言能力增強,適合複雜代碼生成和理解。"
202
238
  },
@@ -212,9 +248,6 @@
212
248
  "ai21-jamba-1.5-mini": {
213
249
  "description": "一個52B參數(12B活躍)多語言模型,提供256K長上下文窗口、函數調用、結構化輸出和基於實體的生成。"
214
250
  },
215
- "ai21-jamba-instruct": {
216
- "description": "一個生產級的基於Mamba的LLM模型,以實現最佳性能、質量和成本效率。"
217
- },
218
251
  "anthropic.claude-3-5-sonnet-20240620-v1:0": {
219
252
  "description": "Claude 3.5 Sonnet提升了行業標準,性能超過競爭對手模型和Claude 3 Opus,在廣泛的評估中表現出色,同時具有我們中等層級模型的速度和成本。"
220
253
  },
@@ -592,9 +625,15 @@
592
625
  "llama-3.1-sonar-small-128k-online": {
593
626
  "description": "Llama 3.1 Sonar Small Online 模型,具備 8B 參數,支持約 127,000 個標記的上下文長度,專為在線聊天設計,能高效處理各種文本交互。"
594
627
  },
628
+ "llama-3.2-11b-vision-instruct": {
629
+ "description": "在高解析度圖像上表現優異的圖像推理能力,適用於視覺理解應用。"
630
+ },
595
631
  "llama-3.2-11b-vision-preview": {
596
632
  "description": "Llama 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
597
633
  },
634
+ "llama-3.2-90b-vision-instruct": {
635
+ "description": "適合視覺理解代理應用的高階圖像推理能力。"
636
+ },
598
637
  "llama-3.2-90b-vision-preview": {
599
638
  "description": "Llama 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
600
639
  },
@@ -652,8 +691,8 @@
652
691
  "meta-llama/Llama-2-13b-chat-hf": {
653
692
  "description": "LLaMA-2 Chat (13B) 提供優秀的語言處理能力和出色的互動體驗。"
654
693
  },
655
- "meta-llama/Llama-2-7b-chat-hf": {
656
- "description": "最佳對話模型之一"
694
+ "meta-llama/Llama-2-70b-hf": {
695
+ "description": "LLaMA-2 提供優秀的語言處理能力和出色的互動體驗。"
657
696
  },
658
697
  "meta-llama/Llama-3-70b-chat-hf": {
659
698
  "description": "LLaMA-3 Chat (70B) 是功能強大的聊天模型,支持複雜的對話需求。"
@@ -661,6 +700,18 @@
661
700
  "meta-llama/Llama-3-8b-chat-hf": {
662
701
  "description": "LLaMA-3 Chat (8B) 提供多語言支持,涵蓋豐富的領域知識。"
663
702
  },
703
+ "meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo": {
704
+ "description": "LLaMA 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
705
+ },
706
+ "meta-llama/Llama-3.2-3B-Instruct-Turbo": {
707
+ "description": "LLaMA 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
708
+ },
709
+ "meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo": {
710
+ "description": "LLaMA 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
711
+ },
712
+ "meta-llama/Llama-Vision-Free": {
713
+ "description": "LLaMA 3.2 旨在處理結合視覺和文本數據的任務。它在圖像描述和視覺問答等任務中表現出色,跨越了語言生成和視覺推理之間的鴻溝。"
714
+ },
664
715
  "meta-llama/Meta-Llama-3-70B-Instruct-Lite": {
665
716
  "description": "Llama 3 70B Instruct Lite 適合需要高效能和低延遲的環境。"
666
717
  },
@@ -739,15 +790,18 @@
739
790
  "minicpm-v": {
740
791
  "description": "MiniCPM-V 是 OpenBMB 推出的新一代多模態大模型,具備卓越的 OCR 識別和多模態理解能力,支持廣泛的應用場景。"
741
792
  },
793
+ "ministral-3b-latest": {
794
+ "description": "Ministral 3B 是 Mistral 的全球頂尖邊緣模型。"
795
+ },
796
+ "ministral-8b-latest": {
797
+ "description": "Ministral 8B 是 Mistral 的性價比極高的邊緣模型。"
798
+ },
742
799
  "mistral": {
743
800
  "description": "Mistral 是 Mistral AI 發布的 7B 模型,適合多變的語言處理需求。"
744
801
  },
745
802
  "mistral-large": {
746
803
  "description": "Mixtral Large 是 Mistral 的旗艦模型,結合代碼生成、數學和推理的能力,支持 128k 上下文窗口。"
747
804
  },
748
- "mistral-large-2407": {
749
- "description": "Mistral Large (2407)是一個先進的大型語言模型(LLM),具有最先進的推理、知識和編碼能力。"
750
- },
751
805
  "mistral-large-latest": {
752
806
  "description": "Mistral Large 是旗艦大模型,擅長多語言任務、複雜推理和代碼生成,是高端應用的理想選擇。"
753
807
  },
@@ -769,12 +823,18 @@
769
823
  "mistralai/Mistral-7B-Instruct-v0.3": {
770
824
  "description": "Mistral (7B) Instruct v0.3 提供高效的計算能力和自然語言理解,適合廣泛的應用。"
771
825
  },
826
+ "mistralai/Mistral-7B-v0.1": {
827
+ "description": "Mistral 7B 是一款緊湊但高效能的模型,擅長批次處理和簡單任務,如分類和文本生成,具有良好的推理能力。"
828
+ },
772
829
  "mistralai/Mixtral-8x22B-Instruct-v0.1": {
773
830
  "description": "Mixtral-8x22B Instruct (141B) 是一款超級大語言模型,支持極高的處理需求。"
774
831
  },
775
832
  "mistralai/Mixtral-8x7B-Instruct-v0.1": {
776
833
  "description": "Mixtral 8x7B 是預訓練的稀疏混合專家模型,用於通用性文本任務。"
777
834
  },
835
+ "mistralai/Mixtral-8x7B-v0.1": {
836
+ "description": "Mixtral 8x7B 是一個稀疏專家模型,利用多個參數提高推理速度,適合處理多語言和代碼生成任務。"
837
+ },
778
838
  "mistralai/mistral-7b-instruct": {
779
839
  "description": "Mistral 7B Instruct 是一款兼具速度優化和長上下文支持的高性能行業標準模型。"
780
840
  },
@@ -802,6 +862,9 @@
802
862
  "nousresearch/hermes-2-pro-llama-3-8b": {
803
863
  "description": "Hermes 2 Pro Llama 3 8B 是 Nous Hermes 2 的升級版本,包含最新的內部開發的數據集。"
804
864
  },
865
+ "nvidia/Llama-3.1-Nemotron-70B-Instruct": {
866
+ "description": "Llama 3.1 Nemotron 70B 是由 NVIDIA 定製的大型語言模型,旨在提升 LLM 生成的回應對用戶查詢的幫助程度。"
867
+ },
805
868
  "o1-mini": {
806
869
  "description": "o1-mini是一款針對程式設計、數學和科學應用場景而設計的快速、經濟高效的推理模型。該模型具有128K上下文和2023年10月的知識截止日期。"
807
870
  },
@@ -988,6 +1051,12 @@
988
1051
  "yi-large-turbo": {
989
1052
  "description": "超高性價比、卓越性能。根據性能和推理速度、成本,進行平衡性高精度調優。"
990
1053
  },
1054
+ "yi-lightning": {
1055
+ "description": "最新高性能模型,保證高品質輸出同時,推理速度大幅提升。"
1056
+ },
1057
+ "yi-lightning-lite": {
1058
+ "description": "輕量化版本,推薦使用 yi-lightning。"
1059
+ },
991
1060
  "yi-medium": {
992
1061
  "description": "中型尺寸模型升級微調,能力均衡,性價比高。深度優化指令遵循能力。"
993
1062
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "1.22.14",
3
+ "version": "1.22.16",
4
4
  "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.",
5
5
  "keywords": [
6
6
  "framework",
@@ -11,12 +11,13 @@ const MobileContentLayout = ({
11
11
  withNav,
12
12
  style,
13
13
  header,
14
+ id = 'lobe-mobile-scroll-container',
14
15
  ...rest
15
16
  }: MobileContentLayoutProps) => {
16
17
  const content = (
17
18
  <Flexbox
18
19
  height="100%"
19
- id={'lobe-mobile-scroll-container'}
20
+ id={id}
20
21
  style={{
21
22
  overflowX: 'hidden',
22
23
  overflowY: 'auto',
@@ -2,30 +2,41 @@
2
2
 
3
3
  import { useResponsive } from 'antd-style';
4
4
  import { PropsWithChildren, ReactNode, memo } from 'react';
5
- import { Flexbox } from 'react-layout-kit';
5
+ import { Flexbox, FlexboxProps } from 'react-layout-kit';
6
6
 
7
- interface SettingContainerProps {
7
+ interface SettingContainerProps extends FlexboxProps {
8
8
  addonAfter?: ReactNode;
9
9
  addonBefore?: ReactNode;
10
- fullWidth?: boolean;
10
+
11
+ maxWidth?: number;
11
12
  }
12
13
  const SettingContainer = memo<PropsWithChildren<SettingContainerProps>>(
13
- ({ children, addonAfter, addonBefore, fullWidth }) => {
14
+ ({
15
+ id = 'lobe-desktop-scroll-container',
16
+ maxWidth = 1024,
17
+ children,
18
+ addonAfter,
19
+ addonBefore,
20
+ style,
21
+ ...rest
22
+ }) => {
14
23
  const { mobile = false } = useResponsive();
15
24
  return (
16
25
  <Flexbox
17
26
  align={'center'}
18
27
  height={'100%'}
28
+ id={id}
19
29
  paddingBlock={mobile ? undefined : 32}
20
- style={{ overflowX: 'hidden', overflowY: 'auto' }}
30
+ style={{ overflowX: 'hidden', overflowY: 'auto', ...style }}
21
31
  width={'100%'}
32
+ {...rest}
22
33
  >
23
34
  {addonBefore}
24
35
  <Flexbox
25
36
  gap={64}
26
37
  paddingInline={mobile ? undefined : 24}
27
38
  style={{
28
- maxWidth: fullWidth ? undefined : 1024,
39
+ maxWidth,
29
40
  }}
30
41
  width={'100%'}
31
42
  >
@@ -14,7 +14,8 @@ const provider = {
14
14
  // TODO(NextAuth ENVs Migration): Remove once nextauth envs migration time end
15
15
  clientId: authEnv.AZURE_AD_CLIENT_ID ?? process.env.AUTH_AZURE_AD_ID,
16
16
  clientSecret: authEnv.AZURE_AD_CLIENT_SECRET ?? process.env.AUTH_AZURE_AD_SECRET,
17
- // tenantId: authEnv.AZURE_AD_TENANT_ID ?? process.env.AUTH_AZURE_AD_TENANT_ID,
17
+ // @ts-ignore
18
+ tenantId: authEnv.AZURE_AD_TENANT_ID ?? process.env.AUTH_AZURE_AD_TENANT_ID,
18
19
  // Remove end
19
20
  // TODO(NextAuth): map unique user id to `providerAccountId` field
20
21
  // profile(profile) {
@@ -1,6 +1,11 @@
1
+ import dayjs from 'dayjs';
1
2
  import { describe, expect, it } from 'vitest';
2
3
 
4
+ import { CNY_TO_USD } from '@/const/discover';
5
+
3
6
  import {
7
+ formatDate,
8
+ formatIntergerNumber,
4
9
  formatNumber,
5
10
  formatPrice,
6
11
  formatPriceByCurrency,
@@ -37,6 +42,15 @@ describe('format', () => {
37
42
  expect(formatSize(1023)).toBe('1.0 KB');
38
43
  expect(formatSize(1073741823)).toBe('1024.0 MB');
39
44
  });
45
+
46
+ it('should handle undefined input', () => {
47
+ expect(formatSize(undefined as any)).toBe('--');
48
+ });
49
+
50
+ it('should use custom fraction digits', () => {
51
+ expect(formatSize(1536, 2)).toBe('1.50 KB');
52
+ expect(formatSize(1572864, 3)).toBe('1.500 MB');
53
+ });
40
54
  });
41
55
 
42
56
  describe('formatSpeed', () => {
@@ -60,6 +74,14 @@ describe('format', () => {
60
74
  expect(formatSpeed(1000 * 1024)).toBe('1000.00 KB/s');
61
75
  expect(formatSpeed(1000.01 * 1024)).toBe('0.98 MB/s');
62
76
  });
77
+
78
+ it('should handle undefined input', () => {
79
+ expect(formatSpeed(undefined as any)).toBe('--');
80
+ });
81
+
82
+ it('should use custom fraction digits', () => {
83
+ expect(formatSpeed(1024, 3)).toBe('1.000 KB/s');
84
+ });
63
85
  });
64
86
 
65
87
  describe('formatTime', () => {
@@ -88,12 +110,16 @@ describe('format', () => {
88
110
  expect(formatTime(59.99)).toBe('60.0 s');
89
111
  expect(formatTime(3599.99)).toBe('60.0 min');
90
112
  });
113
+ it('should handle non-number inputs', () => {
114
+ expect(formatTime('not a number' as any)).toBe('not a number');
115
+ expect(formatTime(undefined as any)).toBe('--');
116
+ });
91
117
  });
92
118
 
93
119
  describe('formatShortenNumber', () => {
94
120
  it('should return the input if it is not a number', () => {
95
121
  expect(formatShortenNumber('not a number')).toBe('not a number');
96
- expect(formatShortenNumber(null)).toBe(null);
122
+ expect(formatShortenNumber(null)).toBe('--');
97
123
  });
98
124
 
99
125
  it('should format numbers less than 10,000 correctly', () => {
@@ -125,7 +151,22 @@ describe('format', () => {
125
151
  it('should handle non-number inputs', () => {
126
152
  expect(formatNumber('1000')).toBe('1,000');
127
153
  expect(formatNumber('not a number')).toBe(Number.NaN.toString());
128
- expect(formatNumber(null)).toBe(undefined);
154
+ expect(formatNumber(0)).toBe('0');
155
+ expect(formatNumber(0, 1)).toBe('0.0');
156
+ expect(formatNumber(null)).toBe('--');
157
+ });
158
+
159
+ it('should handle fraction digits correctly', () => {
160
+ expect(formatNumber(1234.5678, 2)).toBe('1,234.57');
161
+ expect(formatNumber(1234.5678, 3)).toBe('1,234.568');
162
+ });
163
+ });
164
+
165
+ describe('formatIntergerNumber', () => {
166
+ it('should format numbers with commas correctly', () => {
167
+ expect(formatIntergerNumber(1000.12)).toBe('1,000');
168
+ expect(formatIntergerNumber(0)).toBe('0');
169
+ expect(formatIntergerNumber(null)).toBe('--');
129
170
  });
130
171
  });
131
172
 
@@ -150,6 +191,12 @@ describe('format', () => {
150
191
  expect(formatPriceByCurrency(1000, 'CNY')).toBe('140.06');
151
192
  expect(formatPriceByCurrency(6500, 'CNY')).toBe('910.36');
152
193
  });
194
+
195
+ it('should use the correct CNY_TO_USD conversion rate', () => {
196
+ const price = 1000;
197
+ const expectedCNY = formatPrice(price / CNY_TO_USD);
198
+ expect(formatPriceByCurrency(price, 'CNY')).toBe(expectedCNY);
199
+ });
153
200
  });
154
201
 
155
202
  describe('formatTokenNumber', () => {
@@ -192,4 +239,21 @@ describe('format', () => {
192
239
  expect(formatTokenNumber(2097152)).toBe('2M'); // Gemini Pro
193
240
  });
194
241
  });
242
+
243
+ describe('formatDate', () => {
244
+ it('should format date correctly', () => {
245
+ const date = new Date('2023-05-15T12:00:00Z');
246
+ expect(formatDate(date)).toBe('2023-05-15');
247
+ });
248
+
249
+ it('should handle undefined input', () => {
250
+ expect(formatDate(undefined)).toBe('--');
251
+ });
252
+
253
+ it('should use dayjs for formatting', () => {
254
+ const date = new Date('2023-05-15T12:00:00Z');
255
+ const expectedFormat = dayjs(date).format('YYYY-MM-DD');
256
+ expect(formatDate(date)).toBe(expectedFormat);
257
+ });
258
+ });
195
259
  });
@@ -1,10 +1,13 @@
1
+ import dayjs from 'dayjs';
1
2
  import { isNumber } from 'lodash-es';
2
3
  import numeral from 'numeral';
3
4
 
4
5
  import { CNY_TO_USD } from '@/const/discover';
5
6
  import { ModelPriceCurrency } from '@/types/llm';
6
7
 
7
- export const formatSize = (bytes: number, fractionDigits = 1): string => {
8
+ export const formatSize = (bytes: number, fractionDigits: number = 1): string => {
9
+ if (!bytes && bytes !== 0) return '--';
10
+
8
11
  const kbSize = bytes / 1024;
9
12
  if (kbSize < 1024) {
10
13
  return `${kbSize.toFixed(fractionDigits)} KB`;
@@ -21,6 +24,8 @@ export const formatSize = (bytes: number, fractionDigits = 1): string => {
21
24
  * format speed from Byte number to string like KB/s, MB/s or GB/s
22
25
  */
23
26
  export const formatSpeed = (byte: number, fractionDigits = 2) => {
27
+ if (!byte && byte !== 0) return '--';
28
+
24
29
  let word = '';
25
30
 
26
31
  // Byte
@@ -44,6 +49,9 @@ export const formatSpeed = (byte: number, fractionDigits = 2) => {
44
49
  };
45
50
 
46
51
  export const formatTime = (timeInSeconds: number): string => {
52
+ if (!timeInSeconds && timeInSeconds !== 0) return '--';
53
+ if (!isNumber(timeInSeconds)) return timeInSeconds;
54
+
47
55
  if (timeInSeconds < 60) {
48
56
  return `${timeInSeconds.toFixed(1)} s`;
49
57
  } else if (timeInSeconds < 3600) {
@@ -54,7 +62,9 @@ export const formatTime = (timeInSeconds: number): string => {
54
62
  };
55
63
 
56
64
  export const formatShortenNumber = (num: any) => {
65
+ if (!num && num !== 0) return '--';
57
66
  if (!isNumber(num)) return num;
67
+
58
68
  // 使用Intl.NumberFormat来添加千分号
59
69
  const formattedWithComma = new Intl.NumberFormat('en-US').format(num);
60
70
 
@@ -70,16 +80,23 @@ export const formatShortenNumber = (num: any) => {
70
80
  }
71
81
  };
72
82
 
73
- /**
74
- * format number with comma
75
- * @param num
76
- */
77
- export const formatNumber = (num: any) => {
78
- if (!num) return;
79
- return new Intl.NumberFormat('en-US').format(num);
83
+ export const formatNumber = (num: any, fractionDigits?: number) => {
84
+ if (!num && num !== 0) return '--';
85
+
86
+ if (!fractionDigits) return new Intl.NumberFormat('en-US').format(num);
87
+ const [a, b] = num.toFixed(fractionDigits).split('.');
88
+ return `${numeral(a).format('0,0')}.${b}`;
89
+ };
90
+
91
+ export const formatIntergerNumber = (num: any) => {
92
+ if (!num && num !== 0) return '--';
93
+
94
+ return numeral(num).format('0,0');
80
95
  };
81
96
 
82
97
  export const formatTokenNumber = (num: number): string => {
98
+ if (!num && num !== 0) return '--';
99
+
83
100
  if (num > 0 && num < 1024) return '1K';
84
101
 
85
102
  let kiloToken = Math.floor(num / 1024);
@@ -90,8 +107,10 @@ export const formatTokenNumber = (num: number): string => {
90
107
  return kiloToken < 1000 ? `${kiloToken}K` : `${Math.floor(kiloToken / 1000)}M`;
91
108
  };
92
109
 
93
- export const formatPrice = (price: number) => {
94
- const [a, b] = price.toFixed(2).split('.');
110
+ export const formatPrice = (price: number, fractionDigits: number = 2) => {
111
+ if (!price && price !== 0) return '--';
112
+
113
+ const [a, b] = price.toFixed(fractionDigits).split('.');
95
114
  return `${numeral(a).format('0,0')}.${b}`;
96
115
  };
97
116
 
@@ -101,3 +120,9 @@ export const formatPriceByCurrency = (price: number, currency?: ModelPriceCurren
101
120
  }
102
121
  return formatPrice(price);
103
122
  };
123
+
124
+ export const formatDate = (date?: Date) => {
125
+ if (!date) return '--';
126
+
127
+ return dayjs(date).format('YYYY-MM-DD');
128
+ };