更新主页标题和描述
Browse files- README.md +3 -3
- backend/api/analyze.py +1 -1
- client/src/css/start.scss +11 -1
- client/src/index.html +2 -2
- client/src/ts/lang/translations.ts +5 -2
- client/src/ts/start.ts +20 -4
- client/src/ts/vis/ToolTip.ts +1 -1
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title: InfoRadar
|
| 3 |
emoji: 📡
|
| 4 |
colorFrom: gray
|
| 5 |
colorTo: red
|
|
@@ -16,9 +16,9 @@ pinned: false
|
|
| 16 |
license: apache-2.0
|
| 17 |
---
|
| 18 |
|
| 19 |
-
# InfoRadar
|
| 20 |
|
| 21 |
-
Tired of
|
| 22 |
|
| 23 |
**Try InfoRadar.** It uses large language models to analyze text information density and visualizes where the important parts are. The color intensity of each token indicates how much information it carries.
|
| 24 |
|
|
|
|
| 1 |
---
|
| 2 |
+
title: InfoRadar - see what matters.
|
| 3 |
emoji: 📡
|
| 4 |
colorFrom: gray
|
| 5 |
colorTo: red
|
|
|
|
| 16 |
license: apache-2.0
|
| 17 |
---
|
| 18 |
|
| 19 |
+
# InfoRadar
|
| 20 |
|
| 21 |
+
Tired of redundancy and fluff? Want key points at a glance? Or simply curious about the information-theoretic nature of language?
|
| 22 |
|
| 23 |
**Try InfoRadar.** It uses large language models to analyze text information density and visualizes where the important parts are. The color intensity of each token indicates how much information it carries.
|
| 24 |
|
backend/api/analyze.py
CHANGED
|
@@ -20,7 +20,7 @@ class QueueTimeoutError(Exception):
|
|
| 20 |
# 这样可以避免多个请求并发访问模型导致的资源竞争和线程安全问题
|
| 21 |
_analysis_lock = threading.Lock()
|
| 22 |
# 单次分析的总处理时长限制(秒)
|
| 23 |
-
ANALYSIS_TIMEOUT =
|
| 24 |
# 等待获取锁的最大时间(秒)- 如果排队时间过长,直接拒绝请求
|
| 25 |
LOCK_WAIT_TIMEOUT = 10.0
|
| 26 |
|
|
|
|
| 20 |
# 这样可以避免多个请求并发访问模型导致的资源竞争和线程安全问题
|
| 21 |
_analysis_lock = threading.Lock()
|
| 22 |
# 单次分析的总处理时长限制(秒)
|
| 23 |
+
ANALYSIS_TIMEOUT = 30.0
|
| 24 |
# 等待获取锁的最大时间(秒)- 如果排队时间过长,直接拒绝请求
|
| 25 |
LOCK_WAIT_TIMEOUT = 10.0
|
| 26 |
|
client/src/css/start.scss
CHANGED
|
@@ -1021,8 +1021,18 @@ select {
|
|
| 1021 |
overflow: visible;
|
| 1022 |
flex: 1 1 320px;
|
| 1023 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1024 |
.title-formula {
|
| 1025 |
-
font-size:
|
| 1026 |
font-weight: 400;
|
| 1027 |
color: var(--text-muted);
|
| 1028 |
opacity: 0.75;
|
|
|
|
| 1021 |
overflow: visible;
|
| 1022 |
flex: 1 1 320px;
|
| 1023 |
|
| 1024 |
+
.title-main-line {
|
| 1025 |
+
white-space: nowrap;
|
| 1026 |
+
}
|
| 1027 |
+
|
| 1028 |
+
.title-tagline {
|
| 1029 |
+
font-size: 18px;
|
| 1030 |
+
font-weight: 400;
|
| 1031 |
+
margin-left: 1em;
|
| 1032 |
+
}
|
| 1033 |
+
|
| 1034 |
.title-formula {
|
| 1035 |
+
font-size: 10px;
|
| 1036 |
font-weight: 400;
|
| 1037 |
color: var(--text-muted);
|
| 1038 |
opacity: 0.75;
|
client/src/index.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
|
| 4 |
<head>
|
| 5 |
<meta charset="UTF-8">
|
| 6 |
-
<title>InfoRadar —
|
| 7 |
<meta name="description"
|
| 8 |
content="InfoRadar visualizes token-level information density in text using LLMs, helping you quickly find key content and skip redundancy.">
|
| 9 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
@@ -17,7 +17,7 @@
|
|
| 17 |
<div class="floating_content">
|
| 18 |
<header class="home-toolbar">
|
| 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">
|
|
|
|
| 3 |
|
| 4 |
<head>
|
| 5 |
<meta charset="UTF-8">
|
| 6 |
+
<title>InfoRadar — see what matters</title>
|
| 7 |
<meta name="description"
|
| 8 |
content="InfoRadar visualizes token-level information density in text using LLMs, helping you quickly find key content and skip redundancy.">
|
| 9 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
| 17 |
<div class="floating_content">
|
| 18 |
<header class="home-toolbar">
|
| 19 |
<div class="dark-mode-toggle-wrapper">
|
| 20 |
+
<h1 class="home-toolbar-title"><span class="title-main-line"><span data-i18n>InfoRadar</span><span class="title-tagline" data-i18n>- see what matters.</span></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">
|
client/src/ts/lang/translations.ts
CHANGED
|
@@ -19,7 +19,10 @@ export const translations: Translations = {
|
|
| 19 |
// - client/src/content/home.en.html
|
| 20 |
// - client/src/content/home.zh.html
|
| 21 |
// 由 contentLoader.ts 动态加载
|
| 22 |
-
'InfoRadar': 'InfoRadar
|
|
|
|
|
|
|
|
|
|
| 23 |
'LLM × Linguistics × Information Theory': '大模型 × 语言学 × 信息论',
|
| 24 |
|
| 25 |
// ========== 通用按钮和操作 ==========
|
|
@@ -189,7 +192,7 @@ export const translations: Translations = {
|
|
| 189 |
'information density:': '信息密度:',
|
| 190 |
'prob:': '概率:',
|
| 191 |
'This token was merged from multiple BPE units, Top-k info is aggregated.': '该 token 由多个 BPE 合并,Top-k 信息已合并。',
|
| 192 |
-
'
|
| 193 |
'Top-k data not available.': '未提供 Top-k 数据。',
|
| 194 |
'UTF-8 size:': 'UTF-8大小:',
|
| 195 |
|
|
|
|
| 19 |
// - client/src/content/home.en.html
|
| 20 |
// - client/src/content/home.zh.html
|
| 21 |
// 由 contentLoader.ts 动态加载
|
| 22 |
+
'InfoRadar': 'InfoRadar 信息雷达',
|
| 23 |
+
"- see what matters.": ' — 重点一目了然',
|
| 24 |
+
"InfoRadar — see what matters": 'InfoRadar 信息雷达 — 重点一目了然',
|
| 25 |
+
'InfoRadar visualizes token-level information density in text using LLMs, helping you quickly find key content and skip redundancy.': 'InfoRadar 用大模型可视化文本中每个 token 的信息密度,帮你快速找到关键内容、跳过冗余。',
|
| 26 |
'LLM × Linguistics × Information Theory': '大模型 × 语言学 × 信息论',
|
| 27 |
|
| 28 |
// ========== 通用按钮和操作 ==========
|
|
|
|
| 192 |
'information density:': '信息密度:',
|
| 193 |
'prob:': '概率:',
|
| 194 |
'This token was merged from multiple BPE units, Top-k info is aggregated.': '该 token 由多个 BPE 合并,Top-k 信息已合并。',
|
| 195 |
+
'information:': '信息量:',
|
| 196 |
'Top-k data not available.': '未提供 Top-k 数据。',
|
| 197 |
'UTF-8 size:': 'UTF-8大小:',
|
| 198 |
|
client/src/ts/start.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {createToast} from './ui/toast';
|
|
| 16 |
import {initDemoManager, type DemoManager} from './ui/demoManager';
|
| 17 |
import {showAlertDialog, showDialog, createCombinedContent, createNamePathTextContent, createUrlInputContent} from './ui/dialog';
|
| 18 |
// 国际化
|
| 19 |
-
import {tr, initI18n, toggleLanguage} from './lang/i18n-lite';
|
| 20 |
import {loadHomeContent} from './lang/contentLoader';
|
| 21 |
// Demo存储层
|
| 22 |
import { ServerStorage } from './storage/demoStorage';
|
|
@@ -109,10 +109,26 @@ window.onload = () => {
|
|
| 109 |
const metricTotalSurprisal = d3.select('#metric_total_surprisal');
|
| 110 |
const metricModel = d3.select('#metric_model');
|
| 111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 112 |
// 页面初始化时根据当前语言翻译所有带 data-i18n 属性的元素
|
| 113 |
initI18n();
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
loadHomeContent('home-intro-content');
|
| 117 |
|
| 118 |
// minimap启用状态(优先使用URL参数,否则根据设备类型判断:移动端默认为false,桌面端默认为true)
|
|
@@ -271,7 +287,7 @@ window.onload = () => {
|
|
| 271 |
// 更新文件名显示(必须在使用前定义)
|
| 272 |
const openLocalFilename = d3.select('#open_local_demo_filename');
|
| 273 |
const updateFileNameDisplay = (filename: string | null) => {
|
| 274 |
-
openLocalFilename.text(filename || tr(
|
| 275 |
};
|
| 276 |
|
| 277 |
// 创建 Demo 业务逻辑管理器
|
|
|
|
| 16 |
import {initDemoManager, type DemoManager} from './ui/demoManager';
|
| 17 |
import {showAlertDialog, showDialog, createCombinedContent, createNamePathTextContent, createUrlInputContent} from './ui/dialog';
|
| 18 |
// 国际化
|
| 19 |
+
import {tr, initI18n, toggleLanguage, getCurrentLanguage} from './lang/i18n-lite';
|
| 20 |
import {loadHomeContent} from './lang/contentLoader';
|
| 21 |
// Demo存储层
|
| 22 |
import { ServerStorage } from './storage/demoStorage';
|
|
|
|
| 109 |
const metricTotalSurprisal = d3.select('#metric_total_surprisal');
|
| 110 |
const metricModel = d3.select('#metric_model');
|
| 111 |
|
| 112 |
+
// 从 HTML 读取作为 i18n key 的默认文案(须在 initI18n 之前)
|
| 113 |
+
const defaultNoFileLabel = (() => {
|
| 114 |
+
const el = document.getElementById('open_local_demo_filename');
|
| 115 |
+
return el ? el.textContent?.trim().replace(/\s+/g, ' ') : 'No file selected';
|
| 116 |
+
})();
|
| 117 |
+
|
| 118 |
// 页面初始化时根据当前语言翻译所有带 data-i18n 属性的元素
|
| 119 |
initI18n();
|
| 120 |
+
// 首页相关:中文时用 HTML 内的英文作 key 翻译后覆盖标题与描述
|
| 121 |
+
const isZh = getCurrentLanguage() === 'zh';
|
| 122 |
+
document.documentElement.lang = isZh ? 'zh-CN' : 'en';
|
| 123 |
+
if (isZh) {
|
| 124 |
+
document.title = tr(document.title);
|
| 125 |
+
const metaDesc = document.querySelector('meta[name="description"]');
|
| 126 |
+
if (metaDesc) {
|
| 127 |
+
const content = metaDesc.getAttribute('content');
|
| 128 |
+
if (content) metaDesc.setAttribute('content', tr(content));
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
// 加载首页介绍内容(home.en.html / home.zh.html)
|
| 132 |
loadHomeContent('home-intro-content');
|
| 133 |
|
| 134 |
// minimap启用状态(优先使用URL参数,否则根据设备类型判断:移动端默认为false,桌面端默认为true)
|
|
|
|
| 287 |
// 更新文件名显示(必须在使用前定义)
|
| 288 |
const openLocalFilename = d3.select('#open_local_demo_filename');
|
| 289 |
const updateFileNameDisplay = (filename: string | null) => {
|
| 290 |
+
openLocalFilename.text(filename || tr(defaultNoFileLabel));
|
| 291 |
};
|
| 292 |
|
| 293 |
// 创建 Demo 业务逻辑管理器
|
client/src/ts/vis/ToolTip.ts
CHANGED
|
@@ -456,7 +456,7 @@ export class ToolTip {
|
|
| 456 |
const prob = ri.tokenData.real_topk[1];
|
| 457 |
const surprisal = calculateSurprisal(prob);
|
| 458 |
const isClassic = getTokenRenderStyle() === 'classic';
|
| 459 |
-
const surprisalText = `<span style="color: ${detailColor}">${tr('
|
| 460 |
const prop = `<span style="color: ${detailColor}">${tr('prob:')}</span> <span style="color: ${detailColor}">${this.significantF(prob)}</span>`;
|
| 461 |
if (isClassic) {
|
| 462 |
return `${surprisalText}<br/>${prop}`;
|
|
|
|
| 456 |
const prob = ri.tokenData.real_topk[1];
|
| 457 |
const surprisal = calculateSurprisal(prob);
|
| 458 |
const isClassic = getTokenRenderStyle() === 'classic';
|
| 459 |
+
const surprisalText = `<span style="color: ${detailColor}">${tr('information:')}</span> <span style="color: ${valueColor}">${this.significantF(surprisal)}</span> <span style="color: ${detailColor}">bits</span>`;
|
| 460 |
const prop = `<span style="color: ${detailColor}">${tr('prob:')}</span> <span style="color: ${detailColor}">${this.significantF(prob)}</span>`;
|
| 461 |
if (isClassic) {
|
| 462 |
return `${surprisalText}<br/>${prop}`;
|