dqy08 commited on
Commit
bb35e88
·
1 Parent(s): c6aeab1

增强多语言支持,网页默认加载示例

Browse files
Files changed (42) hide show
  1. .gitignore +1 -0
  2. client/src/content/home.en.html +11 -2
  3. client/src/content/home.zh.html +9 -2
  4. client/src/index.html +2 -2
  5. client/src/ts/compare.ts +9 -12
  6. client/src/ts/controllers/demoStorageController.ts +14 -13
  7. client/src/ts/controllers/serverDemoController.ts +7 -6
  8. client/src/ts/controllers/textInputController.ts +2 -1
  9. client/src/ts/lang/translations.ts +37 -0
  10. client/src/ts/start.ts +17 -10
  11. client/src/ts/storage/demoResourceLoader.ts +4 -3
  12. client/src/ts/storage/demoStorage.ts +1 -1
  13. client/src/ts/storage/localDemoCache.ts +9 -9
  14. client/src/ts/storage/localFileIO.ts +8 -6
  15. client/src/ts/ui/demoManager.ts +4 -4
  16. client/src/ts/ui/demoMultiSelect.ts +11 -7
  17. client/src/ts/ui/language.ts +3 -2
  18. client/src/ts/utils/URLHandler.ts +4 -18
  19. client/src/ts/utils/adminManager.ts +1 -1
  20. client/src/ts/utils/demoPathUtils.ts +6 -6
  21. client/src/ts/utils/localFileUtils.ts +4 -3
  22. client/src/ts/utils/settingsMenuManager.ts +1 -1
  23. client/src/ts/utils/visualizationUpdater.ts +4 -3
  24. data/demo/public/CN/GPT-2 large unicorn text(中文翻译)_qwen2.5.json +0 -0
  25. data/demo/public/CN/GPT-2 small top_k 40 temp .7 (中文翻译).json +0 -0
  26. data/demo/public/CN/GPT-2 small top_k 40 temp .7 (中文翻译)_qwen2.5.json +0 -0
  27. data/demo/public/CN/GPT-2 small top_k 5 temp 1 (中文翻译)_qwen2.5.json +0 -0
  28. data/demo/public/CN/{human_ NYTimes article (中文翻译).json → NYTimes article (中文翻译).json} +0 -0
  29. data/demo/public/CN/{human_ academic text (中文翻译).json → academic text (中文翻译).json} +0 -0
  30. data/demo/public/CN/human_ NYTimes article (中文翻译)_qwen2.5.json +0 -0
  31. data/demo/public/CN/human_ academic text (中文翻译)_qwen2.5.json +0 -0
  32. data/demo/public/{GPT-2 large unicorn text → GPT-2 large unicorn text.json} +0 -0
  33. data/demo/public/GPT-2 large unicorn text_qwen2.5.json +0 -0
  34. data/demo/public/GPT-2 small top_k 5 temp 1_qwen2.5.json +0 -0
  35. data/demo/public/{human_ NYTimes article.json → NYTimes article.json} +0 -0
  36. data/demo/public/{human_ academic text.json → academic text.json} +0 -0
  37. data/demo/public/human_ NYTimes article_qwen2.5.json +0 -0
  38. data/demo/public/human_ academic text_qwen2.5.json +0 -0
  39. data/demo/public/human_ woodchuck_qwen2.5.json +0 -964
  40. data/demo/public/quick-start-1.json +593 -0
  41. data/demo/public/quick-start-2.json +593 -0
  42. data/demo/public/{human_ woodchuck.json → woodchuck.json} +0 -0
