Build a Model Catalog Drift Monitor for Chinese AI APIs A developer built a model catalog drift monitor for OpenAI-compatible Chinese AI APIs, designed to catch changes in model names, context windows, output limits, and pricing before they cause incidents. The monitor checks official source pages, such as DeepSeek, Kimi, Z.AI, and QwenCloud, and stores only provider metadata, not credentials or user traffic. It aims to prevent 'boring mismatches' like outdated aliases or incorrect billing assumptions. Chinese AI APIs are moving quickly enough that a static SDK configuration can become stale before the next sprint planning meeting. Model names change, cache billing fields appear, context windows expand, output limits move, and pricing notices can arrive before finance has updated the spreadsheet. That does not mean every application needs a complex provider abstraction. It means production teams need a small control loop that treats model catalogs as live operational data. If your SaaS product calls DeepSeek, Qwen, GLM, Kimi, or an aggregator such as AIWave, the question is not only "does the request succeed?" The better question is "does the model contract we ship today still match the provider facts we checked today?" This article walks through a practical model catalog drift monitor for OpenAI-compatible Chinese AI APIs. The goal is to catch changes before they become incidents: a model version changes, cache pricing moves, the output limit is smaller than your summarizer expects, or a provider adds a peak-hour rule that your cost estimates ignore. I checked the official source pages on August 13, 2026. DeepSeek's pricing page currently lists deepseek-v4-flash and deepseek-v4-pro with 1M context and includes an announced peak/off-peak pricing update for August 16, 2026. Kimi's K3 page lists a 1,048,576-token context window and separate cache-hit, cache-miss, and output rates. Z.AI publishes USD pricing for GLM-5.2 and GLM-5.1, including cached input. QwenCloud's model marketplace lists per-model details for Qwen3.7 Max, Qwen3.7 Flash, and Qwen3 open-source snapshots. AIWave exposes an OpenAI-compatible model list endpoint for applications that want one place to discover available Chinese models. The monitor below does not scrape credentials, does not store prompts, and does not need real user traffic. It stores only provider metadata. Most AI incidents are not dramatic provider outages. They are boring mismatches. A coding agent sends 90K tokens to a model that used to support the request shape, but the configured alias now points somewhere else. A billing forecast assumes one output rate, while the provider has split pricing by cache hit and cache miss. A procurement review compares list prices from last month and misses a dated pricing notice. An engineering team deploys a fallback chain but never checks whether the fallback has function calling, structured outputs, or enough context. These problems are preventable if you promote model metadata to a first-class artifact. At minimum, track: | Field | Why it matters | Example source checked on August 13, 2026 | |---|---|---| | Model ID | Request routing and SDK config depend on exact identifiers. | deepseek-v4-pro , qwen3.7-max , glm-5.2 , kimi-k3 | | Model version | Version changes can affect evaluations and prompt behavior. | DeepSeek lists V4 model versions on its pricing page. | | Context window | Long-context agents fail or truncate silently when assumptions drift. | Kimi K3 and Qwen3.7 pages list 1M context. | | Output limit | Summarizers, code generators, and report writers need realistic caps. | QwenCloud lists max output per model page. | | Cache input rate | Repeated context cost depends on cache treatment. | DeepSeek, Kimi, Z.AI, and QwenCloud expose cache-related fields. | | Output rate | Agent cost is often dominated by generated tokens. | Each provider lists separate output pricing. | | Rate limits | Production concurrency should reflect documented RPM and TPM. | QwenCloud pages include model-level rate limits. | | Upcoming notices | Future changes should create tickets before the effective date. | DeepSeek announces a price schedule change for August 16, 2026. | The table is intentionally operational. It is not a market comparison for a landing page. It is an input to CI, release review, and finance reconciliation. Every provider describes its catalog differently. Some publish one pricing table, some expose model pages, and aggregators usually expose an API endpoint. Normalize those sources into a small schema before you compare anything. python from dataclasses import dataclass, asdict from decimal import Decimal from typing import Optional @dataclass frozen=True class ModelCatalogRow: provider: str model: str source url: str checked date: str input per mtok: Optional Decimal = None cached input per mtok: Optional Decimal = None cache write per mtok: Optional Decimal = None output per mtok: Optional Decimal = None context tokens: Optional int = None max output tokens: Optional int = None rpm: Optional int = None tpm: Optional int = None pricing note: str = "" def serialize row: ModelCatalogRow - dict: data = asdict row for key, value in data.items : if isinstance value, Decimal : data key = str value return data Use Decimal for prices. Float math is tolerable for dashboards, but it is a poor default for billing controls. Also store the source URL and the date you checked it. A price without a date is not an operational fact; it is a rumor waiting to become a stale assumption. Here is a hand-maintained seed file based on the official pages checked today. In production, you can move the collection step behind browser automation, provider APIs, or a manual approval queue. The drift logic stays the same. python from decimal import Decimal CHECKED DATE = "2026-08-13" CATALOG = ModelCatalogRow provider="DeepSeek", model="deepseek-v4-flash", source url="https://api-docs.deepseek.com/quick start/pricing/", checked date=CHECKED DATE, input per mtok=Decimal "0.14" , cached input per mtok=Decimal "0.0028" , output per mtok=Decimal "0.28" , context tokens=1 000 000, max output tokens=384 000, pricing note="Provider page announces new peak/off-peak rates effective 2026-08-16 16:00 UTC.", , ModelCatalogRow provider="DeepSeek", model="deepseek-v4-pro", source url="https://api-docs.deepseek.com/quick start/pricing/", checked date=CHECKED DATE, input per mtok=Decimal "0.435" , cached input per mtok=Decimal "0.003625" , output per mtok=Decimal "0.87" , context tokens=1 000 000, max output tokens=384 000, pricing note="Provider page announces new peak/off-peak rates effective 2026-08-16 16:00 UTC.", , ModelCatalogRow provider="Kimi", model="kimi-k3", source url="https://www.kimi.com/resources/kimi-k3-pricing", checked date=CHECKED DATE, input per mtok=Decimal "3.00" , cached input per mtok=Decimal "0.30" , output per mtok=Decimal "15.00" , context tokens=1 048 576, , ModelCatalogRow provider="Z.AI", model="glm-5.2", source url="https://docs.z.ai/guides/overview/pricing", checked date=CHECKED DATE, input per mtok=Decimal "1.40" , cached input per mtok=Decimal "0.26" , output per mtok=Decimal "4.40" , , ModelCatalogRow provider="QwenCloud", model="qwen3.7-max", source url="https://www.qwencloud.com/models/qwen3.7-max", checked date=CHECKED DATE, input per mtok=Decimal "1.25" , cached input per mtok=Decimal "0.25" , cache write per mtok=Decimal "1.5625" , output per mtok=Decimal "3.75" , context tokens=1 000 000, max output tokens=131 000, rpm=600, tpm=1 000 000, , ModelCatalogRow provider="QwenCloud", model="qwen3.7-flash", source url="https://www.qwencloud.com/models/qwen3.7-flash", checked date=CHECKED DATE, input per mtok=Decimal "0.03" , cached input per mtok=Decimal "0.006" , cache write per mtok=Decimal "0.038" , output per mtok=Decimal "0.13" , context tokens=1 000 000, max output tokens=131 000, rpm=15 000, tpm=5 000 000, , Notice the monitor captures both provider-specific nuance and normalized values. QwenCloud separates implicit cache reads and explicit cache creation. DeepSeek has a dated future pricing notice. Kimi K3 has a large output price compared with its cache-hit input rate. Z.AI publishes cached input rates for GLM. Those details should not be flattened into a single "price" column. Once you have yesterday's snapshot and today's snapshot, drift detection is straightforward. Compare by provider and model, then emit changes that matter to engineering, finance, and product. python import json from pathlib import Path WATCH FIELDS = "input per mtok", "cached input per mtok", "cache write per mtok", "output per mtok", "context tokens", "max output tokens", "rpm", "tpm", "pricing note", def load snapshot path: Path - dict tuple str, str , dict : if not path.exists : return {} rows = json.loads path.read text encoding="utf-8" return { row "provider" , row "model" : row for row in rows} def diff snapshots previous: dict, current: dict - list dict : events = all keys = sorted set previous | set current for key in all keys: before = previous.get key after = current.get key provider, model = key if before is None: events.append {"severity": "info", "provider": provider, "model": model, "change": "model added"} continue if after is None: events.append {"severity": "warning", "provider": provider, "model": model, "change": "model removed"} continue for field in WATCH FIELDS: if before.get field = after.get field : severity = "warning" if field.endswith " per mtok" or field in {"context tokens", "max output tokens"} else "info" events.append { "severity": severity, "provider": provider, "model": model, "change": field, "before": before.get field , "after": after.get field , "source url": after.get "source url" , "checked date": after.get "checked date" , } return events def write snapshot path: Path, rows: list ModelCatalogRow - None: payload = serialize row for row in rows path.write text json.dumps payload, indent=2, ensure ascii=False + "\n", encoding="utf-8" The key design choice is severity. A model added to the marketplace is useful information. A model removed from a configured route is a release blocker. A context window reduction can break user workflows. A cache price change can distort gross margin. A dated pricing notice should create a finance and routing review task even before the number changes. Snapshot diffs tell you what changed. Policy checks tell you whether your application can still operate within its own requirements. For example, suppose a Tier 1 SaaS team uses long-context coding agents and requires: Represent that as code. Keep it small enough that an on-call engineer can read it at 2 a.m. python import datetime as dt def validate policy rows: list ModelCatalogRow , today: str - list str : issues = today date = dt.date.fromisoformat today for row in rows: age = today date - dt.date.fromisoformat row.checked date .days if age 7: issues.append f"{row.provider}/{row.model}: source check is {age} days old" if not row.source url.startswith "https://" : issues.append f"{row.provider}/{row.model}: source URL is missing or not HTTPS" if row.context tokens is not None and row.context tokens < 128 000: issues.append f"{row.provider}/{row.model}: context below 128K" if row.output per mtok is None: issues.append f"{row.provider}/{row.model}: output price missing" if row.cached input per mtok is None and row.context tokens and row.context tokens = 500 000: issues.append f"{row.provider}/{row.model}: long-context model has no cached input field" return issues Run this as part of a daily job and again before changing model routes. If it fails, do not silently update the SDK. Open a review. The point is not to block every change; the point is to make invisible drift visible. If you use a direct provider integration, your monitor should read each provider's public docs or marketplace pages. If you use AIWave, you can also check AIWave's OpenAI-compatible model list endpoint and compare it with the provider facts you care about. The useful pattern is two layers: AIWave can simplify the route layer because your application can keep one OpenAI-compatible client, one USD billing relationship, and one set of operational policies while still switching among 25+ Chinese models. That does not remove the need for validation. It makes validation easier to centralize. Here is a minimal route check against an OpenAI-compatible model list. Use your own base URL and keep the key in the environment. php import os import requests def fetch openai compatible models base url: str - set str : api key = os.environ.get "AIWAVE API KEY" if not api key: raise RuntimeError "AIWAVE API KEY is required" response = requests.get f"{base url.rstrip '/' }/v1/models", headers={"Authorization": f"Bearer {api key}"}, timeout=20, response.raise for status payload = response.json return {item "id" for item in payload.get "data", if "id" in item} def check required routes available: set str , required: set str - list str : return sorted required - available This is intentionally separate from price collection. A production gateway can expose a model while a pricing page has changed; or a provider page can add a model before your gateway makes it available. You need both facts. A good drift monitor produces boring, specific tickets: The ticket should include the source URL, checked date, old value, new value, affected internal route, and owner. Avoid generic alerts like "AI pricing changed." They create work without creating clarity. For finance, keep a compact CSV export. For engineering, keep a JSON snapshot in version control or object storage. For product, summarize changes in release review when they affect user-facing capabilities. Before you trust the monitor, run it through the same discipline as any operational tool: Decimal for price fields.The engineering work is small. The habit is the hard part. Model catalogs are now part of production configuration. Teams that track them explicitly will move faster because every route, fallback, and cost estimate starts from current facts instead of stale notes. Chinese AI model APIs are valuable precisely because the ecosystem is active. New versions, bigger contexts, cache rules, and pricing updates are normal. A model catalog drift monitor lets you benefit from that pace without letting it surprise your SDK, your users, or your invoice review.