dqy08 commited on
Commit
3f516d0
·
1 Parent(s): 0c3e451

评审改动

Browse files
client/src/pages/analysis/index.ts CHANGED
@@ -8,7 +8,6 @@ import type {AnalyzeResponse, FrontendAnalyzeResult, FrontendToken} from "../../
8
  import {GLTR_HoverEvent, GLTR_Mode, GLTR_Text_Box} from "../../shared/vis/GLTR_Text_Box";
9
  import {ToolTip} from "../../shared/vis/ToolTip";
10
  import URLHandler from "../../shared/core/URLHandler";
11
- import {resolveApiBase} from "../../shared/api/resolveApiBase";
12
  import {Histogram, HistogramBinClickEvent} from '../../shared/vis/Histogram';
13
  import {ScatterPlot, type ScatterChunkClickEvent} from '../../shared/vis/ScatterPlot';
14
  import {initThemeManager} from '../../shared/ui/theme';
@@ -79,9 +78,8 @@ const mapIDtoEnum = {
79
 
80
  window.onload = () => {
81
  // 初始化公共应用组件
82
- const api_prefix = resolveApiBase();
83
  const bodyElement = <Element>d3.select('body').node();
84
- const { eventHandler, api, tokenSurprisalColorScale, byteSurprisalColorScale, totalSurprisalFormat } = initializeCommonApp(api_prefix, bodyElement);
85
 
86
  // 管理员模式:从本地恢复 token,并注入到 API(写请求自动带 X-Admin-Token)
87
  const adminManager = AdminManager.getInstance();
@@ -1012,7 +1010,7 @@ window.onload = () => {
1012
  initDensityAttributionSidebar({
1013
  eventHandler,
1014
  getCurrentAnalyzeResult: () => lmf.getCurrentAnalyzeResult(),
1015
- apiPrefix: api_prefix,
1016
  showToast,
1017
  predictionModelVariant: 'base',
1018
  sourcePage: 'analysis',
 
8
  import {GLTR_HoverEvent, GLTR_Mode, GLTR_Text_Box} from "../../shared/vis/GLTR_Text_Box";
9
  import {ToolTip} from "../../shared/vis/ToolTip";
10
  import URLHandler from "../../shared/core/URLHandler";
 
11
  import {Histogram, HistogramBinClickEvent} from '../../shared/vis/Histogram';
12
  import {ScatterPlot, type ScatterChunkClickEvent} from '../../shared/vis/ScatterPlot';
13
  import {initThemeManager} from '../../shared/ui/theme';
 
78
 
79
  window.onload = () => {
80
  // 初始化公共应用组件
 
81
  const bodyElement = <Element>d3.select('body').node();
82
+ const { eventHandler, api, apiBase, tokenSurprisalColorScale, byteSurprisalColorScale, totalSurprisalFormat } = initializeCommonApp(undefined, bodyElement);
83
 
84
  // 管理员模式:从本地恢复 token,并注入到 API(写请求自动带 X-Admin-Token)
85
  const adminManager = AdminManager.getInstance();
 
1010
  initDensityAttributionSidebar({
1011
  eventHandler,
1012
  getCurrentAnalyzeResult: () => lmf.getCurrentAnalyzeResult(),
1013
+ apiPrefix: apiBase,
1014
  showToast,
1015
  predictionModelVariant: 'base',
1016
  sourcePage: 'analysis',
client/src/pages/attribution/index.ts CHANGED
@@ -11,7 +11,6 @@ import { initChatPanelLayout } from '../../shared/ui/chat_panel_layout';
11
  import { PANEL_SPLIT_STORAGE_KEY_ATTRIBUTION } from '../../shared/cross/panelSplitStorage';
12
  import { TextInputController } from '../../shared/controllers/textInputController';
13
  import { initializeCommonApp } from '../../shared/bootstrap';
14
- import { resolveApiBase } from '../../shared/api/resolveApiBase';
15
  import { registerPageBusy } from '../../shared/core/activitySession';
16
  import { showAlertDialog } from '../../shared/ui/dialog';
17
  import { initCachedHistoryQueryDropdown, type CachedHistorySelectContext } from '../../shared/cross/cachedHistoryUi';
@@ -56,11 +55,10 @@ function readStoredAttributionPageModelVariant(): PredictionAttributeModelVarian
56
  return lsReadEnum(ATTRIBUTION_MODEL_VARIANT_STORAGE_KEY, ['base', 'instruct'] as const, 'instruct');
57
  }
58
 
59
- const apiPrefix = resolveApiBase();
60
  const bodyElement = d3.select('body').node() as Element;
61
- const { eventHandler, totalSurprisalFormat, api } = initializeCommonApp(apiPrefix, bodyElement);
62
  /** 与 {@link TextAnalysisAPI} 一致:`?api=` 非空时用其作为基址,否则 `''`,URL 为 `/api/...`(相对当前站点根路径) */
63
- const apiBaseForRequests = apiPrefix === '' ? '' : String(apiPrefix);
64
 
65
  const adminManager = AdminManager.getInstance();
66
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
 
11
  import { PANEL_SPLIT_STORAGE_KEY_ATTRIBUTION } from '../../shared/cross/panelSplitStorage';
12
  import { TextInputController } from '../../shared/controllers/textInputController';
13
  import { initializeCommonApp } from '../../shared/bootstrap';
 
14
  import { registerPageBusy } from '../../shared/core/activitySession';
15
  import { showAlertDialog } from '../../shared/ui/dialog';
16
  import { initCachedHistoryQueryDropdown, type CachedHistorySelectContext } from '../../shared/cross/cachedHistoryUi';
 
55
  return lsReadEnum(ATTRIBUTION_MODEL_VARIANT_STORAGE_KEY, ['base', 'instruct'] as const, 'instruct');
56
  }
57
 
 
58
  const bodyElement = d3.select('body').node() as Element;
59
+ const { eventHandler, totalSurprisalFormat, api, apiBase } = initializeCommonApp(undefined, bodyElement);
60
  /** 与 {@link TextAnalysisAPI} 一致:`?api=` 非空时用其作为基址,否则 `''`,URL 为 `/api/...`(相对当前站点根路径) */
61
+ const apiBaseForRequests = apiBase;
62
 
63
  const adminManager = AdminManager.getInstance();
64
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
client/src/pages/causal_flow/index.ts CHANGED
@@ -11,7 +11,6 @@ import { initChatPanelLayout } from '../../shared/ui/chat_panel_layout';
11
  import { PANEL_SPLIT_STORAGE_KEY_GEN_ATTRIBUTE } from '../../shared/cross/panelSplitStorage';
12
  import { TextInputController } from '../../shared/controllers/textInputController';
13
  import { initializeCommonApp } from '../../shared/bootstrap';
14
- import { resolveApiBase } from '../../shared/api/resolveApiBase';
15
  import { registerPageBusy } from '../../shared/core/activitySession';
16
  import { setPageOptsGetter } from '../../shared/core/clientActivityPing';
17
  import { showAlertDialog } from '../../shared/ui/dialog';
@@ -373,10 +372,9 @@ function readStoredDagLayoutMode(): DagLayoutMode {
373
  );
374
  }
375
 
376
- const apiPrefix = resolveApiBase();
377
  const bodyElement = d3.select('body').node() as Element;
378
- const { totalSurprisalFormat, api } = initializeCommonApp(apiPrefix, bodyElement);
379
- const apiBaseForRequests = apiPrefix === '' ? '' : String(apiPrefix);
380
 
381
  const adminManager = AdminManager.getInstance();
382
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
 
11
  import { PANEL_SPLIT_STORAGE_KEY_GEN_ATTRIBUTE } from '../../shared/cross/panelSplitStorage';
12
  import { TextInputController } from '../../shared/controllers/textInputController';
13
  import { initializeCommonApp } from '../../shared/bootstrap';
 
14
  import { registerPageBusy } from '../../shared/core/activitySession';
15
  import { setPageOptsGetter } from '../../shared/core/clientActivityPing';
16
  import { showAlertDialog } from '../../shared/ui/dialog';
 
372
  );
373
  }
374
 
 
375
  const bodyElement = d3.select('body').node() as Element;
376
+ const { totalSurprisalFormat, api, apiBase } = initializeCommonApp(undefined, bodyElement);
377
+ const apiBaseForRequests = apiBase;
378
 
379
  const adminManager = AdminManager.getInstance();
380
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
client/src/pages/chat/index.ts CHANGED
@@ -13,7 +13,6 @@ import { initChatPanelLayout } from '../../shared/ui/chat_panel_layout';
13
  import { PANEL_SPLIT_STORAGE_KEY_CHAT } from '../../shared/cross/panelSplitStorage';
14
  import { TextInputController } from '../../shared/controllers/textInputController';
15
  import { initializeCommonApp } from '../../shared/bootstrap';
16
- import { resolveApiBase } from '../../shared/api/resolveApiBase';
17
  import { registerPageBusy } from '../../shared/core/activitySession';
18
  import { showAlertDialog } from '../../shared/ui/dialog';
19
  import URLHandler from '../../shared/core/URLHandler';
@@ -94,9 +93,8 @@ void migrateLegacyChatCacheIfNeeded();
94
 
95
  const showToast = createToast('#toast').show;
96
 
97
- const apiPrefix = resolveApiBase();
98
  const bodyElement = d3.select('body').node() as Element;
99
- const { eventHandler, totalSurprisalFormat, api } = initializeCommonApp(apiPrefix, bodyElement);
100
 
101
  const adminManager = AdminManager.getInstance();
102
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
@@ -1207,7 +1205,7 @@ if (chatCopyFulltextBtn) {
1207
  initDensityAttributionSidebar({
1208
  eventHandler,
1209
  getCurrentAnalyzeResult: () => chatTurnsView.getActiveAnalyzeResult(),
1210
- apiPrefix,
1211
  showToast,
1212
  getContextPrefix: () => chatTurnsView.getPromptPrefixForSidebar() || currentPromptUsed,
1213
  predictionModelVariant: 'instruct',
 
13
  import { PANEL_SPLIT_STORAGE_KEY_CHAT } from '../../shared/cross/panelSplitStorage';
14
  import { TextInputController } from '../../shared/controllers/textInputController';
15
  import { initializeCommonApp } from '../../shared/bootstrap';
 
16
  import { registerPageBusy } from '../../shared/core/activitySession';
17
  import { showAlertDialog } from '../../shared/ui/dialog';
18
  import URLHandler from '../../shared/core/URLHandler';
 
93
 
94
  const showToast = createToast('#toast').show;
95
 
 
96
  const bodyElement = d3.select('body').node() as Element;
97
+ const { eventHandler, totalSurprisalFormat, api, apiBase } = initializeCommonApp(undefined, bodyElement);
98
 
99
  const adminManager = AdminManager.getInstance();
100
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
 
1205
  initDensityAttributionSidebar({
1206
  eventHandler,
1207
  getCurrentAnalyzeResult: () => chatTurnsView.getActiveAnalyzeResult(),
1208
+ apiPrefix: apiBase,
1209
  showToast,
1210
  getContextPrefix: () => chatTurnsView.getPromptPrefixForSidebar() || currentPromptUsed,
1211
  predictionModelVariant: 'instruct',
client/src/pages/compare/index.ts CHANGED
@@ -6,7 +6,6 @@ import {SimpleEventHandler} from "../../shared/core/SimpleEventHandler";
6
  import type {AnalysisData, AnalyzeResponse, FrontendAnalyzeResult, FrontendToken} from "../../shared/api/GLTR_API";
7
  import {TextAnalysisAPI} from "../../shared/api/GLTR_API";
8
  import URLHandler from "../../shared/core/URLHandler";
9
- import {resolveApiBase} from "../../shared/api/resolveApiBase";
10
  import {Histogram, type HistogramBinClickEvent} from '../../shared/vis/Histogram';
11
  import {ScatterPlot} from '../../shared/vis/ScatterPlot';
12
  import {getDiffColor} from '../../shared/cross/SurprisalColorConfig';
@@ -133,9 +132,8 @@ type DemoColumnData = {
133
 
134
  window.onload = () => {
135
  // 初始化公共应用组件
136
- const api_prefix = resolveApiBase();
137
  const bodyElement = <Element>d3.select('body').node();
138
- const { eventHandler, api, tokenSurprisalColorScale, byteSurprisalColorScale, totalSurprisalFormat } = initializeCommonApp(api_prefix, bodyElement);
139
 
140
  const container = d3.select('#compare-container');
141
  const mainFrame = d3.select('.main_frame');
 
6
  import type {AnalysisData, AnalyzeResponse, FrontendAnalyzeResult, FrontendToken} from "../../shared/api/GLTR_API";
7
  import {TextAnalysisAPI} from "../../shared/api/GLTR_API";
8
  import URLHandler from "../../shared/core/URLHandler";
 
9
  import {Histogram, type HistogramBinClickEvent} from '../../shared/vis/Histogram';
10
  import {ScatterPlot} from '../../shared/vis/ScatterPlot';
11
  import {getDiffColor} from '../../shared/cross/SurprisalColorConfig';
 
132
 
133
  window.onload = () => {
134
  // 初始化公共应用组件
 
135
  const bodyElement = <Element>d3.select('body').node();
136
+ const { eventHandler, api, tokenSurprisalColorScale, byteSurprisalColorScale, totalSurprisalFormat } = initializeCommonApp(undefined, bodyElement);
137
 
138
  const container = d3.select('#compare-container');
139
  const mainFrame = d3.select('.main_frame');
client/src/pages/home/index.ts CHANGED
@@ -14,7 +14,6 @@ import { getCurrentLanguage, initI18n, tr } from '../../shared/lang/i18n-lite';
14
  import { AdminManager } from '../../shared/cross/adminManager';
15
  import { SettingsMenuManager } from '../../shared/cross/settingsMenuManager';
16
  import { initializeCommonApp } from '../../shared/bootstrap';
17
- import { resolveApiBase } from '../../shared/api/resolveApiBase';
18
  import { DEFAULT_DEMO_URL_PARAM } from '../../shared/cross/contentUrl';
19
 
20
  /** 首页轮播三帧 → 打包 demo slug(与 demos/causal_flow/*.json 文件名一致) */
@@ -214,8 +213,7 @@ bindGenAttributeBadgeLink();
214
 
215
  const syncGenAttributeCardPreview = initGenAttributeCardCarousel();
216
 
217
- const apiPrefix = resolveApiBase();
218
- const { api } = initializeCommonApp(apiPrefix);
219
  const adminManager = AdminManager.getInstance();
220
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
221
 
 
14
  import { AdminManager } from '../../shared/cross/adminManager';
15
  import { SettingsMenuManager } from '../../shared/cross/settingsMenuManager';
16
  import { initializeCommonApp } from '../../shared/bootstrap';
 
17
  import { DEFAULT_DEMO_URL_PARAM } from '../../shared/cross/contentUrl';
18
 
19
  /** 首页轮播三帧 → 打包 demo slug(与 demos/causal_flow/*.json 文件名一致) */
 
213
 
214
  const syncGenAttributeCardPreview = initGenAttributeCardCarousel();
215
 
216
+ const { api } = initializeCommonApp();
 
217
  const adminManager = AdminManager.getInstance();
218
  api.setAdminToken(adminManager.isInAdminMode() ? adminManager.getAdminToken() : null);
219
 
client/src/shared/api/resolveApiBase.ts CHANGED
@@ -6,9 +6,6 @@ import URLHandler from '../core/URLHandler';
6
 
7
  export const INFORADAR_API_BASE_META_NAME = 'inforadar-api-base';
8
 
9
- /** 门户 Space 根 URL(GitHub Pages 构建注入 meta 用)。 */
10
- export const PORTAL_API_BASE = 'https://dqy08-infolens.hf.space';
11
-
12
  export function normalizeApiBase(url: string): string {
13
  const s = url.trim();
14
  if (!s) return '';
 
6
 
7
  export const INFORADAR_API_BASE_META_NAME = 'inforadar-api-base';
8
 
 
 
 
9
  export function normalizeApiBase(url: string): string {
10
  const s = url.trim();
11
  if (!s) return '';
client/src/shared/bootstrap.ts CHANGED
@@ -19,6 +19,8 @@ import { initFrontendBuildTimeDisplay } from './cross/buildTimeDisplay';
19
  export interface CommonAppContext {
20
  eventHandler: SimpleEventHandler;
21
  api: TextAnalysisAPI;
 
 
22
  tokenSurprisalColorScale: (value: number) => string;
23
  byteSurprisalColorScale: (value: number) => string;
24
  totalSurprisalFormat: (n: number | null) => string;
@@ -46,6 +48,7 @@ export function initializeCommonApp(apiPrefix?: string, element?: Element): Comm
46
  return {
47
  eventHandler: new SimpleEventHandler(targetElement),
48
  api,
 
49
  tokenSurprisalColorScale: (v) => getTokenSurprisalColor(v, HISTOGRAM_MIN_ALPHA),
50
  byteSurprisalColorScale: (v) => getByteSurprisalColor(v, 1, HISTOGRAM_MIN_ALPHA),
51
  totalSurprisalFormat: (n: number | null) => n !== null && Number.isFinite(n) ? format(n) : String(n)
 
19
  export interface CommonAppContext {
20
  eventHandler: SimpleEventHandler;
21
  api: TextAnalysisAPI;
22
+ /** 本页 API 根(meta / ?api= / 同源 '');与 TextAnalysisAPI 实例一致 */
23
+ apiBase: string;
24
  tokenSurprisalColorScale: (value: number) => string;
25
  byteSurprisalColorScale: (value: number) => string;
26
  totalSurprisalFormat: (n: number | null) => string;
 
48
  return {
49
  eventHandler: new SimpleEventHandler(targetElement),
50
  api,
51
+ apiBase: base,
52
  tokenSurprisalColorScale: (v) => getTokenSurprisalColor(v, HISTOGRAM_MIN_ALPHA),
53
  byteSurprisalColorScale: (v) => getByteSurprisalColor(v, 1, HISTOGRAM_MIN_ALPHA),
54
  totalSurprisalFormat: (n: number | null) => n !== null && Number.isFinite(n) ? format(n) : String(n)
client/src/shared/prediction_attribution/core/predictionAttributeClient.ts CHANGED
@@ -1,3 +1,7 @@
 
 
 
 
1
  import { apiUrl } from '../../api/resolveApiBase';
2
  import type { AttributionApiResponse, PredictionAttributeModelVariant } from './attributionResultCache';
3
  import type { PromptTokenSpan } from '../causal_flow/genAttributeDagPreprocess';
 
1
+ /**
2
+ * /api/prediction-attribute 与 /api/tokenize:统一请求与 JSON 解析。
3
+ * 归因缓存规则见 {@link ./attributionResultCache}。
4
+ */
5
  import { apiUrl } from '../../api/resolveApiBase';
6
  import type { AttributionApiResponse, PredictionAttributeModelVariant } from './attributionResultCache';
7
  import type { PromptTokenSpan } from '../causal_flow/genAttributeDagPreprocess';
client/src/tests/api/resolveApiBase.test.ts CHANGED
@@ -5,10 +5,11 @@ import {
5
  normalizeApiBase,
6
  resolveApiBaseFromSources,
7
  apiUrl,
8
- PORTAL_API_BASE,
9
  } from '../../shared/api/resolveApiBase';
10
  import { resolveDemoFileUrlFromBase } from '../../shared/api/apiConfig';
11
 
 
 
12
  let passed = 0;
13
  let failed = 0;
14
 
@@ -28,7 +29,7 @@ assert('empty', normalizeApiBase(' '), '');
28
 
29
  console.log('resolveApiBaseFromSources');
30
  assert('meta wins', resolveApiBaseFromSources('http://other', 'https://portal.hf.space'), 'https://portal.hf.space');
31
- assert('meta wins over empty param', resolveApiBaseFromSources('', PORTAL_API_BASE), PORTAL_API_BASE);
32
  assert('?api= when no meta', resolveApiBaseFromSources('http://localhost:5001', null), 'http://localhost:5001');
33
  assert('same-origin default', resolveApiBaseFromSources(undefined, null), '');
34
  assert('same-origin when meta empty', resolveApiBaseFromSources(undefined, ' '), '');
@@ -36,8 +37,8 @@ assert('same-origin when meta empty', resolveApiBaseFromSources(undefined, ' ')
36
  console.log('resolveDemoFileUrlFromBase');
37
  assert(
38
  'portal + demo path',
39
- resolveDemoFileUrlFromBase(PORTAL_API_BASE, '/quick-start-1.json'),
40
- 'https://dqy08-infolens.hf.space/demo/quick-start-1.json',
41
  );
42
  assert(
43
  'same-origin demo',
@@ -46,7 +47,7 @@ assert(
46
  );
47
 
48
  console.log('apiUrl');
49
- assert('portal api path', apiUrl('/api/analyze', PORTAL_API_BASE), `${PORTAL_API_BASE}/api/analyze`);
50
  assert('same-origin api', apiUrl('/api/tokenize', ''), '/api/tokenize');
51
  assert('empty base explicit', apiUrl('/api/check_admin', ''), '/api/check_admin');
52
 
 
5
  normalizeApiBase,
6
  resolveApiBaseFromSources,
7
  apiUrl,
 
8
  } from '../../shared/api/resolveApiBase';
9
  import { resolveDemoFileUrlFromBase } from '../../shared/api/apiConfig';
10
 
11
+ const PORTAL = 'https://portal.example.test';
12
+
13
  let passed = 0;
14
  let failed = 0;
15
 
 
29
 
30
  console.log('resolveApiBaseFromSources');
31
  assert('meta wins', resolveApiBaseFromSources('http://other', 'https://portal.hf.space'), 'https://portal.hf.space');
32
+ assert('meta wins over empty param', resolveApiBaseFromSources('', PORTAL), PORTAL);
33
  assert('?api= when no meta', resolveApiBaseFromSources('http://localhost:5001', null), 'http://localhost:5001');
34
  assert('same-origin default', resolveApiBaseFromSources(undefined, null), '');
35
  assert('same-origin when meta empty', resolveApiBaseFromSources(undefined, ' '), '');
 
37
  console.log('resolveDemoFileUrlFromBase');
38
  assert(
39
  'portal + demo path',
40
+ resolveDemoFileUrlFromBase(PORTAL, '/quick-start-1.json'),
41
+ `${PORTAL}/demo/quick-start-1.json`,
42
  );
43
  assert(
44
  'same-origin demo',
 
47
  );
48
 
49
  console.log('apiUrl');
50
+ assert('portal api path', apiUrl('/api/analyze', PORTAL), `${PORTAL}/api/analyze`);
51
  assert('same-origin api', apiUrl('/api/tokenize', ''), '/api/tokenize');
52
  assert('empty base explicit', apiUrl('/api/check_admin', ''), '/api/check_admin');
53