.gitignore CHANGED
@@ -36,3 +36,4 @@ notes/*
36
  *.swp
37
  *.log
38
  .specstory
 
 
36
  *.swp
37
  *.log
38
  .specstory
39
+ scripts/log.py
client/src/content/home.en.html CHANGED
@@ -23,8 +23,8 @@
23
  <div class="intro-block">
24
  <h4>Intuitive Understanding of Information</h4>
25
  <p>From a linguistic perspective, information represents the novelty/surprise/importance of a word. Words that
26
- are harder to predict from context typically carry more information. A simple example: "Today I saw a 'UFO'"
27
- vs "Today I saw a 'plane'" — clearly "UFO" carries more information.</p>
28
  </div>
29
 
30
  <!-- 技术定义 -->
@@ -63,6 +63,15 @@
63
  improve reading speed.</p>
64
  </div>
65
 
 
 
 
 
 
 
 
 
 
66
  <!-- FAQ -->
67
  <div class="intro-block intro-faq">
68
  <h4>FAQ</h4>
 
23
  <div class="intro-block">
24
  <h4>Intuitive Understanding of Information</h4>
25
  <p>From a linguistic perspective, information represents the novelty/surprise/importance of a word. Words that
26
+ are harder to predict from context typically carry more information. A simple example: “This morning I opened the door and saw a 'UFO'.”
27
+ vs “This morning I opened the door and saw a 'cat'.” — clearly "UFO" carries more information.</p>
28
  </div>
29
 
30
  <!-- 技术定义 -->
 
63
  improve reading speed.</p>
64
  </div>
65
 
66
+ <!-- Tribute -->
67
+ <div class="intro-block">
68
+ <h4>Tribute</h4>
69
+ <p>InfoRadar is built on the classic project <a href="http://gltr.io" target="_blank" rel="noopener">GLTR.io</a>,
70
+ developed by Hendrik Strobelt et al. in 2019. GLTR was a web demo that pioneered using GPT-2 prediction
71
+ probabilities to detect generated text.</p>
72
+ <p>However, this project's goal is not to detect AI text, but to evaluate the "information quality" of text.</p>
73
+ </div>
74
+
75
  <!-- FAQ -->
76
  <div class="intro-block intro-faq">
77
  <h4>FAQ</h4>
client/src/content/home.zh.html CHANGED
@@ -15,8 +15,8 @@
15
  <!-- 原理直觉 -->
16
  <div class="intro-block">
17
  <h4>信息量的直观理解</h4>
18
- <p>从语言学角度看,信息量代表一个词所包含的新意/意外性/关键程度。越难从上下文中预测出来的词,通常携带的信息就越多。一个简单的例子:"今天我在天上看见了'飞碟'" 和
19
- "今天我在天上看见了'飞机'":在这里显然"飞碟"的信息量更大。</p>
20
  </div>
21
 
22
  <!-- 技术定义 -->
@@ -43,6 +43,13 @@
43
  <p>好消息是,大模型进步实在太快了:目前的分析结果已经在一定程度上反映了主流阅读者的主观感受,可以用来评估文章的信息含量,还可以提高阅读速度。</p>
44
  </div>
45
 
 
 
 
 
 
 
 
46
  <!-- FAQ -->
47
  <div class="intro-block intro-faq">
48
  <h4>常见问题</h4>
 
15
  <!-- 原理直觉 -->
16
  <div class="intro-block">
17
  <h4>信息量的直观理解</h4>
18
+ <p>从语言学角度看,信息量代表一个词所包含的新意/意外性/关键程度。越难从上下文中预测出来的词,通常携带的信息就越多。一个简单的例子:"今天早上我打开门看见了一只'飞碟'" 和
19
+ "今天早上我打开门看见了一只''":在这里显然"飞碟"的信息量更大。</p>
20
  </div>
21
 
22
  <!-- 技术定义 -->
 
43
  <p>好消息是,大模型进步实在太快了:目前的分析结果已经在一定程度上反映了主流阅读者的主观感受,可以用来评估文章的信息含量,还可以提高阅读速度。</p>
44
  </div>
45
 
46
+ <!-- 致谢 -->
47
+ <div class="intro-block">
48
+ <h4>致谢</h4>
49
+ <p>InfoRadar 基于 2019 年 Hendrik Strobelt 等人开发的经典项目 <a href="http://gltr.io" target="_blank" rel="noopener">GLTR.io</a>。GLTR 是一个网页演示,率先用 GPT-2 的预测概率来检测生成文本。</p>
50
+ <p>不过本项目的目标不是检测 AI 文本,而是评估文本的“信息质量”。</p>
51
+ </div>
52
+
53
  <!-- FAQ -->
54
  <div class="intro-block intro-faq">
55
  <h4>常见问题</h4>
client/src/index.html CHANGED
@@ -19,7 +19,7 @@
19
  <div class="dark-mode-toggle-wrapper">
20
  <h1 class="home-toolbar-title"><span data-i18n>InfoRadar</span> <span class="title-formula" data-i18n>LLM × Linguistics × Information Theory</span></h1>
21
  <div class="home-toolbar-actions">
22
- <a href="compare.html" target="_blank" class="compare-link" title="Compare analysis results" data-i18n="text,title">Compare results</a>
23
  <div class="settings-menu-wrapper">
24
  <button id="settings_btn" class="settings-btn" title="Settings" data-i18n="title">
25
  <span class="settings-icon">⚙️</span>
@@ -86,7 +86,7 @@
86
  </div>
87
  </div>
88
  <div class="textarea-wrapper">
89
- <textarea id="test_text">The cat was playing in the garden.</textarea>
90
  <div class="button-group">
91
  <div class="button-left">
92
  <button id="submit_text_btn" class="primary-btn" data-i18n>Analyze</button>
 
19
  <div class="dark-mode-toggle-wrapper">
20
  <h1 class="home-toolbar-title"><span data-i18n>InfoRadar</span> <span class="title-formula" data-i18n>LLM × Linguistics × Information Theory</span></h1>
21
  <div class="home-toolbar-actions">
22
+ <a href="compare.html?showTextRender=1&demos=/quick-start-1.json,/quick-start-2.json" target="_blank" class="compare-link" title="Compare analysis results" data-i18n="text,title">Compare results</a>
23
  <div class="settings-menu-wrapper">
24
  <button id="settings_btn" class="settings-btn" title="Settings" data-i18n="title">
25
  <span class="settings-icon">⚙️</span>
 
86
  </div>
87
  </div>
88
  <div class="textarea-wrapper">
89
+ <textarea id="test_text">“I opened the door and saw a bird.”</textarea>
90
  <div class="button-group">
91
  <div class="button-left">
92
  <button id="submit_text_btn" class="primary-btn" data-i18n>Analyze</button>
client/src/ts/compare.ts CHANGED
@@ -149,12 +149,8 @@ window.onload = () => {
149
  let demoPaths: string[] = [];
150
 
151
  if (demosParam) {
152
- if (typeof demosParam === 'string') {
153
- // 逗号分隔的字符串
154
- demoPaths = demosParam.split(',').map(p => p.trim()).filter(p => p.length > 0);
155
- } else if (Array.isArray(demosParam)) {
156
- demoPaths = demosParam.map(p => String(p).trim()).filter(p => p.length > 0);
157
- }
158
  }
159
 
160
  // 解析显示文本渲染和模型差分模式参数
@@ -515,7 +511,7 @@ window.onload = () => {
515
  const result = await demoResourceLoader.load(columnData.demoPath);
516
 
517
  if (!result.success || !result.data) {
518
- columnData.error = result.message || tr('Load failed');
519
  showErrorForColumn(id, columnData.error);
520
  updateModelDiffModeAvailability();
521
  return;
@@ -1015,8 +1011,8 @@ window.onload = () => {
1015
 
1016
  if (!result.success) {
1017
  // 用户取消不提示错误
1018
- if (result.message !== tr('User cancelled file selection')) {
1019
- showAlertDialog(tr('Error'), result.message || tr('Import failed'));
1020
  }
1021
  return;
1022
  }
@@ -1047,7 +1043,7 @@ window.onload = () => {
1047
  });
1048
 
1049
  if (!saveResult.success || !saveResult.hash) {
1050
- errors.push(`${file.filename}: ${saveResult.message || tr('Failed to save to cache')}`);
1051
  continue;
1052
  }
1053
 
@@ -1117,7 +1113,7 @@ window.onload = () => {
1117
  const result = await demoResourceLoader.load(resourceIdentifier);
1118
 
1119
  if (!result.success || !result.data) {
1120
- showAlertDialog(tr('Error'), result.message || tr('Load failed'));
1121
  return;
1122
  }
1123
 
@@ -1233,7 +1229,8 @@ window.onload = () => {
1233
  }
1234
 
1235
  if (demoPaths.length > 0) {
1236
- currentParams['demos'] = demoPaths;
 
1237
  }
1238
 
1239
  URLHandler.updateUrl(currentParams, false);
 
149
  let demoPaths: string[] = [];
150
 
151
  if (demosParam) {
152
+ const raw = String(demosParam).trim();
153
+ demoPaths = raw.split(',').map(p => p.trim()).filter(p => p.length > 0);
 
 
 
 
154
  }
155
 
156
  // 解析显示文本渲染和模型差分模式参数
 
511
  const result = await demoResourceLoader.load(columnData.demoPath);
512
 
513
  if (!result.success || !result.data) {
514
+ columnData.error = tr(result.message || 'Load failed');
515
  showErrorForColumn(id, columnData.error);
516
  updateModelDiffModeAvailability();
517
  return;
 
1011
 
1012
  if (!result.success) {
1013
  // 用户取消不提示错误
1014
+ if (!result.cancelled && result.message) {
1015
+ showAlertDialog(tr('Error'), tr(result.message || 'Import failed'));
1016
  }
1017
  return;
1018
  }
 
1043
  });
1044
 
1045
  if (!saveResult.success || !saveResult.hash) {
1046
+ errors.push(`${file.filename}: ${tr(saveResult.message || 'Failed to save to cache')}`);
1047
  continue;
1048
  }
1049
 
 
1113
  const result = await demoResourceLoader.load(resourceIdentifier);
1114
 
1115
  if (!result.success || !result.data) {
1116
+ showAlertDialog(tr('Error'), tr(result.message || 'Load failed'));
1117
  return;
1118
  }
1119
 
 
1229
  }
1230
 
1231
  if (demoPaths.length > 0) {
1232
+ // demos 始终按数组语义:写入为逗号拼接字符串,避免 URL 出现数组前缀 ".."
1233
+ currentParams['demos'] = demoPaths.join(',');
1234
  }
1235
 
1236
  URLHandler.updateUrl(currentParams, false);
client/src/ts/controllers/demoStorageController.ts CHANGED
@@ -5,6 +5,7 @@
5
  import type { AnalysisData } from '../api/GLTR_API';
6
  import type { IDemoStorage, SaveOptions, SaveResult } from '../storage/demoStorage';
7
  import { showConfirmDialog, showAlertDialog } from '../ui/dialog';
 
8
 
9
  export interface StorageCallbacks {
10
  onStart?: () => void;
@@ -46,7 +47,7 @@ export class DemoStorageController {
46
  onSuccess?.(options.name, result);
47
  // 成功提示:根据 showSuccessToast 决定是否显示
48
  if (showSuccessToast) {
49
- const hint = this.storage.type === 'local' ? '已下载到本地' : '上传成功';
50
  showToast?.(`Demo "${options.name}" ${hint}!`, 'success');
51
  }
52
  }
@@ -58,7 +59,7 @@ export class DemoStorageController {
58
  onError?.(err);
59
 
60
  // 错误提示:统一使用 alert
61
- showAlertDialog('错误', `保存失败: ${err.message}`);
62
  return null;
63
  }
64
  }
@@ -78,25 +79,25 @@ export class DemoStorageController {
78
  return new Promise((resolve) => {
79
  this.callbacks.setLoading?.(false);
80
  showConfirmDialog(
81
- '文件已存在',
82
- `文件 "${options.name}.json" 已存在,是否覆盖?`,
83
  async () => {
84
  this.callbacks.setLoading?.(true);
85
  const saved = await this._doSave(data, options, true);
86
  resolve(saved);
87
  },
88
  () => {
89
- this.callbacks.onError?.(new Error('用户取消保存'));
90
  resolve(null);
91
  },
92
- '覆盖',
93
- '取消'
94
  );
95
  });
96
  }
97
 
98
  if (!result.success) {
99
- throw new Error(result.message || '保存失败');
100
  }
101
 
102
  return result;
@@ -119,11 +120,11 @@ export class DemoStorageController {
119
  onSuccess?.();
120
  return result.data;
121
  } else {
122
- // 用户取消不提示错误
123
- if (result.message !== '用户取消了文件选择') {
124
- const err = new Error(result.message || '加载失败');
125
  onError?.(err);
126
- showAlertDialog('错误', err.message);
127
  }
128
  return null;
129
  }
@@ -131,7 +132,7 @@ export class DemoStorageController {
131
  setLoading?.(false);
132
  const err = error instanceof Error ? error : new Error(String(error));
133
  onError?.(err);
134
- showAlertDialog('错误', `加载失败: ${err.message}`);
135
  return null;
136
  }
137
  }
 
5
  import type { AnalysisData } from '../api/GLTR_API';
6
  import type { IDemoStorage, SaveOptions, SaveResult } from '../storage/demoStorage';
7
  import { showConfirmDialog, showAlertDialog } from '../ui/dialog';
8
+ import { tr, trf } from '../lang/i18n-lite';
9
 
10
  export interface StorageCallbacks {
11
  onStart?: () => void;
 
47
  onSuccess?.(options.name, result);
48
  // 成功提示:根据 showSuccessToast 决定是否显示
49
  if (showSuccessToast) {
50
+ const hint = this.storage.type === 'local' ? tr('Downloaded to local') : tr('Upload successful');
51
  showToast?.(`Demo "${options.name}" ${hint}!`, 'success');
52
  }
53
  }
 
59
  onError?.(err);
60
 
61
  // 错误提示:统一使用 alert
62
+ showAlertDialog(tr('Error'), trf('Save failed: {message}', { message: err.message }));
63
  return null;
64
  }
65
  }
 
79
  return new Promise((resolve) => {
80
  this.callbacks.setLoading?.(false);
81
  showConfirmDialog(
82
+ tr('File already exists'),
83
+ trf('File "{name}.json" already exists, overwrite?', { name: options.name }),
84
  async () => {
85
  this.callbacks.setLoading?.(true);
86
  const saved = await this._doSave(data, options, true);
87
  resolve(saved);
88
  },
89
  () => {
90
+ this.callbacks.onError?.(new Error(tr('User cancelled save')));
91
  resolve(null);
92
  },
93
+ tr('Overwrite'),
94
+ tr('Cancel')
95
  );
96
  });
97
  }
98
 
99
  if (!result.success) {
100
+ throw new Error(result.message || 'Save failed');
101
  }
102
 
103
  return result;
 
120
  onSuccess?.();
121
  return result.data;
122
  } else {
123
+ // 显示错误(这里不涉及用户取消操作)
124
+ if (result.message) {
125
+ const err = new Error(result.message || 'Load failed');
126
  onError?.(err);
127
+ showAlertDialog(tr('Error'), tr(err.message));
128
  }
129
  return null;
130
  }
 
132
  setLoading?.(false);
133
  const err = error instanceof Error ? error : new Error(String(error));
134
  onError?.(err);
135
+ showAlertDialog(tr('Error'), trf('Load failed: {message}', { message: err.message }));
136
  return null;
137
  }
138
  }
client/src/ts/controllers/serverDemoController.ts CHANGED
@@ -11,6 +11,7 @@ import {
11
  getDefaultDemoName,
12
  buildFolderOptions
13
  } from '../utils/demoPathUtils';
 
14
 
15
  /**
16
  * 从保存结果中提取文件名,如果不存在则根据名称生成
@@ -46,11 +47,11 @@ export const showDemoNameInput = (
46
 
47
  // 显示弹框
48
  showDialog({
49
- title: '请输入demo名称:',
50
  content: createCombinedContent(
51
- 'Demo名称:',
52
  defaultName,
53
- '保存目录:',
54
  selectOptions,
55
  defaultPath
56
  ),
@@ -67,13 +68,13 @@ export const showDemoNameInput = (
67
  onCancel: () => {
68
  resolve(null);
69
  },
70
- cancelText: '取消'
71
  });
72
  })
73
  .catch((error) => {
74
  console.error('加载文件夹列表失败:', error);
75
  const errorMessage = error instanceof Error ? error.message : String(error);
76
- showAlertDialog('错误', `加载文件夹列表失败: ${errorMessage}`);
77
  resolve(null);
78
  });
79
  });
@@ -142,7 +143,7 @@ export const handleServerDemoSave = async (options: ServerDemoSaveOptions): Prom
142
  } = options;
143
 
144
  if (!currentData || !rawApiResponse) {
145
- showAlertDialog('提示', '没有可保存的分析结果');
146
  return;
147
  }
148
 
 
11
  getDefaultDemoName,
12
  buildFolderOptions
13
  } from '../utils/demoPathUtils';
14
+ import { tr, trf } from '../lang/i18n-lite';
15
 
16
  /**
17
  * 从保存结果中提取文件名,如果不存在则根据名称生成
 
47
 
48
  // 显示弹框
49
  showDialog({
50
+ title: tr('Please enter demo name:'),
51
  content: createCombinedContent(
52
+ tr('Demo name:'),
53
  defaultName,
54
+ tr('Save directory:'),
55
  selectOptions,
56
  defaultPath
57
  ),
 
68
  onCancel: () => {
69
  resolve(null);
70
  },
71
+ cancelText: tr('Cancel')
72
  });
73
  })
74
  .catch((error) => {
75
  console.error('加载文件夹列表失败:', error);
76
  const errorMessage = error instanceof Error ? error.message : String(error);
77
+ showAlertDialog(tr('Error'), trf('Failed to load folder list: {message}', { message: errorMessage }));
78
  resolve(null);
79
  });
80
  });
 
143
  } = options;
144
 
145
  if (!currentData || !rawApiResponse) {
146
+ showAlertDialog(tr('Info'), tr('No data to save, please analyze text first'));
147
  return;
148
  }
149
 
client/src/ts/controllers/textInputController.ts CHANGED
@@ -4,6 +4,7 @@ import { calculateTextStats } from '../utils/textStatistics';
4
  import { countTokenCharacters } from '../utils/Util';
5
  import type { FrontendAnalyzeResult } from '../api/GLTR_API';
6
  import { updateBasicMetrics, updateTotalSurprisal, updateModel, validateMetricsElements } from '../utils/textMetricsUpdater';
 
7
 
8
  /**
9
  * 扩展的 Input 事件接口
@@ -153,7 +154,7 @@ export class TextInputController {
153
  } catch (error) {
154
  console.error('粘贴失败:', error);
155
  // 如果clipboard API不可用,提示用户手动粘贴
156
- this.options.showAlertDialog('提示', '无法读取剪贴板,请手动粘贴');
157
  }
158
  }
159
 
 
4
  import { countTokenCharacters } from '../utils/Util';
5
  import type { FrontendAnalyzeResult } from '../api/GLTR_API';
6
  import { updateBasicMetrics, updateTotalSurprisal, updateModel, validateMetricsElements } from '../utils/textMetricsUpdater';
7
+ import { tr } from '../lang/i18n-lite';
8
 
9
  /**
10
  * 扩展的 Input 事件接口
 
154
  } catch (error) {
155
  console.error('粘贴失败:', error);
156
  // 如果clipboard API不可用,提示用户手动粘贴
157
+ this.options.showAlertDialog(tr('Info'), tr('Failed to read clipboard, please paste manually'));
158
  }
159
  }
160
 
client/src/ts/lang/translations.ts CHANGED
@@ -40,6 +40,7 @@ export const translations: Translations = {
40
  'Finish editing': '完成编辑',
41
  'Move': '移动',
42
  'OK': '确定',
 
43
  'Paste': '粘贴',
44
  'Save': '保存',
45
  'Upload': '上传',
@@ -47,6 +48,7 @@ export const translations: Translations = {
47
  // ========== 对话框和表单 ==========
48
  'Demo name:': 'Demo名称:',
49
  'Enter folder name': '请输入文件夹名称',
 
50
  'Folder name:': '文件夹名称:',
51
  'New name:': '新名称:',
52
  'Save directory:': '保存目录:',
@@ -55,12 +57,31 @@ export const translations: Translations = {
55
  'URL address:': 'URL 地址:',
56
 
57
  // ========== 状态和提示信息 ==========
 
 
 
58
  'Info': '提示',
59
  'Loading...': '加载中...',
60
  'No file selected': '未选择文件',
61
  'Queuing...': '排队中...',
62
  'Refreshing...': '正在刷新...',
63
  'Success': '成功',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
  // ========== 浏览器兼容性提示 ==========
66
  'Browser does not support IndexedDB, the following features will not be available:':
@@ -202,23 +223,37 @@ export const translations: Translations = {
202
  'Error': '错误',
203
  'Error loading demos, please check console for details.': '加载 demos 时出错,请检查控制台获取详细信息。',
204
  'Failed items:': '失败项:',
 
205
  'Failed to add local file': '添加本地文件失败',
206
  'Failed to create folder': '创建文件夹失败',
 
 
 
207
  'Failed to create folder, please check console for details.': '创建文件夹失败,请检查控制台获取详细信息。',
208
  'Failed to get folder list, please check console for details.': '获取文件夹列表失败,请检查控制台获取详细信息。',
209
  'Failed to load folder list': '加载文件夹列表失败',
 
210
  'Failed to open file': '打开文件失败',
 
 
211
  'Failed to refresh demo list, please check console for details.': '刷新demo列表失败,请检查控制台获取详细信息。',
212
  'Failed to restore': '恢复失败',
213
  'Failed to save to cache': '保存到缓存失败',
 
214
  'File download failed': '文件下载失败',
215
  'File is not a valid JSON format': '文件不是有效的JSON格式',
 
216
  'File opened, but cannot be saved to local cache due to browser security policy restrictions.':
217
  '文件已打开,但由于浏览器安全策略限制,无法保存到本地缓存。',
218
  'Hash value missing': '哈希值缺失',
219
  'Import failed': '导入失败',
220
  'Invalid URL format': 'URL格式无效',
221
  'Load failed': '加载失败',
 
 
 
 
 
222
  'Move failed': '移动失败',
223
  'Move failed, please check console for details.': '移动失败,请检查控制台获取详细信息。',
224
  'No data to save, please analyze text first': '没有可保存的数据,请先分析文本',
@@ -229,7 +264,9 @@ export const translations: Translations = {
229
  'Rename failed': '重命名失败',
230
  'Rename failed, please check console for details.': '重命名失败,请检查控制台获取详细信息。',
231
  'Returned JSON missing valid bpe_strings array': '返回 JSON 缺少合法的 bpe_strings 数组',
 
232
  'Save failed': '保存失败',
 
233
  'Some demos failed to load': '部分 Demo 加载失败',
234
  'Some files import failed': '部分文件导入失败',
235
  'Unable to extract text from URL': '无法从 URL 提取文本',
 
40
  'Finish editing': '完成编辑',
41
  'Move': '移动',
42
  'OK': '确定',
43
+ 'Overwrite': '覆盖',
44
  'Paste': '粘贴',
45
  'Save': '保存',
46
  'Upload': '上传',
 
48
  // ========== 对话框和表单 ==========
49
  'Demo name:': 'Demo名称:',
50
  'Enter folder name': '请输入文件夹名称',
51
+ 'Please enter demo name:': '请输入demo名称:',
52
  'Folder name:': '文件夹名称:',
53
  'New name:': '新名称:',
54
  'Save directory:': '保存目录:',
 
57
  'URL address:': 'URL 地址:',
58
 
59
  // ========== 状态和提示信息 ==========
60
+ 'Downloaded to local': '已下载到本地',
61
+ 'File already exists': '文件已存在',
62
+ 'File "{name}.json" already exists, overwrite?': '文件 "{name}.json" 已存在,是否覆盖?',
63
  'Info': '提示',
64
  'Loading...': '加载中...',
65
  'No file selected': '未选择文件',
66
  'Queuing...': '排队中...',
67
  'Refreshing...': '正在刷新...',
68
  'Success': '成功',
69
+ 'Upload successful': '上传成功',
70
+ 'User cancelled save': '用户取消保存',
71
+ 'Demo path is missing': '缺少demo路径',
72
+ 'Saved to local cache': '已保存到本地缓存',
73
+ 'Storage quota exceeded, please clear cache and try again': '存储空间不足,请清理缓存后重试',
74
+ 'Key is missing': '缺少key',
75
+ 'File not found in local cache, please open again': '本地缓存中未找到该文件,请重新打开',
76
+ 'Failed to read from cache': '从缓存读取失败',
77
+ 'Request failed, please try again later.': '请求失败,请稍后重试。',
78
+ 'File name cannot be empty': '文件名不能为空',
79
+ 'File name too long (max 255 characters)': '文件名过长(最多255个字符)',
80
+ 'File name contains invalid characters (cannot contain < > : " | ? * or control characters)': '文件名包含非法字符(不能包含 < > : " | ? * 或控制字符)',
81
+ 'File name cannot be a system reserved name': '文件名不能使用系统保留名称',
82
+ 'File name cannot start or end with a dot': '文件名不能以点开头或结尾',
83
+ 'File name cannot contain path separators': '文件名不能包含路径分隔符',
84
+ 'Chinese': '中文',
85
 
86
  // ========== 浏览器兼容性提示 ==========
87
  'Browser does not support IndexedDB, the following features will not be available:':
 
223
  'Error': '错误',
224
  'Error loading demos, please check console for details.': '加载 demos 时出错,请检查控制台获取详细信息。',
225
  'Failed items:': '失败项:',
226
+ 'All files failed to read:': '所有文件读取失败:',
227
  'Failed to add local file': '添加本地文件失败',
228
  'Failed to create folder': '创建文件夹失败',
229
+ 'Failed to read file': '文件读取失败',
230
+ 'Partial files failed:': '部分文件失败:',
231
+ 'Read failed': '读取失败',
232
  'Failed to create folder, please check console for details.': '创建文件夹失败,请检查控制台获取详细信息。',
233
  'Failed to get folder list, please check console for details.': '获取文件夹列表失败,请检查控制台获取详细信息。',
234
  'Failed to load folder list': '加载文件夹列表失败',
235
+ 'Failed to load folder list: {message}': '加载文件夹列表失败: {message}',
236
  'Failed to open file': '打开文件失败',
237
+ 'Failed to open IndexedDB': '无法打开 IndexedDB',
238
+ 'Failed to read clipboard, please paste manually': '无法读取剪贴板,请手动粘贴',
239
  'Failed to refresh demo list, please check console for details.': '刷新demo列表失败,请检查控制台获取详细信息。',
240
  'Failed to restore': '恢复失败',
241
  'Failed to save to cache': '保存到缓存失败',
242
+ 'File content is not a valid JSON object': '文件内容不是有效的JSON对象',
243
  'File download failed': '文件下载失败',
244
  'File is not a valid JSON format': '文件不是有效的JSON格式',
245
+ 'Invalid hash format: "{hash}", expected 4 hexadecimal characters': '无效的哈希值格式: "{hash}",应为4位十六进制字符',
246
  'File opened, but cannot be saved to local cache due to browser security policy restrictions.':
247
  '文件已打开,但由于浏览器安全策略限制,无法保存到本地缓存。',
248
  'Hash value missing': '哈希值缺失',
249
  'Import failed': '导入失败',
250
  'Invalid URL format': 'URL格式无效',
251
  'Load failed': '加载失败',
252
+ 'Load failed: {message}': '加载失败: {message}',
253
+ 'Local resource identifier missing hash: "{identifier}", format should be local://filename.json~hash': '本地资源标识符缺少哈希值: "{identifier}",格式应为 local://filename.json~hash',
254
+ 'Missing required "request" field': '缺少必需的"request"字段',
255
+ 'Missing required "result" field': '缺少必需的"result"字段',
256
+ 'Unable to extract local resource info: "{identifier}"': '无法提取本地资源信息: "{identifier}"',
257
  'Move failed': '移动失败',
258
  'Move failed, please check console for details.': '移动失败,请检查控制台获取详细信息。',
259
  'No data to save, please analyze text first': '没有可保存的数据,请先分析文本',
 
264
  'Rename failed': '重命名失败',
265
  'Rename failed, please check console for details.': '重命名失败,请检查控制台获取详细信息。',
266
  'Returned JSON missing valid bpe_strings array': '返回 JSON 缺少合法的 bpe_strings 数组',
267
+ 'Returned JSON missing valid bpe_strings array, processing cancelled.': '返回 JSON 缺少合法的 bpe_strings 数组,已取消本次处理。',
268
  'Save failed': '保存失败',
269
+ 'Save failed: {message}': '保存失败: {message}',
270
  'Some demos failed to load': '部分 Demo 加载失败',
271
  'Some files import failed': '部分文件导入失败',
272
  'Unable to extract text from URL': '无法从 URL 提取文本',
client/src/ts/start.ts CHANGED
@@ -331,7 +331,7 @@ window.onload = () => {
331
  if (urlDemoPath && DemoResourceLoader.isLocalResource(urlDemoPath)) {
332
  updateFileNameDisplay(null);
333
  }
334
- showAlertDialog(tr('Error'), message);
335
  };
336
 
337
  /**
@@ -411,7 +411,7 @@ window.onload = () => {
411
  });
412
  // 本地文件打开不需要toast提示
413
  } else {
414
- throw new Error(loadResult.message || tr('Load failed'));
415
  }
416
  } catch (cacheError) {
417
  // 如果是因为 crypto.subtle 不可用导致保存到缓存失败,跳过缓存,直接渲染文件
@@ -436,13 +436,13 @@ window.onload = () => {
436
  throw cacheError;
437
  }
438
  }
439
- } else if (result.message && result.message !== '用户取消了文件选择') {
440
  // 只有在非取消的情况下才显示错误
441
- showAlertDialog(tr('Error'), result.message);
442
  }
443
  } catch (error) {
444
- const message = error instanceof Error ? error.message : tr('Failed to open file');
445
- showAlertDialog(tr('Error'), message);
446
  } finally {
447
  appStateManager.setGlobalLoading(false);
448
  }
@@ -473,11 +473,12 @@ window.onload = () => {
473
  onRefreshEnd: async () => {
474
  ensureSystemStarted();
475
 
476
- // 只在首次加载时检查URL参数中的demo参数
477
  if (!hasProcessedUrlDemo) {
478
  hasProcessedUrlDemo = true;
479
- const urlDemoPath = URLHandler.parameters['demo'];
480
- if (urlDemoPath && typeof urlDemoPath === 'string') {
 
481
  appStateManager.setGlobalLoading(true);
482
  try {
483
  // 判断资源类型
@@ -491,6 +492,9 @@ window.onload = () => {
491
  disableAnimation: true,
492
  isNewDemo: true
493
  });
 
 
 
494
  } catch (error) {
495
  const errorMessage = extractErrorMessage(error, tr('Invalid URL format'));
496
  console.error('解析本地资源标识符失败:', error);
@@ -507,6 +511,9 @@ window.onload = () => {
507
  disableAnimation: true,
508
  isNewDemo: true
509
  });
 
 
 
510
  // 导航到demo所在文件夹并高亮
511
  if (demoManager) {
512
  await demoManager.navigateToDemoAndHighlight(urlDemoPath);
@@ -709,7 +716,7 @@ window.onload = () => {
709
  // 加载完成后自动触发 Analyze 按钮点击
710
  (submitBtn.node() as HTMLButtonElement)?.click();
711
  } else {
712
- showAlertDialog(tr('Load failed'), result.message || tr('Unable to extract text from URL'));
713
  }
714
  } catch (error) {
715
  const errorMessage = extractErrorMessage(error, tr('URL text extraction failed'));
 
331
  if (urlDemoPath && DemoResourceLoader.isLocalResource(urlDemoPath)) {
332
  updateFileNameDisplay(null);
333
  }
334
+ showAlertDialog(tr('Error'), tr(message));
335
  };
336
 
337
  /**
 
411
  });
412
  // 本地文件打开不需要toast提示
413
  } else {
414
+ throw new Error(loadResult.message || 'Load failed');
415
  }
416
  } catch (cacheError) {
417
  // 如果是因为 crypto.subtle 不可用导致保存到缓存失败,跳过缓存,直接渲染文件
 
436
  throw cacheError;
437
  }
438
  }
439
+ } else if (result.message && !result.cancelled) {
440
  // 只有在非取消的情况下才显示错误
441
+ showAlertDialog(tr('Error'), tr(result.message));
442
  }
443
  } catch (error) {
444
+ const message = error instanceof Error ? error.message : 'Failed to open file';
445
+ showAlertDialog(tr('Error'), tr(message));
446
  } finally {
447
  appStateManager.setGlobalLoading(false);
448
  }
 
473
  onRefreshEnd: async () => {
474
  ensureSystemStarted();
475
 
476
+ // 只在首次加载时检查URL参数中的demo参数;无参数时默认加载 quick-start-1.json
477
  if (!hasProcessedUrlDemo) {
478
  hasProcessedUrlDemo = true;
479
+ const paramDemo = URLHandler.parameters['demo'];
480
+ const urlDemoPath = (paramDemo && typeof paramDemo === 'string') ? paramDemo : '/quick-start-1.json';
481
+ if (urlDemoPath) {
482
  appStateManager.setGlobalLoading(true);
483
  try {
484
  // 判断资源类型
 
492
  disableAnimation: true,
493
  isNewDemo: true
494
  });
495
+ if (!paramDemo) {
496
+ URLHandler.updateURLParam('demo', '/quick-start-1.json', false);
497
+ }
498
  } catch (error) {
499
  const errorMessage = extractErrorMessage(error, tr('Invalid URL format'));
500
  console.error('解析本地资源标识符失败:', error);
 
511
  disableAnimation: true,
512
  isNewDemo: true
513
  });
514
+ if (!paramDemo) {
515
+ URLHandler.updateURLParam('demo', '/quick-start-1.json', false);
516
+ }
517
  // 导航到demo所在文件夹并高亮
518
  if (demoManager) {
519
  await demoManager.navigateToDemoAndHighlight(urlDemoPath);
 
716
  // 加载完成后自动触发 Analyze 按钮点击
717
  (submitBtn.node() as HTMLButtonElement)?.click();
718
  } else {
719
+ showAlertDialog(tr('Load failed'), tr(result.message || 'Unable to extract text from URL'));
720
  }
721
  } catch (error) {
722
  const errorMessage = extractErrorMessage(error, tr('URL text extraction failed'));
client/src/ts/storage/demoResourceLoader.ts CHANGED
@@ -14,6 +14,7 @@ import type { TextAnalysisAPI } from '../api/GLTR_API';
14
  import { ensureJsonExtension, validateDemoFormat } from '../utils/localFileUtils';
15
  import { extractErrorMessage } from '../utils/errorUtils';
16
  import { isValidHash } from '../utils/hashUtils';
 
17
 
18
  export type ResourceIdentifier = string; // "/path/file.json" 或 "local://file.json"
19
 
@@ -39,7 +40,7 @@ function parseResourceIdentifier(identifier: ResourceIdentifier): {
39
 
40
  // 验证 hash 格式(4位十六进制)
41
  if (!isValidHash(hash)) {
42
- throw new Error(`无效的哈希值格式: "${hash}",应为4位十六进制字符`);
43
  }
44
 
45
  return {
@@ -51,7 +52,7 @@ function parseResourceIdentifier(identifier: ResourceIdentifier): {
51
  }
52
 
53
  // 没有 hash,视为无效(不再兼容)
54
- throw new Error(`本地资源标识符缺少哈希值: "${identifier}",格式应为 local://filename.json~hash`);
55
  }
56
 
57
  return {
@@ -153,7 +154,7 @@ export class DemoResourceLoader {
153
  hash: parsed.hash
154
  };
155
  }
156
- throw new Error(`无法提取本地资源信息: "${identifier}"`);
157
  }
158
  }
159
 
 
14
  import { ensureJsonExtension, validateDemoFormat } from '../utils/localFileUtils';
15
  import { extractErrorMessage } from '../utils/errorUtils';
16
  import { isValidHash } from '../utils/hashUtils';
17
+ import { trf } from '../lang/i18n-lite';
18
 
19
  export type ResourceIdentifier = string; // "/path/file.json" 或 "local://file.json"
20
 
 
40
 
41
  // 验证 hash 格式(4位十六进制)
42
  if (!isValidHash(hash)) {
43
+ throw new Error(trf('Invalid hash format: "{hash}", expected 4 hexadecimal characters', { hash }));
44
  }
45
 
46
  return {
 
52
  }
53
 
54
  // 没有 hash,视为无效(不再兼容)
55
+ throw new Error(trf('Local resource identifier missing hash: "{identifier}", format should be local://filename.json~hash', { identifier }));
56
  }
57
 
58
  return {
 
154
  hash: parsed.hash
155
  };
156
  }
157
+ throw new Error(trf('Unable to extract local resource info: "{identifier}"', { identifier }));
158
  }
159
  }
160
 
client/src/ts/storage/demoStorage.ts CHANGED
@@ -79,7 +79,7 @@ export class ServerStorage implements IDemoStorage {
79
 
80
  async load(path: string): Promise<LoadResult> {
81
  if (!path) {
82
- return { success: false, message: '缺少demo路径' };
83
  }
84
 
85
  try {
 
79
 
80
  async load(path: string): Promise<LoadResult> {
81
  if (!path) {
82
+ return { success: false, message: 'Demo path is missing' };
83
  }
84
 
85
  try {
client/src/ts/storage/localDemoCache.ts CHANGED
@@ -44,7 +44,7 @@ export class LocalDemoCache implements IDemoStorage {
44
  const request = indexedDB.open(DB_NAME, DB_VERSION);
45
 
46
  request.onerror = () => {
47
- reject(new Error('无法打开 IndexedDB'));
48
  };
49
 
50
  request.onsuccess = () => {
@@ -97,7 +97,7 @@ export class LocalDemoCache implements IDemoStorage {
97
  request.onsuccess = () => {
98
  resolve({
99
  success: true,
100
- message: '已保存到本地缓存',
101
  file: filename,
102
  hash // 返回计算好的哈希值
103
  });
@@ -108,12 +108,12 @@ export class LocalDemoCache implements IDemoStorage {
108
  if (error && error.name === 'QuotaExceededError') {
109
  resolve({
110
  success: false,
111
- message: '存储空间不足,请清理缓存后重试'
112
  });
113
  } else {
114
  resolve({
115
  success: false,
116
- message: '保存到缓存失败'
117
  });
118
  }
119
  };
@@ -126,12 +126,12 @@ export class LocalDemoCache implements IDemoStorage {
126
  if (error instanceof DOMException && error.name === 'QuotaExceededError') {
127
  return {
128
  success: false,
129
- message: '存储空间不足,请清理缓存后重试'
130
  };
131
  }
132
  return {
133
  success: false,
134
- message: extractErrorMessage(error, '保存失败')
135
  };
136
  }
137
  }
@@ -142,7 +142,7 @@ export class LocalDemoCache implements IDemoStorage {
142
  */
