coreai-catalog 2.0.2__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.
- coreai_catalog/__init__.py +12 -0
- coreai_catalog/__main__.py +6 -0
- coreai_catalog/api.py +254 -0
- coreai_catalog/catalog.py +546 -0
- coreai_catalog/cli.py +1176 -0
- coreai_catalog/data/artifacts.yaml +1110 -0
- coreai_catalog/data/benchmarks.yaml +933 -0
- coreai_catalog/data/catalog.yaml +3885 -0
- coreai_catalog/data/schema/artifact.schema.json +107 -0
- coreai_catalog/data/schema/benchmark.schema.json +77 -0
- coreai_catalog/data/schema/model.schema.json +240 -0
- coreai_catalog/data/schema/term.schema.json +68 -0
- coreai_catalog/data/schema/upstream.schema.json +59 -0
- coreai_catalog/data/sources.yaml +213 -0
- coreai_catalog/data/terms.yaml +391 -0
- coreai_catalog/data/upstreams.yaml +673 -0
- coreai_catalog/exports.py +194 -0
- coreai_catalog/installer.py +280 -0
- coreai_catalog/task_pages.py +193 -0
- coreai_catalog-2.0.2.dist-info/METADATA +658 -0
- coreai_catalog-2.0.2.dist-info/RECORD +26 -0
- coreai_catalog-2.0.2.dist-info/WHEEL +5 -0
- coreai_catalog-2.0.2.dist-info/entry_points.txt +3 -0
- coreai_catalog-2.0.2.dist-info/top_level.txt +2 -0
- mcp_server/__init__.py +1 -0
- mcp_server/server.py +554 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Core AI Catalog — discover, verify, and install Apple Core AI models.
|
|
2
|
+
|
|
3
|
+
Public API:
|
|
4
|
+
from coreai_catalog import Catalog
|
|
5
|
+
|
|
6
|
+
catalog = Catalog.load()
|
|
7
|
+
catalog.recommend(task="ocr", device="iphone")
|
|
8
|
+
catalog.compare("qwen3-vl-2b", "unlimited-ocr")
|
|
9
|
+
"""
|
|
10
|
+
from .api import Catalog
|
|
11
|
+
|
|
12
|
+
__all__ = ["Catalog"]
|
coreai_catalog/api.py
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core AI Catalog — public Python API.
|
|
3
|
+
|
|
4
|
+
A clean, stable interface for programmatic access to the catalog.
|
|
5
|
+
Works with pip-installed package (no repo clone needed).
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
from coreai_catalog import Catalog
|
|
9
|
+
|
|
10
|
+
catalog = Catalog.load()
|
|
11
|
+
catalog.recommend(task="ocr", device="iphone")
|
|
12
|
+
catalog.compare("qwen3-vl-2b", "unlimited-ocr")
|
|
13
|
+
catalog.license_report("qwen3-vl-2b")
|
|
14
|
+
"""
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from .catalog import Catalog as _Catalog, resolve_task as _resolve_task
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Catalog:
|
|
24
|
+
"""High-level catalog API for programmatic access.
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
from coreai_catalog import Catalog
|
|
28
|
+
|
|
29
|
+
# Auto-discovers YAML data (bundled in pip package, or from repo root)
|
|
30
|
+
catalog = Catalog.load()
|
|
31
|
+
|
|
32
|
+
# Search and filter
|
|
33
|
+
results = catalog.search(capability="vision-language", device="iphone")
|
|
34
|
+
|
|
35
|
+
# Get recommendations
|
|
36
|
+
recs = catalog.recommend(task="ocr", device="iphone", license_filter="likely")
|
|
37
|
+
|
|
38
|
+
# Compare models
|
|
39
|
+
diff = catalog.compare("qwen3-vl-2b", "unlimited-ocr")
|
|
40
|
+
|
|
41
|
+
# License triage
|
|
42
|
+
report = catalog.license_report("qwen3-vl-2b")
|
|
43
|
+
|
|
44
|
+
# Browse tasks
|
|
45
|
+
tasks = catalog.tasks()
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, root: Path | None = None) -> None:
|
|
49
|
+
self._cat = _Catalog(root)
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def load(cls) -> "Catalog":
|
|
53
|
+
"""Create a Catalog instance, auto-discovering the YAML data.
|
|
54
|
+
|
|
55
|
+
Search order: CWD → walk up from package → bundled package data.
|
|
56
|
+
"""
|
|
57
|
+
return cls()
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def version(self) -> str:
|
|
61
|
+
"""Catalog version string (e.g. '1.6.0')."""
|
|
62
|
+
self._cat._load()
|
|
63
|
+
# Read from the raw YAML metadata
|
|
64
|
+
import yaml
|
|
65
|
+
cat_path = self._cat.root / "catalog.yaml"
|
|
66
|
+
if cat_path.exists():
|
|
67
|
+
data = yaml.safe_load(cat_path.read_text()) or {}
|
|
68
|
+
return data.get("metadata", {}).get("version", "unknown")
|
|
69
|
+
return "unknown"
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def model_count(self) -> int:
|
|
73
|
+
"""Total number of models in the catalog."""
|
|
74
|
+
return len(self._cat.models)
|
|
75
|
+
|
|
76
|
+
def search(
|
|
77
|
+
self,
|
|
78
|
+
capability: str | None = None,
|
|
79
|
+
device: str | None = None,
|
|
80
|
+
license_filter: str | None = None,
|
|
81
|
+
family: str | None = None,
|
|
82
|
+
source_group: str | None = None,
|
|
83
|
+
modality: str | None = None,
|
|
84
|
+
limit: int = 50,
|
|
85
|
+
) -> list[dict]:
|
|
86
|
+
"""Search models by criteria.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
capability: Filter by capability (e.g. 'chat', 'vision-language').
|
|
90
|
+
device: Filter by device support (e.g. 'iphone', 'mac').
|
|
91
|
+
license_filter: Filter by commercial use ('likely' or 'check_license').
|
|
92
|
+
family: Filter by model family (e.g. 'Qwen', 'Gemma').
|
|
93
|
+
source_group: Filter by source ('official', 'zoo', 'external').
|
|
94
|
+
modality: Filter by input modality ('text', 'image', 'audio').
|
|
95
|
+
limit: Maximum results.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
List of model dicts with capabilities, devices, license, score.
|
|
99
|
+
"""
|
|
100
|
+
results = self._cat.search(
|
|
101
|
+
capability=capability,
|
|
102
|
+
device=device,
|
|
103
|
+
license_type=license_filter,
|
|
104
|
+
family=family,
|
|
105
|
+
source_group=source_group,
|
|
106
|
+
modality=modality,
|
|
107
|
+
)
|
|
108
|
+
return results[:limit]
|
|
109
|
+
|
|
110
|
+
def recommend(
|
|
111
|
+
self,
|
|
112
|
+
task: str,
|
|
113
|
+
device: str | None = None,
|
|
114
|
+
license_filter: str | None = None,
|
|
115
|
+
limit: int = 5,
|
|
116
|
+
) -> list[dict]:
|
|
117
|
+
"""Recommend models for a task.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
task: Task description (e.g. 'robot vision', 'private OCR').
|
|
121
|
+
See ``catalog.tasks()`` for valid keywords.
|
|
122
|
+
device: Target device filter ('iphone', 'mac').
|
|
123
|
+
license_filter: Commercial use filter ('likely' or 'check_license').
|
|
124
|
+
limit: Maximum results.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Sorted list of recommendations with score, matched capabilities,
|
|
128
|
+
and metadata.
|
|
129
|
+
"""
|
|
130
|
+
capabilities = _resolve_task(task)
|
|
131
|
+
return self._cat.recommend_models(
|
|
132
|
+
capabilities=capabilities,
|
|
133
|
+
device=device,
|
|
134
|
+
limit=limit,
|
|
135
|
+
task=task,
|
|
136
|
+
license_type=license_filter,
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
def get_model(self, model_id: str) -> dict | None:
|
|
140
|
+
"""Get full details for a specific model.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
model_id: Model ID (e.g. 'qwen3-vl-2b').
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Model dict with all fields, or None if not found.
|
|
147
|
+
"""
|
|
148
|
+
return self._cat.get_model(model_id)
|
|
149
|
+
|
|
150
|
+
def compare(self, *model_ids: str) -> dict[str, Any]:
|
|
151
|
+
"""Compare two or more models side-by-side.
|
|
152
|
+
|
|
153
|
+
Args:
|
|
154
|
+
*model_ids: Two or more model IDs to compare.
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Dict with 'models' list and field-by-field comparison.
|
|
158
|
+
"""
|
|
159
|
+
if len(model_ids) < 2:
|
|
160
|
+
raise ValueError("compare() requires at least 2 model IDs")
|
|
161
|
+
|
|
162
|
+
models = []
|
|
163
|
+
for mid in model_ids:
|
|
164
|
+
m = self._cat.get_model(mid)
|
|
165
|
+
if m is None:
|
|
166
|
+
raise KeyError(f"Model '{mid}' not found")
|
|
167
|
+
models.append(m)
|
|
168
|
+
|
|
169
|
+
result: dict[str, Any] = {"models": []}
|
|
170
|
+
for m in models:
|
|
171
|
+
entry = {
|
|
172
|
+
"id": m["id"],
|
|
173
|
+
"name": m["name"],
|
|
174
|
+
"family": m.get("family"),
|
|
175
|
+
"capabilities": m.get("capabilities", []),
|
|
176
|
+
"parameters": m.get("size", {}).get("parameters"),
|
|
177
|
+
"precision": m.get("size", {}).get("precision"),
|
|
178
|
+
"devices": m.get("device_support", {}),
|
|
179
|
+
"license": m.get("license", {}),
|
|
180
|
+
"source_group": m.get("source_group"),
|
|
181
|
+
"score": self._cat.readiness_score(m),
|
|
182
|
+
"benchmarks": self._cat.get_benchmarks(m["id"]),
|
|
183
|
+
}
|
|
184
|
+
result["models"].append(entry)
|
|
185
|
+
|
|
186
|
+
return result
|
|
187
|
+
|
|
188
|
+
def license_report(self, model_id: str) -> dict[str, Any]:
|
|
189
|
+
"""Generate a license triage report for a model.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
model_id: Model ID.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
Dict with license name, commercial_use status, and notes.
|
|
196
|
+
"""
|
|
197
|
+
m = self._cat.get_model(model_id)
|
|
198
|
+
if m is None:
|
|
199
|
+
raise KeyError(f"Model '{model_id}' not found")
|
|
200
|
+
|
|
201
|
+
lic = m.get("license", {})
|
|
202
|
+
art = self._cat.get_artifact(model_id) or {}
|
|
203
|
+
off = art.get("officiality", {}) if art else {}
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
"model_id": model_id,
|
|
207
|
+
"name": m.get("name", model_id),
|
|
208
|
+
"license_name": lic.get("name", "unknown"),
|
|
209
|
+
"commercial_use": lic.get("commercial_use", "unknown"),
|
|
210
|
+
"officiality": off,
|
|
211
|
+
"artifact_source": art.get("huggingface", {}).get("url", ""),
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
def tasks(self) -> dict[str, list[str]]:
|
|
215
|
+
"""List all supported task keywords grouped by capability.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Dict mapping capability name to list of task synonyms.
|
|
219
|
+
"""
|
|
220
|
+
from .catalog import TASK_MAP
|
|
221
|
+
from collections import defaultdict
|
|
222
|
+
|
|
223
|
+
cap_to_tasks: dict[str, list[str]] = defaultdict(list)
|
|
224
|
+
for task_syn, caps in TASK_MAP.items():
|
|
225
|
+
for cap in caps:
|
|
226
|
+
cap_to_tasks[cap].append(task_syn)
|
|
227
|
+
|
|
228
|
+
return {cap: sorted(syns) for cap, syns in sorted(cap_to_tasks.items())}
|
|
229
|
+
|
|
230
|
+
def capabilities(self) -> list[dict[str, Any]]:
|
|
231
|
+
"""List all capabilities with model counts.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
List of dicts with capability name, model count, and benchmark count.
|
|
235
|
+
"""
|
|
236
|
+
from collections import Counter
|
|
237
|
+
|
|
238
|
+
cap_counts: Counter = Counter()
|
|
239
|
+
bench_counts: Counter = Counter()
|
|
240
|
+
for m in self._cat.models:
|
|
241
|
+
has_bench = bool(self._cat.get_benchmarks(m["id"]))
|
|
242
|
+
for c in m.get("capabilities", []):
|
|
243
|
+
cap_counts[c] += 1
|
|
244
|
+
if has_bench:
|
|
245
|
+
bench_counts[c] += 1
|
|
246
|
+
|
|
247
|
+
return [
|
|
248
|
+
{
|
|
249
|
+
"capability": cap,
|
|
250
|
+
"model_count": count,
|
|
251
|
+
"benchmark_count": bench_counts.get(cap, 0),
|
|
252
|
+
}
|
|
253
|
+
for cap, count in cap_counts.most_common()
|
|
254
|
+
]
|