open-interpretability 0.0.20__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- open_interpretability-0.0.20.dist-info/METADATA +157 -0
- open_interpretability-0.0.20.dist-info/RECORD +256 -0
- open_interpretability-0.0.20.dist-info/WHEEL +4 -0
- open_interpretability-0.0.20.dist-info/entry_points.txt +2 -0
- open_interpretability-0.0.20.dist-info/licenses/LICENSE +21 -0
- openinterp/__init__.py +6 -0
- openinterp/agents/__init__.py +25 -0
- openinterp/agents/base.py +229 -0
- openinterp/agents/judge.py +149 -0
- openinterp/agents/proposer.py +471 -0
- openinterp/agents/proposer_profiles.py +79 -0
- openinterp/agents/review_measurements.py +173 -0
- openinterp/agents/reviewer.py +498 -0
- openinterp/agreement.py +63 -0
- openinterp/audit_options.py +79 -0
- openinterp/baseline.py +254 -0
- openinterp/benchmark.py +450 -0
- openinterp/blends.py +239 -0
- openinterp/builder/__init__.py +6 -0
- openinterp/builder/agents.py +260 -0
- openinterp/builder/aligned.py +41 -0
- openinterp/builder/charts.py +411 -0
- openinterp/builder/circuit_pages.py +37 -0
- openinterp/builder/circuits.py +264 -0
- openinterp/builder/compiler.py +495 -0
- openinterp/builder/corpora.py +98 -0
- openinterp/builder/coverage.py +46 -0
- openinterp/builder/dashboard.py +255 -0
- openinterp/builder/disk_memo.py +65 -0
- openinterp/builder/experiment.py +105 -0
- openinterp/builder/heat.py +121 -0
- openinterp/builder/hrefs.py +71 -0
- openinterp/builder/learned_baseline.py +204 -0
- openinterp/builder/model_facts.py +138 -0
- openinterp/builder/neuronpedia_export.py +107 -0
- openinterp/builder/parallel.py +100 -0
- openinterp/builder/parquet_export.py +458 -0
- openinterp/builder/pieces.py +127 -0
- openinterp/builder/pii.py +211 -0
- openinterp/builder/registry_stats.py +144 -0
- openinterp/builder/research.py +109 -0
- openinterp/builder/sections.py +28 -0
- openinterp/builder/significance.py +103 -0
- openinterp/builder/sister_graph.py +180 -0
- openinterp/builder/standing.py +185 -0
- openinterp/builder/statuses.py +34 -0
- openinterp/builder/stopped.py +91 -0
- openinterp/builder/stops.py +30 -0
- openinterp/builder/superpositions.py +102 -0
- openinterp/builder/templates/_agent_role_cells.html +9 -0
- openinterp/builder/templates/_causal_chart.html +67 -0
- openinterp/builder/templates/_circuit.html +8 -0
- openinterp/builder/templates/_dashboard.html +133 -0
- openinterp/builder/templates/_experiment.html +500 -0
- openinterp/builder/templates/_macros.html +82 -0
- openinterp/builder/templates/_patchscope.html +33 -0
- openinterp/builder/templates/_prior_art.html +24 -0
- openinterp/builder/templates/_specificity.html +21 -0
- openinterp/builder/templates/_steering.html +34 -0
- openinterp/builder/templates/_superposition.html +62 -0
- openinterp/builder/templates/_vocab_chart.html +88 -0
- openinterp/builder/templates/_wiring.html +44 -0
- openinterp/builder/templates/about.html +95 -0
- openinterp/builder/templates/agent.html +69 -0
- openinterp/builder/templates/agents.html +80 -0
- openinterp/builder/templates/base.html +103 -0
- openinterp/builder/templates/circuit.html +64 -0
- openinterp/builder/templates/circuits.html +46 -0
- openinterp/builder/templates/experiment.html +21 -0
- openinterp/builder/templates/hub.html +16 -0
- openinterp/builder/templates/index.html +387 -0
- openinterp/builder/templates/layer.html +69 -0
- openinterp/builder/templates/learned-baseline.html +44 -0
- openinterp/builder/templates/model.html +151 -0
- openinterp/builder/templates/models.html +47 -0
- openinterp/builder/templates/neuron.html +234 -0
- openinterp/builder/templates/paper.html +39 -0
- openinterp/builder/templates/redirect.html +1 -0
- openinterp/builder/templates/research.html +31 -0
- openinterp/builder/templates/user.html +54 -0
- openinterp/builder/templates/users.html +39 -0
- openinterp/builder/templates/wiki/experiment.md +271 -0
- openinterp/builder/templates/wiki/index.md +32 -0
- openinterp/builder/templates/wiki/neuron.md +30 -0
- openinterp/builder/templates/wiki/stop.md +36 -0
- openinterp/builder/tree.py +470 -0
- openinterp/builder/users.py +142 -0
- openinterp/builder/wiki.py +427 -0
- openinterp/checks.py +429 -0
- openinterp/cli.py +494 -0
- openinterp/cli_baseline.py +332 -0
- openinterp/cli_benchmark.py +300 -0
- openinterp/cli_build.py +128 -0
- openinterp/cli_check.py +51 -0
- openinterp/cli_concepts.py +76 -0
- openinterp/cli_corpus.py +252 -0
- openinterp/cli_costs.py +257 -0
- openinterp/cli_coverage.py +76 -0
- openinterp/cli_crossref.py +86 -0
- openinterp/cli_errata.py +142 -0
- openinterp/cli_evidence.py +495 -0
- openinterp/cli_evidence_store.py +93 -0
- openinterp/cli_explain.py +101 -0
- openinterp/cli_loop.py +125 -0
- openinterp/cli_memory.py +28 -0
- openinterp/cli_neuronpedia.py +175 -0
- openinterp/cli_pause.py +45 -0
- openinterp/cli_pole_effects.py +133 -0
- openinterp/cli_probing.py +119 -0
- openinterp/cli_registry.py +348 -0
- openinterp/cli_reproduce.py +446 -0
- openinterp/cli_review.py +302 -0
- openinterp/cli_scan.py +223 -0
- openinterp/cli_score.py +446 -0
- openinterp/cli_sisters.py +86 -0
- openinterp/cli_submission.py +217 -0
- openinterp/cli_superpositions.py +118 -0
- openinterp/cli_wiring.py +54 -0
- openinterp/codeid.py +73 -0
- openinterp/concepts.py +400 -0
- openinterp/core/__init__.py +59 -0
- openinterp/core/agent_names.py +76 -0
- openinterp/core/attribution.py +101 -0
- openinterp/core/cache_dirs.py +15 -0
- openinterp/core/causal.py +82 -0
- openinterp/core/confounds.py +103 -0
- openinterp/core/contributors.py +26 -0
- openinterp/core/corpora.py +126 -0
- openinterp/core/costs.py +430 -0
- openinterp/core/draws.py +109 -0
- openinterp/core/errata.py +244 -0
- openinterp/core/evidence.py +160 -0
- openinterp/core/examples.py +93 -0
- openinterp/core/exceptions.py +29 -0
- openinterp/core/explanation.py +130 -0
- openinterp/core/fence.py +42 -0
- openinterp/core/heavy_lock.py +114 -0
- openinterp/core/identifiers.py +198 -0
- openinterp/core/isolation.py +149 -0
- openinterp/core/ledger.py +130 -0
- openinterp/core/licenses.py +28 -0
- openinterp/core/manifold.py +117 -0
- openinterp/core/partners.py +32 -0
- openinterp/core/patchscope.py +59 -0
- openinterp/core/paths.py +40 -0
- openinterp/core/pause.py +96 -0
- openinterp/core/pricing.py +178 -0
- openinterp/core/prior_art.py +44 -0
- openinterp/core/probing.py +146 -0
- openinterp/core/profiles.py +221 -0
- openinterp/core/project.py +28 -0
- openinterp/core/run_environment.py +38 -0
- openinterp/core/schemas.py +484 -0
- openinterp/core/specificity.py +49 -0
- openinterp/core/stats.py +172 -0
- openinterp/core/steering.py +49 -0
- openinterp/core/strict.py +19 -0
- openinterp/core/takedowns.py +136 -0
- openinterp/core/transcripts.py +130 -0
- openinterp/core/wiring.py +80 -0
- openinterp/corpus.py +476 -0
- openinterp/corpus_cache.py +145 -0
- openinterp/corpus_layouts.py +108 -0
- openinterp/corpus_presets.py +168 -0
- openinterp/corpus_rebuild.py +93 -0
- openinterp/coverage.py +155 -0
- openinterp/crossref.py +442 -0
- openinterp/data/__init__.py +9 -0
- openinterp/data/offensive_words.txt +58 -0
- openinterp/data/public_suffix_list.dat +15771 -0
- openinterp/data/sample_corpus.txt +40 -0
- openinterp/draw_steps.py +359 -0
- openinterp/errata_checks.py +129 -0
- openinterp/evidence.py +462 -0
- openinterp/evidence_branch.py +119 -0
- openinterp/evidence_lenses.py +75 -0
- openinterp/experiment_loop.py +357 -0
- openinterp/explain.py +252 -0
- openinterp/half_precision.py +79 -0
- openinterp/harness/__init__.py +37 -0
- openinterp/harness/ane/__init__.py +9 -0
- openinterp/harness/ane/backend.py +324 -0
- openinterp/harness/ane/cache.py +276 -0
- openinterp/harness/ane/chunks.py +163 -0
- openinterp/harness/ane/convert.py +116 -0
- openinterp/harness/ane/forward.py +258 -0
- openinterp/harness/ane/qualified.py +40 -0
- openinterp/harness/annotations.py +329 -0
- openinterp/harness/attribution.py +96 -0
- openinterp/harness/causal.py +264 -0
- openinterp/harness/confounds.py +184 -0
- openinterp/harness/covariance.py +301 -0
- openinterp/harness/crossref.py +195 -0
- openinterp/harness/cuda_devices.py +88 -0
- openinterp/harness/dead.py +124 -0
- openinterp/harness/devices.py +401 -0
- openinterp/harness/dictionaries.py +496 -0
- openinterp/harness/dreaming.py +116 -0
- openinterp/harness/environment.py +64 -0
- openinterp/harness/explanation_scores.py +371 -0
- openinterp/harness/features.py +276 -0
- openinterp/harness/first_position.py +137 -0
- openinterp/harness/heads.py +226 -0
- openinterp/harness/hooks.py +499 -0
- openinterp/harness/input_attribution.py +367 -0
- openinterp/harness/jlens.py +183 -0
- openinterp/harness/layer_cache.py +301 -0
- openinterp/harness/layer_major.py +274 -0
- openinterp/harness/lookahead.py +93 -0
- openinterp/harness/manifold.py +200 -0
- openinterp/harness/memory.py +471 -0
- openinterp/harness/moe.py +134 -0
- openinterp/harness/patcher.py +322 -0
- openinterp/harness/patchscope.py +177 -0
- openinterp/harness/probing.py +383 -0
- openinterp/harness/scan.py +462 -0
- openinterp/harness/scan_backend.py +201 -0
- openinterp/harness/sister_passes.py +463 -0
- openinterp/harness/sisters.py +363 -0
- openinterp/harness/sites.py +101 -0
- openinterp/harness/specificity.py +107 -0
- openinterp/harness/steering.py +159 -0
- openinterp/harness/superpositions.py +116 -0
- openinterp/harness/units.py +203 -0
- openinterp/harness/wiring.py +432 -0
- openinterp/harness/wiring_activations.py +285 -0
- openinterp/langid.py +73 -0
- openinterp/names.py +129 -0
- openinterp/neuronpedia_baseline.py +88 -0
- openinterp/neuronpedia_review.py +148 -0
- openinterp/planner.py +466 -0
- openinterp/planner_effects.py +89 -0
- openinterp/planner_heads.py +92 -0
- openinterp/planner_models.py +174 -0
- openinterp/planner_sisters.py +122 -0
- openinterp/planner_states.py +57 -0
- openinterp/planner_superpositions.py +114 -0
- openinterp/pole_effects.py +102 -0
- openinterp/prior_art.py +143 -0
- openinterp/reproduce.py +450 -0
- openinterp/revision.py +45 -0
- openinterp/runner_cache.py +35 -0
- openinterp/score_controls.py +169 -0
- openinterp/sensitive.py +243 -0
- openinterp/show.py +236 -0
- openinterp/signing.py +209 -0
- openinterp/sisters.py +476 -0
- openinterp/superposition_finders.py +225 -0
- openinterp/sync/__init__.py +5 -0
- openinterp/sync/r2.py +280 -0
- openinterp/syntax.py +399 -0
- openinterp/takedown_checks.py +76 -0
- openinterp/toxicity.py +158 -0
- openinterp/verdict_regression.py +79 -0
- openinterp/wiring_backfill.py +170 -0
- openinterp/wordnet.py +362 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""The static site and the Parquet registry, compiled from the archived records."""
|
|
2
|
+
|
|
3
|
+
from openinterp.builder.compiler import BuildReport, compile_site, load_records
|
|
4
|
+
from openinterp.builder.parquet_export import export_registry, records_to_table
|
|
5
|
+
|
|
6
|
+
__all__ = ["BuildReport", "compile_site", "export_registry", "load_records", "records_to_table"]
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
"""The agents page: per agent model and role, its experiments, VERIFIED rate and costs.
|
|
2
|
+
|
|
3
|
+
A model takes part in an experiment in one of three roles. It is the proposer
|
|
4
|
+
(``submitting_agent_model``), the reviewer (``reviewer_agent_model``), or the judge that
|
|
5
|
+
scored the explanation. Self-reviewed experiments are counted apart from the rate. In
|
|
6
|
+
them, the proposer's model also wrote the probes. A model that passes its own probes
|
|
7
|
+
inflates the rate.
|
|
8
|
+
|
|
9
|
+
Records spell one model in several ways. So pages are per canonical name
|
|
10
|
+
(:func:`openinterp.core.agent_names.canonical_agent`). Each old per-spelling page
|
|
11
|
+
redirects to its model's page (:func:`legacy_redirects`).
|
|
12
|
+
|
|
13
|
+
The same page credits the people who ran the agents (:func:`contributors_view`). A
|
|
14
|
+
person's handle is the ``contributor`` that a submission or verdict records. When the
|
|
15
|
+
submission records none, it is the author of the PR that merged it
|
|
16
|
+
(:mod:`openinterp.builder.users`). Each person also gets a page under ``users/``.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from collections.abc import Sequence
|
|
23
|
+
from dataclasses import dataclass, field
|
|
24
|
+
|
|
25
|
+
from openinterp.builder.hrefs import user_href
|
|
26
|
+
from openinterp.builder.significance import STRONG_EVIDENCE
|
|
27
|
+
from openinterp.builder.tree import LABEL_PREFIX, Experiment
|
|
28
|
+
from openinterp.core.agent_names import NOTES, canonical_agent
|
|
29
|
+
from openinterp.core.costs import ROLE_ORDER, by_agent
|
|
30
|
+
from openinterp.core.exceptions import RegistryError
|
|
31
|
+
|
|
32
|
+
RECENT_PER_AGENT = 20 # rows in an agent page's "Most recent experiments"
|
|
33
|
+
RECENT_PER_USER = 10 # rows in each list of a user's page
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _slug(name: str) -> str:
|
|
37
|
+
return re.sub(r"[^a-z0-9._]+", "-", name.lower()).strip("-") or "unknown"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def agent_slug(model: str) -> str:
|
|
41
|
+
"""The agent page's name: ``external/deepseek-flash[1m]`` → ``deepseek-flash``."""
|
|
42
|
+
return _slug(canonical_agent(model))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def agent_href(model: str) -> str:
|
|
46
|
+
"""The agent page of ``model``, by its canonical name."""
|
|
47
|
+
return f"agents/{agent_slug(model)}.html"
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def legacy_href(model: str) -> str:
|
|
51
|
+
"""Return the page that a recorded spelling had before spellings were merged.
|
|
52
|
+
|
|
53
|
+
For example, ``external/deepseek-flash[1m]`` → ``agents/external-deepseek-flash-1m.html``.
|
|
54
|
+
"""
|
|
55
|
+
return f"agents/{_slug(model)}.html"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass
|
|
59
|
+
class RoleStats:
|
|
60
|
+
"""One agent's experiments in one role, and how many were VERIFIED."""
|
|
61
|
+
|
|
62
|
+
role: str
|
|
63
|
+
experiments: int = 0
|
|
64
|
+
verified: int = 0
|
|
65
|
+
self_reviewed: int = 0 # proposer and reviewer only
|
|
66
|
+
self_verified: int = 0
|
|
67
|
+
costs: dict | None = None # a :func:`openinterp.core.costs.by_agent` row
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def independent(self) -> int:
|
|
71
|
+
"""Experiments that another model reviewed."""
|
|
72
|
+
return self.experiments - self.self_reviewed
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def independent_verified(self) -> int:
|
|
76
|
+
"""VERIFIED experiments that another model reviewed."""
|
|
77
|
+
return self.verified - self.self_verified
|
|
78
|
+
|
|
79
|
+
@property
|
|
80
|
+
def rate(self) -> float | None:
|
|
81
|
+
"""VERIFIED / experiments, over independent reviews only.
|
|
82
|
+
|
|
83
|
+
A judge scores explanations after the verdict, so its experiments' verdicts aren't
|
|
84
|
+
its rate.
|
|
85
|
+
"""
|
|
86
|
+
if self.role == "judge" or not self.independent:
|
|
87
|
+
return None
|
|
88
|
+
return self.independent_verified / self.independent
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
@dataclass
|
|
92
|
+
class AgentView:
|
|
93
|
+
"""One agent model's page: its roles, spellings and recent experiments."""
|
|
94
|
+
|
|
95
|
+
model: str # canonical name
|
|
96
|
+
href: str
|
|
97
|
+
roles: dict[str, RoleStats] = field(default_factory=dict)
|
|
98
|
+
spellings: set[str] = field(default_factory=set) # as the records name it
|
|
99
|
+
experiments: int = 0 # experiments it took any part in, in any role
|
|
100
|
+
recent: list[dict] = field(default_factory=list) # newest first, any role
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def role_rows(self) -> list[RoleStats]:
|
|
104
|
+
"""The agent's roles in ``ROLE_ORDER``."""
|
|
105
|
+
return [self.roles[r] for r in ROLE_ORDER if r in self.roles]
|
|
106
|
+
|
|
107
|
+
@property
|
|
108
|
+
def note(self) -> str | None:
|
|
109
|
+
"""The page's note on this model (for example, a remapped name), if any."""
|
|
110
|
+
return NOTES.get(self.model)
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def other_spellings(self) -> list[str]:
|
|
114
|
+
"""Recorded names other than the canonical one, for the page to list."""
|
|
115
|
+
return sorted(s for s in self.spellings if s.removeprefix("external/") != self.model)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _roles_of(e: Experiment) -> dict[str, str]:
|
|
119
|
+
"""``role → model`` for the agents behind one (reviewed) experiment, as recorded."""
|
|
120
|
+
sub, verdict = e.record.submission, e.record.verdict
|
|
121
|
+
roles = {"proposer": sub.submitting_agent_model, "reviewer": verdict.reviewer_agent_model}
|
|
122
|
+
if verdict.explanation_scores and verdict.explanation_scores.judge_model:
|
|
123
|
+
roles["judge"] = verdict.explanation_scores.judge_model
|
|
124
|
+
return roles
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def agents_view(experiments: Sequence[Experiment]) -> list[AgentView]:
|
|
128
|
+
"""One view per agent model, most experiments first."""
|
|
129
|
+
agents: dict[str, AgentView] = {}
|
|
130
|
+
involved: dict[str, list[tuple[Experiment, list[str]]]] = {}
|
|
131
|
+
|
|
132
|
+
def agent(model: str) -> AgentView:
|
|
133
|
+
name = canonical_agent(model)
|
|
134
|
+
view = agents.setdefault(name, AgentView(name, agent_href(name)))
|
|
135
|
+
view.spellings.add(model)
|
|
136
|
+
return view
|
|
137
|
+
|
|
138
|
+
for e in experiments:
|
|
139
|
+
verified = e.record.is_verified
|
|
140
|
+
own = e.record.self_reviewed
|
|
141
|
+
by_model: dict[str, list[str]] = {}
|
|
142
|
+
for role, recorded in _roles_of(e).items():
|
|
143
|
+
model = agent(recorded).model
|
|
144
|
+
stats = agents[model].roles.setdefault(role, RoleStats(role))
|
|
145
|
+
stats.experiments += 1
|
|
146
|
+
stats.verified += verified
|
|
147
|
+
if role != "judge" and own:
|
|
148
|
+
stats.self_reviewed += 1
|
|
149
|
+
stats.self_verified += verified
|
|
150
|
+
by_model.setdefault(model, []).append(role)
|
|
151
|
+
for model, roles in by_model.items():
|
|
152
|
+
involved.setdefault(model, []).append((e, roles))
|
|
153
|
+
|
|
154
|
+
for row in _costs(experiments):
|
|
155
|
+
if row["agent"] in ROLE_ORDER:
|
|
156
|
+
agent(row["model"]).roles.setdefault(row["agent"], RoleStats(row["agent"])).costs = row
|
|
157
|
+
|
|
158
|
+
for model, view in agents.items():
|
|
159
|
+
rows = involved.get(model, [])
|
|
160
|
+
view.experiments = len(rows)
|
|
161
|
+
newest = sorted(rows, key=lambda r: (r[0].record.verdict.timestamp, r[0].id), reverse=True)
|
|
162
|
+
view.recent = [_recent_row(e, roles) for e, roles in newest[:RECENT_PER_AGENT]]
|
|
163
|
+
|
|
164
|
+
_check_slugs_unique(agents)
|
|
165
|
+
return sorted(agents.values(), key=lambda a: (-a.experiments, a.model))
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _costs(experiments: Sequence[Experiment]) -> list[dict]:
|
|
169
|
+
""":func:`openinterp.core.costs.by_agent` rows, one per role and canonical name."""
|
|
170
|
+
return by_agent(
|
|
171
|
+
[
|
|
172
|
+
(e.record.verdict.status, e.record.submission.provenance.costs)
|
|
173
|
+
for e in experiments
|
|
174
|
+
if e.record.submission.provenance
|
|
175
|
+
],
|
|
176
|
+
canonical_agent,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def _recent_row(e: Experiment, roles: list[str]) -> dict:
|
|
181
|
+
ident = e.record.submission.identifier
|
|
182
|
+
return {
|
|
183
|
+
"e": e,
|
|
184
|
+
"roles": roles,
|
|
185
|
+
"href": e.href,
|
|
186
|
+
"model_name": ident.model_name,
|
|
187
|
+
"unit": f"L{ident.layer}/{LABEL_PREFIX[ident.kind]}{_unit_index(ident)}",
|
|
188
|
+
"pole": ident.pole,
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def _unit_index(ident) -> int | str:
|
|
193
|
+
"""What follows the kind's prefix in a unit's label: a superposition's id, else its index."""
|
|
194
|
+
return getattr(ident, "superposition_id", ident.index)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
@dataclass
|
|
198
|
+
class ContributorStats:
|
|
199
|
+
"""One person's part in the registry, as maker of experiments and as reviewer."""
|
|
200
|
+
|
|
201
|
+
handle: str
|
|
202
|
+
experiments: int = 0 # made: proposed, or merged when no contributor is recorded
|
|
203
|
+
verified: int = 0
|
|
204
|
+
conclusive_nulls: int = 0 # well-probed rejections: strong evidence against
|
|
205
|
+
reviews: int = 0
|
|
206
|
+
made: list[dict] = field(default_factory=list) # their newest experiments, at most 10
|
|
207
|
+
reviewed: list[dict] = field(default_factory=list) # the newest they reviewed, at most 10
|
|
208
|
+
|
|
209
|
+
@property
|
|
210
|
+
def href(self) -> str:
|
|
211
|
+
"""Their page on the site."""
|
|
212
|
+
return user_href(self.handle)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def contributors_view(experiments: Sequence[Experiment]) -> list[ContributorStats]:
|
|
216
|
+
"""Return one row per person, most experiments and reviews first.
|
|
217
|
+
|
|
218
|
+
An experiment's maker is ``Experiment.user``. That is the proposer's recorded
|
|
219
|
+
contributor, else the author of the PR that merged it (:mod:`openinterp.builder.users`). Its
|
|
220
|
+
reviewer is the verdict's recorded contributor. Each list of rows is newest first, and
|
|
221
|
+
keeps at most :data:`RECENT_PER_USER` rows. The counts include every experiment.
|
|
222
|
+
"""
|
|
223
|
+
people: dict[str, ContributorStats] = {}
|
|
224
|
+
newest = sorted(experiments, key=lambda e: (e.record.verdict.timestamp, e.id), reverse=True)
|
|
225
|
+
for e in newest:
|
|
226
|
+
verdict = e.record.verdict
|
|
227
|
+
if e.user:
|
|
228
|
+
row = people.setdefault(e.user, ContributorStats(e.user))
|
|
229
|
+
row.experiments += 1
|
|
230
|
+
if len(row.made) < RECENT_PER_USER:
|
|
231
|
+
row.made.append(_recent_row(e, []))
|
|
232
|
+
row.verified += e.record.is_verified
|
|
233
|
+
row.conclusive_nulls += (
|
|
234
|
+
e.sig.direction == "refutes" and e.sig.conclusiveness >= STRONG_EVIDENCE
|
|
235
|
+
)
|
|
236
|
+
if verdict.contributor:
|
|
237
|
+
row = people.setdefault(verdict.contributor, ContributorStats(verdict.contributor))
|
|
238
|
+
row.reviews += 1
|
|
239
|
+
if len(row.reviewed) < RECENT_PER_USER:
|
|
240
|
+
row.reviewed.append(_recent_row(e, []))
|
|
241
|
+
return sorted(people.values(), key=lambda c: (-c.experiments - c.reviews, c.handle.lower()))
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def legacy_redirects(agents: Sequence[AgentView]) -> dict[str, str]:
|
|
245
|
+
"""``old page → its model's page``, for every recorded spelling whose page moved."""
|
|
246
|
+
pages = {a.href for a in agents}
|
|
247
|
+
return {
|
|
248
|
+
old: a.href
|
|
249
|
+
for a in agents
|
|
250
|
+
for old in map(legacy_href, a.spellings)
|
|
251
|
+
if old != a.href and old not in pages
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def _check_slugs_unique(agents: dict[str, AgentView]) -> None:
|
|
256
|
+
seen: dict[str, str] = {}
|
|
257
|
+
for model, view in agents.items():
|
|
258
|
+
other = seen.setdefault(view.href, model)
|
|
259
|
+
if other != model:
|
|
260
|
+
raise RegistryError(f"agent models {other!r} and {model!r} share the page {view.href}")
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""The dictionary latents aligned with a neuron's poles, as its page shows them."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from openinterp.builder.tree import feature_href
|
|
6
|
+
from openinterp.crossref import neuronpedia_url
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def aligned_latents(model, neuron, alignment: dict, studied: set) -> list[dict]:
|
|
10
|
+
"""Return each pole's aligned dictionary latents for a neuron page.
|
|
11
|
+
|
|
12
|
+
Each latent links to its page here (if audited) and on Neuronpedia (if hosted there).
|
|
13
|
+
"""
|
|
14
|
+
if not neuron.is_neuron:
|
|
15
|
+
return []
|
|
16
|
+
poles = []
|
|
17
|
+
for pole in neuron.sides:
|
|
18
|
+
rows = alignment.get(f"{model.slug}/L{neuron.layer}/N{neuron.idx}-{pole}", [])
|
|
19
|
+
views = []
|
|
20
|
+
for row in rows:
|
|
21
|
+
sides = []
|
|
22
|
+
for name in ("writes", "reads"):
|
|
23
|
+
side = getattr(row, name)
|
|
24
|
+
if side is None:
|
|
25
|
+
continue
|
|
26
|
+
matches = []
|
|
27
|
+
for m in side.matches:
|
|
28
|
+
href = feature_href(model.slug, neuron.layer, row.dictionary, m.feature_idx)
|
|
29
|
+
matches.append(
|
|
30
|
+
{
|
|
31
|
+
"m": m,
|
|
32
|
+
"href": href if href in studied else None,
|
|
33
|
+
"neuronpedia": neuronpedia_url(row, m.feature_idx),
|
|
34
|
+
"above": m.cosine > side.chance,
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
sides.append({"name": name, "side": side, "matches": matches})
|
|
38
|
+
views.append({"row": row, "sides": sides})
|
|
39
|
+
if views:
|
|
40
|
+
poles.append({"pole": pole, "rows": views})
|
|
41
|
+
return poles
|