143
  async load(key?: string): Promise<LoadResult> {
144
  if (!key) {
145
- return { success: false, message: '缺少key' };
146
  }
147
 
148
  try {
@@ -159,7 +159,7 @@ export class LocalDemoCache implements IDemoStorage {
159
  if (!record || !record.data) {
160
  resolve({
161
  success: false,
162
- message: '本地缓存中未找到该文件,请重新打开'
163
  });
164
  return;
165
  }
@@ -175,7 +175,7 @@ export class LocalDemoCache implements IDemoStorage {
175
  console.error('从缓存读取失败:', error);
176
  resolve({
177
  success: false,
178
- message: '从缓存读取失败'
179
  });
180
  };
181
  });
 
44
  const request = indexedDB.open(DB_NAME, DB_VERSION);
45
 
46
  request.onerror = () => {
47
+ reject(new Error('Failed to open IndexedDB'));
48
  };
49
 
50
  request.onsuccess = () => {
 
97
  request.onsuccess = () => {
98
  resolve({
99
  success: true,
100
+ message: 'Saved to local cache',
101
  file: filename,
102
  hash // 返回计算好的哈希值
103
  });
 
108
  if (error && error.name === 'QuotaExceededError') {
109
  resolve({
110
  success: false,
111
+ message: 'Storage quota exceeded, please clear cache and try again'
112
  });
113
  } else {
114
  resolve({
115
  success: false,
116
+ message: 'Failed to save to cache'
117
  });
118
  }
119
  };
 
126
  if (error instanceof DOMException && error.name === 'QuotaExceededError') {
127
  return {
128
  success: false,
129
+ message: 'Storage quota exceeded, please clear cache and try again'
130
  };
131
  }
132
  return {
133
  success: false,
134
+ message: extractErrorMessage(error, 'Save failed')
135
  };
136
  }
137
  }
 
