hugpy-discovery 0.1.1__tar.gz
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.
- hugpy_discovery-0.1.1/PKG-INFO +16 -0
- hugpy_discovery-0.1.1/README.md +275 -0
- hugpy_discovery-0.1.1/pyproject.toml +32 -0
- hugpy_discovery-0.1.1/setup.cfg +4 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/__init__.py +2 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/__main__.py +187 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/analysis.py +531 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/catalog.py +72 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/dependencies.py +167 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/__init__.py +6 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/documentation.py +64 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/documentation/documentation.sql +28 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/__init__.py +2 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/engine_probes.sql +18 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/engine_probes/workflow.py +152 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/engines.py +271 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/environment/__init__.py +28 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/environment/environment.py +374 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/environment/environment.sql +33 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/filesystems.py +118 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/__init__.py +15 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/formula_catalog.py +118 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/formula_catalog/formula_catalog.sql +55 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/history/__init__.py +9 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/history/history.py +70 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/history/history.sql +11 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/__init__.py +46 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/api.py +61 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/audit.py +91 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/downloads.py +67 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/identity.py +127 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/__init__.py +16 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/metadata.py +350 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/metadata/metadata.sql +19 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/huggingface/token.py +54 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/identity.py +206 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/__init__.py +79 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/classes.py +19 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/constants.py +417 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/__init__.py +30 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/discovery_paths.py +8 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/environment.py +34 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/huggingface.py +115 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/functions/repositories.py +18 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/imports/init_imports.py +157 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/inventory.py +484 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/__init__.py +10 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/memory_ticks.py +194 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/memory_ticks/memory_ticks.sql +30 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/__init__.py +5 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/operator_environment.py +19 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/operator_environment/operator_environment.sql +17 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/persistence.py +26 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/__init__.py +29 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/preparation.py +593 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/preparation/preparation.sql +156 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/quantification.py +26 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/__init__.py +5 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/runtime_evidence.py +8 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/runtime_evidence/runtime_evidence.sql +39 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/store/__init__.py +6 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/store/schema.py +196 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/store/schema.sql +159 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/__init__.py +8 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/timing_scales.py +303 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/timing_scales/timing_scales.sql +60 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/verification.py +184 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/viewer.html +123 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/viewer.py +312 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/__init__.py +10 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/weight_components.py +97 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/weight_components/weight_components.sql +51 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/__init__.py +6 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/worker_engines.py +104 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/worker_engines/worker_engines.sql +30 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/__init__.py +5 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/workflow.py +57 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/workflow/workflow.sql +46 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/__init__.py +5 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/wrapper_loads.py +96 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery/wrapper_loads/wrapper_loads.sql +20 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/PKG-INFO +16 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/SOURCES.txt +90 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/dependency_links.txt +1 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/entry_points.txt +2 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/requires.txt +14 -0
- hugpy_discovery-0.1.1/src/hugpy_discovery.egg-info/top_level.txt +1 -0
- hugpy_discovery-0.1.1/tests/test_formula_persistence.py +89 -0
- hugpy_discovery-0.1.1/tests/test_formulas.py +69 -0
- hugpy_discovery-0.1.1/tests/test_geometry.py +49 -0
- hugpy_discovery-0.1.1/tests/test_pipeline.py +174 -0
- hugpy_discovery-0.1.1/tests/test_precalculated_tiers.py +86 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: hugpy-discovery
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Independent model inventory and host-scoped engine route evidence
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: hugpy-resources<0.2,>=0.1.2.8
|
|
7
|
+
Requires-Dist: sentencepiece>=0.2
|
|
8
|
+
Requires-Dist: protobuf>=4
|
|
9
|
+
Requires-Dist: hugpy-settings>=0.1.7
|
|
10
|
+
Provides-Extra: test
|
|
11
|
+
Requires-Dist: pytest<10,>=8; extra == "test"
|
|
12
|
+
Provides-Extra: identity
|
|
13
|
+
Requires-Dist: huggingface_hub>=0.20; extra == "identity"
|
|
14
|
+
Provides-Extra: huggingface
|
|
15
|
+
Requires-Dist: huggingface_hub>=0.20; extra == "huggingface"
|
|
16
|
+
Requires-Dist: requests>=2; extra == "huggingface"
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# Hugpy Discovery
|
|
2
|
+
|
|
3
|
+
Worker engine wiring and the schema-10 history import are documented in
|
|
4
|
+
[Wrapper engine observations](docs/worker-engine-observations.md). The populated
|
|
5
|
+
older snapshots remain historical; imports never promote their readiness gates.
|
|
6
|
+
|
|
7
|
+
Standalone inventory, verification and pre-engine evidence for a local model tree. Source model files are read without modification; observations and proofs are written to a separate SQLite database. This package has its own scanner, format readers, engine survey, and browser inspector. It does not import the wrapper application or use its model-record writer.
|
|
8
|
+
|
|
9
|
+
## Source layout
|
|
10
|
+
|
|
11
|
+
`hugpy-resources` is the canonical reference for generic functions, format
|
|
12
|
+
constants and MIME data. Discovery imports those implementations through its
|
|
13
|
+
`imports/init_imports.py` boundary. Its `imports/__init__.py` and
|
|
14
|
+
`imports/functions/__init__.py` retain the existing shared symbol exports.
|
|
15
|
+
|
|
16
|
+
| Owner | Responsibility |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| Resources `imports/functions/json_utils.py`, `formatting.py`, `ast_utils.py` | Serialization, digests, byte formatting and AST helpers |
|
|
19
|
+
| Resources `imports/functions/paths.py`, `locking.py`, `sqlite.py`, `sqlite_connections.py` | Generic filesystem, locking and SQLite utilities |
|
|
20
|
+
| Resources `imports/functions/file_types.py`, `tensor_files.py`, `gguf_*.py` | MIME hints, bounded file identification, tensor headers and GGUF readers |
|
|
21
|
+
| Resources `imports/functions/content_proofs.py` | Stable whole-file SHA256 and Git-blob SHA1 proofs |
|
|
22
|
+
| Resources `imports/constants.py`, `imports/mime_types.json`, `imports/classes.py` | Shared format metadata, MIME definitions, sentinels and parsing errors |
|
|
23
|
+
| Discovery `imports/functions/environment.py`, `repositories.py`, `huggingface.py` | Hugpy environment attribution and provider-specific validation/serialization |
|
|
24
|
+
| Discovery `imports/functions/discovery_paths.py` | Apply Discovery's directory exclusion policy to the generic snapshot helper |
|
|
25
|
+
| Discovery `huggingface/` | HF identity, provider metadata cache, search and explicit snapshot tools |
|
|
26
|
+
|
|
27
|
+
Moved generic helper scripts are removed from Discovery; Resources owns their
|
|
28
|
+
implementations and data. Source fingerprints include the shared package's
|
|
29
|
+
Python and data files. Optional tokenizer and provider SDKs resolve only when
|
|
30
|
+
the corresponding feature requests them. Resources' base install remains
|
|
31
|
+
standard-library-only; `hugpy-resources[inspection]` supplies optional tokenizer
|
|
32
|
+
inspection dependencies.
|
|
33
|
+
|
|
34
|
+
Discovery ledger writes, preparation/readiness decisions, engine surveys and
|
|
35
|
+
Hugpy-specific source pointers remain in their domain modules. The standalone
|
|
36
|
+
engine probe lives in `imports.constants.PROBE` and runs in the surveyed
|
|
37
|
+
environment.
|
|
38
|
+
|
|
39
|
+
Each SQL schema lives with its companion Python code in a package beneath
|
|
40
|
+
`src/hugpy_discovery/`. Each SQL file has a matching Python implementation beside
|
|
41
|
+
it: for example, `preparation/preparation.sql` and `preparation/preparation.py`,
|
|
42
|
+
or `store/schema.sql` and `store/schema.py`. Package `__init__.py` files only
|
|
43
|
+
export the public functions and constants, preserving imports such as
|
|
44
|
+
`hugpy_discovery.preparation`.
|
|
45
|
+
|
|
46
|
+
| Directory | SQL file | Companion Python responsibility |
|
|
47
|
+
| --- | --- | --- |
|
|
48
|
+
| `store/` | `schema.sql` | SQLite store and migration ordering |
|
|
49
|
+
| `preparation/` | `preparation.sql` | Intake and preparation ledger |
|
|
50
|
+
| `environment/` | `environment.sql` | Environment source registry |
|
|
51
|
+
| `operator_environment/` | `operator_environment.sql` | Shared operator contract projection |
|
|
52
|
+
| `documentation/` | `documentation.sql` | Document imports and revisions |
|
|
53
|
+
| `workflow/` | `workflow.sql` | Connected evidence overview |
|
|
54
|
+
| `formula_catalog/` | `formula_catalog.sql` | Formula contracts, sources and validation |
|
|
55
|
+
| `worker_engines/` | `worker_engines.sql` | Historical engine observation imports |
|
|
56
|
+
| `memory_ticks/` | `memory_ticks.sql` | Capacity, memory scenarios and tick ladders |
|
|
57
|
+
| `wrapper_loads/` | `wrapper_loads.sql` | Historical load measurement imports |
|
|
58
|
+
| `runtime_evidence/` | `runtime_evidence.sql` | Runtime provenance schema migration |
|
|
59
|
+
| `weight_components/` | `weight_components.sql` | Disjoint weight accounting |
|
|
60
|
+
|
|
61
|
+
`preparation` continues to export its memory scenario helpers, `environment`
|
|
62
|
+
exports `persist_contract`, and `worker_engines` exports `import_loads` for
|
|
63
|
+
existing callers. SQL files are included as subpackage resources in the wheel.
|
|
64
|
+
|
|
65
|
+
## Preparation and evidence
|
|
66
|
+
|
|
67
|
+
The [formula and validation reference](docs/formulas-and-validation.md) records
|
|
68
|
+
the offline test suite, ten formula contracts, pinned upstream sources and
|
|
69
|
+
existing geometry pointers. Schema v9 stores validation reports and a separate
|
|
70
|
+
static geometry review; incomplete memory totals remain NULL.
|
|
71
|
+
|
|
72
|
+
The [initial operator environment contract](docs/operator-environment-contract.md)
|
|
73
|
+
defines the eleven retained keys, their default pointers and migration aliases.
|
|
74
|
+
Schema v6 exposes this contract alongside the broader source audit; third-party
|
|
75
|
+
additions are deferred. Live service configuration has not yet been migrated.
|
|
76
|
+
|
|
77
|
+
## Assembly before derivation
|
|
78
|
+
|
|
79
|
+
The current review flow is:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
Saved documentation + eleven-key contract + environment source audit
|
|
83
|
+
↓
|
|
84
|
+
Literal intake → declared stores/owners → filesystem and file locations
|
|
85
|
+
↓
|
|
86
|
+
Provider identity → selected units and dependencies → current file proofs
|
|
87
|
+
↓
|
|
88
|
+
pre_derivation_review: requirements passed or explicit blockers
|
|
89
|
+
↓
|
|
90
|
+
Static geometry / memory evidence review → controlled engine checks (not attempted)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Use `prepare --stop-before-derivation` to refresh and connect the existing
|
|
94
|
+
evidence without computing geometry or memory scenarios. Repeat `--document`
|
|
95
|
+
to capture the associated Markdown in the same workflow:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
.venv/bin/python -m hugpy_discovery prepare \
|
|
99
|
+
--database artifacts/pre-engine-v9.sqlite3 \
|
|
100
|
+
--env-file /etc/hugpy/wrapper.env --stop-before-derivation \
|
|
101
|
+
--document README.md --document docs/operator-environment-contract.md
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
For a full documentation snapshot, pass all session documents, as in `save-docs`
|
|
105
|
+
below. With no `--document`, preparation binds the most recent saved import.
|
|
106
|
+
`preparation_context` pins the documentation import, source-registry run and
|
|
107
|
+
exact shared contract JSON/hash. `pre_derivation_review` joins current engine
|
|
108
|
+
candidates to units, ownership, filesystem identity, allowance, selected-file
|
|
109
|
+
verification and eight prerequisite gates. Context blockers remain explicit.
|
|
110
|
+
Preparation rechecks file stat identities and reuses completed proofs; it does
|
|
111
|
+
not read full weight payloads, fetch provider metadata or run benchmarks.
|
|
112
|
+
|
|
113
|
+
`current_execution_readiness` selects the latest completed preparation run;
|
|
114
|
+
historical candidates remain in `execution_plans`. Earlier geometry and memory
|
|
115
|
+
rows remain available, but deferred stages do not recompute or validate them.
|
|
116
|
+
The separate `formula-catalog --derive-static` command refreshes static evidence
|
|
117
|
+
after a passing offline suite, preserving that preparation history.
|
|
118
|
+
This joins the staging evidence flow; live Wrapper/Core configuration migration
|
|
119
|
+
and undeclared ownership remain separate outstanding work.
|
|
120
|
+
|
|
121
|
+
## Documentation snapshots
|
|
122
|
+
|
|
123
|
+
Schema v7 stores full Markdown content with source paths, SHA256 digests,
|
|
124
|
+
capture times and source stat identities. `documentation_current` exposes the
|
|
125
|
+
latest saved text for each document; `documentation_revisions` preserves older
|
|
126
|
+
content. Unchanged imports reuse a revision and record a new observation.
|
|
127
|
+
Source files remain in place. Capturing a document does not turn its historical
|
|
128
|
+
claims into current runtime evidence. Imports are explicit snapshots, not an
|
|
129
|
+
automatic filesystem watcher.
|
|
130
|
+
|
|
131
|
+
```sh
|
|
132
|
+
.venv/bin/python -m hugpy_discovery save-docs \
|
|
133
|
+
--database artifacts/pre-engine-v9.sqlite3 \
|
|
134
|
+
README.md docs/*.md \
|
|
135
|
+
../hugpy-settings/package/README.md
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The inspector searches document text using its normal table search. Select a
|
|
139
|
+
row in `documentation_current` to read `content_markdown`. Markdown is displayed
|
|
140
|
+
as text, so embedded HTML and scripts are never executed.
|
|
141
|
+
|
|
142
|
+
## Build and inspect
|
|
143
|
+
|
|
144
|
+
```sh
|
|
145
|
+
.venv/bin/python -m hugpy_discovery build /path/to/models --database artifacts/discovery.sqlite3
|
|
146
|
+
.venv/bin/python -m hugpy_discovery serve /path/to/models --output artifacts --database artifacts/discovery.sqlite3
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`build` creates a **new** database outside the model tree. An existing database is never overwritten. `--engine-python /path/to/python` may be repeated to include specific engine environments. The built-in survey checks a bounded set of local interpreters and native binaries before scanning models. Its results are scoped to this host and the surveyed executables; they do not describe remote fleet capacity.
|
|
150
|
+
|
|
151
|
+
The static `build` evidence path is:
|
|
152
|
+
|
|
153
|
+
1. Record engine package presence, Transformers loader registration, and host hardware.
|
|
154
|
+
2. Inventory the model tree, attribute directories/files to shared filesystem records, and inspect bounded file headers, manifests, and config documents.
|
|
155
|
+
3. Form weight sets, shard groups, and component dependencies. Keep alternative weight variants separate.
|
|
156
|
+
4. Derive per-bundle engine routes with explicit blockers or a `static-candidate` state.
|
|
157
|
+
5. Validate database references, estimate coverage, and source metadata stability.
|
|
158
|
+
|
|
159
|
+
`static-candidate` requires complete dependency evidence and a known loader mapping. Other routes retain `dependency-unresolved` or `loader-unresolved`. Even a `static-candidate` does **not** mean a model will load, fit memory, or run correctly. Static source stability is based on directory metadata plus hashes of inspected evidence bytes; `build` does not content-hash tensor payloads. The separate `prepare` and `verify` stages record readiness requirements and full-file proofs before a guarded engine check. Loader-specific files, custom code, version support, memory allocation, and runtime behavior remain to be checked by engine-specific execution in a later stage.
|
|
160
|
+
|
|
161
|
+
The original discovery prototype and its SQLite database remain in the wrapper staging tree as historical evidence. New discovery passes and the inspector should use this package and its own database.
|
|
162
|
+
|
|
163
|
+
## Filesystem attribution
|
|
164
|
+
|
|
165
|
+
Schema v2 adds `filesystem_info`; `model_records.filesystem_id` and
|
|
166
|
+
`model_record_files.filesystem_id` reference it. Many models share one filesystem
|
|
167
|
+
row. File references describe the resolved file location, including a file on a
|
|
168
|
+
different filesystem from its model directory. The filesystem row records UUID
|
|
169
|
+
and PARTUUID when visible through `/dev/disk`, observed device major/minor and
|
|
170
|
+
path, filesystem type, mount entries/options, capacity and observation time.
|
|
171
|
+
Mount entries are plural because bind mounts can expose the same filesystem at
|
|
172
|
+
several paths with different options.
|
|
173
|
+
|
|
174
|
+
The primary key uses the host and observed filesystem UUID when available;
|
|
175
|
+
otherwise it uses the host, boot and observed filesystem device. UUID is not
|
|
176
|
+
assumed globally unique across hosts. Unknown identifiers remain NULL.
|
|
177
|
+
This is local observation, not fleet store identity or
|
|
178
|
+
a physical-disk topology inventory. Ownership, model allowance and write/delete
|
|
179
|
+
authority belong to declared stores/access policy; mount `rw` grants none of
|
|
180
|
+
those permissions. No write probe or throughput benchmark runs here.
|
|
181
|
+
|
|
182
|
+
Opening a v1 database through the writable Store adds the references, leaving
|
|
183
|
+
historical rows unattributed. The read-only inspector does not migrate a database.
|
|
184
|
+
A fresh build populates current filesystem observations. Legacy `drive_*` columns
|
|
185
|
+
remain for compatibility; new consumers should join `filesystem_info`.
|
|
186
|
+
|
|
187
|
+
## Intake and ownership target
|
|
188
|
+
|
|
189
|
+
The next rung follows the [D1–D6 storage ownership contract](../hugpy-resources/docs/nomenclature.md): local declarations establish authority; Wrappers host and serve worker and central stores with separate budgets; Core consolidates their evidence and coordinates sharing. Undeclared drives are immutable. Configuration cleanup and host/drive intake must precede engine probes in that target flow.
|
|
190
|
+
|
|
191
|
+
## Model identity resolver
|
|
192
|
+
|
|
193
|
+
The HF resolver uses Discovery's own `huggingface.identity` adapter,
|
|
194
|
+
`ModelMetadataStore` and shared `serialize_model_info` helper, extracted from
|
|
195
|
+
Storage. Install the `identity` extra; no Storage package is needed for these
|
|
196
|
+
lookups. For this staging checkout:
|
|
197
|
+
|
|
198
|
+
```sh
|
|
199
|
+
.venv/bin/python -m pip install -e '.[identity]'
|
|
200
|
+
.venv/bin/python -m hugpy_discovery resolve --database artifacts/discovery.sqlite3 --all
|
|
201
|
+
.venv/bin/python -m hugpy_discovery resolve --database artifacts/discovery.sqlite3 --model-dir /absolute/model/directory --offline
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
`--all` processes model directories with artifacts or configuration, skipping
|
|
205
|
+
empty inventory-only directories. `--worker` scopes a worker and `--limit` bounds
|
|
206
|
+
a batch. `build --resolve-identities` enriches a fresh inventory after its static
|
|
207
|
+
pass. Ordinary builds remain offline with respect to model providers.
|
|
208
|
+
|
|
209
|
+
The default cache is `provider-metadata.sqlite3` beside the discovery database
|
|
210
|
+
(or in the inspector's output directory). `--provider-cache` selects another
|
|
211
|
+
cache outside model trees. Successful responses persist without expiry;
|
|
212
|
+
`--refresh` explicitly replaces them, and `--offline` uses only cached results.
|
|
213
|
+
Errors remain distinct from empty search results and receive a ten-minute
|
|
214
|
+
retry delay. Credentials use Hugging Face's environment/saved token resolution;
|
|
215
|
+
requests are restricted to `https://huggingface.co`. Cache keys separate credential
|
|
216
|
+
scopes without storing tokens. No root provisioning helpers are imported.
|
|
217
|
+
|
|
218
|
+
The inspector serves these operations:
|
|
219
|
+
|
|
220
|
+
| Method and route | JSON body / query |
|
|
221
|
+
| --- | --- |
|
|
222
|
+
| `POST /api/identity/search` | `{"query":"model name","limit":5}` |
|
|
223
|
+
| `POST /api/identity/describe` | `{"model_id":"owner/repository","revision":"optional revision"}` |
|
|
224
|
+
| `POST /api/identity/resolve` | `{"model_dir":"/absolute/model/directory"}`; optional `worker` |
|
|
225
|
+
| `GET /api/identity/resolution` | `model_dir` and optional `worker`; reads the latest persisted result |
|
|
226
|
+
|
|
227
|
+
POST bodies must use `Content-Type: application/json`. Optional `offline` and
|
|
228
|
+
`refresh` booleans apply to the three POST operations. The initial provider is
|
|
229
|
+
`hf`; other provider names are rejected explicitly. The inspector's model-record
|
|
230
|
+
details also offer **Resolve identity**.
|
|
231
|
+
|
|
232
|
+
Schema v3 retains resolution history and candidate/provider evidence. Exact
|
|
233
|
+
repository hints plus matching local-inventory filenames and sizes can produce
|
|
234
|
+
`metadata-supported`; that status populates `hub_id` with an explicit
|
|
235
|
+
`hub_id_source`. Name-search matches stay candidates. Disagreement, ambiguity,
|
|
236
|
+
provider failures and offline cache misses remain visible. Comparisons use the
|
|
237
|
+
recorded scan and retain its input signature; this does not revalidate disk
|
|
238
|
+
contents. A provider's current commit is stored as `provider_revision`, never
|
|
239
|
+
silently assigned to the local `revision`. No weight hashing, downloading,
|
|
240
|
+
loading or geometry derivation is performed by identity resolution.
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
## Hugging Face tools
|
|
244
|
+
|
|
245
|
+
Discovery owns Hugging Face identity, metadata caching, search, repository size
|
|
246
|
+
lookups, snapshot audit and explicit repair/download helpers under
|
|
247
|
+
`src/hugpy_discovery/huggingface/`. Install `.[huggingface]` for the full tool
|
|
248
|
+
set, including token validation. See [Hugging Face extraction](docs/huggingface-tools.md)
|
|
249
|
+
for source ownership, cache paths and examples. Storage's implementation remains
|
|
250
|
+
intact. File verification now uses the identical content-hashing implementation
|
|
251
|
+
from Resources, so Discovery no longer imports Storage.
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
Internal imports use relative paths. Shared schemas, catalog metadata, status
|
|
255
|
+
sets, and option lists live in `imports/constants.py`; workflow modules import
|
|
256
|
+
them at module scope. Optional provider SDKs, parser backends, and hardware
|
|
257
|
+
libraries remain deferred, as do documented imports that break workflow cycles.
|
|
258
|
+
Resource helpers resolve directly to their definitions in
|
|
259
|
+
`hugpy_resources.imports.functions` and `hugpy_resources.imports.constants`.
|
|
260
|
+
|
|
261
|
+
Shared metadata and exact NVML observations resolve through the Resources import
|
|
262
|
+
boundary. Discovery no longer imports Wrapper's NVML module. Discovery retains
|
|
263
|
+
provider/repository workflows and persistence; generic parsing stays in Resources
|
|
264
|
+
so lower-level consumers do not acquire a dependency on this application.
|
|
265
|
+
|
|
266
|
+
## Embedding in Wrapper
|
|
267
|
+
|
|
268
|
+
`inventory.build_database(..., store=host_store)` and
|
|
269
|
+
`inventory.create_database(..., store=host_store)` accept a host-owned Store.
|
|
270
|
+
Wrapper supplies its own Store and applies its own migrations before Discovery
|
|
271
|
+
writes inventory, filesystem, tensor and route evidence. Discovery neither
|
|
272
|
+
opens its standalone Store nor closes the supplied Store. The existing
|
|
273
|
+
standalone commands retain their own separate schema for standalone use.
|
|
274
|
+
`catalog.discover` supplies bounded traversal with host callbacks for configured
|
|
275
|
+
roots/exclusions, quant election and runtime eligibility.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "hugpy-discovery"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Independent model inventory and host-scoped engine route evidence"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = ["hugpy-resources>=0.1.2.8,<0.2", "sentencepiece>=0.2", "protobuf>=4", "hugpy-settings>=0.1.7"]
|
|
11
|
+
|
|
12
|
+
[project.optional-dependencies]
|
|
13
|
+
test = ["pytest>=8,<10"]
|
|
14
|
+
identity = ["huggingface_hub>=0.20"]
|
|
15
|
+
huggingface = ["huggingface_hub>=0.20", "requests>=2"]
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
hugpy-discovery = "hugpy_discovery.__main__:main"
|
|
19
|
+
|
|
20
|
+
[tool.setuptools]
|
|
21
|
+
package-dir = {"" = "src"}
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["src"]
|
|
25
|
+
|
|
26
|
+
[tool.setuptools.package-data]
|
|
27
|
+
hugpy_discovery = ["viewer.html"]
|
|
28
|
+
"*" = ["*.sql"]
|
|
29
|
+
|
|
30
|
+
[tool.pytest.ini_options]
|
|
31
|
+
testpaths = ["tests"]
|
|
32
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""CLI for the independent discovery package."""
|
|
2
|
+
|
|
3
|
+
from .inventory import build_database
|
|
4
|
+
from .worker_engines import (
|
|
5
|
+
import_loads,
|
|
6
|
+
import_observations,
|
|
7
|
+
)
|
|
8
|
+
from .store import Store
|
|
9
|
+
from .identity import (
|
|
10
|
+
resolve_database,
|
|
11
|
+
validate_output,
|
|
12
|
+
)
|
|
13
|
+
from .weight_components import derive
|
|
14
|
+
from .timing_scales import derive as derive_timing
|
|
15
|
+
from .formula_catalog import establish
|
|
16
|
+
from .documentation import import_documents
|
|
17
|
+
from .environment import build_registry
|
|
18
|
+
from .preparation import prepare
|
|
19
|
+
from .verification import verify
|
|
20
|
+
from .viewer import main as viewer_main
|
|
21
|
+
from .imports.init_imports import (
|
|
22
|
+
Path,
|
|
23
|
+
argparse,
|
|
24
|
+
json,
|
|
25
|
+
sys,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def main():
|
|
30
|
+
parser = argparse.ArgumentParser(description='Local model and engine evidence survey')
|
|
31
|
+
sub = parser.add_subparsers(dest='command',required=True)
|
|
32
|
+
build = sub.add_parser('build',help='create a fresh SQLite evidence database')
|
|
33
|
+
build.add_argument('root',type=Path)
|
|
34
|
+
build.add_argument('--database',required=True,type=Path)
|
|
35
|
+
build.add_argument('--engine-python',action='append',default=[])
|
|
36
|
+
build.add_argument('--resolve-identities', action='store_true', help='resolve observed models through the provider cache/API after inventory')
|
|
37
|
+
build.add_argument('--provider-cache', type=Path)
|
|
38
|
+
resolve = sub.add_parser('resolve', help='resolve observed model identities using existing provider metadata')
|
|
39
|
+
resolve.add_argument('--database', required=True, type=Path)
|
|
40
|
+
target = resolve.add_mutually_exclusive_group(required=True)
|
|
41
|
+
target.add_argument('--model-dir', type=Path)
|
|
42
|
+
target.add_argument('--all', action='store_true', help='resolve all nonempty model directories')
|
|
43
|
+
resolve.add_argument('--worker')
|
|
44
|
+
resolve.add_argument('--limit', type=int)
|
|
45
|
+
resolve.add_argument('--provider-cache', type=Path)
|
|
46
|
+
resolve.add_argument('--offline', action='store_true')
|
|
47
|
+
resolve.add_argument('--refresh', action='store_true')
|
|
48
|
+
prepare = sub.add_parser('prepare', help='build the complete pre-engine evidence/readiness database')
|
|
49
|
+
prepare.add_argument('--database', required=True, type=Path)
|
|
50
|
+
prepare.add_argument('--source-database', type=Path, help='copy an existing inventory to a new database first')
|
|
51
|
+
prepare.add_argument('--env-file', action='append', type=Path, default=[])
|
|
52
|
+
prepare.add_argument('--declarations', type=Path, help='explicit store ownership, execution paths, allowances and selections')
|
|
53
|
+
prepare.add_argument('--stop-before-derivation', action='store_true', help='connect existing evidence and record blockers without computing geometry or memory scenarios')
|
|
54
|
+
prepare.add_argument('--document', type=Path, action='append', default=[], help='Markdown to snapshot and bind to this run; repeatable')
|
|
55
|
+
verify = sub.add_parser('verify', help='process resumable full-file hash jobs; never loads engines')
|
|
56
|
+
verify.add_argument('--database', required=True, type=Path)
|
|
57
|
+
verify.add_argument('--byte-budget', type=int, default=64 * 1024**2)
|
|
58
|
+
verify.add_argument('--all-bytes', action='store_true', help='remove the per-invocation I/O byte budget')
|
|
59
|
+
verify.add_argument('--max-files', type=int)
|
|
60
|
+
verify.add_argument('--model-dir', type=Path)
|
|
61
|
+
verify.add_argument('--proofs-database', type=Path, help='reuse current Wrapper storage_content_hashes proofs read-only')
|
|
62
|
+
engines = sub.add_parser('import-wrapper-engines', help='import recorded worker engine readiness; source is read-only')
|
|
63
|
+
engines.add_argument('--database', required=True, type=Path)
|
|
64
|
+
engines.add_argument('--wrapper-database', required=True, type=Path)
|
|
65
|
+
engines.add_argument('--request-id')
|
|
66
|
+
engines.add_argument('--limit', type=int, default=1000, help='maximum recent calls to import')
|
|
67
|
+
components = sub.add_parser('derive-weight-components', help='derive expert/non-expert weight breakdown from recorded tensor facts')
|
|
68
|
+
components.add_argument('--database', required=True, type=Path)
|
|
69
|
+
timing = sub.add_parser('timing-scales', help='price every bundle, representation and placement per token from the box read rates')
|
|
70
|
+
timing.add_argument('--database', required=True, type=Path)
|
|
71
|
+
loads = sub.add_parser('import-wrapper-loads', help='import recorded transformers loads, measured decode and drive reads; source is read-only')
|
|
72
|
+
loads.add_argument('--database', required=True, type=Path)
|
|
73
|
+
loads.add_argument('--wrapper-database', required=True, type=Path, action='append')
|
|
74
|
+
registry = sub.add_parser('env-registry', help='record environment default/source pointers without applying configuration')
|
|
75
|
+
registry.add_argument('--database', required=True, type=Path)
|
|
76
|
+
registry.add_argument('--staging', required=True, type=Path)
|
|
77
|
+
registry.add_argument('--seed-report', required=True, type=Path)
|
|
78
|
+
registry.add_argument('--report', type=Path)
|
|
79
|
+
formulas = sub.add_parser('formula-catalog', help='record pinned formulas, implementation pointers and offline suite results')
|
|
80
|
+
formulas.add_argument('--database', required=True, type=Path)
|
|
81
|
+
formulas.add_argument('--manifest', required=True, type=Path)
|
|
82
|
+
formulas.add_argument('--staging', required=True, type=Path)
|
|
83
|
+
formulas.add_argument('--junit', type=Path)
|
|
84
|
+
formulas.add_argument('--derive-static', action='store_true')
|
|
85
|
+
documents = sub.add_parser('save-docs', help='save full Markdown documents and retain content revisions')
|
|
86
|
+
documents.add_argument('--database', required=True, type=Path)
|
|
87
|
+
documents.add_argument('paths', nargs='+', type=Path)
|
|
88
|
+
serve = sub.add_parser('serve',help='open the read-only inspector; build on demand')
|
|
89
|
+
serve.add_argument('root',type=Path)
|
|
90
|
+
serve.add_argument('--output',required=True,type=Path)
|
|
91
|
+
serve.add_argument('--database',type=Path)
|
|
92
|
+
serve.add_argument('--host',default='127.0.0.1')
|
|
93
|
+
serve.add_argument('--port',type=int,default=8766)
|
|
94
|
+
engine_probe = sub.add_parser('engine-discovery', help='collect runtime surveys and correlate probe evidence; never loads models')
|
|
95
|
+
engine_probe.add_argument('--database', required=True, type=Path)
|
|
96
|
+
engine_probe.add_argument('--wrapper-database', type=Path)
|
|
97
|
+
engine_probe.add_argument('--probe-results', action='append', type=Path, default=[])
|
|
98
|
+
engine_probe.add_argument('--survey', action='store_true')
|
|
99
|
+
engine_probe.add_argument('--engine-python', action='append', default=[])
|
|
100
|
+
engine_probe.add_argument('--limit', type=int, default=1000)
|
|
101
|
+
args = parser.parse_args()
|
|
102
|
+
if args.command == 'engine-discovery':
|
|
103
|
+
from .engine_probes import collect
|
|
104
|
+
print(json.dumps(collect(args.database, wrapper_database=args.wrapper_database,
|
|
105
|
+
result_paths=args.probe_results, survey=args.survey,
|
|
106
|
+
engine_paths=args.engine_python, limit=args.limit), indent=2))
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
if args.command == 'import-wrapper-engines':
|
|
110
|
+
print(json.dumps(import_observations(args.database, args.wrapper_database,
|
|
111
|
+
request_id=args.request_id, limit=args.limit), indent=2))
|
|
112
|
+
return
|
|
113
|
+
if args.command == 'derive-weight-components':
|
|
114
|
+
database = args.database.resolve(strict=True)
|
|
115
|
+
validate_output(database, database.parent / 'provider-metadata.sqlite3')
|
|
116
|
+
db = Store(database)
|
|
117
|
+
try:
|
|
118
|
+
with db.transaction() as conn:
|
|
119
|
+
report = derive(conn)
|
|
120
|
+
print(json.dumps(report, indent=2))
|
|
121
|
+
finally:
|
|
122
|
+
db.close()
|
|
123
|
+
return
|
|
124
|
+
if args.command == 'timing-scales':
|
|
125
|
+
database = args.database.resolve(strict=True)
|
|
126
|
+
validate_output(database, database.parent / 'provider-metadata.sqlite3')
|
|
127
|
+
db = Store(database)
|
|
128
|
+
try:
|
|
129
|
+
with db.transaction() as conn:
|
|
130
|
+
report = derive_timing(conn)
|
|
131
|
+
print(json.dumps(report, indent=2))
|
|
132
|
+
finally:
|
|
133
|
+
db.close()
|
|
134
|
+
return
|
|
135
|
+
if args.command == 'import-wrapper-loads':
|
|
136
|
+
print(json.dumps([import_loads(args.database, source) for source in args.wrapper_database], indent=2))
|
|
137
|
+
return
|
|
138
|
+
if args.command == 'formula-catalog':
|
|
139
|
+
print(json.dumps(establish(args.database,manifest=args.manifest,staging=args.staging,
|
|
140
|
+
junit=args.junit,derive_static=args.derive_static),indent=2))
|
|
141
|
+
return
|
|
142
|
+
if args.command == 'save-docs':
|
|
143
|
+
print(json.dumps(import_documents(args.database, args.paths), indent=2))
|
|
144
|
+
return
|
|
145
|
+
if args.command == 'env-registry':
|
|
146
|
+
print(json.dumps(build_registry(args.database, args.staging, args.seed_report, args.report), indent=2))
|
|
147
|
+
return
|
|
148
|
+
if args.command == 'prepare':
|
|
149
|
+
result = prepare(args.database, source_database=args.source_database, env_files=args.env_file,
|
|
150
|
+
declarations_path=args.declarations, stop_before_derivation=args.stop_before_derivation,
|
|
151
|
+
document_paths=args.document)
|
|
152
|
+
print(json.dumps(result, indent=2))
|
|
153
|
+
return
|
|
154
|
+
if args.command == 'verify':
|
|
155
|
+
result = verify(args.database, byte_budget=None if args.all_bytes else args.byte_budget,
|
|
156
|
+
max_files=args.max_files, model_dir=args.model_dir, proofs_database=args.proofs_database)
|
|
157
|
+
print(json.dumps(result, indent=2))
|
|
158
|
+
return
|
|
159
|
+
if args.command == 'resolve':
|
|
160
|
+
results = resolve_database(args.database, cache_path=args.provider_cache, model_dir=args.model_dir,
|
|
161
|
+
worker=args.worker, offline=args.offline, refresh=args.refresh, limit=args.limit)
|
|
162
|
+
print(json.dumps([dict(model_dir=r['model_dir'], status=r['status'], model_id=r['model_id'],
|
|
163
|
+
candidates=len(r['candidates'])) for r in results], indent=2))
|
|
164
|
+
return
|
|
165
|
+
if args.command=='serve':
|
|
166
|
+
sys.argv = [sys.argv[0],str(args.root),'--output',str(args.output),'--host',args.host,'--port',str(args.port)]
|
|
167
|
+
if args.database:
|
|
168
|
+
sys.argv.extend(['--database',str(args.database)])
|
|
169
|
+
viewer_main()
|
|
170
|
+
return
|
|
171
|
+
last_phase = None
|
|
172
|
+
def progress(**event):
|
|
173
|
+
nonlocal last_phase
|
|
174
|
+
phase = event.get('phase')
|
|
175
|
+
if phase != last_phase:
|
|
176
|
+
print(json.dumps({'phase': phase}), flush=True)
|
|
177
|
+
last_phase = phase
|
|
178
|
+
report=build_database(args.root,args.database,engine_paths=args.engine_python,progress=progress)
|
|
179
|
+
print(json.dumps(report['database'],indent=2,sort_keys=True))
|
|
180
|
+
if args.resolve_identities:
|
|
181
|
+
results = resolve_database(args.database, cache_path=args.provider_cache)
|
|
182
|
+
print(json.dumps({'identities': [dict(model_dir=r['model_dir'], status=r['status'],
|
|
183
|
+
model_id=r['model_id']) for r in results]}, indent=2))
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__=='__main__':
|
|
187
|
+
main()
|