TokenTrace / DESIGN_PROMPT.md
cccmmd
feat: add Tiny-NLA activation explanation with trained model weights
9d0d4e9
|
Raw History Blame Contribute Delete
23.5 kB

InfoLens / INNERSCOPE — 统一工作流重设计 Prompt

目标受众:专精 UI/UX 设计的 Agent
任务:理解现有前端架构和各功能模块,设计一个统一的工作流 demo,将当前孤立的 7 个功能(含新训练的 Tiny-NLA)有机融合为一个流畅的「输入文本 → 多维度探索模型内部」体验。
输出形式:给出初步的 HTML/CSS/JS demo(可以是静态原型或可交互 demo),不需要对接真实后端 API。
重要的:这是概念验证 demo,不是产品实现。你可以自由选择任何设计方向、技术栈、视觉风格。不要被现有代码的样式束缚。


一、项目是什么

InfoLens(品牌名 INNERSCOPE) 是一个「透视大语言模型内部」的可视化工具箱。用户输入一段文本,通过不同的分析维度观察模型在想什么。

  • 服务端:Python Flask/Connexion,跑在本地 M4 Pro Mac 上
  • 模型:Qwen3-0.6B (base + instruct),本地 CPU/MPS 推理
  • 用户画像:AI 研究者 / 可解释性爱好者,希望直观看到模型内部状态

二、现有前端代码结构(供参考,不需要遵循)

client/src/
├── index.html                    # 首页(导航网格)
├── analysis.html                 # Info Highlight 页
├── chat.html                     # Raw Chat 页
├── attribution.html              # Attribution 页
├── causal_flow.html              # Causal Flow 页
├── logit_lens.html               # Logit Lens 页
├── branch_tree.html              # Branch Tree 页
│
├── webpack.config.js             # 多入口打包
│
├── pages/                        # 每个页面的 TS 入口
│   ├── home/index.ts
│   ├── analysis/index.ts
│   ├── chat/index.ts             # ~800 行,最复杂
│   ├── attribution/index.ts
│   ├── causal_flow/index.ts
│   ├── logit_lens/index.ts
│   └── branch_tree/index.ts
│
├── shared/                       # 跨页面共享基础设施
│   ├── api/GLTR_API.ts           # TextAnalysisAPI 类(所有后端通信)
│   ├── core/                     # URL 解析、事件总线、工具函数
│   ├── ui/                       # toast, dialog, 主题/语言切换, 面板布局
│   ├── vis/                      # D3 可视化组件(Token着色、Tooltip、直方图、散点图)
│   └── lang/translations.ts      # i18n 翻译
│
├── partials/                     # HTML 片段(被 include 到页面中)
│
├── features/                     # 按功能域拆分
│   ├── analysis/                 # Info Highlight 流程
│   ├── chat/                     # 对话/续写逻辑
│   ├── causal_flow/              # Causal Flow 逻辑
│   └── demo/                     # Demo 存储
│
└── css/pages/                    # 每页独立的 SCSS

三、7 个功能模块详解(含完整 API Schema)

3.1 Info Highlight — Token 级别信息密度分析

做什么:展示模型对文本中每个 token 的「意外程度」——哪些词模型觉得理所当然,哪些词让它意外。

API:POST /api/analyze

请求:
{
  "model": "base" | "instruct",
  "text": "water freezes into solid ice",
  "stream": false              // 可选,true 时 SSE 流式返回
}

响应 200:
{
  "request": { "text": "water freezes into solid ice" },
  "result": {
    "model": "qwen3-0.6b-base",
    "bpe_strings": [
      {
        "offset": [0, 5],        // 字符偏移 [start, end)
        "raw": "water",           // token 原文
        "real_topk": [156, 0.023],  // [模型排序名次, softmax 概率]
        "pred_topk": [            // 该位置 top-N 候选
          ["ice", 0.34],
          ["liquid", 0.18],
          ...
        ]
      },
      ...
    ]
  }
}

错误:400 (缺参数) / 404 (模型未注册) / 500 (推理失败) / 503 (模型加载失败)