142
  */
143
  async load(key?: string): Promise<LoadResult> {
144
  if (!key) {
145
+ return { success: false, message: 'Key is missing' };
146
  }
147
 
148
  try {
 
159
  if (!record || !record.data) {
160
  resolve({
161
  success: false,
162
+ message: 'File not found in local cache, please open again'
163
  });
164
  return;
165
  }
 
175
  console.error('从缓存读取失败:', error);
176
  resolve({
177
  success: false,
178
+ message: 'Failed to read from cache'
179
  });
180
  };
181
  });
client/src/ts/storage/localFileIO.ts CHANGED
@@ -7,12 +7,14 @@
7
  import type { AnalysisData } from '../api/GLTR_API';
8
  import { validateDemoFormat, ensureJsonExtension } from '../utils/localFileUtils';
9
  import { extractErrorMessage } from '../utils/errorUtils';
 
10
 
11
  export interface ImportResult {
12
  success: boolean;
13
  data?: AnalysisData;
14
  filename?: string;
15
  message?: string;
 
16
  // 多选模式返回的文件列表
17
  files?: Array<{
18
  data: AnalysisData;
@@ -46,7 +48,7 @@ export class LocalFileIO {
46
  const files = (e.target as HTMLInputElement).files;
47
  if (!files || files.length === 0) {
48
  cleanup();
49
- resolve({ success: false, message: '未选择文件' });
50
  return;
51
  }
52
 
@@ -68,7 +70,7 @@ export class LocalFileIO {
68
  filename: cleanFilename
69
  });
70
  } catch (err) {
71
- const message = extractErrorMessage(err, '读取失败');
72
  errors.push(`${file.name}: ${message}`);
73
  }
74
  }
@@ -79,14 +81,14 @@ export class LocalFileIO {
79
  if (fileResults.length === 0) {
80
  resolve({
81
  success: false,
82
- message: `所有文件读取失败:\n${errors.join('\n')}`
83
  });
84
  } else {
85
  // 部分或全部成功,返回成功结果(如果有错误信息,可以包含在message中)
86
  resolve({
87
  success: true,
88
  files: fileResults,
89
- message: errors.length > 0 ? `部分文件失败:\n${errors.join('\n')}` : undefined
90
  });
91
  }
92
  } else {
@@ -106,14 +108,14 @@ export class LocalFileIO {
106
  }
107
  } catch (error) {
108
  cleanup();
109
- const message = extractErrorMessage(error, '文件读取失败');
110
  resolve({ success: false, message });
111
  }
112
  };
113
 
114
  input.oncancel = () => {
115
  cleanup();
116
- resolve({ success: false, message: '用户取消了文件选择' });
117
  };
118
 
119
  document.body.appendChild(input);
 
7
  import type { AnalysisData } from '../api/GLTR_API';
8
  import { validateDemoFormat, ensureJsonExtension } from '../utils/localFileUtils';
9
  import { extractErrorMessage } from '../utils/errorUtils';
10
+ import { tr } from '../lang/i18n-lite';
11
 
12
  export interface ImportResult {
13
  success: boolean;
14
  data?: AnalysisData;
15
  filename?: string;
16
  message?: string;
17
+ cancelled?: boolean; // 用户取消操作
18
  // 多选模式返回的文件列表
19
  files?: Array<{
20
  data: AnalysisData;
 
48
  const files = (e.target as HTMLInputElement).files;
49
  if (!files || files.length === 0) {
50
  cleanup();
51
+ resolve({ success: false, message: tr('No file selected') });
52
  return;
53
  }
54
 
 
70
  filename: cleanFilename
71
  });
72
  } catch (err) {
73
+ const message = extractErrorMessage(err, tr('Read failed'));
74
  errors.push(`${file.name}: ${message}`);
75
  }
76
  }
 
81
  if (fileResults.length === 0) {
82
  resolve({
83
  success: false,
84
+ message: `${tr('All files failed to read:')}\n${errors.join('\n')}`
85
  });
86
  } else {
87
  // 部分或全部成功,返回成功结果(如果有错误信息,可以包含在message中)
88
  resolve({
89
  success: true,
90
  files: fileResults,
91
+ message: errors.length > 0 ? `${tr('Partial files failed:')}\n${errors.join('\n')}` : undefined
92
  });
93
  }
94
  } else {
 
108
  }
109
  } catch (error) {
110
  cleanup();
111
+ const message = extractErrorMessage(error, tr('Failed to read file'));
112
  resolve({ success: false, message });
113
  }
114
  };
115
 
116
  input.oncancel = () => {
117
  cleanup();
118
+ resolve({ success: false, message: tr('User cancelled file selection'), cancelled: true });
119
  };
120
 
121
  document.body.appendChild(input);
client/src/ts/ui/demoManager.ts CHANGED
@@ -119,7 +119,7 @@ export function initDemoManager(options: DemoManagerOptions): DemoManager {
119
  if (result.success) {
120
  await fetchDemoList();
121
  } else {
122
- showAlertDialog(tr('Error'), result.message || tr('Failed to create folder'));
123
  }
124
  } catch (err) {
125
  console.error('创建文件夹失败:', err);
@@ -350,7 +350,7 @@ export function initDemoManager(options: DemoManagerOptions): DemoManager {
350
  if (result.success) {
351
  await fetchDemoList();
352
  } else {
353
- showAlertDialog(tr('Error'), result.message || tr('Move failed'));
354
  }
355
  } catch (err) {
356
  console.error('移动失败:', err);
@@ -381,7 +381,7 @@ export function initDemoManager(options: DemoManagerOptions): DemoManager {
381
  if (result.success) {
382
  await fetchDemoList();
383
  } else {
384
- showAlertDialog(tr('Error'), result.message || tr('Rename failed'));
385
  }
386
  } catch (err) {
387
  console.error('重命名失败:', err);
@@ -406,7 +406,7 @@ export function initDemoManager(options: DemoManagerOptions): DemoManager {
406
  if (result.success) {
407
  await fetchDemoList();
408
  } else {
409
- showAlertDialog(tr('Error'), result.message || tr('Delete failed'));
410
  }
411
  } catch (err) {
412
  console.error('删除失败:', err);
 
119
  if (result.success) {
120
  await fetchDemoList();
121
  } else {
122
+ showAlertDialog(tr('Error'), tr(result.message || 'Failed to create folder'));
123
  }
124
  } catch (err) {
125
  console.error('创建文件夹失败:', err);
 
350
  if (result.success) {
351
  await fetchDemoList();
352
  } else {
353
+ showAlertDialog(tr('Error'), tr(result.message || 'Move failed'));
354
  }
355
  } catch (err) {
356
  console.error('移动失败:', err);
 
381
  if (result.success) {
382
  await fetchDemoList();
383
  } else {
384
+ showAlertDialog(tr('Error'), tr(result.message || 'Rename failed'));
385
  }
386
  } catch (err) {
387
  console.error('重命名失败:', err);
 
406
  if (result.success) {
407
  await fetchDemoList();
408
  } else {
409
+ showAlertDialog(tr('Error'), tr(result.message || 'Delete failed'));
410
  }
411
  } catch (err) {
412
  console.error('删除失败:', err);
client/src/ts/ui/demoMultiSelect.ts CHANGED
@@ -159,12 +159,12 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
159
  // 更新所有按钮的可用状态
160
  multiSelectBar.selectAll('.refresh-btn').each(function() {
161
  const btn = d3.select(this);
162
- const text = btn.text();
163
  let isActive = false;
164
 
165
- if (text === tr('Select all')) {
166
  isActive = hasUnselected; // 有未选中项时可用
167
- } else if (text === tr('Clear') || text === tr('Delete') || text === tr('Move')) {
168
  isActive = selectedCount > 0; // 有选中项时可用
169
  }
170
 
@@ -240,11 +240,11 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
240
  successCount++;
241
  } else {
242
  failCount++;
243
- errors.push(`${item.name}: ${result.message || tr('Delete failed')}`);
244
  }
245
  } catch (err) {
246
  failCount++;
247
- errors.push(`${item.name}: ${err instanceof Error ? err.message : tr('Delete failed')}`);
248
  }
249
  }
250
 
@@ -332,11 +332,11 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
332
  successCount++;
333
  } else {
334
  failCount++;
335
- errors.push(`${item.name}: ${result.message || tr('Move failed')}`);
336
  }
337
  } catch (err) {
338
  failCount++;
339
- errors.push(`${item.name}: ${err instanceof Error ? err.message : tr('Move failed')}`);
340
  }
341
  }
342
 
@@ -429,6 +429,7 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
429
 
430
  multiSelectBar.append('button')
431
  .attr('class', 'refresh-btn')
 
432
  .attr('title', tr('Select all'))
433
  .text(tr('Select all'))
434
  .on('click', () => {
@@ -450,6 +451,7 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
450
 
451
  multiSelectBar.append('button')
452
  .attr('class', 'refresh-btn')
 
453
  .attr('title', tr('Clear'))
454
  .text(tr('Clear'))
455
  .on('click', clearSelection);
@@ -458,12 +460,14 @@ export function createMultiSelect(options: MultiSelectOptions): MultiSelect {
458
  if (!disableModeToggle) {
459
  multiSelectBar.append('button')
460
  .attr('class', 'refresh-btn')
 
461
  .attr('title', tr('Delete'))
462
  .text(tr('Delete'))
463
  .on('click', handleBatchDelete);
464
 
465
  multiSelectBar.append('button')
466
  .attr('class', 'refresh-btn')
 
467
  .attr('title', tr('Move'))
468
  .text(tr('Move'))
469
  .on('click', handleBatchMove);
 
159
  // 更新所有按钮的可用状态
160
  multiSelectBar.selectAll('.refresh-btn').each(function() {
161
  const btn = d3.select(this);
162
+ const action = btn.attr('data-action');
163
  let isActive = false;
164
 
165
+ if (action === 'select-all') {
166
  isActive = hasUnselected; // 有未选中项时可用
167
+ } else if (action === 'clear' || action === 'delete' || action === 'move') {
168
  isActive = selectedCount > 0; // 有选中项时可用
169
  }
170
 
 
240
  successCount++;
241
  } else {
242
  failCount++;
243
+ errors.push(`${item.name}: ${tr(result.message || 'Delete failed')}`);
244
  }
245
  } catch (err) {
246
  failCount++;
247
+ errors.push(`${item.name}: ${err instanceof Error ? tr(err.message) : tr('Delete failed')}`);
248
  }
249
  }
250
 
 
332
  successCount++;
333
  } else {
334
  failCount++;
335
+ errors.push(`${item.name}: ${tr(result.message || 'Move failed')}`);
336
  }
337
  } catch (err) {
338
  failCount++;
339
+ errors.push(`${item.name}: ${err instanceof Error ? tr(err.message) : tr('Move failed')}`);
340
  }
341
  }
342
 
 
429
 
430
  multiSelectBar.append('button')
431
  .attr('class', 'refresh-btn')
432
+ .attr('data-action', 'select-all')
433
  .attr('title', tr('Select all'))
434
  .text(tr('Select all'))
