hugpy-curation 0.2.0a0__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.
Files changed (37) hide show
  1. hugpy_curation/__init__.py +64 -0
  2. hugpy_curation/cli.py +142 -0
  3. hugpy_curation/config.py +161 -0
  4. hugpy_curation/dossier/__init__.py +88 -0
  5. hugpy_curation/dossier/build.py +238 -0
  6. hugpy_curation/dossier/cards.py +481 -0
  7. hugpy_curation/dossier/community.py +509 -0
  8. hugpy_curation/dossier/dossier.py +737 -0
  9. hugpy_curation/dossier/fetch.py +208 -0
  10. hugpy_curation/dossier/llm.py +188 -0
  11. hugpy_curation/dossier/oracle_source.py +99 -0
  12. hugpy_curation/dossier/radar.py +339 -0
  13. hugpy_curation/dossier/research.py +265 -0
  14. hugpy_curation/dossier/screening.py +101 -0
  15. hugpy_curation/dossier/store.py +178 -0
  16. hugpy_curation/dossier/trial.py +528 -0
  17. hugpy_curation/dossier/verdicts.py +405 -0
  18. hugpy_curation/dossier/weights.py +249 -0
  19. hugpy_curation/providers.py +98 -0
  20. hugpy_curation/py.typed +0 -0
  21. hugpy_curation/review/__init__.py +56 -0
  22. hugpy_curation/review/__main__.py +218 -0
  23. hugpy_curation/review/criteria.py +185 -0
  24. hugpy_curation/review/download.py +175 -0
  25. hugpy_curation/review/fleet_grading.py +340 -0
  26. hugpy_curation/review/judge.py +164 -0
  27. hugpy_curation/review/pipeline.py +419 -0
  28. hugpy_curation/review/push.py +215 -0
  29. hugpy_curation/review/screen.py +454 -0
  30. hugpy_curation/review/smoke.py +231 -0
  31. hugpy_curation/review/store.py +358 -0
  32. hugpy_curation-0.2.0a0.dist-info/METADATA +71 -0
  33. hugpy_curation-0.2.0a0.dist-info/RECORD +37 -0
  34. hugpy_curation-0.2.0a0.dist-info/WHEEL +5 -0
  35. hugpy_curation-0.2.0a0.dist-info/entry_points.txt +2 -0
  36. hugpy_curation-0.2.0a0.dist-info/licenses/LICENSE +41 -0
  37. hugpy_curation-0.2.0a0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,64 @@