附加子功能 — 语义搜索:POST /api/analyze-semantic

请求:
{
  "query": "frozen",            // 查询主题
  "text": "...",                // 原文
  "stream": false,              // 可选 SSE 流式
  "submode": "count",           // 可选: count / fill_blank
  "debug_info": true            // 可选,返回 top10 预测
}

响应 200:
{
  "success": true,
  "model": "qwen3-0.6b-instruct",
  "token_attention": [
    {
      "offset": [13, 19],
      "raw": "solid",
      "score": 0.87             // 对 query 的语义关注度
    },
    ...
  ],
  "debug_info": {               // 仅 debug_info=true 时
    "abbrev": "...",
    "topk_tokens": [...],
    "topk_probs": [...]
  }
}

3.2 Raw Chat — 对话 & 续写

做什么:和模型对话,可视化每次续写中每个生成 token 的细节。支持 Raw 模式(直接给 prompt)和 Chat 模式(system + user prompt + chat template)。

API 链(3 步):

Step 1 — 组装 prompt:POST /v1/completions/prompt

请求:
{
  "model": "qwen3-0.6b-instruct",
  "messages": [
    { "role": "system", "content": "You are a helpful assistant." },
    { "role": "user", "content": "What is water?" }
  ],
  "tools": [...],               // 可选 OpenAI tools schema
  "enable_thinking": false      // 可选,启用 Qwen3 thinking 模式
}

响应 200:
{
  "prompt_used": "<|im_start|>system\n...<|im_end|>\n<|im_start|>user\nWhat is water?<|im_end|>\n<|im_start|>assistant\n"
}

Step 2 — 续写(SSE 流式):POST /v1/completions

请求:
{
  "model": "qwen3-0.6b-instruct",
  "prompt": "<|im_start|>system\n...",  // 从上一步或直接构造
  "max_tokens": 256,                      // 可选,正整数
  "temperature": 0.7,                     // 可选,0-2
  "top_p": 0.9,                           // 可选,0-1
  "stop": ["\n\n"]                        // 可选,停止序列(最多4个)
}
// 响应恒为 text/event-stream (SSE)
// type=delta → 增量 token
// type=result → 末条,data 同 OpenAICompletionsResponse

SSE 末条 data (type=result):
{
  "id": "cmpl-xxx",
  "object": "text_completion",
  "created": 1719000000,
  "model": "qwen3-0.6b-instruct",
  "choices": [{
    "text": "Water is a chemical substance...",
    "index": 0,
    "finish_reason": "stop"     // stop / length / content_filter
  }],
  "usage": {
    "prompt_tokens": 24,
    "completion_tokens": 45,
    "total_tokens": 69
  },
  "info_radar": {               // 续写 token 级分析
    "bpe_strings": [
      { "offset": [0, 5], "raw": "Water", "real_topk": [1, 0.92], "pred_topk": [...] },
      ...
    ]
  }
}

Step 3 — 停止生成:POST /v1/completions/stop

请求:(无 body)
响应 200:{ "ok": true }

高级功能:Tool Calling 多轮模拟(通过 /v1/completions/prompt-incremental 计算 tool response 增量后缀)、Teacher Forcing(强制续写特定文本)、multi-turn 对话缓存与恢复。


3.3 Attribution — 输入对预测的因果归因

做什么:给定上下文和目标预测,分析「是哪些输入词驱动了这个预测」。提供两种方法:梯度归因(gradient-based)和消融归因(ablation/occlusion-based)。

方法 A — 梯度归因:POST /api/prediction-attribute

请求:
{
  "context": "water freezes and turns into solid",   // 必填,token 数 ≤ 2000
  "target_prediction": " ice",                        // 可选,缺省用 top-1
  "model": "base" | "instruct",                      // 必填
  "source_page": "attribution",                       // 必填
  "flow_id": null,                                    // 可选,连续归因会话 ID
  "flow_step": null                                   // 可选,连续归因步骤
}

