kiku-agent 1.3.2 → 1.3.3
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.
- package/README.md +69 -12
- package/package.json +2 -1
- package/server/agent/agentCore.js +319 -46
- package/server/agent/appPaths.js +31 -0
- package/server/agent/audioPlayer.js +339 -12
- package/server/agent/autoContext.js +193 -0
- package/server/agent/catalogEntityResolver.js +170 -28
- package/server/agent/clarifyingQuestions.js +137 -35
- package/server/agent/cli.js +177 -48
- package/server/agent/cloudAdapters.js +116 -0
- package/server/agent/commandRegistry.js +409 -80
- package/server/agent/commands.js +1056 -125
- package/server/agent/config.js +1088 -690
- package/server/agent/contextCompactor.js +213 -21
- package/server/agent/cpuMetrics.js +199 -0
- package/server/agent/engineService.js +591 -0
- package/server/agent/eval/modules/evaluation/runner.js +4 -14
- package/server/agent/eval/modules/evaluation/scoring.js +15 -3
- package/server/agent/eval/modules/server/evalApi.js +5 -5
- package/server/agent/eval/modules/ui/evalUi.js +7 -4
- package/server/agent/eventBus.js +1 -0
- package/server/agent/ink/main.jsx +196 -191
- package/server/agent/jobManager.js +11 -1
- package/server/agent/lanDiscovery.js +721 -23
- package/server/agent/llmClient.js +317 -71
- package/server/agent/lmStudioWakeup.js +517 -65
- package/server/agent/locationService.js +797 -0
- package/server/agent/mcpQuizData.js +509 -0
- package/server/agent/memory/contextAllocator.js +19 -7
- package/server/agent/memory.js +3 -1
- package/server/agent/modelCompatibility.js +352 -0
- package/server/agent/modelDefaults.js +1 -0
- package/server/agent/modelManager.js +46 -2
- package/server/agent/newsWatch.js +9 -3
- package/server/agent/processManager.js +229 -0
- package/server/agent/prompts.js +174 -8
- package/server/agent/routingInterceptor.js +9 -1
- package/server/agent/sanitizer.js +41 -6
- package/server/agent/searchQueryPlanner.js +202 -0
- package/server/agent/session.js +59 -4
- package/server/agent/tests/agentFollowUps.test.js +128 -2
- package/server/agent/tests/agentMusicControl.test.js +245 -0
- package/server/agent/tests/apiRouter.test.js +1 -1
- package/server/agent/tests/autoContext.test.js +176 -0
- package/server/agent/tests/bilibiliEmbed.test.js +45 -0
- package/server/agent/tests/chatHardening.test.js +121 -0
- package/server/agent/tests/chineseWebSearchEscalation.test.js +62 -0
- package/server/agent/tests/clarifyingQuestions.test.js +33 -0
- package/server/agent/tests/cliAutomation.test.js +38 -1
- package/server/agent/tests/cloudProviders.test.js +91 -3
- package/server/agent/tests/commands.test.js +92 -3
- package/server/agent/tests/contextIntelligence.test.js +50 -3
- package/server/agent/tests/cpuMetrics.test.js +101 -0
- package/server/agent/tests/decisionAndSearchEnhancements.test.js +32 -0
- package/server/agent/tests/edgeCasesScenarios.test.js +82 -0
- package/server/agent/tests/engineService.test.js +436 -0
- package/server/agent/tests/engineUnload.test.js +94 -0
- package/server/agent/tests/envCommand.test.js +69 -0
- package/server/agent/tests/evalMetrics.test.js +8 -0
- package/server/agent/tests/fetchApi.test.js +99 -0
- package/server/agent/tests/hybridWebSearch.test.js +2 -0
- package/server/agent/tests/lanDiscovery.test.js +5 -0
- package/server/agent/tests/lanInterfaces.test.js +510 -0
- package/server/agent/tests/lmStudioWakeup.test.js +278 -0
- package/server/agent/tests/locationTool.test.js +278 -0
- package/server/agent/tests/memoryRoute.test.js +173 -0
- package/server/agent/tests/memoryUiNormalization.test.js +75 -0
- package/server/agent/tests/modelCompatibility.test.js +148 -0
- package/server/agent/tests/modelManager.test.js +32 -0
- package/server/agent/tests/musicControlUiBridge.test.js +113 -0
- package/server/agent/tests/nextGenArchitecture.test.js +4 -2
- package/server/agent/tests/openDomainPrompt.test.js +197 -0
- package/server/agent/tests/openDomainSearch.test.js +121 -0
- package/server/agent/tests/processManager.test.js +144 -0
- package/server/agent/tests/providerPersistence.test.js +10 -5
- package/server/agent/tests/quickActionsAndModals.test.js +180 -0
- package/server/agent/tests/searchQueryPlanner.test.js +108 -0
- package/server/agent/tests/securityAuditRemediation.test.js +16 -9
- package/server/agent/tests/securityAuditRemediations2.test.js +154 -0
- package/server/agent/tests/securityHardening.test.js +4 -4
- package/server/agent/tests/sessionAndCopy.test.js +39 -4
- package/server/agent/tests/sidebarControls.test.js +34 -0
- package/server/agent/tests/statefulMemory.test.js +8 -1
- package/server/agent/tests/textProtocolLoop.test.js +71 -0
- package/server/agent/tests/textToolParsing.test.js +48 -0
- package/server/agent/tests/toolRoutingRegressions.test.js +41 -0
- package/server/agent/tests/unifiedEndpoints.test.js +13 -6
- package/server/agent/tests/v110Features.test.js +1 -1
- package/server/agent/tests/vramEstimator.test.js +75 -0
- package/server/agent/tests/webChatDocs.test.js +199 -0
- package/server/agent/tests/webChatInferenceControl.test.js +298 -0
- package/server/agent/tests/webChatInspection.test.js +256 -5
- package/server/agent/tests/webChatMcp.test.js +94 -0
- package/server/agent/tests/webExtract.test.js +23 -0
- package/server/agent/tests/webSources.test.js +46 -12
- package/server/agent/textToolProtocol.js +173 -46
- package/server/agent/toolRouter.js +318 -44
- package/server/agent/tools.js +877 -96
- package/server/agent/ui.js +39 -34
- package/server/agent/vramService.js +35 -54
- package/server/agent/webSearch.js +441 -162
- package/server/agent/websearch/orchestrator.js +15 -5
- package/server/agent/websearch/resilience/cache.js +9 -2
- package/server/agent/websearch/security/ssrf.js +41 -10
- package/server/agent/youtubeAuth.js +5 -20
- package/server/apiRouter.js +5558 -4422
- package/server/mcp/data/discography.js +2 -2
- package/server/mcp/examples/antigravity.example.json +17 -0
- package/server/mcp/handler.js +8 -4
- package/server/mcp/security.js +220 -21
- package/server/mcp/server.js +2 -1
- package/server/mcp/tests/connection.test.js +14 -8
- package/server/mcp/tests/mcpKeyAuth.test.js +156 -0
- package/server/mcp/tools.js +7 -1
- package/server/supabase_migration_prefix.sql +102 -0
- package/server/supabase_schema.sql +18 -18
- package/server/web-chat/core/connection.js +179 -218
- package/server/web-chat/core/conversationContext.js +9 -2
- package/server/web-chat/core/directCatalogEngine.js +52 -28
- package/server/web-chat/core/dramaKnowledge.js +33 -22
- package/server/web-chat/core/followUpEngine.js +735 -81
- package/server/web-chat/core/futureEventGuard.js +5 -1
- package/server/web-chat/core/musicControlAction.js +70 -0
- package/server/web-chat/core/security.js +32 -21
- package/server/web-chat/core/toolInspector.js +6 -6
- package/server/web-chat/core/urlGuard.js +45 -0
- package/server/web-chat/router.js +204 -157
- package/server/web-chat/routes/chatRoute.js +885 -488
- package/server/web-chat/routes/engineRoute.js +270 -0
- package/server/web-chat/routes/exportRoute.js +1 -1
- package/server/web-chat/routes/lanDiscoveryRoute.js +17 -2
- package/server/web-chat/routes/lmStudioLoadRoute.js +172 -0
- package/server/web-chat/routes/mcpRoute.js +386 -0
- package/server/web-chat/routes/memoryRoute.js +253 -0
- package/server/web-chat/routes/providerRoute.js +49 -16
- package/server/web-chat/routes/staticRoute.js +306 -17
- package/server/web-chat/routes/statusRoute.js +194 -73
- package/server/web-chat/routes/suggestRoute.js +11 -3
- package/server/web-chat/routes/verifyRoute.js +26 -4
- package/server/web-chat/server.js +7 -6
- package/server/web-chat/ui/docsBuilder.js +3558 -0
- package/server/web-chat/ui/htmlBuilder.js +12 -0
- package/server/web-chat/ui/scripts/client.js +3401 -1302
- package/server/web-chat/ui/scripts/webchatI18n.js +155 -153
- package/server/web-chat/ui/settingsBuilder.js +7870 -0
- package/server/web-chat/ui/styles/lan-card.css +165 -0
- package/server/web-chat/ui/styles/main.css +4289 -447
- package/server/web-chat/ui/sw.js +64 -0
- package/server/web-chat/ui/templates/body.html +407 -281
- package/src/data/awardsData.js +146 -146
- package/src/data/musicVideoData.js +6 -4
- package/src/lib/vram/estimator.js +195 -19
package/src/data/awardsData.js
CHANGED
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
export const awardsData = [
|
|
2
|
-
{
|
|
3
|
-
id: "award-2024-weibo",
|
|
4
|
-
year: 2024,
|
|
5
|
-
titleTh: "นักแสดงหญิงยอดนิยมแห่งปี (Popular Actress of the Year)",
|
|
6
|
-
titleCn: "年度人气女演员",
|
|
7
|
-
ceremony: "Weibo TV & Internet Video Summit 2024",
|
|
8
|
-
work: "In Blossom (ฮวาเจียนลิ่ง ในม่านเมฆ)",
|
|
9
|
-
category: "Acting"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
id: "award-2023-weibo-night",
|
|
13
|
-
year: 2023,
|
|
14
|
-
titleTh: "รางวัลบุคคลผู้ทรงอิทธิพลแห่งปี (Influential Figure of the Year)",
|
|
15
|
-
titleCn: "年度影响力艺人",
|
|
16
|
-
ceremony: "Weibo Night 2023",
|
|
17
|
-
work: "Beauty of Resilience (ตำนานเลือดฟีนิกซ์)",
|
|
18
|
-
category: "Honor"
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
id: "award-2022-erc",
|
|
22
|
-
year: 2022,
|
|
23
|
-
titleTh: "นักร้องยอดนิยมแห่งปี (Popular Singer of the Year)",
|
|
24
|
-
titleCn: "年度最佳人气歌手",
|
|
25
|
-
ceremony: "29th ERC Chinese Top Ten Awards (第29届东方风云榜)",
|
|
26
|
-
work: "Single '0.2s' & Solo Music Portfolio",
|
|
27
|
-
category: "Music"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
id: "award-2021-tencent",
|
|
31
|
-
year: 2021,
|
|
32
|
-
titleTh: "นักแสดงนำหญิงซีรีส์ยอดเยี่ยมแห่งปี (Outstanding Actress)",
|
|
33
|
-
titleCn: "年度卓越女演员",
|
|
34
|
-
ceremony: "Tencent Video Starlight Awards 2021",
|
|
35
|
-
work: "Rebirth for You (มู่หนานจือ)",
|
|
36
|
-
category: "Acting"
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
id: "award-2020-erc-stage",
|
|
40
|
-
year: 2020,
|
|
41
|
-
titleTh: "การแสดงบนเวทียอดเยี่ยมแห่งปี (Best Stage Interpretation)",
|
|
42
|
-
titleCn: "最佳舞台演绎",
|
|
43
|
-
ceremony: "27th ERC Chinese Top Ten Awards (第27届东方风云榜)",
|
|
44
|
-
work: "Love Emergency Report (恋爱告急)",
|
|
45
|
-
category: "Music"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
id: "award-2020-iqiyi-breakthrough",
|
|
49
|
-
year: 2020,
|
|
50
|
-
titleTh: "นักแสดงหญิงผู้ก้าวกระโดดยอดเยี่ยม (Breakthrough Actress)",
|
|
51
|
-
titleCn: "年度飞跃女演员",
|
|
52
|
-
ceremony: "iQIYI Scream Night 2020",
|
|
53
|
-
work: "The Blooms at Ruyi Pavilion & In a Class of Her Own",
|
|
54
|
-
category: "Acting"
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
id: "award-2019-china-canada",
|
|
58
|
-
year: 2019,
|
|
59
|
-
titleTh: "นักแสดงนำหญิงยอดเยี่ยม (Best Actress - Web Series)",
|
|
60
|
-
titleCn: "最佳网剧女主角",
|
|
61
|
-
ceremony: "China Canada Television Festival Award 2019 (中加电视节)",
|
|
62
|
-
work: "Legend of Yunxi (ตำนานหยุนซี)",
|
|
63
|
-
category: "Acting"
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: "award-2019-erc-trend",
|
|
67
|
-
year: 2019,
|
|
68
|
-
titleTh: "นักร้องผู้นำเทรนด์แห่งปี (Trend Singer Award)",
|
|
69
|
-
titleCn: "年度风尚歌手",
|
|
70
|
-
ceremony: "26th ERC Chinese Top Ten Awards (第26届东方风云榜)",
|
|
71
|
-
work: "Solo Music & OST Works",
|
|
72
|
-
category: "Music"
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
id: "award-2019-iqiyi-drama-actress",
|
|
76
|
-
year: 2019,
|
|
77
|
-
titleTh: "นักแสดงหญิงยอดนิยมด้านการแสดง (Drama Actress of the Year)",
|
|
78
|
-
titleCn: "年度戏剧人气女艺人",
|
|
79
|
-
ceremony: "iQIYI Scream Night 2019",
|
|
80
|
-
work: "The Legend of White Snake (ตำนานนางพญางูขาว)",
|
|
81
|
-
category: "Acting"
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
id: "award-2018-weibo-improved",
|
|
85
|
-
year: 2018,
|
|
86
|
-
titleTh: "ศิลปินผู้มีพัฒนาการก้าวกระโดดแห่งปี (Improved Artist of the Year)",
|
|
87
|
-
titleCn: "年度进取艺人",
|
|
88
|
-
ceremony: "Weibo Awards Ceremony 2018",
|
|
89
|
-
work: "Legend of Yunxi & Solo Career Launch",
|
|
90
|
-
category: "Honor"
|
|
91
|
-
},
|
|
92
|
-
{
|
|
93
|
-
id: "award-2017-may4th-medal",
|
|
94
|
-
year: 2017,
|
|
95
|
-
titleTh: "เหรียญรางวัลเกียรติยศเยาวชน 4 พฤษภาคม (May 4th Youth Medal)",
|
|
96
|
-
titleCn: "五四优秀青年勋章",
|
|
97
|
-
ceremony: "Chinese Communist Youth League (共青团中央)",
|
|
98
|
-
work: "เยาวชนตัวอย่างผู้สร้างคุณประโยชน์ทางศิลปวัฒนธรรม",
|
|
99
|
-
category: "State Honor"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
id: "award-2017-erc-breakthrough",
|
|
103
|
-
year: 2017,
|
|
104
|
-
titleTh: "ศิลปินผู้มีพัฒนาการโดดเด่นยอดเยี่ยม (Best Breakthrough Artist)",
|
|
105
|
-
titleCn: "最佳飞跃艺人",
|
|
106
|
-
ceremony: "24th ERC Chinese Top Ten Awards (第24届东方风云榜)",
|
|
107
|
-
work: "EP Everyday & Music Solo Works",
|
|
108
|
-
category: "Music"
|
|
109
|
-
},
|
|
110
|
-
{
|
|
111
|
-
id: "award-2017-migu-top10",
|
|
112
|
-
year: 2017,
|
|
113
|
-
titleTh: "1 ใน 10 เพลงยอดเยี่ยมแห่งปี (Top 10 Songs of the Year)",
|
|
114
|
-
titleCn: "年度十大金曲",
|
|
115
|
-
ceremony: "11th Migu Music Awards (第11届音乐盛典咪咕汇)",
|
|
116
|
-
work: "Think of You (想你了)",
|
|
117
|
-
category: "Music"
|
|
118
|
-
},
|
|
119
|
-
{
|
|
120
|
-
id: "award-2017-snh48-champion",
|
|
121
|
-
year: 2017,
|
|
122
|
-
titleTh: "ชนะเลิศอันดับ 1 การเลือกตั้งทั่วไป SNH48 ครั้งที่ 4 (แชมป์ 2 สมัยซ้อน)",
|
|
123
|
-
titleCn: "SNH48第四届偶像年度人气总决选冠军 (晋升明星殿堂)",
|
|
124
|
-
ceremony: "SNH48 4th General Election",
|
|
125
|
-
work: "บรรจุเข้าสู่ SNH48 Star Hall of Fame (วิหารแห่งดาว)",
|
|
126
|
-
category: "Hall of Fame"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
id: "award-2016-tencent-new-actress",
|
|
130
|
-
year: 2016,
|
|
131
|
-
titleTh: "นักแสดงโทรทัศน์หน้าใหม่ยอดเยี่ยมแห่งปี (New Television Actress)",
|
|
132
|
-
titleCn: "年度新锐电视剧女演员",
|
|
133
|
-
ceremony: "Tencent Video Star Awards 2016 (腾讯视频星光大赏)",
|
|
134
|
-
work: "Novoland: The Castle in the Sky (九州·天空城)",
|
|
135
|
-
category: "Acting"
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
id: "award-2016-snh48-champion",
|
|
139
|
-
year: 2016,
|
|
140
|
-
titleTh: "ชนะเลิศอันดับ 1 การเลือกตั้งทั่วไป SNH48 ครั้งที่ 3 (คะแนนเกิน 230,000)",
|
|
141
|
-
titleCn: "SNH48第三届偶像年度人气总决选冠军",
|
|
142
|
-
ceremony: "SNH48 3rd General Election",
|
|
143
|
-
work: "เซ็นเตอร์เพลง Princess's Cloak (公主披风)",
|
|
144
|
-
category: "Idol & Acting"
|
|
145
|
-
}
|
|
146
|
-
];
|
|
1
|
+
export const awardsData = [
|
|
2
|
+
{
|
|
3
|
+
id: "award-2024-weibo",
|
|
4
|
+
year: 2024,
|
|
5
|
+
titleTh: "นักแสดงหญิงยอดนิยมแห่งปี (Popular Actress of the Year)",
|
|
6
|
+
titleCn: "年度人气女演员",
|
|
7
|
+
ceremony: "Weibo TV & Internet Video Summit 2024",
|
|
8
|
+
work: "In Blossom (ฮวาเจียนลิ่ง ในม่านเมฆ)",
|
|
9
|
+
category: "Acting"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "award-2023-weibo-night",
|
|
13
|
+
year: 2023,
|
|
14
|
+
titleTh: "รางวัลบุคคลผู้ทรงอิทธิพลแห่งปี (Influential Figure of the Year)",
|
|
15
|
+
titleCn: "年度影响力艺人",
|
|
16
|
+
ceremony: "Weibo Night 2023",
|
|
17
|
+
work: "Beauty of Resilience (ตำนานเลือดฟีนิกซ์)",
|
|
18
|
+
category: "Honor"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
id: "award-2022-erc",
|
|
22
|
+
year: 2022,
|
|
23
|
+
titleTh: "นักร้องยอดนิยมแห่งปี (Popular Singer of the Year)",
|
|
24
|
+
titleCn: "年度最佳人气歌手",
|
|
25
|
+
ceremony: "29th ERC Chinese Top Ten Awards (第29届东方风云榜)",
|
|
26
|
+
work: "Single '0.2s' & Solo Music Portfolio",
|
|
27
|
+
category: "Music"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: "award-2021-tencent",
|
|
31
|
+
year: 2021,
|
|
32
|
+
titleTh: "นักแสดงนำหญิงซีรีส์ยอดเยี่ยมแห่งปี (Outstanding Actress)",
|
|
33
|
+
titleCn: "年度卓越女演员",
|
|
34
|
+
ceremony: "Tencent Video Starlight Awards 2021",
|
|
35
|
+
work: "Rebirth for You (มู่หนานจือ)",
|
|
36
|
+
category: "Acting"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "award-2020-erc-stage",
|
|
40
|
+
year: 2020,
|
|
41
|
+
titleTh: "การแสดงบนเวทียอดเยี่ยมแห่งปี (Best Stage Interpretation)",
|
|
42
|
+
titleCn: "最佳舞台演绎",
|
|
43
|
+
ceremony: "27th ERC Chinese Top Ten Awards (第27届东方风云榜)",
|
|
44
|
+
work: "Love Emergency Report (恋爱告急)",
|
|
45
|
+
category: "Music"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: "award-2020-iqiyi-breakthrough",
|
|
49
|
+
year: 2020,
|
|
50
|
+
titleTh: "นักแสดงหญิงผู้ก้าวกระโดดยอดเยี่ยม (Breakthrough Actress)",
|
|
51
|
+
titleCn: "年度飞跃女演员",
|
|
52
|
+
ceremony: "iQIYI Scream Night 2020",
|
|
53
|
+
work: "The Blooms at Ruyi Pavilion & In a Class of Her Own",
|
|
54
|
+
category: "Acting"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: "award-2019-china-canada",
|
|
58
|
+
year: 2019,
|
|
59
|
+
titleTh: "นักแสดงนำหญิงยอดเยี่ยม (Best Actress - Web Series)",
|
|
60
|
+
titleCn: "最佳网剧女主角",
|
|
61
|
+
ceremony: "China Canada Television Festival Award 2019 (中加电视节)",
|
|
62
|
+
work: "Legend of Yunxi (ตำนานหยุนซี)",
|
|
63
|
+
category: "Acting"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "award-2019-erc-trend",
|
|
67
|
+
year: 2019,
|
|
68
|
+
titleTh: "นักร้องผู้นำเทรนด์แห่งปี (Trend Singer Award)",
|
|
69
|
+
titleCn: "年度风尚歌手",
|
|
70
|
+
ceremony: "26th ERC Chinese Top Ten Awards (第26届东方风云榜)",
|
|
71
|
+
work: "Solo Music & OST Works",
|
|
72
|
+
category: "Music"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "award-2019-iqiyi-drama-actress",
|
|
76
|
+
year: 2019,
|
|
77
|
+
titleTh: "นักแสดงหญิงยอดนิยมด้านการแสดง (Drama Actress of the Year)",
|
|
78
|
+
titleCn: "年度戏剧人气女艺人",
|
|
79
|
+
ceremony: "iQIYI Scream Night 2019",
|
|
80
|
+
work: "The Legend of White Snake (ตำนานนางพญางูขาว)",
|
|
81
|
+
category: "Acting"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
id: "award-2018-weibo-improved",
|
|
85
|
+
year: 2018,
|
|
86
|
+
titleTh: "ศิลปินผู้มีพัฒนาการก้าวกระโดดแห่งปี (Improved Artist of the Year)",
|
|
87
|
+
titleCn: "年度进取艺人",
|
|
88
|
+
ceremony: "Weibo Awards Ceremony 2018",
|
|
89
|
+
work: "Legend of Yunxi & Solo Career Launch",
|
|
90
|
+
category: "Honor"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: "award-2017-may4th-medal",
|
|
94
|
+
year: 2017,
|
|
95
|
+
titleTh: "เหรียญรางวัลเกียรติยศเยาวชน 4 พฤษภาคม (May 4th Youth Medal)",
|
|
96
|
+
titleCn: "五四优秀青年勋章",
|
|
97
|
+
ceremony: "Chinese Communist Youth League (共青团中央)",
|
|
98
|
+
work: "เยาวชนตัวอย่างผู้สร้างคุณประโยชน์ทางศิลปวัฒนธรรม",
|
|
99
|
+
category: "State Honor"
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: "award-2017-erc-breakthrough",
|
|
103
|
+
year: 2017,
|
|
104
|
+
titleTh: "ศิลปินผู้มีพัฒนาการโดดเด่นยอดเยี่ยม (Best Breakthrough Artist)",
|
|
105
|
+
titleCn: "最佳飞跃艺人",
|
|
106
|
+
ceremony: "24th ERC Chinese Top Ten Awards (第24届东方风云榜)",
|
|
107
|
+
work: "EP Everyday & Music Solo Works",
|
|
108
|
+
category: "Music"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: "award-2017-migu-top10",
|
|
112
|
+
year: 2017,
|
|
113
|
+
titleTh: "1 ใน 10 เพลงยอดเยี่ยมแห่งปี (Top 10 Songs of the Year)",
|
|
114
|
+
titleCn: "年度十大金曲",
|
|
115
|
+
ceremony: "11th Migu Music Awards (第11届音乐盛典咪咕汇)",
|
|
116
|
+
work: "Think of You (想你了)",
|
|
117
|
+
category: "Music"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "award-2017-snh48-champion",
|
|
121
|
+
year: 2017,
|
|
122
|
+
titleTh: "ชนะเลิศอันดับ 1 การเลือกตั้งทั่วไป SNH48 ครั้งที่ 4 (แชมป์ 2 สมัยซ้อน)",
|
|
123
|
+
titleCn: "SNH48第四届偶像年度人气总决选冠军 (晋升明星殿堂)",
|
|
124
|
+
ceremony: "SNH48 4th General Election",
|
|
125
|
+
work: "บรรจุเข้าสู่ SNH48 Star Hall of Fame (วิหารแห่งดาว)",
|
|
126
|
+
category: "Hall of Fame"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "award-2016-tencent-new-actress",
|
|
130
|
+
year: 2016,
|
|
131
|
+
titleTh: "นักแสดงโทรทัศน์หน้าใหม่ยอดเยี่ยมแห่งปี (New Television Actress)",
|
|
132
|
+
titleCn: "年度新锐电视剧女演员",
|
|
133
|
+
ceremony: "Tencent Video Star Awards 2016 (腾讯视频星光大赏)",
|
|
134
|
+
work: "Novoland: The Castle in the Sky (九州·天空城)",
|
|
135
|
+
category: "Acting"
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: "award-2016-snh48-champion",
|
|
139
|
+
year: 2016,
|
|
140
|
+
titleTh: "ชนะเลิศอันดับ 1 การเลือกตั้งทั่วไป SNH48 ครั้งที่ 3 (คะแนนเกิน 230,000)",
|
|
141
|
+
titleCn: "SNH48第三届偶像年度人气总决选冠军",
|
|
142
|
+
ceremony: "SNH48 3rd General Election",
|
|
143
|
+
work: "เซ็นเตอร์เพลง Princess's Cloak (公主披风)",
|
|
144
|
+
category: "Idol & Acting"
|
|
145
|
+
}
|
|
146
|
+
];
|
|
@@ -59,12 +59,12 @@ export const musicVideoData = [
|
|
|
59
59
|
titlePinyin: "Lu Zhu Zai Chen Xi Qian Xiao San",
|
|
60
60
|
releaseYear: 2026,
|
|
61
61
|
category: "OST",
|
|
62
|
-
dramaName: "Veil of Shadows (《月鳞绮纪》)
|
|
63
|
-
aliases: ["Dewdrops", "Dewdrops Dissipate Before Dawn", "Dew Before Dawn", "露珠在晨曦前消散", "หยาดน้ำค้างสลายก่อนรุ่งอรุณ", "หยาดน้ำค้าง", "D-vEPdasbLo"],
|
|
64
|
-
keywords: ["dewdrops", "veil of shadows", "lu wuyi", "月鳞绮纪", "露珠", "เพลงลูกทรง"],
|
|
62
|
+
dramaName: "Veil of Shadows (《月鳞绮纪》) / In Blossom (《花间令》)",
|
|
63
|
+
aliases: ["Dewdrops", "Dewdrops Dissipate Before Dawn", "Dew Before Dawn", "In Blossom", "花间令", "露水", "露珠在晨曦前消散", "หยาดน้ำค้างสลายก่อนรุ่งอรุณ", "หยาดน้ำค้าง", "D-vEPdasbLo"],
|
|
64
|
+
keywords: ["dewdrops", "in blossom", "veil of shadows", "lu wuyi", "花间令", "月鳞绮纪", "露珠", "露水", "เพลงลูกทรง"],
|
|
65
65
|
youtubeId: "D-vEPdasbLo",
|
|
66
66
|
duration: "04:42",
|
|
67
|
-
description: "เพลงลูกทรงของลู่หวู่อีจากซีรีส์ Veil of Shadows เวอร์ชันทางการเผยแพร่โดย Tencent Music",
|
|
67
|
+
description: "เพลงลูกทรงของลู่หวู่อีจากซีรีส์ Veil of Shadows / In Blossom เวอร์ชันทางการเผยแพร่โดย Tencent Music",
|
|
68
68
|
isFeatured: true
|
|
69
69
|
},
|
|
70
70
|
{
|
|
@@ -283,6 +283,8 @@ export const musicVideoData = [
|
|
|
283
283
|
releaseYear: 2019,
|
|
284
284
|
category: "Single",
|
|
285
285
|
dramaName: "Dance Pop EP",
|
|
286
|
+
aliases: ["Heartbeat Alert", "Love Emergency", "Love Emergency Report", "恋爱告急", "แจ้งเตือนหัวใจฉุกเฉิน", "Heartbeat", "5MLPdCmnlmE"],
|
|
287
|
+
keywords: ["heartbeat alert", "love emergency", "恋爱告急", "แจ้งเตือนหัวใจฉุกเฉิน"],
|
|
286
288
|
youtubeId: "5MLPdCmnlmE",
|
|
287
289
|
duration: "03:35",
|
|
288
290
|
description: "เพลงแดนซ์ป็อปไวรัลสุดสดใส คว้ารางวัล Best Stage Interpretation",
|
|
@@ -115,31 +115,96 @@ export function formatGb(bytes, digits = 2) {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
export
|
|
118
|
+
export const KV_CACHE_DTYPE_BYTES = Object.freeze({
|
|
119
|
+
fp32: 4.0,
|
|
120
|
+
f32: 4.0,
|
|
121
|
+
fp16: 2.0,
|
|
122
|
+
f16: 2.0,
|
|
123
|
+
bf16: 2.0,
|
|
124
|
+
q8_0: 1.0625,
|
|
125
|
+
q8: 1.0625,
|
|
126
|
+
q4_0: 0.5625,
|
|
127
|
+
q4: 0.5625,
|
|
128
|
+
q4_1: 0.625,
|
|
129
|
+
q5_0: 0.6875,
|
|
130
|
+
q5_1: 0.75,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export function resolveKvBytesPerValue(cacheBits = 16, cacheType = null) {
|
|
134
|
+
if (cacheType && typeof cacheType === 'string') {
|
|
135
|
+
const key = cacheType.toLowerCase().replace(/[^a-z0-9_]/g, '');
|
|
136
|
+
if (KV_CACHE_DTYPE_BYTES[key] !== undefined) return KV_CACHE_DTYPE_BYTES[key];
|
|
137
|
+
}
|
|
138
|
+
if (typeof cacheBits === 'string') {
|
|
139
|
+
const key = cacheBits.toLowerCase().replace(/[^a-z0-9_]/g, '');
|
|
140
|
+
if (KV_CACHE_DTYPE_BYTES[key] !== undefined) return KV_CACHE_DTYPE_BYTES[key];
|
|
141
|
+
}
|
|
142
|
+
const n = Number(cacheBits);
|
|
143
|
+
if (Number.isFinite(n) && n > 0) {
|
|
144
|
+
return n / 8;
|
|
145
|
+
}
|
|
146
|
+
return 2.0;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function estimateWeightsBytes({
|
|
150
|
+
paramCount = null,
|
|
151
|
+
paramsB = null,
|
|
152
|
+
quant = 'q4_k_m',
|
|
153
|
+
weightBytesOverride = null,
|
|
154
|
+
gpuLayers = null,
|
|
155
|
+
totalLayers = null,
|
|
156
|
+
} = {}) {
|
|
119
157
|
const bpw = parseBpw(quant);
|
|
158
|
+
let rawBytes = null;
|
|
159
|
+
let count = paramCount;
|
|
120
160
|
if (weightBytesOverride !== null && weightBytesOverride !== undefined && Number.isFinite(Number(weightBytesOverride)) && Number(weightBytesOverride) > 0) {
|
|
121
|
-
|
|
161
|
+
rawBytes = Math.round(Number(weightBytesOverride));
|
|
162
|
+
if (count === null || count === undefined) {
|
|
163
|
+
count = paramsB !== null && paramsB !== undefined && Number.isFinite(Number(paramsB))
|
|
164
|
+
? Math.round(Number(paramsB) * 1e9)
|
|
165
|
+
: null;
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
122
168
|
if (count === null || count === undefined) {
|
|
123
169
|
count = paramsB !== null && paramsB !== undefined && Number.isFinite(Number(paramsB))
|
|
124
170
|
? Math.round(Number(paramsB) * 1e9)
|
|
125
171
|
: null;
|
|
126
172
|
}
|
|
127
|
-
|
|
173
|
+
if (count && count > 0 && bpw !== null) {
|
|
174
|
+
rawBytes = Math.round(count * bpw / 8);
|
|
175
|
+
}
|
|
128
176
|
}
|
|
129
|
-
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
177
|
+
|
|
178
|
+
if (rawBytes === null) {
|
|
179
|
+
return { bytes: null, bpw, paramCount: count };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (gpuLayers !== null && gpuLayers !== undefined && totalLayers !== null && totalLayers !== undefined) {
|
|
183
|
+
const gL = Number(gpuLayers);
|
|
184
|
+
const tL = Number(totalLayers);
|
|
185
|
+
if (Number.isFinite(gL) && Number.isFinite(tL) && tL > 0 && gL >= 0 && gL < tL) {
|
|
186
|
+
const fraction = Math.min(1, Math.max(0, gL / tL));
|
|
187
|
+
return {
|
|
188
|
+
bytes: Math.round(rawBytes * fraction),
|
|
189
|
+
bpw,
|
|
190
|
+
paramCount: count,
|
|
191
|
+
totalWeightBytes: rawBytes,
|
|
192
|
+
offloadFraction: fraction,
|
|
193
|
+
gpuLayers: gL,
|
|
194
|
+
totalLayers: tL,
|
|
195
|
+
source: weightBytesOverride ? 'override-fractional' : 'fractional',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
134
198
|
}
|
|
135
|
-
|
|
136
|
-
return { bytes:
|
|
199
|
+
|
|
200
|
+
return { bytes: rawBytes, bpw, paramCount: count, source: weightBytesOverride ? 'override' : undefined };
|
|
137
201
|
}
|
|
138
202
|
|
|
139
203
|
|
|
140
|
-
export function computeKvBytesPerToken({ layers, kvHeads, headDim, cacheBits = 16 } = {}) {
|
|
204
|
+
export function computeKvBytesPerToken({ layers, kvHeads, headDim, cacheBits = 16, cacheType = null } = {}) {
|
|
141
205
|
if (!layers || !kvHeads || !headDim) return null;
|
|
142
|
-
|
|
206
|
+
const bytesPerVal = resolveKvBytesPerValue(cacheBits, cacheType);
|
|
207
|
+
return 2 * layers * kvHeads * headDim * bytesPerVal;
|
|
143
208
|
}
|
|
144
209
|
|
|
145
210
|
export function estimateKvCacheBytes({
|
|
@@ -149,10 +214,12 @@ export function estimateKvCacheBytes({
|
|
|
149
214
|
contextLength = null,
|
|
150
215
|
batchSize = 1,
|
|
151
216
|
cacheBits = 16,
|
|
217
|
+
cacheType = null,
|
|
152
218
|
swa = null,
|
|
153
219
|
} = {}) {
|
|
220
|
+
const bytesPerVal = resolveKvBytesPerValue(cacheBits, cacheType);
|
|
154
221
|
const perLayerPerToken = (layers && kvHeads && headDim)
|
|
155
|
-
? 2 * kvHeads * headDim *
|
|
222
|
+
? 2 * kvHeads * headDim * bytesPerVal
|
|
156
223
|
: null;
|
|
157
224
|
const bytesPerToken = perLayerPerToken !== null ? perLayerPerToken * layers : null;
|
|
158
225
|
const ctx = Number(contextLength);
|
|
@@ -197,16 +264,25 @@ export function estimateActivationBytes({
|
|
|
197
264
|
queryHeads = null,
|
|
198
265
|
kvHeads = null,
|
|
199
266
|
activationBits = 16,
|
|
267
|
+
contextLength = null,
|
|
200
268
|
} = {}) {
|
|
269
|
+
const batch = Math.max(1, Number(batchSize) || 1);
|
|
270
|
+
const ctx = Number(contextLength) || 0;
|
|
271
|
+
let dynamicScratchGb = DEFAULT_ACTIVATION_GB;
|
|
272
|
+
if (ctx >= 32768) {
|
|
273
|
+
dynamicScratchGb = Math.max(dynamicScratchGb, 0.70);
|
|
274
|
+
} else if (ctx >= 16384) {
|
|
275
|
+
dynamicScratchGb = Math.max(dynamicScratchGb, 0.50);
|
|
276
|
+
}
|
|
277
|
+
|
|
201
278
|
if (!hiddenSize) {
|
|
202
|
-
return { analyticBytes: null, reservedBytes: Math.round(
|
|
279
|
+
return { analyticBytes: null, reservedBytes: Math.round(dynamicScratchGb * GIB) };
|
|
203
280
|
}
|
|
204
281
|
const gqaFactor = queryHeads && kvHeads ? 5 * (queryHeads / kvHeads) : 5;
|
|
205
|
-
const batch = Math.max(1, Number(batchSize) || 1);
|
|
206
282
|
const analyticBytes = Math.round(
|
|
207
283
|
batch * hiddenSize * (34 + gqaFactor) * (Number(activationBits || 16) / 8)
|
|
208
284
|
);
|
|
209
|
-
return { analyticBytes, reservedBytes: Math.round(
|
|
285
|
+
return { analyticBytes, reservedBytes: Math.round(dynamicScratchGb * GIB) };
|
|
210
286
|
}
|
|
211
287
|
|
|
212
288
|
/**
|
|
@@ -219,10 +295,14 @@ export function estimateActivationBytes({
|
|
|
219
295
|
* @param {string} [input.quant='q4_k_m'] Weight quantization.
|
|
220
296
|
* @param {number} [input.contextLength] Runtime sequence limit (text tokens).
|
|
221
297
|
* @param {number} [input.batchSize=1]
|
|
222
|
-
* @param {number} [input.cacheBits=16] KV cache precision (FP16=16, Q8_0=8).
|
|
298
|
+
* @param {number} [input.cacheBits=16] KV cache precision (FP16=16, Q8_0=8, or 'q8_0').
|
|
299
|
+
* @param {string} [input.cacheType] KV cache type ('fp16', 'q8_0', 'q4_0').
|
|
300
|
+
* @param {number} [input.gpuLayers] Number of layers offloaded to GPU.
|
|
301
|
+
* @param {number} [input.totalLayers] Total model layers.
|
|
223
302
|
* @param {number} [input.layers|kvHeads|queryHeads|headDim|hiddenSize]
|
|
224
303
|
* @param {object} [input.vision] { images, tokensPerImage, encoderParamsB }
|
|
225
304
|
* @param {number} [input.activationGb] Override static activation reservation.
|
|
305
|
+
* @param {number} [input.scratchGb] Alias for activationGb.
|
|
226
306
|
* @param {number} [input.overheadGb] Override driver/runtime overhead.
|
|
227
307
|
* @returns {object} Breakdown in bytes + binary GB, warnings included.
|
|
228
308
|
*/
|
|
@@ -235,6 +315,8 @@ export function estimateVramFootprint(input = {}) {
|
|
|
235
315
|
paramsB: input.paramsB,
|
|
236
316
|
quant,
|
|
237
317
|
weightBytesOverride: input.weightBytesOverride,
|
|
318
|
+
gpuLayers: input.gpuLayers,
|
|
319
|
+
totalLayers: input.totalLayers || input.layers,
|
|
238
320
|
});
|
|
239
321
|
|
|
240
322
|
const vision = input.vision || null;
|
|
@@ -262,6 +344,7 @@ export function estimateVramFootprint(input = {}) {
|
|
|
262
344
|
contextLength: effectiveContextLength || null,
|
|
263
345
|
batchSize: input.batchSize,
|
|
264
346
|
cacheBits: input.cacheBits,
|
|
347
|
+
cacheType: input.cacheType,
|
|
265
348
|
swa: input.swa,
|
|
266
349
|
});
|
|
267
350
|
|
|
@@ -271,9 +354,11 @@ export function estimateVramFootprint(input = {}) {
|
|
|
271
354
|
queryHeads: input.queryHeads,
|
|
272
355
|
kvHeads: input.kvHeads,
|
|
273
356
|
activationBits: 16,
|
|
357
|
+
contextLength: effectiveContextLength || textCtx,
|
|
274
358
|
});
|
|
275
|
-
const
|
|
276
|
-
|
|
359
|
+
const actOverride = input.activationGb ?? input.scratchGb;
|
|
360
|
+
const activationBytes = actOverride !== undefined && actOverride !== null
|
|
361
|
+
? Math.round(Number(actOverride) * GIB)
|
|
277
362
|
: activation.reservedBytes;
|
|
278
363
|
const overheadBytes = input.overheadGb !== undefined && input.overheadGb !== null
|
|
279
364
|
? Math.round(Number(input.overheadGb) * GIB)
|
|
@@ -462,3 +547,94 @@ export function recommendAdjustments(estimate, availableBytes, { targetZone = 'G
|
|
|
462
547
|
|
|
463
548
|
return suggestions;
|
|
464
549
|
}
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Simulate VRAM distribution across multiple GPUs in layer-split mode.
|
|
553
|
+
*
|
|
554
|
+
* @param {object} options
|
|
555
|
+
* @param {number} [options.totalBytes]
|
|
556
|
+
* @param {number} [options.weightsBytes]
|
|
557
|
+
* @param {number} [options.kvCacheBytes]
|
|
558
|
+
* @param {number} [options.activationBytes]
|
|
559
|
+
* @param {number} [options.overheadBytes]
|
|
560
|
+
* @param {number} [options.gpuCount=2]
|
|
561
|
+
* @param {string|number[]} [options.tensorSplit] e.g. '20,12' or [20, 12]
|
|
562
|
+
* @param {number} [options.mainGpu=0]
|
|
563
|
+
* @param {number} [options.mainGpuScratchHeadroomGb=2.0] Headroom for scratchpad/context on main GPU
|
|
564
|
+
* @returns {object} Breakdown per GPU
|
|
565
|
+
*/
|
|
566
|
+
export function simulateMultiGpuFootprint({
|
|
567
|
+
totalBytes = null,
|
|
568
|
+
weightsBytes = null,
|
|
569
|
+
kvCacheBytes = null,
|
|
570
|
+
activationBytes = null,
|
|
571
|
+
overheadBytes = null,
|
|
572
|
+
gpuCount = 2,
|
|
573
|
+
tensorSplit = null,
|
|
574
|
+
mainGpu = 0,
|
|
575
|
+
mainGpuScratchHeadroomGb = 2.0,
|
|
576
|
+
} = {}) {
|
|
577
|
+
const count = Math.max(1, Number(gpuCount) || 2);
|
|
578
|
+
const mg = Math.max(0, Math.min(count - 1, Number(mainGpu) || 0));
|
|
579
|
+
|
|
580
|
+
let ratios = [];
|
|
581
|
+
if (typeof tensorSplit === 'string' && tensorSplit.trim()) {
|
|
582
|
+
ratios = tensorSplit.split(',').map(s => Number(s.trim())).filter(n => Number.isFinite(n) && n >= 0);
|
|
583
|
+
} else if (Array.isArray(tensorSplit)) {
|
|
584
|
+
ratios = tensorSplit.map(n => Number(n)).filter(n => Number.isFinite(n) && n >= 0);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (ratios.length < count) {
|
|
588
|
+
while (ratios.length < count) {
|
|
589
|
+
ratios.push(1);
|
|
590
|
+
}
|
|
591
|
+
} else if (ratios.length > count) {
|
|
592
|
+
ratios = ratios.slice(0, count);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const sumRatios = ratios.reduce((a, b) => a + b, 0) || count;
|
|
596
|
+
const normalizedRatios = ratios.map(r => r / sumRatios);
|
|
597
|
+
|
|
598
|
+
const wBytes = weightsBytes ?? 0;
|
|
599
|
+
const kvBytes = kvCacheBytes ?? 0;
|
|
600
|
+
const actBytes = activationBytes ?? Math.round(DEFAULT_ACTIVATION_GB * GIB);
|
|
601
|
+
const ovBytes = overheadBytes ?? Math.round(DEFAULT_OVERHEAD_GB * GIB);
|
|
602
|
+
const mgHeadroomBytes = Math.round(Number(mainGpuScratchHeadroomGb || 2.0) * GIB);
|
|
603
|
+
|
|
604
|
+
const gpus = normalizedRatios.map((ratio, idx) => {
|
|
605
|
+
const isMain = idx === mg;
|
|
606
|
+
const gpuWeights = Math.round(wBytes * ratio);
|
|
607
|
+
const gpuKv = Math.round(kvBytes * ratio);
|
|
608
|
+
const gpuAct = isMain ? actBytes + mgHeadroomBytes : Math.round(actBytes * 0.5);
|
|
609
|
+
const gpuOv = ovBytes;
|
|
610
|
+
const gpuTotal = gpuWeights + gpuKv + gpuAct + gpuOv;
|
|
611
|
+
|
|
612
|
+
return {
|
|
613
|
+
gpuIndex: idx,
|
|
614
|
+
isMain,
|
|
615
|
+
ratio: Number((ratio * 100).toFixed(1)),
|
|
616
|
+
ratioRaw: ratios[idx],
|
|
617
|
+
weightsBytes: gpuWeights,
|
|
618
|
+
kvCacheBytes: gpuKv,
|
|
619
|
+
activationBytes: gpuAct,
|
|
620
|
+
overheadBytes: gpuOv,
|
|
621
|
+
totalBytes: gpuTotal,
|
|
622
|
+
gb: {
|
|
623
|
+
weights: Number((gpuWeights / GIB).toFixed(2)),
|
|
624
|
+
kvCache: Number((gpuKv / GIB).toFixed(2)),
|
|
625
|
+
activation: Number((gpuAct / GIB).toFixed(2)),
|
|
626
|
+
overhead: Number((gpuOv / GIB).toFixed(2)),
|
|
627
|
+
total: Number((gpuTotal / GIB).toFixed(2)),
|
|
628
|
+
},
|
|
629
|
+
};
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
return {
|
|
633
|
+
gpuCount: count,
|
|
634
|
+
mainGpu: mg,
|
|
635
|
+
tensorSplit: ratios.join(','),
|
|
636
|
+
gpus,
|
|
637
|
+
totalAllocatedBytes: gpus.reduce((acc, g) => acc + g.totalBytes, 0),
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
|