Spaces:
Sleeping
Sleeping
Commit ·
42ae447
1
Parent(s): 96418df
Moved glossary button to header instead of hidden in sidebar
Browse files- .claude/settings.local.json +2 -1
- .context/data/decisions.md +8 -0
- .context/data/lessons.md +6 -0
- .context/data/sessions.md +7 -0
- app.py +10 -3
- assets/style.css +24 -0
- components/sidebar.py +0 -10
.claude/settings.local.json
CHANGED
|
@@ -11,7 +11,8 @@
|
|
| 11 |
"Bash(python3:*)",
|
| 12 |
"Bash(find /c/Users/cdpea/OneDrive/Documents/GradProject/.context -type f -name *.md)",
|
| 13 |
"Bash(wc:*)",
|
| 14 |
-
"Bash(ls -la /c/Users/cdpea/OneDrive/Documents/GradProject/utils/*.py)"
|
|
|
|
| 15 |
]
|
| 16 |
}
|
| 17 |
}
|
|
|
|
| 11 |
"Bash(python3:*)",
|
| 12 |
"Bash(find /c/Users/cdpea/OneDrive/Documents/GradProject/.context -type f -name *.md)",
|
| 13 |
"Bash(wc:*)",
|
| 14 |
+
"Bash(ls -la /c/Users/cdpea/OneDrive/Documents/GradProject/utils/*.py)",
|
| 15 |
+
"WebSearch"
|
| 16 |
]
|
| 17 |
}
|
| 18 |
}
|
.context/data/decisions.md
CHANGED
|
@@ -66,3 +66,11 @@
|
|
| 66 |
**Decision**: Option 2 — `load_model_for_inference()` in model_patterns.py, forces float32 and verifies weight tying
|
| 67 |
**Reasoning**: 6 call sites meant high risk of missing one; central helper is DRY and adds weight-tying safety net for tied-weight models
|
| 68 |
**Revisit if**: GPU deployment makes float16/bfloat16 desirable for performance
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
**Decision**: Option 2 — `load_model_for_inference()` in model_patterns.py, forces float32 and verifies weight tying
|
| 67 |
**Reasoning**: 6 call sites meant high risk of missing one; central helper is DRY and adds weight-tying safety net for tied-weight models
|
| 68 |
**Revisit if**: GPU deployment makes float16/bfloat16 desirable for performance
|
| 69 |
+
|
| 70 |
+
## Dedicated store for ablation results instead of overwriting pipeline store
|
| 71 |
+
**Date**: 2026-03-31
|
| 72 |
+
**Context**: Ablation experiment wrote ablated data to `session-activation-store`, causing the pipeline to silently re-render with ablated visuals
|
| 73 |
+
**Options considered**: (1) Stop writing to pipeline store and use `no_update` (ablation panel loses data source), (2) Repurpose `session-activation-store-original` for ablated data (conflicts with scrubber's original-data read), (3) Add new `session-ablation-results-store` dedicated to ablation
|
| 74 |
+
**Decision**: Option 3 — new `session-ablation-results-store`
|
| 75 |
+
**Reasoning**: Clean separation of concerns. Pipeline store is never polluted. Scrubber reads original from `-original` and ablated from the new store. Reset just clears the new store. Only app.py changes, no component changes needed.
|
| 76 |
+
**Revisit if**: More experiment types are added that also need separate result storage — may want a generalized experiment-results store pattern
|
.context/data/lessons.md
CHANGED
|
@@ -32,3 +32,9 @@
|
|
| 32 |
**Root cause**: `get_active_head_summary()` returns categories with key `'heads'`, but the raw JSON file (`head_categories.json`) uses `'top_heads'`. Code in app.py used the raw key against the enriched object.
|
| 33 |
**Fix**: Changed `cat_data.get('top_heads', [])` to `cat_data.get('heads', [])` in app.py
|
| 34 |
**Rule going forward**: When consuming data from a helper function, check the helper's return schema — don't assume it mirrors the raw data file's keys.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
**Root cause**: `get_active_head_summary()` returns categories with key `'heads'`, but the raw JSON file (`head_categories.json`) uses `'top_heads'`. Code in app.py used the raw key against the enriched object.
|
| 33 |
**Fix**: Changed `cat_data.get('top_heads', [])` to `cat_data.get('heads', [])` in app.py
|
| 34 |
**Rule going forward**: When consuming data from a helper function, check the helper's return schema — don't assume it mirrors the raw data file's keys.
|
| 35 |
+
|
| 36 |
+
## 2026-03-31 — Shared dcc.Store as implicit coupling between unrelated callbacks
|
| 37 |
+
**What happened**: Running an ablation experiment silently replaced the pipeline's data, making it show ablated visuals without any indication
|
| 38 |
+
**Root cause**: `run_ablation_experiment()` wrote its results to `session-activation-store` — the same store the pipeline reads from. This was intentional (to show ablated state in the pipeline) but wrong (pipeline should always show original data). The "reset" mechanism papered over the issue.
|
| 39 |
+
**Fix**: Added a dedicated `session-ablation-results-store` so ablation results never touch the pipeline's data source
|
| 40 |
+
**Rule going forward**: When a callback produces data for a specific panel/feature, use a dedicated store rather than overwriting a shared store that other callbacks depend on. Shared stores create invisible coupling.
|
.context/data/sessions.md
CHANGED
|
@@ -47,3 +47,10 @@
|
|
| 47 |
**Decisions made**: Specs live in `docs/`; checkpoint and lessons auto-invokable, spec manual-only; neutral session tone.
|
| 48 |
**Memory created**: Skills section and Spec Workflow section in CLAUDE.md; `docs/` directory
|
| 49 |
**Open threads**: None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
**Decisions made**: Specs live in `docs/`; checkpoint and lessons auto-invokable, spec manual-only; neutral session tone.
|
| 48 |
**Memory created**: Skills section and Spec Workflow section in CLAUDE.md; `docs/` directory
|
| 49 |
**Open threads**: None
|
| 50 |
+
|
| 51 |
+
## 2026-03-31 — Fix Ablation Data Leaking into Pipeline Visuals
|
| 52 |
+
**Area**: State management, ablation callbacks (app.py)
|
| 53 |
+
**Work done**: Diagnosed and fixed bug where pipeline visuals silently switched to ablated data after running an ablation experiment. Root cause: `run_ablation_experiment()` wrote ablated data to `session-activation-store`, which the pipeline listens to. Fix: added a dedicated `session-ablation-results-store` so ablated data never touches the pipeline's data source. Simplified `reset_ablation()` (no longer needs to restore from backup). 6 surgical edits in app.py, no other files changed. All 120 tests pass.
|
| 54 |
+
**Decisions made**: Used new dedicated store over repurposing existing stores
|
| 55 |
+
**Memory created**: None
|
| 56 |
+
**Open threads**: Needs manual verification (5 test scenarios in plan)
|
app.py
CHANGED
|
@@ -72,9 +72,16 @@ app.layout = html.Div([
|
|
| 72 |
html.Div([
|
| 73 |
# Header
|
| 74 |
html.Div([
|
| 75 |
-
html.
|
| 76 |
-
|
| 77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
], className="header"),
|
| 79 |
|
| 80 |
# Main content area
|
|
|
|
| 72 |
html.Div([
|
| 73 |
# Header
|
| 74 |
html.Div([
|
| 75 |
+
html.Div([
|
| 76 |
+
html.H1("Transformer Explanation Dashboard", className="header-title"),
|
| 77 |
+
html.P("Understand how transformer models process text and make predictions",
|
| 78 |
+
className="header-subtitle")
|
| 79 |
+
], className="header-text"),
|
| 80 |
+
html.Button(
|
| 81 |
+
[html.I(className="fas fa-book", style={'marginRight': '8px'}), "Glossary"],
|
| 82 |
+
id="open-glossary-btn",
|
| 83 |
+
className="header-glossary-btn",
|
| 84 |
+
)
|
| 85 |
], className="header"),
|
| 86 |
|
| 87 |
# Main content area
|
assets/style.css
CHANGED
|
@@ -31,7 +31,14 @@ body {
|
|
| 31 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 32 |
color: white;
|
| 33 |
padding: 2rem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
text-align: center;
|
|
|
|
| 35 |
}
|
| 36 |
|
| 37 |
.header-title {
|
|
@@ -45,6 +52,23 @@ body {
|
|
| 45 |
opacity: 0.9;
|
| 46 |
}
|
| 47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
/* Content container */
|
| 49 |
.content-container {
|
| 50 |
display: flex;
|
|
|
|
| 31 |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 32 |
color: white;
|
| 33 |
padding: 2rem;
|
| 34 |
+
display: flex;
|
| 35 |
+
align-items: center;
|
| 36 |
+
justify-content: space-between;
|
| 37 |
+
}
|
| 38 |
+
|
| 39 |
+
.header-text {
|
| 40 |
text-align: center;
|
| 41 |
+
flex: 1;
|
| 42 |
}
|
| 43 |
|
| 44 |
.header-title {
|
|
|
|
| 52 |
opacity: 0.9;
|
| 53 |
}
|
| 54 |
|
| 55 |
+
.header-glossary-btn {
|
| 56 |
+
background: rgba(255, 255, 255, 0.15);
|
| 57 |
+
color: white;
|
| 58 |
+
border: 1px solid rgba(255, 255, 255, 0.4);
|
| 59 |
+
padding: 0.5rem 1rem;
|
| 60 |
+
border-radius: 6px;
|
| 61 |
+
cursor: pointer;
|
| 62 |
+
font-size: 0.9rem;
|
| 63 |
+
white-space: nowrap;
|
| 64 |
+
transition: background 0.2s;
|
| 65 |
+
flex-shrink: 0;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
.header-glossary-btn:hover {
|
| 69 |
+
background: rgba(255, 255, 255, 0.3);
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
/* Content container */
|
| 73 |
.content-container {
|
| 74 |
display: flex;
|
components/sidebar.py
CHANGED
|
@@ -23,16 +23,6 @@ def create_sidebar():
|
|
| 23 |
|
| 24 |
# Sidebar content (hidden when collapsed)
|
| 25 |
html.Div([
|
| 26 |
-
# Help / Glossary Button
|
| 27 |
-
html.Div([
|
| 28 |
-
html.Button(
|
| 29 |
-
[html.I(className="fas fa-book", style={'marginRight': '8px'}), "Glossary"],
|
| 30 |
-
id="open-glossary-btn",
|
| 31 |
-
className="action-button secondary-button",
|
| 32 |
-
style={'marginBottom': '1rem', 'width': '100%'}
|
| 33 |
-
)
|
| 34 |
-
]),
|
| 35 |
-
|
| 36 |
html.H3("Module Selection", className="sidebar-title"),
|
| 37 |
html.P("Advanced: Select which model components to inspect. "
|
| 38 |
"The defaults work well for most explorations.",
|
|
|
|
| 23 |
|
| 24 |
# Sidebar content (hidden when collapsed)
|
| 25 |
html.Div([
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
html.H3("Module Selection", className="sidebar-title"),
|
| 27 |
html.P("Advanced: Select which model components to inspect. "
|
| 28 |
"The defaults work well for most explorations.",
|