响应 200:
{
  "success": true,
  "model": "qwen3-0.6b-base",
  "target_token": "ice",           // 归因目标 token
  "target_prob": 0.34,             // 预测概率
  "token_attribution": [
    {
      "offset": [0, 5],            // 字符偏移 [start, end]
      "raw": "water",
      "score": 0.42                // 梯度 L2 范数归因分(正值=支撑,越低越无关)
    },
    { "offset": [30, 35], "raw": "solid", "score": 0.78 },
    ...
  ],
  "debug_info": {                  // 下一 token 的 top-10
    "topk_tokens": ["ice", "liquid", "crystal", ...],
    "topk_probs": [0.34, 0.18, 0.12, ...]
  },
  "is_eos": false                  // target 是否为 EOS token
}

方法 B — 消融归因:POST /api/ablation-attribute

请求:
{
  "context": "water freezes and turns into solid",   // 必填,token 数 ≤ 500
  "target_prediction": " ice",                        // 可选,与 target_token_id 互斥
  "target_token_id": null,                            // 可选,直接指定 token id
  "model": "base" | "instruct",
  "source_page": "attribution"
}

响应 200:
{
  "success": true,
  "target_token": "ice",
  "target_prob": 0.34,             // baseline 概率
  "token_attribution": [
    {
      "offset": [0, 5],
      "raw": "water",
      "score": 0.12,               // ΔP = baseline_prob − occluded_prob(可为负)
      "delta_logit": 0.38          // Δlogit
    },
    ...
  ],
  "is_eos": false
}

错误:400 (缺字段/model非法/超长) / 500 (推理失败) / 503 (繁忙)

3.4 Logit Lens — 逐层解码轨迹

做什么:看模型在每一层的「中间想法」——把每层 hidden state 投影到词表(final norm + lm_head),展示每层 top-k 候选词和目标词概率如何逐层演化。

API:POST /api/logit-lens

请求:
{
  "context": "The sun rises in the east and sets in the",  // 必填,token 数 ≤ 500
  "target_prediction": " west",                             // 可选,与 target_token_id 互斥
  "target_token_id": null,                                  // 可选
  "model": "base" | "instruct",
  "source_page": "logit_lens"
}

响应 200:
{
  "success": true,
  "model": "qwen3-0.6b-base",
  "target_token": "west",
  "n_layers": 28,                    // Transformer 层数(不含 embedding)
  "final_target_prob": 0.72,         // 最终层目标 token 概率
  "layers": [
    {
      "layer": 0,
      "is_embedding": true,          // 第 0 层为 embedding 层
      "topk_tokens": ["the", "a", "in", "and", ...],
      "topk_probs": [0.12, 0.09, 0.07, 0.06, ...],
      "target_prob": 0.001           // 目标词在该层的概率
    },
    {
      "layer": 1,
      "is_embedding": false,
      "topk_tokens": ["in", "the", "to", "of", ...],
      "topk_probs": [0.15, 0.11, 0.08, 0.07, ...],
      "target_prob": 0.003
    },
    ...                               // 共 n_layers+1 层(含 embedding)
    {
      "layer": 28,
      "is_embedding": false,
      "topk_tokens": ["west", "east", "north", ...],  // 最终层
      "topk_probs": [0.72, 0.08, 0.03, ...],
      "target_prob": 0.72
    }
  ],
  "is_eos": false
}

关键概念 — Eureka 层:目标词首次跃至 top-1 的那一层。例如 layer 18 时 west 概率首次超过所有其他候选,这就是「模型想通了这是 west 的那一层」。


3.5 Branch Tree — 续写分支展开

做什么:输入前缀,展开模型所有可能的续写路径(top-k tree),递归探索「模型会怎么往下写」。

API:POST /api/branch-next

请求:
{
  "prefix": "The sun rises in the",   // 必填
  "model": "base" | "instruct",       // 必填
  "source_page": "branch_tree",       // 必填
  "top_k": 10                         // 可选,候选数(默认10,上限50)
}