1
+ """hugpy_curation — discovery dossiers and the HF model review pipeline.
2
+
3
+ Two subpackages, one lifecycle:
4
+
5
+ * :mod:`hugpy_curation.review` — search, screen, download (through
6
+ ``hugpy_storage``), smoke-load, judge; the on-box review record and the
7
+ worker->central push.
8
+ * :mod:`hugpy_curation.dossier` — the comprehensive per-model dossier the
9
+ review files for every survivor (card digest, weights, research,
10
+ community, trial, verdict) and the gem radar.
11
+
12
+ Seams:
13
+
14
+ * :mod:`hugpy_curation.config` — every state root, env-overridable.
15
+ * :mod:`hugpy_curation.providers` — the fleet doctrine the dossier judge
16
+ reads (``DoctrineSource``; null default).
17
+ * :mod:`hugpy_curation.dossier.oracle_source` — the dossier store as the
18
+ oracle's ``DossierSource``; :func:`install_providers` registers it.
19
+
20
+ This ``__init__`` is deliberately light: nothing heavy (huggingface_hub,
21
+ llama_cpp, the review sqlite, the job mirror) is imported here.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any, Optional
27
+
28
+ try: # the installed distribution's version: the workspace tag/commit, never a literal
29
+ from importlib.metadata import version as _dist_version
30
+ __version__ = _dist_version("hugpy-curation")
31
+ except Exception: # noqa: BLE001 — source tree without metadata
32
+ __version__ = "0.0.0+unknown"
33
+
34
+ __all__ = ["__version__", "install_providers"]
35
+
36
+
37
+ def install_providers(doctrine_source: Optional[Any] = None,
38
+ dossier_root: Optional[str] = None) -> dict[str, Any]:
39
+ """Wire curation's seams in this process; returns what was wired.
40
+
41
+ * Installs :class:`~hugpy_curation.dossier.oracle_source.DossierStoreSource`
42
+ into ``hugpy_oracle.providers`` (``set_dossier_source``) so the oracle's
43
+ interim ledger can list discovery dossiers.
44
+ * Installs ``doctrine_source`` (anything with ``latest()``) into
45
+ :mod:`hugpy_curation.providers` when given; the server passes the
46
+ fleet's ``hugpy_fleet.doctrine`` adapter here. Without one, the
47
+ doctrine falls back to whatever the oracle has installed, else null.
48
+
49
+ Called by ``hugpy_server`` at startup and by
50
+ ``hugpy-curation install-providers``.
51
+ """
52
+ from hugpy_curation.dossier.oracle_source import install_dossier_source
53
+ from hugpy_curation.providers import set_doctrine_source
54
+
55
+ report: dict[str, Any] = {}
56
+ source = install_dossier_source(dossier_root)
57
+ report["dossier_source"] = {"installed": True, "root": source.root()}
58
+ if doctrine_source is not None:
59
+ set_doctrine_source(doctrine_source)
60
+ report["doctrine_source"] = {"installed": True,
61
+ "impl": type(doctrine_source).__name__}
62
+ else:
63
+ report["doctrine_source"] = {"installed": False, "impl": "default"}
64
+ return report
hugpy_curation/cli.py ADDED
@@ -0,0 +1,142 @@
1
+ """``hugpy-curation`` — the package's command line.
2
+
3
+ Subcommands:
4
+
5
+ ``review ...``
6
+ The review pipeline's own CLI (``hugpy_curation.review.__main__``):
7
+ ``screen``, ``review``, ``run <criteria>``, ``criteria``, ``reports``,
8
+ ``push``. Everything after ``review`` is handed to it untouched, so the
9
+ systemd units run ``hugpy-curation review run %i --report ...``.
10
+
11
+ ``dossier list [criteria]``
12
+ The discovery dossiers the store holds — every criteria, or one — as the
13
+ compact summary rows the console lists, newest first.
14
+
15
+ ``install-providers``
16
+ Wire this process's seams: the dossier store into
17
+ ``hugpy_oracle.providers`` (``set_dossier_source``) and, when a fleet
18
+ doctrine source is importable, the doctrine into
19
+ ``hugpy_curation.providers``. Prints what was wired as JSON.
20
+
21
+ No pathlib; os.path only (project discipline).
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import argparse
27
+ import json
28
+ import sys
29
+ from typing import Any, Optional, Sequence
30
+
31
+ __all__ = ["main", "build_parser"]
32
+
33
+
34
+ def build_parser() -> argparse.ArgumentParser:
35
+ from hugpy_curation import __version__
36
+
37
+ parser = argparse.ArgumentParser(
38
+ prog="hugpy-curation",
39
+ description="Hugpy curation: discovery dossiers and the HF model review pipeline.")
40
+ parser.add_argument("--version", action="version",
41
+ version=f"hugpy-curation {__version__}")
42
+ sub = parser.add_subparsers(dest="command", required=True)
43
+
44
+ review = sub.add_parser(
45
+ "review", help="the review pipeline (screen / review / run / criteria / reports / push)",
46
+ description="Arguments are passed to the review pipeline's CLI; "
47
+ "`hugpy-curation review --help` lists them.")
48
+ review.add_argument("args", nargs=argparse.REMAINDER,
49
+ help="review pipeline arguments")
50
+ review.set_defaults(func=_cmd_review)
51
+
52
+ dossier = sub.add_parser("dossier", help="discovery dossiers")
53
+ dsub = dossier.add_subparsers(dest="dossier_command", required=True)
54
+ dlist = dsub.add_parser("list", help="list stored dossiers (summary rows)")
55
+ dlist.add_argument("criteria", nargs="?", default=None,
56
+ help="one criteria name (default: every criteria)")
57
+ dlist.add_argument("--limit", type=int, default=50,
58
+ help="rows per criteria (default 50)")
59
+ dlist.add_argument("--json", action="store_true", help="JSON instead of a table")
60
+ dlist.set_defaults(func=_cmd_dossier_list)
61
+
62
+ providers = sub.add_parser(
63
+ "install-providers",
64
+ help="install curation's dossier source in the oracle (and a doctrine source when available)")
65
+ providers.set_defaults(func=_cmd_install_providers)
66
+ return parser
67
+
68
+
69
+ # ---------------------------------------------------------------------------
70
+ # review
71
+ # ---------------------------------------------------------------------------
72
+
73
+ def _cmd_review(args: argparse.Namespace) -> int:
74
+ from hugpy_curation.review.__main__ import main as review_main
75
+ rest = list(args.args)
76
+ if rest and rest[0] == "--":
77
+ rest = rest[1:]
78
+ return int(review_main(rest or ["--help"]) or 0)
79
+
80
+
81
+ # ---------------------------------------------------------------------------
82
+ # dossier list
83
+ # ---------------------------------------------------------------------------
84
+
85
+ def dossier_rows(criteria: Optional[str] = None, limit: int = 50) -> list[dict[str, Any]]:
86
+ """Summary rows for the stored dossiers, newest first per criteria."""
87
+ import os
88
+ from hugpy_curation.dossier import store as dstore
89
+
90
+ if criteria:
91
+ names = [criteria]
92
+ else:
93
+ root = dstore.root_dir()
94
+ try:
95
+ names = sorted(n for n in os.listdir(root)
96
+ if os.path.isdir(os.path.join(root, n)))
97
+ except OSError:
98
+ names = []
99
+ rows: list[dict[str, Any]] = []
100
+ for name in names:
101
+ for path in dstore.list_for(name)[:max(1, int(limit))]:
102
+ dossier = dstore.load_path(path)
103
+ if dossier is not None:
104
+ rows.append(dstore.summary(dossier, path))
105
+ return rows
106
+
107
+
108
+ def _cmd_dossier_list(args: argparse.Namespace) -> int:
109
+ rows = dossier_rows(args.criteria, args.limit)
110
+ if args.json:
111
+ print(json.dumps(rows, indent=2, default=str))
112
+ return 0
113
+ if not rows:
114
+ from hugpy_curation.dossier import store as dstore
115
+ print(f"(no dossiers under {dstore.root_dir()})")
116
+ return 0
117
+ for r in rows:
118
+ verdict = r.get("verdict") or "-"
119
+ print(f"{r.get('criteria')}\t{r.get('hub_id')}\t{verdict}\t"
120
+ f"{r.get('best_quant') or '-'}\t{r.get('generated_at') or ''}")
121
+ return 0
122
+
123
+
124
+ # ---------------------------------------------------------------------------
125
+ # install-providers
126
+ # ---------------------------------------------------------------------------
127
+
128
+ def _cmd_install_providers(args: argparse.Namespace) -> int:
129
+ from hugpy_curation import install_providers
130
+ report = install_providers()
131
+ print(json.dumps(report, indent=2, default=str))
132
+ return 0
133
+
134
+
135
+ def main(argv: Optional[Sequence[str]] = None) -> int:
136
+ parser = build_parser()
137
+ args = parser.parse_args(list(argv) if argv is not None else None)
138
+ return int(args.func(args) or 0)
139
+
140
+
141
+ if __name__ == "__main__":
142
+ sys.exit(main())
@@ -0,0 +1,161 @@
1
+ """Where curation keeps its own state — one place, every root injectable.
2
+
3
+ Curation is the sole owner of the review record (sqlite), the discovery
4
+ dossiers (one JSON file per criteria/repo, verdict included), the trial
5
+ artifacts a dossier's sample battery writes, the saved review criteria and the
6
+ dossier fetch cache (``PARTITION.md`` "State ownership"). Every module that
7
+ used to derive its root on its own — from ``hugpy_platform.constants
8
+ .DEFAULT_ROOT``, ``~/.config``, ``~/.cache`` or, for trials, the ORACLE's
9
+ benchmark run root — now asks here, so an operator (or a test conftest) can
10
+ move the whole set with one variable and still override any single root with
11
+ the env var that module always honoured.
12
+
13
+ Resolution order for every root:
14
+
15
+ 1. the module's own env var (``REVIEW_DB``, ``DOSSIER_DIR``,
16
+ ``DOSSIER_TRIAL_ROOT``, ``REVIEW_CRITERIA_DIR``, ``DOSSIER_CACHE_DIR``) —
17
+ kept verbatim, so existing deployments (the ``hugpy-review@`` units set
18
+ ``REVIEW_DB``) and the tests keep working;
19
+ 2. the package-wide ``HUGPY_CURATION_ROOT`` (state) / ``HUGPY_CURATION_CACHE``;
20
+ 3. the platform's per-OS application directories (``hugpy_platform.app_dirs``):
21
+ ``models_root()/review`` for the record, dossiers and trials — the tree the
22
+ review has always written under (``<DEFAULT_ROOT>/review``), so a box that
23
+ upgrades finds its history where it left it — ``config_dir()/review`` for
24
+ the saved criteria and ``cache_dir()/discovery-dossier`` for the fetch
25
+ cache (both byte-identical to the historical ``~/.config/hugpy/review`` and
26
+ ``~/.cache/hugpy/discovery-dossier`` on Linux).
27
+
28
+ Trials used to fall back to ``hugpy_oracle.benchmark.default_run_root()``;
29
+ that is the oracle's state and curation must not write into it, so the
30
+ default is now ``<review_root>/trials``. ``DOSSIER_TRIAL_ROOT`` still wins.
31
+
32
+ Env reads are plain ``os.environ`` on purpose: a state root must not depend
33
+ on a ``.env`` loader having run, and a test that sets ``monkeypatch.setenv``
34
+ must see the change immediately. Nothing here creates directories except
35
+ :func:`ensure_dir`; callers that write call it, callers that read do not.
36
+
37
+ No pathlib; os.path only (project discipline).
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ import logging
43
+ import os
44
+ from typing import Optional
45
+
46
+ logger = logging.getLogger(__name__)
47
+
48
+ __all__ = [
49
+ "CURATION_ROOT_ENV",
50
+ "CURATION_CACHE_ENV",
51
+ "REVIEW_DB_ENV",
52
+ "DOSSIER_DIR_ENV",
53
+ "TRIAL_ROOT_ENV",
54
+ "CRITERIA_DIR_ENV",
55
+ "FETCH_CACHE_ENV",
56
+ "review_root",
57
+ "review_db_path",
58
+ "dossiers_root",
59
+ "trials_root",
60
+ "criteria_dir",
61
+ "fetch_cache_dir",
62
+ "ensure_dir",
63
+ ]
64
+
65
+ CURATION_ROOT_ENV = "HUGPY_CURATION_ROOT"
66
+ CURATION_CACHE_ENV = "HUGPY_CURATION_CACHE"
67
+
68
+ # Per-store env vars, unchanged from the modules that introduced them.
69
+ REVIEW_DB_ENV = "REVIEW_DB"
70
+ DOSSIER_DIR_ENV = "DOSSIER_DIR"
71
+ TRIAL_ROOT_ENV = "DOSSIER_TRIAL_ROOT"
72
+ CRITERIA_DIR_ENV = "REVIEW_CRITERIA_DIR"
73
+ FETCH_CACHE_ENV = "DOSSIER_CACHE_DIR"
74
+
75
+
76
+ def _env(name: str) -> Optional[str]:
77
+ value = os.environ.get(name)
78
+ value = value.strip() if value else ""
79
+ return value or None
80
+
81
+
82
+ def _home_fallback(*parts: str) -> str:
83
+ return os.path.join(os.path.expanduser("~"), ".local", "share", "hugpy", *parts)
84
+
85
+
86
+ def _platform_models_root() -> str:
87
+ try:
88
+ from hugpy_platform.app_dirs import models_root
89
+ return models_root()
90
+ except Exception as exc: # noqa: BLE001 — a root must always resolve
91
+ logger.warning("curation config: models_root unreadable (%s: %s); "
92
+ "using ~/.local/share/hugpy", type(exc).__name__, exc)
93
+ return _home_fallback()
94
+
95
+
96
+ def _platform_config_dir() -> str:
97
+ try:
98
+ from hugpy_platform.app_dirs import config_dir
99
+ return config_dir()
100
+ except Exception as exc: # noqa: BLE001
101
+ logger.warning("curation config: config_dir unreadable (%s: %s); "
102
+ "using ~/.config/hugpy", type(exc).__name__, exc)
103
+ return os.path.join(os.path.expanduser("~"), ".config", "hugpy")
104
+
105
+
106
+ def _platform_cache_dir() -> str:
107
+ try:
108
+ from hugpy_platform.app_dirs import cache_dir
109
+ return cache_dir()
110
+ except Exception as exc: # noqa: BLE001
111
+ logger.warning("curation config: cache_dir unreadable (%s: %s); "
112
+ "using ~/.cache/hugpy", type(exc).__name__, exc)
113
+ base = os.environ.get("XDG_CACHE_HOME") or os.path.join(os.path.expanduser("~"), ".cache")
114
+ return os.path.join(base, "hugpy")
115
+
116
+
117
+ def ensure_dir(path: str) -> str:
118
+ """``makedirs`` that never raises — a state root that cannot be created is
119
+ reported by the write that follows, not by the path lookup."""
120
+ try:
121
+ os.makedirs(path, exist_ok=True)
122
+ except OSError as exc:
123
+ logger.warning("curation config: cannot create %s (%s)", path, exc)
124
+ return path
125
+
126
+
127
+ def review_root() -> str:
128
+ """The review record, dossiers and trials live under this tree.
129
+ ``HUGPY_CURATION_ROOT`` else ``<models_root>/review`` (historically
130
+ ``<DEFAULT_ROOT>/review``)."""
131
+ return _env(CURATION_ROOT_ENV) or os.path.join(_platform_models_root(), "review")
132
+
133
+
134
+ def review_db_path() -> str:
135
+ """The on-box review record (sqlite). ``REVIEW_DB`` wins."""
136
+ return _env(REVIEW_DB_ENV) or os.path.join(review_root(), "reviews.db")
137
+
138
+
139
+ def dossiers_root() -> str:
140
+ """``<dossiers_root>/<criteria>/<org__repo>.json``. ``DOSSIER_DIR`` wins."""
141
+ return _env(DOSSIER_DIR_ENV) or os.path.join(review_root(), "dossiers")
142
+
143
+
144
+ def trials_root() -> str:
145
+ """Sample artifacts of a dossier's trial battery. ``DOSSIER_TRIAL_ROOT``
146
+ wins; otherwise ``<review_root>/trials`` (curation's own tree, never the
147
+ oracle's benchmark root)."""
148
+ return _env(TRIAL_ROOT_ENV) or os.path.join(review_root(), "trials")
149
+
150
+
151
+ def criteria_dir() -> str:
152
+ """Saved review criteria (``<name>.json``). ``REVIEW_CRITERIA_DIR`` wins;
153
+ otherwise ``<config_dir>/review``."""
154
+ return _env(CRITERIA_DIR_ENV) or os.path.join(_platform_config_dir(), "review")
155
+
156
+
157
+ def fetch_cache_dir() -> str:
158
+ """The dossier fetch cache. ``DOSSIER_CACHE_DIR`` wins, then
159
+ ``HUGPY_CURATION_CACHE``, then ``<cache_dir>/discovery-dossier``."""
160
+ return (_env(FETCH_CACHE_ENV) or _env(CURATION_CACHE_ENV)
161
+ or os.path.join(_platform_cache_dir(), "discovery-dossier"))
@@ -0,0 +1,88 @@
1
+ """k120 — comprehensive model-discovery dossiers.
2
+
3
+ The nightly reviewer (``review/``) has run since July: screen HF on metadata,
4
+ download the best few, load-test them on the GPU, ask an agent for a verdict.
5
+ It works, and what it hands the operator is a MODEL NAME with a score. The
6
+ operator's read of that, verbatim:
7
+
8
+ "just model names… this needs to be comprehensive in nature and allow for
9
+ that complexity to be dictated. specializations and overall weights,
10
+ research outside of the download sources themselves, trial download and
11
+ sample data to compare various models. this needs to be genuinely useful."
12
+
13
+ "scraping social media, AI forums, reddits, youtube transcriptions — all of
14
+ these things to keep the edge on a gem that exists."
15
+
16
+ This package is the answer, in eight sections and one rule.
17
+
18
+ dossier.py the types. Every field SOURCED or None; model-generated
19
+ text labelled as such, everywhere it appears.
20
+ cards.py the README read like a reviewer — benchmark tables as
21
+ CLAIMS, limitations, the author's own purpose sentences,
22
+ and a 0..1 weight per specialization with its evidence.
23
+ weights.py params, every quant, and a VRAM number for EACH of them at
24
+ the same target context. The KV maths is ``review.screen``'s,
25
+ imported — two estimators that disagree is a 3am bug.
26
+ fetch.py the only way out to the network: never raises, polite
27
+ (real UA, one request per host per 2s), disk-cached for 20h.
28
+ research.py model card + linked papers + a written summary from a
29
+ catalog-resolved model, with its sources cited.
30
+ community.py Reddit / HN / HF discussions as typed Mentions, claims
31
+ extracted with the QUOTE that supports them, and a
32
+ recency-weighted heat. YouTube is wired and honest about
33
+ needing a dependency it will never hard-require (k121).
34
+ radar.py GEM RADAR: a second pass over the SAME cached pulls looking
35
+ for models no card is asking about yet.
36
+ trial.py k109b's stationary battery, borrowed whole. The candidate
37
+ does the SAME fixed work the incumbent in the routing
38
+ matrix was scored on, so subtracting the two means something.
39
+ verdicts.py THE RULE: no evidence, no verdict. A blocked trial can only
40
+ produce "screened only — trial blocked: <cause>".
41
+ build.py the orchestrator; a section that cannot be built leaves a
42
+ note and the other seven still arrive.
43
+ store.py the full dossier is a file; the review row carries a
44
+ compact summary and the path.
45
+
46
+ Nothing here is on the request path and nothing here is required: every entry
47
+ point degrades to an honest ``unavailable`` record rather than failing the
48
+ review that called it.
49
+ """
50
+ from __future__ import annotations
51
+
52
+ from hugpy_curation.dossier.build import build_dossier
53
+ from hugpy_curation.dossier.dossier import (
54
+ BenchmarkClaim,
55
+ CardDigest,
56
+ Claim,
57
+ Community,
58
+ EmphasisWeight,
59
+ ExternalResearch,
60
+ Identity,
61
+ IncumbentComparison,
62
+ Mention,
63
+ ModelDossier,
64
+ PaperRef,
65
+ QuantFact,
66
+ SCHEMA_VERSION,
67
+ SampleOutput,
68
+ SampleScore,
69
+ Source,
70
+ Specialization,
71
+ TRIAL_DEPTHS,
72
+ TrialEvidence,
73
+ TrustSignals,
74
+ VERDICTS,
75
+ Verdict,
76
+ WeightsFacts,
77
+ )
78
+ from hugpy_curation.dossier.radar import RadarHit, scan as radar_scan
79
+ from hugpy_curation.dossier.verdicts import decide, rule_verdict
80
+
81
+ __all__ = [
82
+ "BenchmarkClaim", "CardDigest", "Claim", "Community", "EmphasisWeight",
83
+ "ExternalResearch", "Identity", "IncumbentComparison", "Mention",
84
+ "ModelDossier", "PaperRef", "QuantFact", "RadarHit", "SCHEMA_VERSION",
85
+ "SampleOutput", "SampleScore", "Source", "Specialization", "TRIAL_DEPTHS",
86
+ "TrialEvidence", "TrustSignals", "VERDICTS", "Verdict", "WeightsFacts",
87
+ "build_dossier", "decide", "radar_scan", "rule_verdict",
88
+ ]