"""Qwen (Alibaba) — official blog RSS → ANNOUNCEMENT / RELEASE events; release posts followed for LLM extraction. Almost every Qwen post announces a model (Qwen3-…, Qwen-Image, Qwen3Guard…), so items whose title names a model are treated as releases and their article is queued with `llm_task: release_announcement` (the model passport is filled by the LLM stage, never guessed here). """ from __future__ import annotations import re from aiatlas.registry import org_ref from aiatlas.sdk.connector import BaseConnector, Parsed, RunContext from aiatlas.sdk.facts import Facts, Target from aiatlas.sdk.fetch import FetchResult from ._common import RELEASE_WORDS FEED = "https://qwenlm.github.io/blog/index.xml" MODEL_IN_TITLE = re.compile(r"\b(Qwen[\w.\-]*|QwQ[\w.\-]*|QVQ[\w.\-]*|Qwen-Image[\w.\-]*|Qwen-Agent|Wan[\w.\-]*)\b", re.IGNORECASE) MAX_FOLLOW = 30 class QwenConnector(BaseConnector): name = "qwen" label = "Qwen — blog feed" description = "Qwen team blog (qwenlm.github.io) RSS: model release posts as RELEASE announcements queued for LLM extraction." source_key = "qwenlm.github.io" version = "1" parser_version = "1" interval_seconds = 3600 min_interval_seconds = 1800 rate_per_min = 10 tier = 1 priority = 0 expected_min_records = 1 concurrency = 2 async def discover(self, ctx: RunContext) -> list[Target]: return [Target(url=FEED, doc_type="feed", key="feed", min_bytes=1000)] async def extract(self, ctx: RunContext, target: Target, res: FetchResult, parsed: Parsed) -> Facts: facts = Facts() org = org_ref("qwen") facts.entities.append(org) if parsed.kind != "feed": return facts for i, it in enumerate(parsed.feed_items): if not it.url or not it.title: continue names = sorted({m.group(1) for m in MODEL_IN_TITLE.finditer(it.title)}) is_release = bool(names) or bool(RELEASE_WORDS.search(f"{it.title} {it.summary or ''}")) facts.event("ANNOUNCEMENT", "release" if is_release else "company", f"Qwen: {it.title}", entity=org, importance=2 if is_release else 1, effective_at=it.published_at, dedupe_key=f"ANNOUNCEMENT:{it.url}", source_url=it.url, meta={"source": "qwenlm.github.io/blog", "summary": (it.summary or "")[:300], "models_mentioned": names[:5], "is_release": is_release}) if i < MAX_FOLLOW: facts.follow(it.url, doc_type="news", needs_llm=is_release, priority=1 if is_release else 3, meta={"llm_task": "release_announcement", "published_at": it.published_at.isoformat() if it.published_at else None, "title": it.title, "models_mentioned": names[:5]}) facts.document_title, facts.document_entity = "Qwen blog", org return facts CONNECTORS = [QwenConnector]