响应 200:
{
  "success": true,
  "model": "qwen3-0.6b-base",
  "prefix_tokens": 5,                  // prefix 的 token 数
  "candidates": [
    { "token": "east",  "token_id": 8423,  "prob": 0.48 },
    { "token": "west",  "token_id": 2534,  "prob": 0.22 },
    { "token": "sky",   "token_id": 6712,  "prob": 0.08 },
    ...
  ],
  "is_context_full": false             // true 时前端应禁用展开
}

错误:400 (缺参数/model非法/超长) / 500 / 503

递归模式:选择一个候选 → 拼接进 prefix → 再次调用 branch-next → 形成树。前端负责树的构建和渲染逻辑。


3.6 Causal Flow — 因果信息流

做什么:追踪信息如何在模型层间流动,观察归因信号沿生成步骤的传播。核心是「文本自回归生成 + 每一步的输入 token 对输出 token 的梯度归因」的串行管道。

依赖的 API(Causal Flow 是客户端编排的复合流程):

  1. POST /api/tokenize — 分词(见下方 3.6.1)
  2. POST /api/branch-next — 获取 top-k 候选(同 3.5)
  3. POST /api/prediction-attribute — 每一步的梯度归因(同 3.3),带 flow_id + flow_step 连续归因
  4. POST /v1/completions/prompt — 组装 prompt(同 3.2 Step 1)
  5. POST /v1/completions — 续写生成下一个 token

客户端流程:输入 context → tokenize → 自动循环:用当前 context 调用 branch-next,选 top-1 → 调用 prediction-attribute 归因当前步 → 拼接 token → 继续下一步(或手动选择分支方向)

预计算 Demo 数据:可加载预计算的完整归因 DAG,以 D3 力导向图或传播动画播放,无需实时推理。


3.6.1 Tokenize — 文本分词(通用工具端点)

API:POST /api/tokenize

请求:
{
  "context": "Hello, world!",          // 必填
  "model": "base" | "instruct"         // 必填
}

响应 200:
{
  "success": true,
  "spans": [
    { "offset": [0, 5],  "raw": "Hello" },
    { "offset": [5, 6],  "raw": "," },
    { "offset": [6, 7],  "raw": " " },
    { "offset": [7, 12], "raw": "world" },
    { "offset": [12, 13], "raw": "!" }
  ]
}

错误:400 (缺字段/model非法)

特点:不持有推理锁,不做前向/梯度计算,响应极快。是构建统一工作流的「第一步」。


3.7 🆕 Tiny-NLA Activation Explainer(新训练的模型)

做什么:给定一个 token 位置的激活向量(从模型 layer 19 残差流提取的 1024 维向量),用 LoRA 微调的小模型解释「这个激活向量代表了什么概念」。支持两种输入模式:传入文本让后端自动提取激活,或直接传入向量。

模型细节:

  • 架构:Qwen3-0.6B-Base + LoRA adapter (r=8, alpha=16) @ layer 19 + AR head(线性层 1024→1024)
  • 推理精度:float32 + eager(独立加载,不复用 base 槽位的 float16)
  • 训练数据:284 条 teacher labeled 激活-解释对
  • 设备:Apple M4 Pro MPS
  • 核心机制:用特殊 token ㈎(id=149705)作为激活注入锚点,注入归一化后的激活向量(injection_scale=126.223),AV 模型 generate 出自然语言解释,AR head 重建后计算 cosine 评估可信度

API:POST /api/activation-explain

请求模式 A — 文本模式(自动提取激活):
{
  "model": "base" | "instruct",        // 必填
  "source_page": "logit_lens",         // 必填
  "text": "water freezes into solid ice",  // 输入上下文
  "token_index": 4                     // 目标 token 位置(text 模式必填,必须 ≥ 0 且在范围内)
}

请求模式 B — 向量模式(直接传入):
{
  "model": "base",
  "source_page": "workspace",
  "vector": [0.12, -0.34, 0.56, ...]  // 恰好 1024 个 float(与 text 互斥)
}

