cdpearlman commited on
Commit
018a9f2
·
1 Parent(s): bff3e4d

Added pre-built prompts for app and chatbot

Browse files
RESEARCH-jargon-reduction.md DELETED
@@ -1,78 +0,0 @@
1
- # RESEARCH-jargon-reduction
2
-
3
- ## Objective
4
- Analyze the LLMVis project for technical jargon (e.g., "head", "ablation", "tokenizing") that may confuse younger or less technical audiences, and outline plain-English alternatives and explanations. The goal is to make the educational dashboard more accessible without completely losing technical accuracy.
5
-
6
- ## Findings: Jargon in User-Facing Components
7
-
8
- ### 1. "Ablation" / "Ablate"
9
- **Locations found:**
10
- - `app.py`: "Ablation" tab in the Investigation Panel
11
- - `components/ablation_panel.py`: "What is Ablation?", "Add Head to Ablation List", "Run Ablation Experiment", "Ablated Output"
12
-
13
- **Issue:** "Ablation" is a highly specialized term originally from neuroscience/medicine, adapted for machine learning to mean removing a component to observe its effect. It is completely opaque to a layperson.
14
-
15
- **Proposed Replacements:**
16
- - Replace primary "Ablation" headers with "Component Removal" or "Test by Removing".
17
- - Replace "Run Ablation Experiment" with "Test What Happens When Removed".
18
- - Keep "Ablation" only in an advanced glossary, a tooltip or as a secondary subtitle: "Test by Removing (Ablation)".
19
-
20
- ### 2. "Token" / "Tokenization" / "Tokenizing"
21
- **Locations found:**
22
- - `app.py`: "Number of New Tokens"
23
- - `components/pipeline.py`: "Tokenization" pipeline stage, "Your text is split into tokens"
24
- - `components/investigation_panel.py`: "Token Attribution", "Target Token"
25
-
26
- **Issue:** While "token" is explained somewhat in the app ("pieces that the model can understand"), phrases like "Token Attribution" or "Tokenization" sound overly academic as top-level headings.
27
-
28
- **Proposed Replacements:**
29
- - Use "Text Chunking" or "Word Pieces" as the primary heading, introducing "Tokens" as the technical equivalent inside the explanation.
30
- - Change "Token Attribution" to "Which words influenced the answer?" or "Word Influence Score".
31
-
32
- ### 3. "Attention Head" / "Head"
33
- **Locations found:**
34
- - `components/pipeline.py`: "Attention has multiple heads"
35
- - `components/ablation_panel.py`: "Select heads to ablate", "Attention Head Roles"
36
-
37
- **Issue:** "Head" in "Attention Head" is an architectural metaphor that doesn't organically mean anything to someone unfamiliar with the transformer architecture (multi-head attention).
38
-
39
- **Proposed Replacements:**
40
- - Reframe as "Attention Pattern", "Context Detector" or "Feature Spotter".
41
- - Explain "Heads" as "Specialized Detectors" or "Information Filters" (e.g., "The model uses multiple 'Detectors' (called heads) to find relationships...").
42
-
43
- ### 4. "Embedding" / "Vector"
44
- **Locations found:**
45
- - `components/pipeline.py`: "Embedding" stage, "high-dimensional vector", "lookup table"
46
-
47
- **Issue:** "Vector" and "high-dimensional" sound like advanced mathematical phrases which may intimidate a younger user.
48
-
49
- **Proposed Replacements:**
50
- - Instead of "Embedding", use "Meaning Translation" or "Number Dictionary".
51
- - Instead of "high-dimensional vector", use "list of numbers representing meaning".
52
-
53
- ### 5. "MLP" / "Feed-Forward"
54
- **Locations found:**
55
- - `components/pipeline.py`: "MLP (Feed-Forward)", "MLP layers"
56
-
57
- **Issue:** MLP (Multi-Layer Perceptron) is legacy neural network jargon that is not intuitive in the context of what it actually does (storing factual knowledge).
58
-
59
- **Proposed Replacements:**
60
- - Rename the pipeline stage to "Factual Knowledge" or "Memory Layers".
61
- - Include "(MLP/Feed-Forward)" only as a small subtitle for those who want the exact technical term.
62
-
63
- ### 6. "Logit" / "Probability" / "Activation Score"
64
- **Locations found:**
65
- - `components/ablation_panel.py`: "Average prob shift", "activation: 85%"
66
-
67
- **Issue:** Jargon related to raw model outputs. "Activation score" sounds like a futuristic/sci-fi term.
68
-
69
- **Proposed Replacements:**
70
- - "Activation score" -> "Confidence level" or "Strength of focus".
71
- - "Average prob shift" -> "Average change in confidence".
72
-
73
- ## What Was Ruled Out
74
- - **Completely eliminating all technical terms:** We ruled out removing words like "Token" or "Model" entirely because learning some valid terminology is part of the educational value of the tool. Instead, we will prioritize plain English for headings and actions, and introduce the technical terms in parentheses or explanatory sentences.
75
- - **Rewriting the RAG Docs right now:** The `rag_docs/` folder contains extensive markdown documentation. For this primary pass, we ruled out modifying those long-form files, focusing entirely on the primary UI headers, buttons, and short stage descriptions in `app.py` and the `components/` directory to maximize immediate impact.
76
-
77
- ## Next Steps
78
- Review this document. If these jargon replacements aligned with the intended goal for younger audiences, we can draft `SPEC-jargon-reduction.md` with explicit strings to be updated across the application.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py CHANGED
@@ -25,7 +25,7 @@ from utils.token_attribution import compute_integrated_gradients, compute_simple
25
 
