"""Apple Machine Learning Research — RSS feed → `paper` entities (title, date, abstract, URL) + ANNOUNCEMENT events. Each research page is followed deterministically (no LLM) to pick up the arXiv / PDF links and the author list when present. """ from __future__ import annotations import re from aiatlas.registry import org_ref from aiatlas.sdk.connector import BaseConnector, Parsed, RunContext from aiatlas.sdk.extract.html import node_text from aiatlas.sdk.facts import EntityRef, Facts, Target from aiatlas.sdk.fetch import FetchResult from ._common import announcement_events FEED = "https://machinelearning.apple.com/rss.xml" ARXIV = re.compile(r"arxiv\.org/(?:abs|pdf)/(\d{4}\.\d{4,5})(?:v\d+)?") class AppleMLConnector(BaseConnector): name = "apple_ml" label = "Apple Machine Learning Research — feed" description = "Apple Machine Learning Research RSS: research items as paper entities (+ arXiv links from the research pages) and events." source_key = "machinelearning.apple.com" version = "1" parser_version = "1" interval_seconds = 21600 min_interval_seconds = 7200 rate_per_min = 10 tier = 1 priority = 1 expected_min_records = 5 concurrency = 2 async def discover(self, ctx: RunContext) -> list[Target]: return [Target(url=FEED, doc_type="feed", key="feed", min_bytes=500)] async def extract(self, ctx: RunContext, target: Target, res: FetchResult, parsed: Parsed) -> Facts: facts = Facts() org = org_ref("apple") facts.entities.append(org) if parsed.kind == "feed": for it in parsed.feed_items: if not it.url or not it.title: continue paper = facts.entity("paper", it.title, identifiers={"url": it.url.rstrip("/")}, organization=org) facts.claim(paper, "published_at", it.published_at.date().isoformat() if it.published_at else None) facts.claim(paper, "abstract", (it.summary or "")[:2000] or None) facts.claim(paper, "authors", it.authors or None) facts.claim(paper, "paper_url", it.url) facts.relate(paper, "published_by", org) facts.follow(it.url, doc_type="paper_page", entity=paper, key=f"paper:{it.url.rstrip('/').rsplit('/', 1)[-1]}", priority=2, min_bytes=1000) announcement_events(facts, org, parsed.feed_items, source_name="machinelearning.apple.com", follow=False, importance_default=1) facts.document_title, facts.document_entity = "Apple Machine Learning Research", org elif target.doc_type == "paper_page" and parsed.html: url = (res.final_url or res.url).rstrip("/") title = next((t for lvl, t in parsed.html.headings if lvl == 1), None) or (parsed.html.title or "").split(" - Apple")[0].strip() paper = target.entity or (EntityRef(entity_type="paper", name=title, identifiers={"url": url}, organization=org) if title else None) if paper is not None: self._paper_page(facts, org, paper, parsed) return facts def _paper_page(self, facts: Facts, org: EntityRef, paper: EntityRef, parsed: Parsed) -> None: html = parsed.html assert html if paper not in facts.entities: facts.entities.append(paper) facts.relate(paper, "published_by", org) facts.document_entity = paper facts.document_title = html.title for href, _text in html.links: m = ARXIV.search(href) if m: paper.identifiers.setdefault("arxiv", m.group(1)) facts.claim(paper, "arxiv_id", m.group(1)) facts.claim(paper, "pdf_url", f"https://arxiv.org/pdf/{m.group(1)}") break else: pdf = next((h for h, _t in html.links if h.lower().endswith(".pdf")), None) facts.claim(paper, "pdf_url", pdf) #

AuthorsName‡, Name†**, …

— footnote marks (affiliations) stripped authors: list[str] = [] for p in html.css("p"): span = p.css_first("span.a11y") if span is None or node_text(span).lower() != "authors": continue text = node_text(p)[len(node_text(span)):] for raw in text.split(","): name_ = re.sub(r"[‡†§*¶#0-9]+", "", raw).strip() if 3 <= len(name_) <= 60 and name_ not in authors: authors.append(name_) break if authors: facts.claim(paper, "authors", authors[:40]) # publication date comes from the feed (day precision); the page only states the month CONNECTORS = [AppleMLConnector]