响应 200:
{
  "success": true,
  "concept": "",                       // 概念标签(当前为空,可后续扩展)
  "explanation": "This activation vector encodes the concept of water turning into a solid state through freezing, capturing the physical phase transition from liquid to ice.",
  "roundtrip_cosine": 0.6631,          // 重建可信度分数 (0-1)
  "vector_dim": 1024,                  // 向量维度
  "note": ""                           // 备注或状态说明
}

错误:
  400 — 缺字段、model 非法、text/vector 均未提供、token_index 越界、向量维度不为 1024
  500 — Tiny-NLA 推理失败
  503 — 推理锁等待超时(30s)

可信度解读(roundtrip_cosine):

  • ≥ 0.70 — 优秀(Excellent):解释高度忠实于激活
  • 0.60–0.70 — 良好(Good):解释与激活有较强关联
  • 0.50–0.60 — 可用(Fair):解释方向大致正确
  • < 0.50 — 保留(Low):解释与激活关联较弱,仅供参考

模型性能基线:

  • AV(Activation Vector 模型):best_val_loss = 0.64
  • AR(Auto-Regressive head):best_val_cosine = 0.6631,mean baseline cosine = 0.5962,shuffled baseline = 0.5252
  • 相比随机 baseline 提升 0.07(统计显著)

四、核心问题

现状:6 个功能 = 6 个独立页面
  ❌ 同一段文本要在不同页面反复输入
  ❌ 结果之间没有关联(Logit Lens 的结果不能顺手看 Attribution)
  ❌ 新模型(Tiny-NLA)完全没接入前端
  ❌ 用户体验割裂——每个功能像独立的工具而非一个整体

五、设计目标

输入一次文本,在一个页面上以多种「透镜」/「视角」探索模型内部。

期望的用户旅程:

  1. 用户输入一段文本 → tokenize 为可交互的 token 序列
  2. 用户选中某个 token → 可以从多个维度探索:
    • 📊 Info Highlight:看 surprisal
    • 🎯 Attribution:看哪些前文驱动了这个 token
    • 🔍 Logit Lens:看逐层解码轨迹
    • 🌳 Branch Tree:展开可能的续写
    • 🧠 Activation Explainer:解释激活向量代表什么概念
    • 🔗 Causal Flow:看信息流向
  3. 多个分析视图可以同时打开,共享同一份输入上下文

你可以完全自由地设计交互模式和视觉风格,不需要考虑现有前端代码的任何约束。


六、Mock 数据 & 接口设计自由度

现有接口参考

所有后端的完整请求/响应 schema 见第三章各小节。demo 中构造 mock 数据时,请直接参考对应功能的 API 响应结构。

🆕 可以设计新接口

你不必拘泥于现有接口。 如果统一工作流的交互需要新的后端接口来达到更好的效果,完全可以提出新的 API 设计。

前提条件:新接口必须在我们后端能力范围内。我们后端的能力边界是:

  • 运行时:Python Flask/Connexion,单个 server.py 注册函数即自动生成路由
  • 模型能力:
    • Qwen3-0.6B (base + instruct) — 前向推理、logits 获取、hidden states 提取、tokenize
    • Tiny-NLA (LoRA + AR head) — 激活解释(已有)
  • 可做的计算:
    • 单个 token 的前向传播及 hidden states
    • 任意层的 hidden state 投影到词表(logit lens 的核心操作)
    • 梯度计算(需 backward)
    • 两个向量的 cosine 相似度、L2 距离
    • token 级别的概率获取
  • 做不到的:
    • 大规模 batch 训练(但我们的训练代码在 experiments/tiny_nla/ 中,可以离线跑)
    • 需要额外预训练模型的计算(除非把模型文件放到 artifacts/ 下)

如果你设计了新接口,在 demo 中用 mock 数据即可。我们在后续实现阶段会在后端补上。