26
  # Import modular components
27
  from components.sidebar import create_sidebar
28
- from components.model_selector import create_model_selector
29
  from components.glossary import create_glossary_modal
30
  from components.pipeline import (create_pipeline_container, create_tokenization_content,
31
  create_embedding_content, create_attention_content,
@@ -33,7 +33,7 @@ from components.pipeline import (create_pipeline_container, create_tokenization_
33
  _build_token_display, _build_top5_chart)
34
  from components.investigation_panel import create_investigation_panel, create_attribution_results_display
35
  from components.ablation_panel import create_selected_heads_display, create_ablation_results_display
36
- from components.chatbot import create_chatbot_container, render_messages
37
 
38
  # Initialize Dash app
39
  app = dash.Dash(
@@ -1442,6 +1442,44 @@ app.clientside_callback(
1442
  )
1443
 
1444
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1445
  if __name__ == '__main__':
1446
  # Use 0.0.0.0:7860 for Hugging Face Spaces, fallback to localhost:8050 for local dev
1447
  import os
 
25
 
26
  # Import modular components
27
  from components.sidebar import create_sidebar
28
+ from components.model_selector import create_model_selector, EXAMPLE_PROMPTS
29
  from components.glossary import create_glossary_modal
30
  from components.pipeline import (create_pipeline_container, create_tokenization_content,
31
  create_embedding_content, create_attention_content,
 
33
  _build_token_display, _build_top5_chart)
34
  from components.investigation_panel import create_investigation_panel, create_attribution_results_display
35
  from components.ablation_panel import create_selected_heads_display, create_ablation_results_display
36
+ from components.chatbot import create_chatbot_container, render_messages, SUGGESTED_QUESTIONS
37
 
38
  # Initialize Dash app
39
  app = dash.Dash(
 
1442
  )
1443
 
1444
 
1445
+ # ============================================================================
1446
+ # EXAMPLE PROMPT CHIPS
1447
+ # ============================================================================
1448
+
1449
+ @callback(
1450
+ Output('prompt-input', 'value', allow_duplicate=True),
1451
+ Input({"type": "example-prompt-btn", "index": ALL}, "n_clicks"),
1452
+ prevent_initial_call=True
1453
+ )
1454
+ def fill_prompt_from_chip(n_clicks_list):
1455
+ """Populate the prompt textarea when an example prompt chip is clicked."""
1456
+ if not any(n_clicks_list):
1457
+ return no_update
1458
+ triggered = dash.ctx.triggered_id
1459
+ if triggered and "index" in triggered:
1460
+ return EXAMPLE_PROMPTS[triggered["index"]]["prompt"]
1461
+ return no_update
1462
+
1463
+
1464
+ # ============================================================================
1465
+ # CHAT SUGGESTION CHIPS
1466
+ # ============================================================================
1467
+
1468
+ @callback(
1469
+ Output('chat-input', 'value', allow_duplicate=True),
1470
+ Input({"type": "chat-suggestion-btn", "index": ALL}, "n_clicks"),
1471
+ prevent_initial_call=True
1472
+ )
1473
+ def fill_chat_from_suggestion(n_clicks_list):
1474
+ """Populate the chat textarea when a suggestion chip is clicked."""
1475
+ if not any(n_clicks_list):
1476
+ return no_update
1477
+ triggered = dash.ctx.triggered_id
1478
+ if triggered and "index" in triggered:
1479
+ return SUGGESTED_QUESTIONS[triggered["index"]]
1480
+ return no_update
1481
+
1482
+
1483
  if __name__ == '__main__':
1484
  # Use 0.0.0.0:7860 for Hugging Face Spaces, fallback to localhost:8050 for local dev
1485
  import os
assets/style.css CHANGED
@@ -1566,4 +1566,66 @@ details[open].transformer-layers-container .transformer-layers-summary::before {
1566
  padding: 25px;
1567
  overflow-y: auto;
1568
  flex: 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1569
  }
 
1566
  padding: 25px;
1567
  overflow-y: auto;
1568
  flex: 1;
1569
+ }
1570
+
1571
+ /* ============================================================================
1572
+ EXAMPLE PROMPT CHIPS
1573
+ ============================================================================ */
1574
+
1575
+ .example-prompts-label {
1576
+ font-size: 0.8rem;
1577
+ color: #888;
1578
+ margin-bottom: 6px;
1579
+ }
1580
+
1581
+ .example-prompts-container {
1582
+ display: flex;
1583
+ flex-wrap: wrap;
1584
+ gap: 8px;
1585
+ margin-bottom: 10px;
1586
+ }
1587
+
1588
+ .example-prompt-chip {
1589
+ border-radius: 16px;
1590
+ border: 1px solid #667eea;
1591
+ color: #667eea;
1592
+ background: transparent;
1593
+ padding: 4px 12px;
1594
+ font-size: 0.8rem;
1595
+ cursor: pointer;
1596
+ transition: background-color 0.2s, color 0.2s;
1597
+ }
1598
+
1599
+ .example-prompt-chip:hover {
1600
+ background-color: #667eea;
1601
+ color: white;
1602
+ }
1603
+
1604
+ /* ============================================================================
1605
+ CHAT SUGGESTION CHIPS
1606
+ ============================================================================ */
1607
+
1608
+ .chat-suggestions-container {
1609
+ display: flex;
1610
+ flex-wrap: wrap;
1611
+ gap: 6px;
1612
+ padding: 8px 12px;
1613
+ border-bottom: 1px solid #e9ecef;
1614
+ }
1615
+
1616
+ .chat-suggestion-chip {
1617
+ border-radius: 16px;
1618
+ border: 1px solid #667eea;
1619
+ color: #667eea;
1620
+ background: transparent;
1621
+ padding: 3px 10px;
1622
+ font-size: 0.75rem;
1623
+ cursor: pointer;
1624
+ text-align: left;
1625
+ transition: background-color 0.2s, color 0.2s;
1626
+ }
1627
+
1628
+ .chat-suggestion-chip:hover {
1629
+ background-color: #667eea;
1630
+ color: white;
1631
  }
components/chatbot.py CHANGED
@@ -17,9 +17,16 @@ I can help you understand:
17
  - What various experiments can reveal about model behavior
18
  - General transformer and ML concepts
19
 
20
- Try asking: "What does attention detector 0 in layer 1 do?" or "Why did removing this detector change the output?"
21
  """
22
 
 
 
 
 
 
 
 
23
 
24
  def create_chat_icon():
25
  """
@@ -158,6 +165,15 @@ def create_input_area():
158
  Dash HTML component for input area
159
  """
160
  return html.Div([
 
 
 
 
 
 
 
 
 
161
  html.Div([
162
  dcc.Textarea(
163
  id="chat-input",
 
17
  - What various experiments can reveal about model behavior
18
  - General transformer and ML concepts
19
 
20
+ Try one of the suggestions below, or ask your own question!
21
  """
22
 
23
+ SUGGESTED_QUESTIONS = [
24
+ "Walk me through an example experiment step by step",
25
+ "What prompt should I start with and why?",
26
+ "What can I learn from this dashboard?",
27
+ "What should I look for in the attention patterns?"
28
+ ]
29
+
30
 
31
  def create_chat_icon():
32
  """
 
165
  Dash HTML component for input area
166
  """
167
  return html.Div([
168
+ html.Div([
169
+ html.Button(
170
+ q,
171
+ id={"type": "chat-suggestion-btn", "index": i},
172
+ className="chat-suggestion-chip",
173
+ n_clicks=0
174
+ )
175
+ for i, q in enumerate(SUGGESTED_QUESTIONS)
176
+ ], className="chat-suggestions-container"),
177
  html.Div([
178
  dcc.Textarea(
179
  id="chat-input",
components/model_selector.py CHANGED
@@ -8,6 +8,30 @@ This component provides the interface for:
8
 
9
  from dash import html, dcc
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  # Available models organized by family
12
  AVAILABLE_MODELS = [
13
  # GPT-2 family (OpenAI) — absolute positional encoding, LayerNorm, GELU
@@ -47,6 +71,17 @@ def create_model_selector():
47
  # Prompt input
48
  html.Div([
49
  html.Label("Enter Prompt:", className="input-label"),
 
 
 
 
 
 
 
 
 
 
 
50
  dcc.Textarea(
51
  id='prompt-input',
52
  placeholder="Enter text prompt for analysis...",
 
8
 
9
  from dash import html, dcc
10
 
11
+ # Example prompts for guiding users toward meaningful experiments
12
+ EXAMPLE_PROMPTS = [
13
+ {
14
+ "label": "Track indirect objects",
15
+ "prompt": "The chef gave the waiter a generous tip because",
16
+ "tooltip": "Tests whether the model tracks who gave and who received across clauses"
17
+ },
18
+ {
19
+ "label": "Resolve ambiguity",
20
+ "prompt": "The bat flew over the",
21
+ "tooltip": "Tests how earlier context shapes predictions when a word has multiple meanings (bat)"
22
+ },
23
+ {
24
+ "label": "Understand repetition",
25
+ "prompt": "The cat sat on the mat. The cat sat on the",
26
+ "tooltip": "Activates duplicate-token and induction detectors that complete repeated sequences"
27
+ },
28
+ {
29
+ "label": "Link pronouns",
30
+ "prompt": "The nurse said that she",
31
+ "tooltip": "Tests coreference resolution and reveals gender bias in attention detectors"
32
+ }
33
+ ]
34
+
35
  # Available models organized by family
36
  AVAILABLE_MODELS = [
37
  # GPT-2 family (OpenAI) — absolute positional encoding, LayerNorm, GELU
 
71
  # Prompt input
72
  html.Div([
73
  html.Label("Enter Prompt:", className="input-label"),
74
+ html.Div("Not sure what to prompt? See how models:", className="example-prompts-label"),
75
+ html.Div([
76
+ html.Button(
77
+ p["label"],
78
+ id={"type": "example-prompt-btn", "index": i},
79
+ className="example-prompt-chip",
80
+ title=p["tooltip"],
81
+ n_clicks=0
82
+ )
83
+ for i, p in enumerate(EXAMPLE_PROMPTS)
84
+ ], className="example-prompts-container"),
85
  dcc.Textarea(
86
  id='prompt-input',
87
  placeholder="Enter text prompt for analysis...",
debug_logs.md DELETED
@@ -1,163 +0,0 @@
1
- -------------------------------------------------------
2
- Qwen2ForCausalLM LOAD REPORT from: Qwen/Qwen2.5-0.5B
3
- Key | Status |
4
- ---------------+---------+-
5
- lm_head.weight | MISSING |
6
-
7
- Notes:
8
- - MISSING :those params were newly initialized because missing from the checkpoint. Consider training on your downstream task.
9
- -------------------------------------------------------
10
- Traceback (most recent call last):
11
- File "/app/app.py", line 383, in run_generation
12
- results = perform_beam_search(model, tokenizer, prompt, beam_width, max_new_tokens)
13
- File "/app/utils/beam_search.py", line 142, in perform_beam_search
14
- outputs = model(seq)
15
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1776, in _wrapped_call_impl
16
- return self._call_impl(*args, **kwargs)
17
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1787, in _call_impl
18
- return forward_call(*args, **kwargs)
19
- File "/usr/local/lib/python3.10/site-packages/transformers/utils/generic.py", line 843, in wrapper
20
- output = func(self, *args, **kwargs)
21
- File "/usr/local/lib/python3.10/site-packages/transformers/models/qwen2/modeling_qwen2.py", line 476, in forward
22
- outputs: BaseModelOutputWithPast = self.model(
23
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1776, in _wrapped_call_impl
24
- return self._call_impl(*args, **kwargs)
25
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1787, in _call_impl
26
- return forward_call(*args, **kwargs)
27
- File "/usr/local/lib/python3.10/site-packages/transformers/utils/generic.py", line 917, in wrapper
28
- output = func(self, *args, **kwargs)
29
- File "/usr/local/lib/python3.10/site-packages/transformers/utils/output_capturing.py", line 253, in wrapper
30
- outputs = func(self, *args, **kwargs)
31
- File "/usr/local/lib/python3.10/site-packages/transformers/models/qwen2/modeling_qwen2.py", line 411, in forward
32
- hidden_states = decoder_layer(
33
- File "/usr/local/lib/python3.10/site-packages/transformers/modeling_layers.py", line 93, in __call__
34
- return super().__call__(*args, **kwargs)
35
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1776, in _wrapped_call_impl
36
- return self._call_impl(*args, **kwargs)
37
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1787, in _call_impl
38
- return forward_call(*args, **kwargs)
39
- File "/usr/local/lib/python3.10/site-packages/transformers/models/qwen2/modeling_qwen2.py", line 298, in forward
40
- hidden_states, _ = self.self_attn(
41
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1776, in _wrapped_call_impl
42
- return self._call_impl(*args, **kwargs)
43
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1787, in _call_impl
44
- return forward_call(*args, **kwargs)
45
- File "/usr/local/lib/python3.10/site-packages/transformers/models/qwen2/modeling_qwen2.py", line 218, in forward
46
- query_states = self.q_proj(hidden_states).view(hidden_shape).transpose(1, 2)
47
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1776, in _wrapped_call_impl
48
- return self._call_impl(*args, **kwargs)
49
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/module.py", line 1787, in _call_impl
50
- return forward_call(*args, **kwargs)
51
- File "/usr/local/lib/python3.10/site-packages/torch/nn/modules/linear.py", line 134, in forward
52
- return F.linear(input, self.weight, self.bias)
53
- RuntimeError: mat1 and mat2 must have the same dtype, but got Float and BFloat16
54
- -------------------------------------------------------
55
- Qwen2ForCausalLM LOAD REPORT from: Qwen/Qwen2.5-0.5B
56
- Key | Status |
57
- ---------------+---------+-
58
- lm_head.weight | MISSING |
59
-
60
- Notes:
61
- - MISSING :those params were newly initialized because missing from the checkpoint. Consider training on your downstream task.
62
- 10.16.43.195 - - [19/Mar/2026 19:47:47] "POST /_dash-update-component HTTP/1.1" 200 -
63
- 10.16.43.195 - - [19/Mar/2026 19:47:55] "POST /_dash-update-component HTTP/1.1" 200 -
64
- 10.16.43.195 - - [19/Mar/2026 19:47:55] "POST /_dash-update-component HTTP/1.1" 200 -
65
- Executing forward pass with prompt: 'Draw ascii art for a cat'
66
- Captured 48 module outputs using PyVene
67
- Loading weights: 0%| | 0/290 [00:00<?, ?it/s]10.16.31.44 - - [19/Mar/2026 19:47:55] "POST /_dash-update-component HTTP/1.1" 200 -
68
- [2026-03-19 19:47:55,972] ERROR in app: Exception on /_dash-update-component [POST]
69
- Traceback (most recent call last):
70
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1511, in wsgi_app
71
- response = self.full_dispatch_request()
72
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 919, in full_dispatch_request
73
- rv = self.handle_user_exception(e)
74
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 917, in full_dispatch_request
75
- rv = self.dispatch_request()
76
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 902, in dispatch_request
77
- return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
78
- File "/usr/local/lib/python3.10/site-packages/dash/_get_app.py", line 17, in wrap
79
- return ctx.run(func, self, *args, **kwargs)
80
- File "/usr/local/lib/python3.10/site-packages/dash/dash.py", line 1600, in dispatch
81
- response_data = ctx.run(partial_func)
82
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 720, in add_context
83
- raise err
84
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 711, in add_context
85
- output_value = _invoke_callback(func, *func_args, **func_kwargs) # type: ignore[reportArgumentType]
86
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 58, in _invoke_callback
87
- return func(*args, **kwargs) # %% callback invoked %%
88
- File "/app/app.py", line 1090, in update_attribution_target_options
89
- options.append({'label': f"{t['token']} ({t['probability']:.1%})", 'value': t['token']})
90
- TypeError: unsupported format string passed to NoneType.__format__
91
- -------------------------------------------------------
92
- DEBUG extract_layer_data: Found 24 attention modules
93
- Loading model: gpt2-medium
94
- Loading weights: 0%| | 0/292 [00:00<?, ?it/s]
95
- Loading weights: 51%|█████ | 149/292 [00:00<00:00, 1299.04it/s]
96
- Loading weights: 100%|██████████| 292/292 [00:00<00:00, 1450.02it/s]
97
- GPT2LMHeadModel LOAD REPORT from: gpt2-medium
98
- Key | Status |
99
- ---------------+---------+-
100
- lm_head.weight | MISSING |
101
-
102
- Notes:
103
- - MISSING :those params were newly initialized because missing from the checkpoint. Consider training on your downstream task.
104
- -------------------------------------------------------
105
- 10.16.43.195 - - [19/Mar/2026 20:11:03] "POST /_dash-update-component HTTP/1.1" 200 -
106
- [2026-03-19 20:11:03,238] ERROR in app: Exception on /_dash-update-component [POST]
107
- Traceback (most recent call last):
108
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 1511, in wsgi_app
109
- response = self.full_dispatch_request()
110
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 919, in full_dispatch_request
111
- rv = self.handle_user_exception(e)
112
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 917, in full_dispatch_request
113
- rv = self.dispatch_request()
114
- File "/usr/local/lib/python3.10/site-packages/flask/app.py", line 902, in dispatch_request
115
- return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return]
116
- File "/usr/local/lib/python3.10/site-packages/dash/_get_app.py", line 17, in wrap
117
- return ctx.run(func, self, *args, **kwargs)
118
- File "/usr/local/lib/python3.10/site-packages/dash/dash.py", line 1600, in dispatch
119
- response_data = ctx.run(partial_func)
120
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 720, in add_context
121
- raise err
122
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 711, in add_context
123
- output_value = _invoke_callback(func, *func_args, **func_kwargs) # type: ignore[reportArgumentType]
124
- File "/usr/local/lib/python3.10/site-packages/dash/_callback.py", line 58, in _invoke_callback
125
- return func(*args, **kwargs) # %% callback invoked %%
126
- File "/app/app.py", line 1090, in update_attribution_target_options
127
- options.append({'label': f"{t['token']} ({t['probability']:.1%})", 'value': t['token']})
128
- TypeError: unsupported format string passed to NoneType.__format__
129
- 10.16.43.195 - - [19/Mar/2026 20:11:03] "POST /_dash-update-component HTTP/1.1" 500 -
130
- 10.16.43.195 - - [19/Mar/2026 20:11:03] "POST /_dash-update-component HTTP/1.1" 200 -
131
- Traceback (most recent call last):
132
- File "/app/utils/model_patterns.py", line 1337, in generate_bertviz_html
133
- attention_weights = torch.tensor(attention_output[1]) # [batch, heads, seq, seq]
134
- RuntimeError: Could not infer dtype of NoneType
135
- Traceback (most recent call last):
136
- File "/app/app.py", line 691, in update_pipeline_content
137
- outputs.append(create_output_content(
138
- File "/app/components/pipeline.py", line 1130, in create_output_content
139
- text=[f"{p:.1%}" for p in probs], textposition='outside',
140
- File "/app/components/pipeline.py", line 1130, in <listcomp>
141
- text=[f"{p:.1%}" for p in probs], textposition='outside',
142
- TypeError: unsupported format string passed to NoneType.__format__
143
- -------------------------------------------------------
144
- 10.16.43.195 - - [19/Mar/2026 20:26:26] "POST /_dash-update-component HTTP/1.1" 200 -
145
- DEBUG extract_layer_data: Found 24 attention modules
146
- Warning: Could not compute logit lens for gpt_neox.layers.0: mixed dtype (CPU): expect parameter to have scalar type of Float
147
- Warning: Could not compute token probabilities for gpt_neox.layers.0: mixed dtype (CPU): expect parameter to have scalar type of Float
148
- Warning: Could not compute logit lens for gpt_neox.layers.1: mixed dtype (CPU): expect parameter to have scalar type of Float
149
- Warning: Could not compute token probabilities for gpt_neox.layers.1: mixed dtype (CPU): expect parameter to have scalar type of Float
150
- Warning: Could not compute logit lens for gpt_neox.layers.2: mixed dtype (CPU): expect parameter to have scalar type of Float
151
- Warning: Could not compute token probabilities for gpt_neox.layers.2: mixed dtype (CPU): expect parameter to have scalar type of Float
152
- -------------------------------------------------------
153
- Warning: Could not compute logit lens for gpt_neox.layers.13: mixed dtype (CPU): expect parameter to have scalar type of Float
154
- Warning: Could not compute token probabilities for gpt_neox.layers.13: mixed dtype (CPU): expect parameter to have scalar type of Float
155
- Warning: Could not compute logit lens for gpt_neox.layers.14: Could not infer dtype of NoneType
156
- Warning: Could not compute token probabilities for gpt_neox.layers.14: Could not infer dtype of NoneType
157
- Warning: Could not compute logit lens for gpt_neox.layers.15: Could not infer dtype of NoneType
158
- Warning: Could not compute token probabilities for gpt_neox.layers.15: Could not infer dtype of NoneType
159
- Warning: Could not compute logit lens for gpt_neox.layers.16: Could not infer dtype of NoneType
160
- Warning: Could not compute token probabilities for gpt_neox.layers.16: Could not infer dtype of NoneType
161
- Warning: Could not compute logit lens for gpt_neox.layers.17: Could not infer dtype of NoneType
162
- Warning: Could not compute token probabilities for gpt_neox.layers.17: Could not infer dtype of NoneType
163
- -------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
plans.md CHANGED
@@ -1,16 +1,3 @@
1
- To Do:
2
- - clicking send in the chatbot doesn't immediately show the purple text bubble from the user and the typing animation, there are a couple seconds of nothing. It should immediately populate the text bubble and start the typing animation
3
-
4
- Done:
5
- - change attention to entire generated sequence
6
- - change width of chatbot window
7
- - add output token generation to attention, tokenization, etc
8
- - output slider to look at each token (scrubber with top-5 at each position)
9
- - experiment results side by side comparison
10
- - output streaming for chatbot
11
- - shorter, concise responses in system prompt
12
- - add video links to glossary
13
- - three blue one brown
14
- - specs on what each attention head does
15
- - generating with 1 output token doesn't show the "selected" beam, so users can't see the output from the model
16
- - add head index numbers to color swatches in BertViz visualization graph
 
1
+ - make it more obvious that this is an experiment (pre-loaded things to ask)
2
+ - make sure chatbot explains simpler
3
+ - glossary button move
 
 
 
 
 
 
 
 
 
 
 
 
 
todo.md DELETED
@@ -1,227 +0,0 @@
1
- # Todo
2
-
3
- ## Completed: Test Suite Setup (Done)
4
- - [x] Create `tests/` folder with `__init__.py` and `conftest.py` (shared fixtures)
5
- - [x] Create `test_model_config.py` - 15 tests for model family lookups
6
- - [x] Create `test_ablation_metrics.py` - 8 tests for KL divergence and probability deltas
7
- - [x] Create `test_head_detection.py` - 20 tests for attention head categorization
8
- - [x] Create `test_model_patterns.py` - 16 tests for merge_token_probabilities, safe_to_serializable
9
- - [x] Create `test_token_attribution.py` - 11 tests for visualization data formatting
10
- - [x] Verify all 73 tests pass with `pytest tests/ -v`
11
-
12
- ## Completed: Pipeline Explanation Refactor
13
-
14
- ### Phase 1: New Components (Done)
15
- - [x] Create `components/pipeline.py` with 5 expandable stages
16
- - [x] Create `utils/token_attribution.py` with Integrated Gradients
17
- - [x] Create `components/investigation_panel.py` (ablation + attribution)
18
-
19
- ### Phase 2: Simplifications (Done)
20
- - [x] Remove comparison UI from `model_selector.py`
21
- - [x] Refactor `app.py`: wire pipeline, remove heatmap/comparison callbacks
22
-
23
- ### Phase 3: Cleanup (Done)
24
- - [x] Delete `main_panel.py`
25
- - [x] Delete `prompt_comparison.py`
26
- - [x] Update `utils/__init__.py` exports
27
- - [x] Add pipeline CSS styles to `assets/style.css`
28
-
29
- ## Completed: Pipeline Clarity Improvements (Agent A)
30
-
31
- - [x] Rename "Max New Tokens:" to "Number of New Tokens:" in app.py
32
- - [x] Rename "Beam Width:" to "Number of Generation Choices:" in app.py
33
- - [x] Remove score display from generated sequences in app.py
34
- - [x] Update glossary to clarify "Number of Generation Choices" relates to Beam Search
35
-
36
- ## Completed: Pipeline Clarity Improvements (Agent E)
37
-
38
- - [x] Modified output display to show full prompt with predicted token highlighted
39
- - [x] Fixed top-5 tokens hover to show "Token (X%)" format instead of long decimals
40
- - [x] Added Plotly hovertemplate for cleaner hover formatting
41
-
42
- ## Completed: Pipeline Clarity Improvements (Agent C)
43
-
44
- - [x] Add educational explanation for embedding stage (pre-learned lookup table concept)
45
- - [x] Add educational explanation for MLP stage (knowledge storage during training)
46
- - [x] Add educational explanation for attention stage (how to interpret BertViz visualization)
47
-
48
- ## Completed: Pipeline Clarity Improvements (Agent B)
49
-
50
- - [x] Convert tokenization from horizontal three-column layout to vertical rows
51
- - [x] Each token row shows: [token] → [ID] → [embedding placeholder]
52
- - [x] Maintain existing color scheme and educational tooltips
53
- - [x] Update CSS styles for .tokenization-rows and .token-row layout
54
- - [x] Add responsive styles for mobile (stack on small screens)
55
-
56
- ## Completed: Pipeline Clarity Improvements (Agent D)
57
-
58
- - [x] Switch generate_bertviz_html from model_view to head_view in model_patterns.py
59
- - [x] Deprecate _get_top_attended_tokens function (remove usage in extract_layer_data)
60
- - [x] Add generate_head_view_with_categories function for categorized attention heads
61
- - [x] Add get_head_category_counts helper function for UI display
62
- - [x] Run tests to verify no regressions (73 tests pass)
63
-
64
- ## Completed: Pipeline Clarity Improvements (Agent F - Analysis Scope)
65
-
66
- - [x] Add session-original-prompt-store and session-selected-beam-store to app.py
67
- - [x] Modify run_generation to analyze ORIGINAL PROMPT only (not generated beam)
68
- - [x] Store beam generation results separately for post-experiment comparison
69
- - [x] Update analyze_selected_sequence to store beam for comparison instead of re-analyzing
70
- - [x] Update ablation experiment to show selected beam context in results
71
-
72
- ## Completed: Pipeline Clarity Improvements (Agent G - Integration & Attention UI)
73
-
74
- - [x] Remove deprecated "Most attended tokens" section from attention stage
75
- - [x] Wire head categorization into attention stage UI (shows category counts)
76
- - [x] Add enhanced navigation instructions for BertViz head view
77
- - [x] Verify all 73 tests pass
78
-
79
- ## Completed: UI/UX Fixes (5 Issues)
80
-
81
- ### Issue 1: "Select for Comparison" Button
82
- - [x] Update store_selected_beam callback in app.py to update UI
83
- - [x] Clear all other generated sequences when one is selected
84
- - [x] Display selected sequence with "Selected for Comparison" badge
85
-
86
- ### Issue 2: Tokenization Vertical Layout
87
- - [x] Modify create_tokenization_content in pipeline.py to use vertical layout
88
- - [x] Each row displays: [token] → [ID] with header row
89
-
90
- ### Issue 3: Expandable Attention Categories
91
- - [x] Convert category chips to expandable `<details>` elements in pipeline.py
92
- - [x] Update app.py to pass full categorize_all_heads() data instead of counts
93
- - [x] Show list of heads (L0-H3, L2-H5, etc.) when category is expanded
94
-
95
- ### Issue 4: BertViz Navigation Instructions
96
- - [x] Add single-click explanation: selects/deselects that head
97
- - [x] Add double-click explanation: selects only that head (deselects others)
98
-
99
- ### Issue 5: Multi-Layer Ablation Head Selection
100
- - [x] Change ablation-selected-heads store to hold [{layer, head}, ...] objects
101
- - [x] Add create_selected_heads_display function in investigation_panel.py
102
- - [x] Show selected heads as chips with "x" buttons to remove
103
- - [x] Update head buttons to show visual selection state per layer
104
- - [x] Preserve selections across layer dropdown changes
105
- - [x] Update run_ablation_experiment to handle multi-layer ablation
106
- - [x] Verify all 73 tests pass
107
-
108
- ## Completed: Fix Multi-Layer Ablation Bug
109
-
110
- - [x] Create `execute_forward_pass_with_multi_layer_head_ablation` in model_patterns.py
111
- - [x] Export new function in utils/__init__.py
112
- - [x] Replace per-layer ablation loop in app.py with single call to new function
113
- - [x] Add 5 tests for multi-layer ablation in test_model_patterns.py
114
- - [x] Verify all 78 tests pass
115
-
116
- ## Completed: Codebase Cleanup
117
-
118
- - [x] Delete unused file: `components/tokenization_panel.py` (302 lines, 6 functions)
119
- - [x] Remove 6 unused imports from `app.py`
120
- - [x] Remove deprecated `_get_top_attended_tokens()` function from model_patterns.py
121
- - [x] Remove `top_attended_tokens` field from extract_layer_data() return values
122
- - [x] Remove unused `create_stage_summary()` function from pipeline.py
123
- - [x] Remove 7 unused utility functions from utils/:
124
- - `get_check_token_probabilities`
125
- - `execute_forward_pass_with_layer_ablation`
126
- - `generate_category_bertviz_html`
127
- - `generate_head_view_with_categories`
128
- - `compute_sequence_trajectory`
129
- - `compute_layer_wise_summaries`
130
- - `compute_position_layer_matrix`
131
- - [x] Update `utils/__init__.py` exports
132
- - [x] Update README.md to remove reference to deleted file
133
-
134
- ## Completed: AI Chatbot Integration
135
-
136
- - [x] Create `rag_docs/` folder with placeholder README for RAG documents
137
- - [x] Create `utils/gemini_client.py` with Gemini API wrapper (generate + embed)
138
- - [x] Create `utils/rag_utils.py` with document loading, chunking, and retrieval
139
- - [x] Create `components/chatbot.py` with UI components (icon, window, messages)
140
- - [x] Add chatbot CSS to `assets/style.css` (floating button, chat window, message bubbles)
141
- - [x] Modify `app.py` to add chat layout and callbacks
142
- - [x] Add `google-generativeai` to `requirements.txt`
143
- - [x] Test end-to-end: toggle, message send, context awareness
144
- - [x] Verify all 81 tests pass
145
-
146
- ## Completed: Hugging Face Deployment Prep
147
-
148
- - [x] Create `.gitignore` to exclude `.env`, `__pycache__/`, etc.
149
- - [x] Add `load_dotenv()` to `app.py` for local development
150
- - [x] Create `tests/test_gemini_connection.py` to verify API key connectivity
151
- - [x] Tests verify: API key is set, can list models, flash model available
152
- - Note: On Hugging Face Spaces, set `GEMINI_API_KEY` in Repository Secrets
153
-
154
- ## Completed: Migrate to New Google GenAI SDK (Superseded)
155
-
156
- - [x] Update `requirements.txt`: `google-generativeai` → `google-genai>=1.0.0`
157
- - [x] Rewrite `utils/gemini_client.py` using new centralized Client architecture
158
- - [x] All 4 connection tests pass
159
- - [x] Verified: embeddings work (3072 dimensions), chat generation works
160
-
161
- ## Completed: Migrate from Gemini to OpenRouter
162
-
163
- - [x] Create `utils/openrouter_client.py` with OpenAI-compatible API
164
- - Global model config: `DEFAULT_CHAT_MODEL` and `DEFAULT_EMBEDDING_MODEL`
165
- - Chat via: `POST /api/v1/chat/completions`
166
- - Embeddings via: `POST /api/v1/embeddings`
167
- - [x] Update `utils/rag_utils.py` imports to use openrouter_client
168
- - [x] Update `app.py` imports to use openrouter_client
169
- - [x] Create `tests/test_openrouter_connection.py` for API connectivity tests
170
- - [x] Delete old `utils/gemini_client.py` and `tests/test_gemini_connection.py`
171
- - [x] Update `requirements.txt`: remove `google-genai`, add `requests>=2.28.0`
172
- - [x] Environment variable: `GEMINI_API_KEY` → `OPENROUTER_API_KEY`
173
-
174
- ## Completed: Switch to Paid OpenRouter Models (Cost-Optimized)
175
-
176
- - [x] Evaluate OpenRouter models for chatbot use case (cost vs quality)
177
- - [x] Switch chat model: `google/gemini-2.5-flash-lite`
178
- - $0.10/$0.40 per 1M tokens (input/output)
179
- - 1M context window, 318 tok/s, multimodal
180
- - [x] Switch embedding model: `openai/text-embedding-3-small`
181
- - $0.02 per 1M tokens
182
- - 1536 dimensions, high quality
183
- - [x] Remove local `sentence-transformers` dependency (simpler, no TF conflicts)
184
- - [x] Estimated cost: ~$1.50/month for moderate usage
185
-
186
- ## Completed: Enhance RAG Documents for Chatbot
187
-
188
- - [x] Category 1: 8 general LLM/Transformer knowledge files (what_is_an_llm.md through key_terminology.md)
189
- - [x] Category 2: 7 dashboard component documentation files (dashboard_overview.md through model_selector_guide.md)
190
- - [x] Category 3: 3 model-specific documentation files (gpt2_overview.md, llama_overview.md, opt_overview.md)
191
- - [x] Category 4: 6 step-by-step guided experiment files (experiment_first_analysis.md through experiment_beam_search.md)
192
- - [x] Category 5: 6 interpretation/troubleshooting/research files (interpreting_*.md, troubleshooting_and_faq.md, recommended_starting_points.md, mechanistic_interpretability_intro.md)
193
- - [x] Delete embeddings_cache.json, update rag_docs/README.md with full inventory
194
- - [x] Update todo.md and conductor docs
195
- - Total: 30 RAG documents covering transformer concepts, dashboard usage, guided experiments, interpretation, troubleshooting, and research context
196
-
197
- ## Completed: Resizable Chat Window
198
-
199
- - [x] Add drag handle div to left edge of chat window in chatbot.py
200
- - [x] Add CSS for `.chat-resize-handle` (cursor, hover highlight) in style.css
201
- - [x] Add `assets/chat_resize.js` for mousedown/mousemove/mouseup drag logic
202
- - Default size unchanged (25vw, 320px–450px); drag overrides max-width up to 80vw
203
-
204
- ## Completed: Full-Sequence Attention Visualization
205
-
206
- - [x] Modified `run_generation()` in app.py: for single-token generation, run forward pass on full beam text (prompt + generated token) instead of prompt only
207
- - [x] Enhanced `store_selected_beam()` in app.py: added `session-activation-store` output and `session-activation-store` State; re-runs `execute_forward_pass()` on selected beam's full text when user picks a beam
208
- - [x] Added 5 tests in `test_model_patterns.py` (`TestFullSequenceAttentionData`) verifying attention matrix dimensions match full sequence length
209
- - Attention visualization now covers the entire chosen output (input + generated tokens), not just the input prompt
210
- - No changes needed in `model_patterns.py`, `beam_search.py`, `pipeline.py`, or `head_detection.py`
211
-
212
- ## Completed: Output Token Scrubber
213
-
214
- - [x] Add `compute_per_position_top5()` to `utils/model_patterns.py` — extracts top-5 next-token probabilities at each generated-token position from a single forward pass
215
- - [x] Add `original_prompt` parameter to `execute_forward_pass()` — when provided, computes per-position top-5 data and stores in activation_data
216
- - [x] Export `compute_per_position_top5` in `utils/__init__.py`
217
- - [x] Update `run_generation()` in app.py — passes `original_prompt=prompt` for single-token generation
218
- - [x] Update `store_selected_beam()` in app.py — reads original prompt from session store and passes to forward pass
219
- - [x] Rewrite `create_output_content()` in `components/pipeline.py` — scrubber mode with `dcc.Slider`, token display, and top-5 chart; falls back to static mode when no per-position data
220
- - [x] Add `_build_token_display()` and `_build_top5_chart()` helpers in pipeline.py
221
- - [x] Add `update_output_scrubber()` callback in app.py — responds to slider changes, updates token highlight and chart
222
- - [x] Update `update_pipeline_content()` in app.py — extracts per-position data and passes to output content
223
- - [x] Add 10 tests for `compute_per_position_top5` in `test_model_patterns.py`
224
- - [x] Fix `conftest.py` to set `USE_TF=0` for test import compatibility
225
- - [x] All 100 tests pass
226
- - Scrubber shows prompt context (gray) + highlighted token (cyan) + top-5 bar chart at each slider position
227
- - Pre-beam-selection falls back to static output display; scrubber activates after beam selection or single-token generation