SPB Git forge

spb/ai-atlas

Public
41commits 1branches 0releases
4.6 MBsize
maindefault branch
12 days agolast push
HTML 77.2% TypeScript 10.5% Python 9.6% JavaScript 2.5%

OpenRouter routers are products, not models; official-org quantisations are artifacts with a same-org canonical (None when unsure)

`openrouter/*` ids (auto, auto-beta, pareto-code, free, fusion…) → `product` entities (kind router) operated by OpenRouter, price booked
against the product when not dynamic. Hugging Face: a quant/precision token in the repo name makes the repo an artifact even under the
developer's own org (nvidia/Gemma-4-31B-IT-NVFP4, tencent/HY-MT1.5-1.8B-FP8, LiquidAI/LFM2.5-230M-GGUF, black-forest-labs/FLUX.2-klein-4b-fp8);
canonical = the model built from the stripped name under the family's developer (medium confidence), or None when nothing can be stripped
or the developer is unknown — never an invented model.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed 12 days ago (Sep 12, 2026) parent dfd3abf

4 changed files +62 −3

modified src/aiatlas/connectors/hub/huggingface.py +9 −3
@@ -393,13 +393,17 @@ class HuggingFaceConnector(BaseConnector):
393 393 facts.claim(ref, "hf_repo", base_id)
394 394 return ref
395 395
396 − def _canonical_ref(self, facts: Facts, repo_id: str, analysis: NameAnalysis, bases: list[tuple[str, str | None]]) -> EntityRef:
397 − """The model an artifact packages: the `base_model` repo when present, otherwise the analysed base name (medium confidence)."""
396 + def _canonical_ref(self, facts: Facts, repo_id: str, analysis: NameAnalysis, bases: list[tuple[str, str | None]]) -> EntityRef | None:
397 + """The model an artifact packages: the `base_model` repo when present, otherwise the analysed base name (medium confidence) —
398 + `nvidia/Gemma-4-31B-IT-NVFP4` → same-org model "Gemma-4-31B-IT". None when the base cannot be named confidently (no token to strip
399 + from the name, or a redistributor repo whose family is unknown): never an invented model."""
398 400 base = next((b for b, k in bases if k == "quantized" and "/" in b), None) or next((b for b, _ in bases if "/" in b), None)
399 401 if base and base.lower() != repo_id.lower():
400 402 return self._base_ref(facts, base)
401 403 org_slug, _, repo_name = repo_id.partition("/")
402 404 name = canonical_name(repo_name)
405 + if not name or name.lower() == repo_name.lower() or not re.search(r"[a-z]", name, re.IGNORECASE):
406 + return None
403 407 org: EntityRef | None = None
404 408 family_orgs = _family_orgs(repo_name)
405 409 if family_orgs and org_slug.lower() in family_orgs:
@@ -408,7 +412,9 @@ class HuggingFaceConnector(BaseConnector):
408 412 hf_org = next((o for o in sorted(family_orgs) if org_by_hf(o)), None)
409 413 org = self._org_ref(facts, org_by_hf(hf_org)["hf_org"], None) if hf_org else None # type: ignore[index]
410 414 elif org_slug.lower() not in REDISTRIBUTORS:
411 − org = self._org_ref(facts, org_slug, None)
415 + org = self._org_ref(facts, org_slug, None) # the official developer's own quantisation / conversion → its own model
416 + if org is None:
417 + return None
412 418 for e in facts.entities:
413 419 if e.entity_type == "model" and e.name.lower() == name.lower() and (org is None or e.organization is None or e.organization.identifiers == org.identifiers):
414 420 return e
modified src/aiatlas/connectors/providers/openrouter.py +17 −0
@@ -79,6 +79,9 @@ class OpenRouterConnector(BaseConnector):
79 79 variant = variant.lower() if variant else None
80 80 base_id = f"{vendor}/{base_slug}"
81 81 name = _display_name(item.get("name") or base_slug, vendor)
82 + if vendor == "openrouter":
83 + self._router_product(facts, item, aggregator, full_id, base_id, name, variant)
84 + return
82 85 org, provider_key = self._vendor(facts, vendor, item.get("name") or "", base_slug)
83 86 ids = {"openrouter": base_id}
84 87 hf = item.get("hugging_face_id")
@@ -103,6 +106,20 @@ class OpenRouterConnector(BaseConnector):
103 106 # still note the listing so `available_through` exists even without a usable price
104 107 facts.claim(ref, "openrouter_listed", True)
105 108
109 + def _router_product(self, facts: Facts, item: dict[str, Any], aggregator: EntityRef, full_id: str, base_id: str, name: str, variant: str | None) -> None:
110 + """`openrouter/auto`, `openrouter/pareto-code`, `openrouter/free`… are OpenRouter's own routing products, not models: a `product`
111 + entity (kind router) operated by OpenRouter. Their price (when not dynamic `-1`) is booked against the product."""
112 + ref = next((e for e in facts.entities if e.entity_type == "product" and e.identifiers.get("openrouter") == base_id), None)
113 + if ref is None:
114 + org = org_ref_in(facts, "openrouter")
115 + ref = facts.entity("product", name, identifiers={"openrouter": base_id}, organization=org, aliases=[a for a in {item.get("name"), base_id} if a and a != name],
116 + attributes={"kind": "router"}, identity_confidence="high")
117 + facts.claim(ref, "openrouter_id", base_id)
118 + facts.claim(ref, "description", (item.get("description") or "").strip()[:2000] or None)
119 + facts.claim(ref, "context_length", _int(item.get("context_length")), unit="tokens")
120 + facts.relate(aggregator, "operates", ref)
121 + self._price(facts, ref, item, "openrouter", "openrouter", aggregator, full_id, variant)
122 +
106 123 def _claims(self, facts: Facts, ref: EntityRef, item: dict[str, Any]) -> None:
107 124 arch = item.get("architecture") or {}
108 125 top = item.get("top_provider") or {}
modified tests/test_huggingface.py +26 −0
@@ -114,6 +114,32 @@ def test_identity_helpers():
114 114 assert pipeline_modalities("text-to-image") == (["text"], ["image"]) and pipeline_modalities("unknown-tag") == ([], [])
115 115
116 116
117 +def test_official_org_quantisations_are_artifacts(connector):
118 + """A quant/precision token makes the repo an artifact even under the developer's own org; canonical = the same-org model from the stripped
119 + name; None when the base cannot be named confidently."""
120 + from aiatlas.sdk.facts import Facts
121 +
122 + cases = {"nvidia/Gemma-4-31B-IT-NVFP4": ("quantization", "Gemma-4-31B-IT", "Google"), # Gemma is Google's family: NVIDIA quantises it
123 + "tencent/HY-MT1.5-1.8B-FP8": ("quantization", "HY-MT1.5-1.8B", "Tencent"),
124 + "LiquidAI/LFM2.5-230M-GGUF": ("quantization", "LFM2.5-230M", "Liquid AI"), "black-forest-labs/FLUX.2-klein-4b-fp8": ("quantization", "FLUX.2-klein-4b", "Black Forest Labs"),
125 + "Qwen/Qwen3-8B-MLX-bf16": ("conversion", "Qwen3-8B", "Qwen")}
126 + for repo, (kind, base, org_name) in cases.items():
127 + facts = Facts()
128 + org = connector._org_ref(facts, repo.split("/")[0], None)
129 + ref = connector._model_ref(facts, repo, org)
130 + assert ref.entity_type == "artifact" and ref.artifact_kind == kind and ref.name == repo, repo
131 + assert ref.canonical is not None and ref.canonical.entity_type == "model" and ref.canonical.name == base, repo
132 + assert ref.canonical.organization.name == org_name and ref.canonical.identity_confidence == "medium", repo
133 + assert not any(r.predicate == "develops" and r.object is ref for r in facts.relations)
134 + # unsure → no invented model
135 + facts = Facts()
136 + ref = connector._model_ref(facts, "mradermacher/FooBar-GGUF", connector._org_ref(facts, "mradermacher", None))
137 + assert ref.entity_type == "artifact" and ref.canonical is None # redistributor, unknown family
138 + facts = Facts()
139 + ref = connector._model_ref(facts, "Qwen/Qwen3-8B", connector._org_ref(facts, "Qwen", None), quant_format="gguf")
140 + assert ref.entity_type == "artifact" and ref.canonical is None # quantised per tags only: nothing to strip from the name
141 +
142 +
117 143 async def test_daily_papers(connector):
118 144 facts = await extract_from_fixture(connector, Target(url="https://huggingface.co/papers", doc_type="listing", key="papers"), fixture_path("huggingface", "papers.html"))
119 145 papers = [e for e in facts.entities if e.entity_type == "paper"]
modified tests/test_openrouter.py +10 −0
@@ -35,6 +35,16 @@ async def test_catalogue():
35 35 assert not any(p.input_per_mtok is not None and p.input_per_mtok < 0 for p in facts.prices) # dynamic "-1" prices skipped
36 36 assert any("hf_repo" in e.identifiers for e in models)
37 37 assert not any(c.property == "release_date" for c in facts.claims)
38 + # OpenRouter's own routers are products, never models
39 + assert not any(e.identifiers.get("openrouter", "").startswith("openrouter/") for e in models)
40 + routers = [e for e in facts.entities if e.entity_type == "product"]
41 + assert {e.identifiers["openrouter"] for e in routers} >= {"openrouter/auto", "openrouter/pareto-code", "openrouter/free"}
42 + auto = next(e for e in routers if e.identifiers["openrouter"] == "openrouter/auto")
43 + assert auto.name == "Auto Router" and auto.attributes == {"kind": "router"} and auto.organization.name == "OpenRouter"
44 + assert any(r.predicate == "operates" and r.object is auto for r in facts.relations)
45 + assert not any(p.provider_model_id == "openrouter/auto" for p in facts.prices) # dynamic (-1) price skipped
46 + free = next(p for p in facts.prices if p.provider_model_id == "openrouter/free")
47 + assert free.model.entity_type == "product" and free.input_per_mtok == 0.0
38 48
39 49
40 50 def test_helpers():
41 51