435
  .on('click', () => {
 
451
 
452
  multiSelectBar.append('button')
453
  .attr('class', 'refresh-btn')
454
+ .attr('data-action', 'clear')
455
  .attr('title', tr('Clear'))
456
  .text(tr('Clear'))
457
  .on('click', clearSelection);
 
460
  if (!disableModeToggle) {
461
  multiSelectBar.append('button')
462
  .attr('class', 'refresh-btn')
463
+ .attr('data-action', 'delete')
464
  .attr('title', tr('Delete'))
465
  .text(tr('Delete'))
466
  .on('click', handleBatchDelete);
467
 
468
  multiSelectBar.append('button')
469
  .attr('class', 'refresh-btn')
470
+ .attr('data-action', 'move')
471
  .attr('title', tr('Move'))
472
  .text(tr('Move'))
473
  .on('click', handleBatchMove);
client/src/ts/ui/language.ts CHANGED
@@ -1,5 +1,6 @@
1
  import * as d3 from 'd3';
2
  import { getCurrentLanguage, setLanguage, type Language } from '../lang/i18n-lite';
 
3
  import { createSettingsDropdown } from './settingsDropdown';
4
 
5
  export type LanguageManagerOptions = {
@@ -12,7 +13,7 @@ export type LanguageManager = {
12
 
13
  const languageOptions: Array<{ lang: Language; label: string }> = [
14
  { lang: 'en', label: 'English' },
15
- { lang: 'zh', label: '中文' },
16
  ];
17
 
18
  export function initLanguageManager(options: LanguageManagerOptions = {}, containerSelector: string = '#language_toggle'): LanguageManager {
@@ -29,7 +30,7 @@ export function initLanguageManager(options: LanguageManagerOptions = {}, contai
29
  const dropdown = createSettingsDropdown<Language>({
30
  container,
31
  classPrefix: 'language',
32
- options: languageOptions.map(({ lang, label }) => ({ value: lang, html: `<span>${label}</span>` })),
33
  dataAttr: 'data-lang',
34
  bodyClickNamespace: 'language-dropdown',
35
  onSelect: selectLang,
 
1
  import * as d3 from 'd3';
2
  import { getCurrentLanguage, setLanguage, type Language } from '../lang/i18n-lite';
3
+ import { tr } from '../lang/i18n-lite';
4
  import { createSettingsDropdown } from './settingsDropdown';
5
 
6
  export type LanguageManagerOptions = {
 
13
 
14
  const languageOptions: Array<{ lang: Language; label: string }> = [
15
  { lang: 'en', label: 'English' },
16
+ { lang: 'zh', label: 'Chinese' },
17
  ];
18
 
19
  export function initLanguageManager(options: LanguageManagerOptions = {}, containerSelector: string = '#language_toggle'): LanguageManager {
 
30
  const dropdown = createSettingsDropdown<Language>({
31
  container,
32
  classPrefix: 'language',
33
+ options: languageOptions.map(({ lang, label }) => ({ value: lang, html: `<span>${tr(label)}</span>` })),
34
  dataAttr: 'data-lang',
35
  bodyClickNamespace: 'language-dropdown',
36
  onSelect: selectLang,
client/src/ts/utils/URLHandler.ts CHANGED
@@ -39,21 +39,9 @@ export default class URLHandler {
39
  if (v.length > 0) {
40
  const splits = v.split('=');
41
  const key = decodeURIComponent(splits[0]);
42
- let raw_value = decodeURIComponent(splits[1]);
43
-
44
- const isArray = raw_value.startsWith('..');
45
- if (isArray) {
46
- raw_value = raw_value.slice(2);
47
- }
48
-
49
- if (raw_value.length < 1) {
50
- urlParameters[key] = isArray ? [] : '';
51
- } else if (isArray) {
52
- urlParameters[key] = raw_value.split(',')
53
- .map(val => typeCast(val));
54
- } else {
55
- urlParameters[key] = typeCast(raw_value);
56
- }
57
  }
58
  });
59
 
@@ -72,9 +60,7 @@ export default class URLHandler {
72
  Object.keys(urlParameters).forEach(k => {
73
  const v = urlParameters[k];
74
  if (v !== undefined) {
75
- let value = v;
76
- if (Array.isArray(v)) value = '..' + v.join(',');
77
- attr.push(encodeURI(k + '=' + value))
78
  }
79
  });
80
 
 
39
  if (v.length > 0) {
40
  const splits = v.split('=');
41
  const key = decodeURIComponent(splits[0]);
42
+ const raw_value = decodeURIComponent(splits[1]);
43
+
44
+ urlParameters[key] = raw_value.length < 1 ? '' : typeCast(raw_value);
 
 
 
 
 
 
 
 
 
 
 
 
45
  }
46
  });
47
 
 
60
  Object.keys(urlParameters).forEach(k => {
61
  const v = urlParameters[k];
62
  if (v !== undefined) {
63
+ attr.push(encodeURI(k + '=' + v))
 
 
64
  }
65
  });
66
 
client/src/ts/utils/adminManager.ts CHANGED
@@ -87,7 +87,7 @@ export class AdminManager {
87
  // 网络等异常场景单独返回一条通用错误
88
  return {
89
  success: false,
90
- message: '请求失败,请稍后重试。'
91
  };
92
  }
93
  }
 
87
  // 网络等异常场景单独返回一条通用错误
88
  return {
89
  success: false,
90
+ message: 'Request failed, please try again later.'
91
  };
92
  }
93
  }
client/src/ts/utils/demoPathUtils.ts CHANGED
@@ -58,36 +58,36 @@ export const composeDemoFullPath = (folderPath: string | null | undefined, fileN
58
  */
59
  export const validateFileName = (fileName: string): { valid: boolean; message?: string } => {
60
  if (!fileName || !fileName.trim()) {
61
- return { valid: false, message: '文件名不能为空' };
62
  }
63
 
64
  const trimmed = fileName.trim();
65
 
66
  // 检查长度
67
  if (trimmed.length > 255) {
68
- return { valid: false, message: '文件名过长(最多255个字符)' };
69
  }
70
 
71
  // Windows 和 Unix 系统都不允许的字符
72
  const illegalChars = /[<>:"|?*\x00-\x1f]/;
73
  if (illegalChars.test(trimmed)) {
74
- return { valid: false, message: '文件名包含非法字符(不能包含 < > : " | ? * 或控制字符)' };
75
  }
76
 
77
  // 检查保留名称(Windows)
78
  const reservedNames = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i;
79
  if (reservedNames.test(trimmed)) {
80
- return { valid: false, message: '文件名不能使用系统保留名称' };
81
  }
82
 
83
  // 检查不能以点或空格开头/结尾(某些系统)
84
  if (trimmed.startsWith('.') || trimmed.endsWith('.')) {
85
- return { valid: false, message: '文件名不能以点开头或结尾' };
86
  }
87
 
88
  // 检查不能包含路径分隔符
89
  if (trimmed.includes('/') || trimmed.includes('\\')) {
90
- return { valid: false, message: '文件名不能包含路径分隔符' };
91
  }
92
 
93
  return { valid: true };
 
58
  */
59
  export const validateFileName = (fileName: string): { valid: boolean; message?: string } => {
60
  if (!fileName || !fileName.trim()) {
61
+ return { valid: false, message: 'File name cannot be empty' };
62
  }
63
 
64
  const trimmed = fileName.trim();
65
 
66
  // 检查长度
67
  if (trimmed.length > 255) {
68
+ return { valid: false, message: 'File name too long (max 255 characters)' };
69
  }
70
 
71
  // Windows 和 Unix 系统都不允许的字符
72
  const illegalChars = /[<>:"|?*\x00-\x1f]/;
73
  if (illegalChars.test(trimmed)) {
74
+ return { valid: false, message: 'File name contains invalid characters (cannot contain < > : " | ? * or control characters)' };
75
  }
76
 
77
  // 检查保留名称(Windows)
78
  const reservedNames = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i;
79
  if (reservedNames.test(trimmed)) {
80
+ return { valid: false, message: 'File name cannot be a system reserved name' };
81
  }
82
 
83
  // 检查不能以点或空格开头/结尾(某些系统)
84
  if (trimmed.startsWith('.') || trimmed.endsWith('.')) {
85
+ return { valid: false, message: 'File name cannot start or end with a dot' };
86
  }
87
 
88
  // 检查不能包含路径分隔符
89
  if (trimmed.includes('/') || trimmed.includes('\\')) {
90
+ return { valid: false, message: 'File name cannot contain path separators' };
91
  }
92
 
93
  return { valid: true };
client/src/ts/utils/localFileUtils.ts CHANGED
@@ -8,6 +8,7 @@ import {
8
  validateTokenProbabilities,
9
  validateTokenConsistency
10
  } from './dataValidation';
 
11
 
12
  /**
13
  * Demo JSON格式验证错误类型
@@ -26,12 +27,12 @@ export class DemoFormatError extends Error {
26
  export function validateDemoFormat(data: any): data is AnalysisData {
27
  // 1. 检查基本结构:是否为有效的JSON对象
28
  if (!data || typeof data !== 'object') {
29
- throw new DemoFormatError('文件内容不是有效的JSON对象');
30
  }
31
 
32
  // 2. 检查request字段:是否存在且为对象
33
  if (!data.request || typeof data.request !== 'object') {
34
- throw new DemoFormatError('缺少必需的"request"字段');
35
  }
36
 
37
  if (typeof data.request.text !== 'string') {
@@ -40,7 +41,7 @@ export function validateDemoFormat(data: any): data is AnalysisData {
40
 
41
  // 3. 检查result字段:是否存在且为对象
42
  if (!data.result || typeof data.result !== 'object') {
43
- throw new DemoFormatError('缺少必需的"result"字段');
44
  }
45
 
46
  // 4. 检查bpe_strings数组:是否存在且为非空数组
 
8
  validateTokenProbabilities,
9
  validateTokenConsistency
10
  } from './dataValidation';
11
+ import { tr } from '../lang/i18n-lite';
12
 
13
  /**
14
  * Demo JSON格式验证错误类型
 
27
  export function validateDemoFormat(data: any): data is AnalysisData {
28
  // 1. 检查基本结构:是否为有效的JSON对象
29
  if (!data || typeof data !== 'object') {
30
+ throw new DemoFormatError(tr('File content is not a valid JSON object'));
31
  }
32
 
33
  // 2. 检查request字段:是否存在且为对象
34
  if (!data.request || typeof data.request !== 'object') {
35
+ throw new DemoFormatError(tr('Missing required "request" field'));
36
  }
37
 
38
  if (typeof data.request.text !== 'string') {
 
41
 
42
  // 3. 检查result字段:是否存在且为对象
43
  if (!data.result || typeof data.result !== 'object') {
44
+ throw new DemoFormatError(tr('Missing required "result" field'));
45
  }
46
 
47
  // 4. 检查bpe_strings数组:是否存在且为非空数组
client/src/ts/utils/settingsMenuManager.ts CHANGED
@@ -163,7 +163,7 @@ export class SettingsMenuManager {
163
  const { success, message } = await this.adminManager.setAdminTokenAndNotify(token);
164
  if (!success) {
165
  // 直接使用后端返回的 message,不在前端自定义文案
166
- showAlertDialog(tr('Error'), message || tr('Admin token verification failed.'));
167
  return;
168
  }
169
 
 
163
  const { success, message } = await this.adminManager.setAdminTokenAndNotify(token);
164
  if (!success) {
165
  // 直接使用后端返回的 message,不在前端自定义文案
166
+ showAlertDialog(tr('Error'), message ? tr(message) : tr('Admin token verification failed.'));
167
  return;
168
  }
169
 
client/src/ts/utils/visualizationUpdater.ts CHANGED
@@ -27,6 +27,7 @@ import {
27
  } from './textStatistics';
28
  import { getTokenSurprisalHistogramConfig, getSurprisalProgressConfig } from "./visualizationConfigs";
29
  import { showAlertDialog } from '../ui/dialog';
 
30
 
31
  /**
32
  * 可视化更新依赖
@@ -177,7 +178,7 @@ export class VisualizationUpdater {
177
 
178
  const abortDueToInvalidResponse = (message: string) => {
179
  console.error(message);
180
- showAlertDialog('错误', message);
181
  // 数据无效,清除数据标记(AppStateManager 会自动隐藏 TextMetrics,包括模型显示)
182
  this.deps.appStateManager.updateState({ hasValidData: false });
183
  };
@@ -205,7 +206,7 @@ export class VisualizationUpdater {
205
 
206
  // 确保所有必需的字段都存在且类型正确
207
  if (!Array.isArray(result.bpe_strings) || result.bpe_strings.length === 0) {
208
- abortDueToInvalidResponse('返回 JSON 缺少合法的 bpe_strings 数组,已取消本次处理。');
209
  return;
210
  }
211
  const predTopkError = validateTokenPredictions(result.bpe_strings as Array<{ pred_topk?: [string, number][] }>);
@@ -290,7 +291,7 @@ export class VisualizationUpdater {
290
  this.deps.appStateManager.setGlobalLoading(false);
291
  // analyze失败时,清除数据标记(AppStateManager 会自动隐藏 TextMetrics,包括模型显示)
292
  this.deps.appStateManager.updateState({ hasValidData: false });
293
- showAlertDialog('错误', 'Error rendering visualization. Check console for details.');
294
  return;
295
  }
296
 
 
27
  } from './textStatistics';
28
  import { getTokenSurprisalHistogramConfig, getSurprisalProgressConfig } from "./visualizationConfigs";
29
  import { showAlertDialog } from '../ui/dialog';
30
+ import { tr } from '../lang/i18n-lite';
31
 
32
  /**
33
  * 可视化更新依赖
 
178
 
179
  const abortDueToInvalidResponse = (message: string) => {
180
  console.error(message);
181
+ showAlertDialog(tr('Error'), message);
182
  // 数据无效,清除数据标记(AppStateManager 会自动隐藏 TextMetrics,包括模型显示)
183
  this.deps.appStateManager.updateState({ hasValidData: false });
184
  };
 
206
 
207
  // 确保所有必需的字段都存在且类型正确
208
  if (!Array.isArray(result.bpe_strings) || result.bpe_strings.length === 0) {
209
+ abortDueToInvalidResponse(tr('Returned JSON missing valid bpe_strings array, processing cancelled.'));
210
  return;
211
  }
212
  const predTopkError = validateTokenPredictions(result.bpe_strings as Array<{ pred_topk?: [string, number][] }>);
 
291
  this.deps.appStateManager.setGlobalLoading(false);
292
  // analyze失败时,清除数据标记(AppStateManager 会自动隐藏 TextMetrics,包括模型显示)
293
  this.deps.appStateManager.updateState({ hasValidData: false });
294
+ showAlertDialog(tr('Error'), 'Error rendering visualization. Check console for details.');
295
  return;
296
  }
297
 
data/demo/public/CN/GPT-2 large unicorn text(中文翻译)_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/CN/GPT-2 small top_k 40 temp .7 (中文翻译).json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/CN/GPT-2 small top_k 40 temp .7 (中文翻译)_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/CN/GPT-2 small top_k 5 temp 1 (中文翻译)_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/CN/{human_ NYTimes article (中文翻译).json → NYTimes article (中文翻译).json} RENAMED
File without changes
data/demo/public/CN/{human_ academic text (中文翻译).json → academic text (中文翻译).json} RENAMED
File without changes
data/demo/public/CN/human_ NYTimes article (中文翻译)_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/CN/human_ academic text (中文翻译)_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/{GPT-2 large unicorn text → GPT-2 large unicorn text.json} RENAMED
File without changes
data/demo/public/GPT-2 large unicorn text_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/GPT-2 small top_k 5 temp 1_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/{human_ NYTimes article.json → NYTimes article.json} RENAMED
File without changes
data/demo/public/{human_ academic text.json → academic text.json} RENAMED
File without changes
data/demo/public/human_ NYTimes article_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/human_ academic text_qwen2.5.json DELETED
The diff for this file is too large to render. See raw diff
 
data/demo/public/human_ woodchuck_qwen2.5.json DELETED
@@ -1,964 +0,0 @@
1
- {
2
- "request": {
3
- "text": "How much wood would a woodchuck chuck if a woodchuck could chuck wood?"
4
- },
5
- "result": {
6
- "model": "Qwen2.5-0.5B",
7
- "bpe_strings": [
8
- {
9
- "offset": [
10
- 0,
11
- 3
12
- ],
13
- "raw": "How",
14
- "real_topk": [
15
- 0,
16
- 0.0039215087890625
17
- ],
18
- "pred_topk": [
19
- [
20
- "Human",
21
- 0.390625
22
- ],
23
- [
24
- "import",
25
- 0.05084228515625
26
- ],
27
- [
28
- "#",
29
- 0.04150390625
30
- ],
31
- [
32
- "def",
33
- 0.0163726806640625
34
- ],
35
- [
36
- "The",
37
- 0.0136871337890625
38
- ],
39
- [
40
- "class",
41
- 0.0130615234375
42
- ],
43
- [
44
- "from",
45
- 0.01285552978515625
46
- ],
47
- [
48
- "public",
49
- 0.01099395751953125
50
- ],
51
- [
52
- "以下",
53
- 0.01099395751953125
54
- ],
55
- [
56
- "I",
57
- 0.00732421875
58
- ]
59
- ]
60
- },
61
- {
62
- "offset": [
63
- 3,
64
- 8
65
- ],
66
- "raw": " much",
67
- "real_topk": [
68
- 0,
69
- 0.05035400390625
70
- ],
71
- "pred_topk": [
72
- [
73
- " to",
74
- 0.1600341796875
75
- ],
76
- [
77
- " many",
78
- 0.1502685546875
79
- ],
80
- [
81
- " can",
82
- 0.09857177734375
83
- ],
84
- [
85
- " do",
86
- 0.0911865234375
87
- ],
88
- [
89
- " does",
90
- 0.057037353515625
91
- ],
92
- [
93
- " much",
94
- 0.05035400390625
95
- ],
96
- [
97
- " long",
98
- 0.0257110595703125
99
- ],
100
- [
101
- " did",
102
- 0.0255126953125
103
- ],
104
- [
105
- " is",
106
- 0.0253143310546875
107
- ],
108
- [
109
- " would",
110
- 0.0230560302734375
111
- ]
112
- ]
113
- },
114
- {
115
- "offset": [
116
- 8,
117
- 13
118
- ],
119
- "raw": " wood",
120
- "real_topk": [
121
- 0,
122
- 0.001251220703125
123
- ],
124
- "pred_topk": [
125
- [
126
- " does",
127
- 0.11895751953125
128
- ],
129
- [
130
- " is",
131
- 0.0870361328125
132
- ],
133
- [
134
- " do",
135
- 0.065673828125
136
- ],
137
- [
138
- " money",
139
- 0.056182861328125
140
- ],
141
- [
142
- " did",
143
- 0.051971435546875
144
- ],
145
- [
146
- " of",
147
- 0.04620361328125
148
- ],
149
- [
150
- " will",
151
- 0.045135498046875
152
- ],
153
- [
154
- " would",
155
- 0.038330078125
156
- ],
157
- [
158
- " time",
159
- 0.032257080078125
160
- ],
161
- [
162
- " can",
163
- 0.030548095703125
164
- ]
165
- ]
166
- },
167
- {
168
- "offset": [
169
- 13,
170
- 19
171
- ],
172
- "raw": " would",
173
- "real_topk": [
174
- 0,
175
- 0.39453125
176
- ],
177
- "pred_topk": [
178
- [
179
- " could",
180
- 0.4833984375
181
- ],
182
- [
183
- " would",
184
- 0.39453125
185
- ],
186
- [
187
- " can",
188
- 0.0814208984375
189
- ],
190
- [
191
- " did",
192
- 0.0083160400390625
193
- ],
194
- [
195
- " was",
196
- 0.005245208740234375
197
- ],
198
- [
199
- " do",
200
- 0.004119873046875
201
- ],
202
- [
203
- " does",
204
- 0.003360748291015625
205
- ],
206
- [
207
- " is",
208
- 0.0024776458740234375
209
- ],
210
- [
211
- "?",
212
- 0.001743316650390625
213
- ],
214
- [
215
- "[token#220]",
216
- 0.0014801025390625
217
- ]
218
- ]
219
- },
220
- {
221
- "offset": [
222
- 19,
223
- 21
224
- ],
225
- "raw": " a",
226
- "real_topk": [
227
- 0,
228
- 0.431396484375
229
- ],
230
- "pred_topk": [
231
- [
232
- " a",
233
- 0.431396484375
234
- ],
235
- [
236
- " be",
237
- 0.0985107421875
238
- ],
239
- [
240
- "[token#220]",
241
- 0.035125732421875
242
- ],
243
- [
244
- " I",
245
- 0.0286712646484375
246
- ],
247
- [
248
- " you",
249
- 0.0286712646484375
250
- ],
251
- [
252
- " John",
253
- 0.0286712646484375
254
- ],
255
- [
256
- " the",
257
- 0.0284423828125
258
- ],
259
- [
260
- " Jack",
261
- 0.0204925537109375
262
- ],
263
- [
264
- " four",
265
- 0.012725830078125
266
- ],
267
- [
268
- " Joe",
269
- 0.00867462158203125
270
- ]
271
- ]
272
- },
273
- {
274
- "offset": [
275
- 21,
276
- 26
277
- ],
278
- "raw": " wood",
279
- "real_topk": [
280
- 0,
281
- 0.9580078125
282
- ],
283
- "pred_topk": [
284
- [
285
- " wood",
286
- 0.9580078125
287
- ],
288
- [
289
- " tree",
290
- 0.0088958740234375
291
- ],
292
- [
293
- " sw",
294
- 0.003025054931640625
295
- ],
296
- [
297
- "[token#220]",
298
- 0.0022487640380859375
299
- ],
300
- [
301
- " swallow",
302
- 0.0017786026000976562
303
- ],
304
- [
305
- " hundred",
306
- 0.0013637542724609375
307
- ],
308
- [
309
- " stick",
310
- 0.0010137557983398438
311
- ],
312
- [
313
- " Wood",
314
- 0.0009374618530273438
315
- ],
316
- [
317
- " thousand",
318
- 0.00084686279296875
319
- ],
320
- [
321
- " single",
322
- 0.0006966590881347656
323
- ]
324
- ]
325
- },
326
- {
327
- "offset": [
328
- 26,
329
- 28
330
- ],
331
- "raw": "ch",
332
- "real_topk": [
333
- 0,
334
- 0.9677734375
335
- ],
336
- "pred_topk": [
337
- [
338
- "ch",
339
- 0.9677734375
340
- ],
341
- [
342
- " stove",
343
- 0.01153564453125
344
- ],
345
- [
346
- " chuck",
347
- 0.0087738037109375
348
- ],
349
- [
350
- "pe",
351
- 0.00360107421875
352
- ],
353
- [
354
- " ch",
355
- 0.0023250579833984375
356
- ],
357
- [
358
- "-ch",
359
- 0.0014219284057617188
360
- ],
361
- [
362
- "st",
363
- 0.0007791519165039062
364
- ],
365
- [
366
- "cut",
367
- 0.0004687309265136719
368
- ],
369
- [
370
- "chip",
371
- 0.00024890899658203125
372
- ],
373
- [
374
- "Ch",
375
- 0.0002162456512451172
376
- ]
377
- ]
378
- },
379
- {
380
- "offset": [
381
- 28,
382
- 31
383
- ],
384
- "raw": "uck",
385
- "real_topk": [
386
- 0,
387
- 0.9638671875
388
- ],
389
- "pred_topk": [
390
- [
391
- "uck",
392
- 0.9638671875
393
- ],
394
- [
395
- "opper",
396
- 0.0155792236328125
397
- ],
398
- [
399
- "op",
400
- 0.005641937255859375
401
- ],
402
- [
403
- "ips",
404
- 0.0032901763916015625
405
- ],
406
- [
407
- "ucks",
408
- 0.0027923583984375
409
- ],
410
- [
411
- "ucking",
412
- 0.0017747879028320312
413
- ],
414
- [
415
- "im",
416
- 0.0012197494506835938
417
- ],
418
- [
419
- "andler",
420
- 0.0008320808410644531
421
- ],
422
- [
423
- "oppers",
424
- 0.0005125999450683594
425
- ],
426
- [
427
- "oping",
428
- 0.00043511390686035156
429
- ]
430
- ]
431
- },
432
- {
433
- "offset": [
434
- 31,
435
- 37
436
- ],
437
- "raw": " chuck",
438
- "real_topk": [
439
- 0,
440
- 0.9189453125
441
- ],
442
- "pred_topk": [
443
- [
444
- " chuck",
445
- 0.9189453125
446
- ],
447
- [
448
- " pull",
449
- 0.0141754150390625
450
- ],
451
- [
452
- " carry",
453
- 0.01363372802734375
454
- ],
455
- [
456
- " lift",
457
- 0.00482177734375
458
- ],
459
- [
460
- " pump",
461
- 0.004093170166015625
462
- ],
463
- [
464
- " push",
465
- 0.0033664703369140625
466
- ],
467
- [
468
- " draw",
469
- 0.0027484893798828125
470
- ],
471
- [
472
- " fill",
473
- 0.002025604248046875
474
- ],
475
- [
476
- " punch",
477
- 0.001995086669921875
478
- ],
479
- [
480
- " hole",
481
- 0.0017604827880859375
482
- ]
483
- ]
484
- },
485
- {
486
- "offset": [
487
- 37,
488
- 40
489
- ],
490
- "raw": " if",
491
- "real_topk": [
492
- 0,
493
- 0.429931640625
494
- ],
495
- "pred_topk": [
496
- [
497
- " if",
498
- 0.429931640625
499
- ],
500
- [
501
- "?",
502
- 0.12127685546875
503
- ],
504
- [
505
- "?\n\n",
506
- 0.097412109375
507
- ],
508
- [
509
- ",",
510
- 0.06097412109375
511
- ],
512
- [
513
- "?\n",
514
- 0.057281494140625
515
- ],
516
- [
517
- " in",
518
- 0.0235137939453125
519
- ],
520
- [
521
- " (",
522
- 0.018890380859375
523
- ],
524
- [
525
- " on",
526
- 0.0129852294921875
527
- ],
528
- [
529
- " for",
530
- 0.01239013671875
531
- ],
532
- [
533
- " If",
534
- 0.01163482666015625
535
- ]
536
- ]
537
- },
538
- {
539
- "offset": [
540
- 40,
541
- 42
542
- ],
543
- "raw": " a",
544
- "real_topk": [
545
- 0,
546
- 0.962890625
547
- ],
548
- "pred_topk": [
549
- [
550
- " a",
551
- 0.962890625
552
- ],
553
- [
554
- " he",
555
- 0.0182037353515625
556
- ],
557
- [
558
- " it",
559
- 0.013519287109375
560
- ],
561
- [
562
- " every",
563
- 0.0009493827819824219
564
- ],
565
- [
566
- " the",
567
- 0.000598907470703125
568
- ],
569
- [
570
- " all",
571
- 0.00046634674072265625
572
- ],
573
- [
574
- " both",
575
- 0.00020694732666015625
576
- ],
577
- [
578
- " you",
579
- 0.00018990039825439453
580
- ],
581
- [
582
- " each",
583
- 0.00018405914306640625
584
- ],
585
- [
586
- " we",
587
- 0.00016248226165771484
588
- ]
589
- ]
590
- },
591
- {
592
- "offset": [
593
- 42,
594
- 47
595
- ],
596
- "raw": " wood",
597
- "real_topk": [
598
- 0,
599
- 0.9833984375
600
- ],
601
- "pred_topk": [
602
- [
603
- " wood",
604
- 0.9833984375
605
- ],
606
- [
607
- " tree",
608
- 0.0023250579833984375
609
- ],
610
- [
611
- " water",
612
- 0.0007376670837402344
613
- ],
614
- [
615
- " h",
616
- 0.0006208419799804688
617
- ],
618
- [
619
- " log",
620
- 0.0005354881286621094
621
- ],
622
- [
623
- "[token#220]",
624
- 0.0005311965942382812
625
- ],
626
- [
627
- " wooden",
628
- 0.00043702125549316406
629
- ],
630
- [
631
- " Wood",
632
- 0.00037670135498046875
633
- ],
634
- [
635
- " deer",
636
- 0.0003707408905029297
637
- ],
638
- [
639
- " bear",
640
- 0.0003566741943359375
641
- ]
642
- ]
643
- },
644
- {
645
- "offset": [
646
- 47,
647
- 49
648
- ],
649
- "raw": "ch",
650
- "real_topk": [
651
- 0,
652
- 0.9970703125
653
- ],
654
- "pred_topk": [
655
- [
656
- "ch",
657
- 0.9970703125
658
- ],
659
- [
660
- " chuck",
661
- 0.001865386962890625
662
- ],
663
- [
664
- " ch",
665
- 0.00019979476928710938
666
- ],
667
- [
668
- "st",
669
- 0.00011926889419555664
670
- ],
671
- [
672
- "pe",
673
- 0.00010526180267333984
674
- ],
675
- [
676
- "h",
677
- 8.726119995117188e-05
678
- ],
679
- [
680
- "chip",
681
- 7.581710815429688e-05
682
- ],
683
- [
684
- "wh",
685
- 4.220008850097656e-05
686
- ],
687
- [
688
- "pile",
689
- 3.212690353393555e-05
690
- ],
691
- [
692
- " stove",
693
- 2.7239322662353516e-05
694
- ]
695
- ]
696
- },
697
- {
698
- "offset": [
699
- 49,
700
- 52
701
- ],
702
- "raw": "uck",
703
- "real_topk": [
704
- 0,
705
- 0.99951171875
706
- ],
707
- "pred_topk": [
708
- [
709
- "uck",
710
- 0.99951171875
711
- ],
712
- [
713
- "ucks",
714
- 0.00030040740966796875
715
- ],
716
- [
717
- "uk",
718
- 0.00013971328735351562
719
- ],
720
- [
721
- "ucking",
722
- 5.3048133850097656e-05
723
- ],
724
- [
725
- "ucker",
726
- 4.13060188293457e-05
727
- ],
728
- [
729
- "ook",
730
- 3.88026237487793e-05
731
- ],
732
- [
733
- "uckle",
734
- 3.7610530853271484e-05
735
- ],
736
- [
737
- "ock",
738
- 1.7464160919189453e-05
739
- ],
740
- [
741
- "ill",
742
- 1.615285873413086e-05
743
- ],
744
- [
745
- "unk",
746
- 1.5676021575927734e-05
747
- ]
748
- ]
749
- },
750
- {
751
- "offset": [
752
- 52,
753
- 58
754
- ],
755
- "raw": " could",
756
- "real_topk": [
757
- 0,
758
- 0.6064453125
759
- ],
760
- "pred_topk": [
761
- [
762
- " could",
763
- 0.6064453125
764
- ],
765
- [
766
- " would",
767
- 0.1251220703125
768
- ],
769
- [
770
- " were",
771
- 0.084716796875
772
- ],
773
- [
774
- " can",
775
- 0.03759765625
776
- ],
777
- [
778
- " chuck",
779
- 0.0177459716796875
780
- ],
781
- [
782
- " ch",
783
- 0.01415252685546875
784
- ],
785
- [
786
- " was",
787
- 0.01404571533203125
788
- ],
789
- [
790
- " had",
791
- 0.005718231201171875
792
- ],
793
- [
794
- "[token#198]",
795
- 0.00463104248046875
796
- ],
797
- [
798
- " is",
799
- 0.0033359527587890625
800
- ]
801
- ]
802
- },
803
- {
804
- "offset": [
805
- 58,
806
- 64
807
- ],
808
- "raw": " chuck",
809
- "real_topk": [
810
- 0,
811
- 0.96337890625
812
- ],
813
- "pred_topk": [
814
- [
815
- " chuck",
816
- 0.96337890625
817
- ],
818
- [
819
- " ch",
820
- 0.0173797607421875
821
- ],
822
- [
823
- " just",
824
- 0.0025424957275390625
825
- ],
826
- [
827
- " carry",
828
- 0.0014944076538085938
829
- ],
830
- [
831
- " really",
832
- 0.001010894775390625
833
- ],
834
- [
835
- " talk",
836
- 0.001010894775390625
837
- ],
838
- [
839
- " chip",
840
- 0.0005807876586914062
841
- ],
842
- [
843
- " chop",
844
- 0.000545501708984375
845
- ],
846
- [
847
- " rot",
848
- 0.0005288124084472656
849
- ],
850
- [
851
- " h",
852
- 0.00047016143798828125
853
- ]
854
- ]
855
- },
856
- {
857
- "offset": [
858
- 64,
859
- 69
860
- ],
861
- "raw": " wood",
862
- "real_topk": [
863
- 0,
864
- 0.9970703125
865
- ],
866
- "pred_topk": [
867
- [
868
- " wood",
869
- 0.9970703125
870
- ],
871
- [
872
- " enough",
873
- 0.0004982948303222656
874
- ],
875
- [
876
- " trees",
877
- 0.0003345012664794922
878
- ],
879
- [
880
- " things",
881
- 0.00030684471130371094
882
- ],
883
- [
884
- " woods",
885
- 0.0002372264862060547
886
- ],
887
- [
888
- " logs",
889
- 0.0001748800277709961
890
- ],
891
- [
892
- "wood",
893
- 0.00013947486877441406
894
- ],
895
- [
896
- " wooden",
897
- 0.00010204315185546875
898
- ],
899
- [
900
- " Wood",
901
- 7.462501525878906e-05
902
- ],
903
- [
904
- " its",
905
- 6.282329559326172e-05
906
- ]
907
- ]
908
- },
909
- {
910
- "offset": [
911
- 69,
912
- 70
913
- ],
914
- "raw": "?",
915
- "real_topk": [
916
- 0,
917
- 0.34912109375
918
- ],
919
- "pred_topk": [
920
- [
921
- "?",
922
- 0.34912109375
923
- ],
924
- [
925
- "?\n",
926
- 0.25146484375
927
- ],
928
- [
929
- "?\n\n",
930
- 0.2476806640625
931
- ],
932
- [
933
- "?\\",
934
- 0.0273590087890625
935
- ],
936
- [
937
- "?",
938
- 0.0233917236328125
939
- ],
940
- [
941
- "???",
942
- 0.010223388671875
943
- ],
944
- [
945
- "[token#271]",
946
- 0.006916046142578125
947
- ],
948
- [
949
- ",",
950
- 0.006103515625
951
- ],
952
- [
953
- " at",
954
- 0.005733489990234375
955
- ],
956
- [
957
- "?,",
958
- 0.0048675537109375
959
- ]
960
- ]
961
- }
962
- ]
963
- }
964
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
data/demo/public/quick-start-1.json ADDED
@@ -0,0 +1,593 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "request": {
3
+ "text": "“This morning I opened the door and saw a UFO.”"
4
+ },
5
+ "result": {
6
+ "model": "qwen3.0-0.6b",
7
+ "bpe_strings": [
8
+ {
9
+ "offset": [
10
+ 0,
11
+ 5
12
+ ],
13
+ "raw": "“This",
14
+ "real_topk": [
15
+ 0,
16
+ 2.8431415557861328e-05
17
+ ],
18
+ "pred_topk": [
19
+ [
20
+ "Human",
21
+ 0.05517578125
22
+ ],
23
+ [
24
+ "The",
25
+ 0.032196044921875
26
+ ],
27
+ [
28
+ "What",
29
+ 0.0231781005859375
30
+ ],
31
+ [
32
+ "#",
33
+ 0.0228271484375
34
+ ],
35
+ [
36
+ "以下",
37
+ 0.0201416015625
38
+ ],
39
+ [
40
+ "Given",
41
+ 0.0161895751953125
42
+ ],
43
+ [
44
+ "@",
45
+ 0.01556396484375
46
+ ],
47
+ [
48
+ "###",
49
+ 0.0141754150390625
50
+ ],
51
+ [
52
+ "import",
53
+ 0.009368896484375
54
+ ],
55
+ [
56
+ "Find",
57
+ 0.00901031494140625
58
+ ]
59
+ ]
60
+ },
61
+ {
62
+ "offset": [
63
+ 5,
64
+ 13
65
+ ],
66
+ "raw": " morning",
67
+ "real_topk": [
68
+ 0,
69
+ 0.00493621826171875
70
+ ],
71
+ "pred_topk": [
72
+ [
73
+ " is",
74
+ 0.315185546875
75
+ ],
76
+ [
77
+ "”",
78
+ 0.01922607421875
79
+ ],
80
+ [
81
+ " was",
82
+ 0.0161895751953125
83
+ ],
84
+ [
85
+ " one",
86
+ 0.01342010498046875
87
+ ],
88
+ [
89
+ " year",
90
+ 0.01320648193359375
91
+ ],
92
+ [
93
+ " week",
94
+ 0.01320648193359375
95
+ ],
96
+ [
97
+ " time",
98
+ 0.01061248779296875
99
+ ],
100
+ [
101
+ " will",
102
+ 0.00814056396484375
103
+ ],
104
+ [
105
+ " book",
106
+ 0.0078887939453125
107
+ ],
108
+ [
109
+ " article",
110
+ 0.00653839111328125
111
+ ]
112
+ ]
113
+ },
114
+ {
115
+ "offset": [
116
+ 13,
117
+ 15
118
+ ],
119
+ "raw": " I",
120
+ "real_topk": [
121
+ 0,
122
+ 0.2440185546875
123
+ ],
124
+ "pred_topk": [
125
+ [
126
+ ",",
127
+ 0.289794921875
128
+ ],
129
+ [
130
+ " I",
131
+ 0.2440185546875
132
+ ],
133
+ [
134
+ " we",
135
+ 0.06671142578125
136
+ ],
137
+ [
138
+ " the",
139
+ 0.04241943359375
140
+ ],
141
+ [
142
+ " at",
143
+ 0.0253143310546875
144
+ ],
145
+ [
146
+ "’s",
147
+ 0.022705078125
148
+ ],
149
+ [
150
+ " my",
151
+ 0.0160980224609375
152
+ ],
153
+ [
154
+ " in",
155
+ 0.0151214599609375
156
+ ],
157
+ [
158
+ " you",
159
+ 0.0151214599609375
160
+ ],
161
+ [
162
+ ",”",
163
+ 0.01442718505859375
164
+ ]
165
+ ]
166
+ },
167
+ {
168
+ "offset": [
169
+ 15,
170
+ 22
171
+ ],
172
+ "raw": " opened",
173
+ "real_topk": [
174
+ 0,
175
+ 0.0025539398193359375
176
+ ],
177
+ "pred_topk": [
178
+ [
179
+ " was",
180
+ 0.12298583984375
181
+ ],
182
+ [
183
+ " woke",
184
+ 0.06903076171875
185
+ ],
186
+ [
187
+ " had",
188
+ 0.04742431640625
189
+ ],
190
+ [
191
+ " went",
192
+ 0.0386962890625
193
+ ],
194
+ [
195
+ " got",
196
+ 0.0296783447265625
197
+ ],
198
+ [
199
+ " am",
200
+ 0.0274505615234375
201
+ ],
202
+ [
203
+ "’m",
204
+ 0.0270233154296875
205
+ ],
206
+ [
207
+ " saw",
208
+ 0.025390625
209
+ ],
210
+ [
211
+ " have",
212
+ 0.020721435546875
213
+ ],
214
+ [
215
+ " met",
216
+ 0.01515960693359375
217
+ ]
218
+ ]
219
+ },
220
+ {
221
+ "offset": [
222
+ 22,
223
+ 26
224
+ ],
225
+ "raw": " the",
226
+ "real_topk": [
227
+ 0,
228
+ 0.401123046875
229
+ ],
230
+ "pred_topk": [
231
+ [
232
+ " the",
233
+ 0.401123046875
234
+ ],
235
+ [
236
+ " my",
237
+ 0.348388671875
238
+ ],
239
+ [
240
+ " a",
241
+ 0.0968017578125
242
+ ],
243
+ [
244
+ " up",
245
+ 0.04644775390625
246
+ ],
247
+ [
248
+ " an",
249
+ 0.012115478515625
250
+ ],
251
+ [
252
+ " this",
253
+ 0.00669097900390625
254
+ ],
255
+ [
256
+ " one",
257
+ 0.005374908447265625
258
+ ],
259
+ [
260
+ " our",
261
+ 0.004894256591796875
262
+ ],
263
+ [
264
+ " to",
265
+ 0.004596710205078125
266
+ ],
267
+ [
268
+ " and",
269
+ 0.003993988037109375
270
+ ]
271
+ ]
272
+ },
273
+ {
274
+ "offset": [
275
+ 26,
276
+ 31
277
+ ],
278
+ "raw": " door",
279
+ "real_topk": [
280
+ 0,
281
+ 0.19775390625
282
+ ],
283
+ "pred_topk": [
284
+ [
285
+ " door",
286
+ 0.19775390625
287
+ ],
288
+ [
289
+ " window",
290
+ 0.10919189453125
291
+ ],
292
+ [
293
+ " front",
294
+ 0.026763916015625
295
+ ],
296
+ [
297
+ " box",
298
+ 0.022186279296875
299
+ ],
300
+ [
301
+ " book",
302
+ 0.0183868408203125
303
+ ],
304
+ [
305
+ " windows",
306
+ 0.01477813720703125
307
+ ],
308
+ [
309
+ " mail",
310
+ 0.01454925537109375
311
+ ],
312
+ [
313
+ " doors",
314
+ 0.01324462890625
315
+ ],
316
+ [
317
+ " fridge",
318
+ 0.01206207275390625
319
+ ],
320
+ [
321
+ " gate",
322
+ 0.01081085205078125
323
+ ]
324
+ ]
325
+ },
326
+ {
327
+ "offset": [
328
+ 31,
329
+ 35
330
+ ],
331
+ "raw": " and",
332
+ "real_topk": [
333
+ 0,
334
+ 0.2431640625
335
+ ],
336
+ "pred_topk": [
337
+ [
338
+ " to",
339
+ 0.41357421875
340
+ ],
341
+ [
342
+ " and",
343
+ 0.2431640625
344
+ ],
345
+ [
346
+ " of",
347
+ 0.11663818359375
348
+ ],
349
+ [
350
+ ",",
351
+ 0.0802001953125
352
+ ],
353
+ [
354
+ ".",
355
+ 0.024078369140625
356
+ ],
357
+ [
358
+ " for",
359
+ 0.0160369873046875
360
+ ],
361
+ [
362
+ " in",
363
+ 0.0081939697265625
364
+ ],
365
+ [
366
+ " with",
367
+ 0.006580352783203125
368
+ ],
369
+ [
370
+ " just",
371
+ 0.0045928955078125
372
+ ],
373
+ [
374
+ ",”",
375
+ 0.0045928955078125
376
+ ]
377
+ ]
378
+ },
379
+ {
380
+ "offset": [
381
+ 35,
382
+ 39
383
+ ],
384
+ "raw": " saw",
385
+ "real_topk": [
386
+ 0,
387
+ 0.25
388
+ ],
389
+ "pred_topk": [
390
+ [
391
+ " saw",
392
+ 0.25
393
+ ],
394
+ [
395
+ " found",
396
+ 0.10589599609375
397
+ ],
398
+ [
399
+ " there",
400
+ 0.04925537109375
401
+ ],
402
+ [
403
+ " was",
404
+ 0.048492431640625
405
+ ],
406
+ [
407
+ " the",
408
+ 0.0477294921875
409
+ ],
410
+ [
411
+ " I",
412
+ 0.025146484375
413
+ ],
414
+ [
415
+ " walked",
416
+ 0.022552490234375
417
+ ],
418
+ [
419
+ " looked",
420
+ 0.021514892578125
421
+ ],
422
+ [
423
+ " went",
424
+ 0.018402099609375
425
+ ],
426
+ [
427
+ " it",
428
+ 0.0178375244140625
429
+ ]
430
+ ]
431
+ },
432
+ {
433
+ "offset": [
434
+ 39,
435
+ 41
436
+ ],
437
+ "raw": " a",
438
+ "real_topk": [
439
+ 0,
440
+ 0.2431640625
441
+ ],
442
+ "pred_topk": [
443
+ [
444
+ " a",
445
+ 0.2431640625
446
+ ],
447
+ [
448
+ " the",
449
+ 0.10137939453125
450
+ ],
451
+ [
452
+ " that",
453
+ 0.0789794921875
454
+ ],
455
+ [
456
+ " my",
457
+ 0.0718994140625
458
+ ],
459
+ [
460
+ " you",
461
+ 0.047882080078125
462
+ ],
463
+ [
464
+ " an",
465
+ 0.0264434814453125
466
+ ],
467
+ [
468
+ " him",
469
+ 0.025238037109375
470
+ ],
471
+ [
472
+ " two",
473
+ 0.0244598388671875
474
+ ],
475
+ [
476
+ " her",
477
+ 0.018463134765625
478
+ ],
479
+ [
480
+ " three",
481
+ 0.013092041015625
482
+ ]
483
+ ]
484
+ },
485
+ {
486
+ "offset": [
487
+ 41,
488
+ 45
489
+ ],
490
+ "raw": " UFO",
491
+ "real_topk": [
492
+ 0,
493
+ 7.462501525878906e-05
494
+ ],
495
+ "pred_topk": [
496
+ [
497
+ " man",
498
+ 0.07867431640625
499
+ ],
500
+ [
501
+ " young",
502
+ 0.0389404296875
503
+ ],
504
+ [
505
+ " woman",
506
+ 0.037750244140625
507
+ ],
508
+ [
509
+ " beautiful",
510
+ 0.03033447265625
511
+ ],
512
+ [
513
+ " little",
514
+ 0.022186279296875
515
+ ],
516
+ [
517
+ " girl",
518
+ 0.0198974609375
519
+ ],
520
+ [
521
+ " small",
522
+ 0.0170135498046875
523
+ ],
524
+ [
525
+ " group",
526
+ 0.0150146484375
527
+ ],
528
+ [
529
+ " large",
530
+ 0.0147857666015625
531
+ ],
532
+ [
533
+ " boy",
534
+ 0.0147857666015625
535
+ ]
536
+ ]
537
+ },
538
+ {
539
+ "offset": [
540
+ 45,
541
+ 47
542
+ ],
543
+ "raw": ".”",
544
+ "real_topk": [
545
+ 0,
546
+ 0.043243408203125
547
+ ],
548
+ "pred_topk": [
549
+ [
550
+ ".",
551
+ 0.10211181640625
552
+ ],
553
+ [
554
+ " flying",
555
+ 0.093017578125
556
+ ],
557
+ [
558
+ " hovering",
559
+ 0.0833740234375
560
+ ],
561
+ [
562
+ ",",
563
+ 0.0538330078125
564
+ ],
565
+ [
566
+ " in",
567
+ 0.052154541015625
568
+ ],
569
+ [
570
+ " coming",
571
+ 0.049774169921875
572
+ ],
573
+ [
574
+ ".”",
575
+ 0.043243408203125
576
+ ],
577
+ [
578
+ "!”",
579
+ 0.0283660888671875
580
+ ],
581
+ [
582
+ "!",
583
+ 0.0238800048828125
584
+ ],
585
+ [
586
+ " with",
587
+ 0.0180206298828125
588
+ ]
589
+ ]
590
+ }
591
+ ]
592
+ }
593
+ }
data/demo/public/quick-start-2.json ADDED
@@ -0,0 +1,593 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "request": {
3
+ "text": "“This morning I opened the door and saw a cat.”"
4
+ },
5
+ "result": {
6
+ "model": "qwen3.0-0.6b",
7
+ "bpe_strings": [
8
+ {
9
+ "offset": [
10
+ 0,
11
+ 5
12
+ ],
13
+ "raw": "“This",
14
+ "real_topk": [
15
+ 0,
16
+ 2.8431415557861328e-05
17
+ ],
18
+ "pred_topk": [
19
+ [
20
+ "Human",
21
+ 0.05517578125
22
+ ],
23
+ [
24
+ "The",
25
+ 0.032196044921875
26
+ ],
27
+ [
28
+ "What",
29
+ 0.0231781005859375
30
+ ],
31
+ [
32
+ "#",
33
+ 0.0228271484375
34
+ ],
35
+ [
36
+ "以下",
37
+ 0.0201416015625
38
+ ],
39
+ [
40
+ "Given",
41
+ 0.0161895751953125
42
+ ],
43
+ [
44
+ "@",
45
+ 0.01556396484375
46
+ ],
47
+ [
48
+ "###",
49
+ 0.0141754150390625
50
+ ],
51
+ [
52
+ "import",
53
+ 0.009368896484375
54
+ ],
55
+ [
56
+ "Find",
57
+ 0.00901031494140625
58
+ ]
59
+ ]
60
+ },
61
+ {
62
+ "offset": [
63
+ 5,
64
+ 13
65
+ ],
66
+ "raw": " morning",
67
+ "real_topk": [
68
+ 0,
69
+ 0.00493621826171875
70
+ ],
71
+ "pred_topk": [
72
+ [
73
+ " is",
74
+ 0.315185546875
75
+ ],
76
+ [
77
+ "”",
78
+ 0.01922607421875
79
+ ],
80
+ [
81
+ " was",
82
+ 0.0161895751953125
83
+ ],
84
+ [
85
+ " one",
86
+ 0.01342010498046875
87
+ ],
88
+ [
89
+ " year",
90
+ 0.01320648193359375
91
+ ],
92
+ [
93
+ " week",
94
+ 0.01320648193359375
95
+ ],
96
+ [
97
+ " time",
98
+ 0.01061248779296875
99
+ ],
100
+ [
101
+ " will",
102
+ 0.00814056396484375
103
+ ],
104
+ [
105
+ " book",
106
+ 0.0078887939453125
107
+ ],
108
+ [
109
+ " article",
110
+ 0.00653839111328125
111
+ ]
112
+ ]
113
+ },
114
+ {
115
+ "offset": [
116
+ 13,
117
+ 15
118
+ ],
119
+ "raw": " I",
120
+ "real_topk": [
121
+ 0,
122
+ 0.2440185546875
123
+ ],
124
+ "pred_topk": [
125
+ [
126
+ ",",
127
+ 0.289794921875
128
+ ],
129
+ [
130
+ " I",
131
+ 0.2440185546875
132
+ ],
133
+ [
134
+ " we",
135
+ 0.06671142578125
136
+ ],
137
+ [
138
+ " the",
139
+ 0.04241943359375
140
+ ],
141
+ [
142
+ " at",
143
+ 0.0253143310546875
144
+ ],
145
+ [
146
+ "’s",
147
+ 0.022705078125
148
+ ],
149
+ [
150
+ " my",
151
+ 0.0160980224609375
152
+ ],
153
+ [
154
+ " in",
155
+ 0.0151214599609375
156
+ ],
157
+ [
158
+ " you",
159
+ 0.0151214599609375
160
+ ],
161
+ [
162
+ ",”",
163
+ 0.01442718505859375
164
+ ]
165
+ ]
166
+ },
167
+ {
168
+ "offset": [
169
+ 15,
170
+ 22
171
+ ],
172
+ "raw": " opened",
173
+ "real_topk": [
174
+ 0,
175
+ 0.0025539398193359375
176
+ ],
177
+ "pred_topk": [
178
+ [
179
+ " was",
180
+ 0.12298583984375
181
+ ],
182
+ [
183
+ " woke",
184
+ 0.06903076171875
185
+ ],
186
+ [
187
+ " had",
188
+ 0.04742431640625
189
+ ],
190
+ [
191
+ " went",
192
+ 0.0386962890625
193
+ ],
194
+ [
195
+ " got",
196
+ 0.0296783447265625
197
+ ],
198
+ [
199
+ " am",
200
+ 0.0274505615234375
201
+ ],
202
+ [
203
+ "’m",
204
+ 0.0270233154296875
205
+ ],
206
+ [
207
+ " saw",
208
+ 0.025390625
209
+ ],
210
+ [
211
+ " have",
212
+ 0.020721435546875
213
+ ],
214
+ [
215
+ " met",
216
+ 0.01515960693359375
217
+ ]
218
+ ]
219
+ },
220
+ {
221
+ "offset": [
222
+ 22,
223
+ 26
224
+ ],
225
+ "raw": " the",
226
+ "real_topk": [
227
+ 0,
228
+ 0.401123046875
229
+ ],
230
+ "pred_topk": [
231
+ [
232
+ " the",
233
+ 0.401123046875
234
+ ],
235
+ [
236
+ " my",
237
+ 0.348388671875
238
+ ],
239
+ [
240
+ " a",
241
+ 0.0968017578125
242
+ ],
243
+ [
244
+ " up",
245
+ 0.04644775390625
246
+ ],
247
+ [
248
+ " an",
249
+ 0.012115478515625
250
+ ],
251
+ [
252
+ " this",
253
+ 0.00669097900390625
254
+ ],
255
+ [
256
+ " one",
257
+ 0.005374908447265625
258
+ ],
259
+ [
260
+ " our",
261
+ 0.004894256591796875
262
+ ],
263
+ [
264
+ " to",
265
+ 0.004596710205078125
266
+ ],
267
+ [
268
+ " and",
269
+ 0.003993988037109375
270
+ ]
271
+ ]
272
+ },
273
+ {
274
+ "offset": [
275
+ 26,
276
+ 31
277
+ ],
278
+ "raw": " door",
279
+ "real_topk": [
280
+ 0,
281
+ 0.19775390625
282
+ ],
283
+ "pred_topk": [
284
+ [
285
+ " door",
286
+ 0.19775390625
287
+ ],
288
+ [
289
+ " window",
290
+ 0.10919189453125
291
+ ],
292
+ [
293
+ " front",
294
+ 0.026763916015625
295
+ ],
296
+ [
297
+ " box",
298
+ 0.022186279296875
299
+ ],
300
+ [
301
+ " book",
302
+ 0.0183868408203125
303
+ ],
304
+ [
305
+ " windows",
306
+ 0.01477813720703125
307
+ ],
308
+ [
309
+ " mail",
310
+ 0.01454925537109375
311
+ ],
312
+ [
313
+ " doors",
314
+ 0.01324462890625
315
+ ],
316
+ [
317
+ " fridge",
318
+ 0.01206207275390625
319
+ ],
320
+ [
321
+ " gate",
322
+ 0.01081085205078125
323
+ ]
324
+ ]
325
+ },
326
+ {
327
+ "offset": [
328
+ 31,
329
+ 35
330
+ ],
331
+ "raw": " and",
332
+ "real_topk": [
333
+ 0,
334
+ 0.2431640625
335
+ ],
336
+ "pred_topk": [
337
+ [
338
+ " to",
339
+ 0.41357421875
340
+ ],
341
+ [
342
+ " and",
343
+ 0.2431640625
344
+ ],
345
+ [
346
+ " of",
347
+ 0.11663818359375
348
+ ],
349
+ [
350
+ ",",
351
+ 0.0802001953125
352
+ ],
353
+ [
354
+ ".",
355
+ 0.024078369140625
356
+ ],
357
+ [
358
+ " for",
359
+ 0.0160369873046875
360
+ ],
361
+ [
362
+ " in",
363
+ 0.0081939697265625
364
+ ],
365
+ [
366
+ " with",
367
+ 0.006580352783203125
368
+ ],
369
+ [
370
+ " just",
371
+ 0.0045928955078125
372
+ ],
373
+ [
374
+ ",”",
375
+ 0.0045928955078125
376
+ ]
377
+ ]
378
+ },
379
+ {
380
+ "offset": [
381
+ 35,
382
+ 39
383
+ ],
384
+ "raw": " saw",
385
+ "real_topk": [
386
+ 0,
387
+ 0.25
388
+ ],
389
+ "pred_topk": [
390
+ [
391
+ " saw",
392
+ 0.25
393
+ ],
394
+ [
395
+ " found",
396
+ 0.10589599609375
397
+ ],
398
+ [
399
+ " there",
400
+ 0.04925537109375
401
+ ],
402
+ [
403
+ " was",
404
+ 0.048492431640625
405
+ ],
406
+ [
407
+ " the",
408
+ 0.0477294921875
409
+ ],
410
+ [
411
+ " I",
412
+ 0.025146484375
413
+ ],
414
+ [
415
+ " walked",
416
+ 0.022552490234375
417
+ ],
418
+ [
419
+ " looked",
420
+ 0.021514892578125
421
+ ],
422
+ [
423
+ " went",
424
+ 0.018402099609375
425
+ ],
426
+ [
427
+ " it",
428
+ 0.0178375244140625
429
+ ]
430
+ ]
431
+ },
432
+ {
433
+ "offset": [
434
+ 39,
435
+ 41
436
+ ],
437
+ "raw": " a",
438
+ "real_topk": [
439
+ 0,
440
+ 0.2431640625
441
+ ],
442
+ "pred_topk": [
443
+ [
444
+ " a",
445
+ 0.2431640625
446
+ ],
447
+ [
448
+ " the",
449
+ 0.10137939453125
450
+ ],
451
+ [
452
+ " that",
453
+ 0.0789794921875
454
+ ],
455
+ [
456
+ " my",
457
+ 0.0718994140625
458
+ ],
459
+ [
460
+ " you",
461
+ 0.047882080078125
462
+ ],
463
+ [
464
+ " an",
465
+ 0.0264434814453125
466
+ ],
467
+ [
468
+ " him",
469
+ 0.025238037109375
470
+ ],
471
+ [
472
+ " two",
473
+ 0.0244598388671875
474
+ ],
475
+ [
476
+ " her",
477
+ 0.018463134765625
478
+ ],
479
+ [
480
+ " three",
481
+ 0.013092041015625
482
+ ]
483
+ ]
484
+ },
485
+ {
486
+ "offset": [
487
+ 41,
488
+ 45
489
+ ],
490
+ "raw": " cat",
491
+ "real_topk": [
492
+ 0,
493
+ 0.003566741943359375
494
+ ],
495
+ "pred_topk": [
496
+ [
497
+ " man",
498
+ 0.07867431640625
499
+ ],
500
+ [
501
+ " young",
502
+ 0.0389404296875
503
+ ],
504
+ [
505
+ " woman",
506
+ 0.037750244140625
507
+ ],
508
+ [
509
+ " beautiful",
510
+ 0.03033447265625
511
+ ],
512
+ [
513
+ " little",
514
+ 0.022186279296875
515
+ ],
516
+ [
517
+ " girl",
518
+ 0.0198974609375
519
+ ],
520
+ [
521
+ " small",
522
+ 0.0170135498046875
523
+ ],
524
+ [
525
+ " group",
526
+ 0.0150146484375
527
+ ],
528
+ [
529
+ " large",
530
+ 0.0147857666015625
531
+ ],
532
+ [
533
+ " boy",
534
+ 0.0147857666015625
535
+ ]
536
+ ]
537
+ },
538
+ {
539
+ "offset": [
540
+ 45,
541
+ 47
542
+ ],
543
+ "raw": ".”",
544
+ "real_topk": [
545
+ 0,
546
+ 0.030792236328125
547
+ ],
548
+ "pred_topk": [
549
+ [
550
+ ".",
551
+ 0.0963134765625
552
+ ],
553
+ [
554
+ " sitting",
555
+ 0.07049560546875
556
+ ],
557
+ [
558
+ " in",
559
+ 0.060272216796875
560
+ ],
561
+ [
562
+ ",",
563
+ 0.055755615234375
564
+ ],
565
+ [
566
+ " running",
567
+ 0.044097900390625
568
+ ],
569
+ [
570
+ " lying",
571
+ 0.044097900390625
572
+ ],
573
+ [
574
+ " on",
575
+ 0.038909912109375
576
+ ],
577
+ [
578
+ ".”",
579
+ 0.030792236328125
580
+ ],
581
+ [
582
+ " with",
583
+ 0.02984619140625
584
+ ],
585
+ [
586
+ " standing",
587
+ 0.02435302734375
588
+ ]
589
+ ]
590
+ }
591
+ ]
592
+ }
593
+ }
data/demo/public/{human_ woodchuck.json → woodchuck.json} RENAMED
File without changes