关键端点速查:

  • Info Highlight → 3.1 节 POST /api/analyze 响应
  • Info Highlight 语义搜索 → 3.1 节 POST /api/analyze-semantic 响应
  • Raw Chat → 3.2 节 POST /v1/completions SSE 末条响应
  • Attribution 梯度 → 3.3 节 POST /api/prediction-attribute 响应
  • Attribution 消融 → 3.3 节 POST /api/ablation-attribute 响应
  • Logit Lens → 3.4 节 POST /api/logit-lens 响应(注意 layers 数组结构)
  • Branch Tree → 3.5 节 POST /api/branch-next 响应
  • Causal Flow → 3.6 节复合流程(tokenize + branch-next + prediction-attribute 串行)
  • Tokenize → 3.6.1 节 POST /api/tokenize 响应
  • 🆕 Activation Explainer → 3.7 节 POST /api/activation-explain 响应

七、设计资源 & 参考

设计灵感网站(自由参考)

本地设计仓库(内含设计规范)

impeccable — Anti-Design-Slop 检测器

  • AGENTS.md — 仓库规范和工作流
  • DESIGN.md — Neo Kinpaku 设计系统(暗色漆器 + 金箔 + 铜绿),包含完整的色彩、排版、圆角、间距 token 和组件规范(button、input、card、nav-link 等)
  • CLAUDE.md — Claude 专用的详细行为规范和交互模式
  • docs/STYLE.md — 风格指南
  • 核心哲学:避免 AI 生成设计中的常见反模式(AI-purple gradients、三列等大 Feature Cards、过度 glassmorphism、无限循环微动画等)

taste-skill — Anti-Slop 前端 Skill

  • skills/taste-skill/SKILL.md — 核心设计 Skill(85KB),包含:
    • 「Read the Room」——先推断设计意图再动手
    • 「三旋钮」系统(DESIGN_VARIANCE / MOTION_INTENSITY / VISUAL_DENSITY)从 1-10 控制视觉风格
    • 设计系统映射表(何时用 Fluent UI / Material / Carbon / Primer / govuk-frontend / shadcn 等)
    • 反默认纪律(避免 LLM 默认审美)
  • skills/minimalist-skill/SKILL.md — 极简风格
  • skills/brutalist-skill/SKILL.md — 粗野主义风格
  • skills/soft-skill/SKILL.md — 柔和风格
  • skills/redesign-skill/SKILL.md — 重设计方法论
  • skills/stitch-skill/SKILL.md — 设计缝合参考

建议在开始设计前,至少阅读 impeccable/DESIGN.md 和 taste-skill/skills/taste-skill/SKILL.md 以了解高质量设计的核心原则。


八、交付要求

必须包含

  1. 统一输入区:一个文本框接受用户输入,tokenize 后展示为可交互的 token 序列
  2. 至少 3 种分析入口:包括至少 Logit Lens、Attribution、Tiny-NLA Activation Explainer
  3. 多视图共存:可以同时看到至少 2 种分析的输出(不互斥)
  4. Token 选择交互:点击 token 触发对应分析
  5. Mock 数据:用静态数据代替真实 API 响应

不需要做的

  • 不需要对接真实后端 API
  • 不需要实现完整的 i18n
  • 不需要考虑 webpack 集成(独立 HTML 即可)
  • 不需要实现 Admin / Settings 功能

交付物

一个或多个独立的 HTML/CSS/JS 文件,可以在浏览器中直接打开运行。


九、自由发挥空间

以下内容完全由你决定,不受任何限制:

  • 🎨 视觉风格:暗色/亮色、极简/丰富、任何配色方案
  • 🖼️ 布局方式:面板/分屏/Tab/卡片网格/画布/任何创意布局
  • 🎬 动效设计:过渡/微交互/动画,完全自由
  • 📐 交互模式:点击/悬停/拖拽/快捷键/手势
  • 🏗️ 技术选型:原生 CSS / Tailwind / 任何 CSS 框架 / 任何 JS 库
  • 📝 文案风格:技术性 / 产品化 / 趣味化,任意

唯一的要求是:看起来不像"又一个 AI 生成的 demo",而是像一个真正有设计思考的产品。