درجہ بندی کے ماڈل روٹنگ کا استعمال کرتے ہوئے لاگت سے موثر AI ایجنٹوں کو کیسے بنایا جائے۔

زیادہ تر AI ایجنٹ ٹیوٹوریلز ایک ہی غلطی کرتے ہیں۔ یعنی، یہ تمام آپریشنز کو دستیاب مہنگے ترین ماڈل تک پہنچاتا ہے۔

کریکٹر گنتی کے لیے GPT-4 کی ضرورت نہیں ہے۔ سونیٹ کی موجودگی کی جانچ کرنے کی ضرورت نہیں ہے۔ ریگولر ایکسپریشنز کو ازگر سے زیادہ کچھ نہیں چاہیے۔

غلطی اے آئی کا استعمال نہیں کرنا ہے، لیکن یہ جاننا ہے کہ اسے کب استعمال کرنا بند کرنا ہے۔

یہ ٹیوٹوریل دکھاتا ہے کہ کس طرح ایک درجہ بندی کا روٹنگ سسٹم بنایا جائے جو کام کو سستے ترین ماڈل کی طرف لے جائے جو مسئلہ کو حل کر سکے۔ اس پیٹرن کو لاگت کا وکر کہا جاتا ہے۔ یہ ہفتے کے آخر میں تین ڈویلپرز کے نفاذ کے بارے میں ایک DEV.to مضمون پر تبصرے کے دھاگے سے آیا ہے جس نے زیادہ تر صفحات پر ایک حقیقی SEO آڈٹ ایجنٹ کی لاگت کو \(0.006 سے مؤثر طریقے سے \)0 تک کم کر دیا ہے۔

آخر میں، آپ کا کام ہو جائے گا cost_curve.py ماڈیول کسی بھی ایجنٹ پروجیکٹ میں شامل کیے جاسکتے ہیں۔

کیا تعمیر کرنا ہے

تین درجے کی روٹنگ کی خصوصیات میں شامل ہیں:

  • پہلے ڈیٹرمنسٹک ازگر چیک چلائیں – کوئی API لاگت نہیں ہے۔

  • میں واقعی مبہم معاملات کے لیے صرف کلاڈ ہائیکو کی طرف بڑھتا ہوں۔ ~$0.0001 فی کال

  • Claude Sonnet کی طرف بڑھیں صرف اس صورت میں جب معنوی فیصلوں کی ضرورت ہو۔ ~$0.006 فی کال

  • اگر ایک پرت ناکام ہو جاتی ہے، تو یہ خوبصورتی سے واپس آتی ہے۔

  • درخواست پر کارروائی کرنے والے درجے سے قطع نظر ایک مستقل نتیجہ کا اسکیما لوٹاتا ہے۔

مکمل نفاذ dannwaneri/seo-agent کا حصہ ہے، جو ایک کھلا بنیادی SEO آڈٹ ایجنٹ ہے۔ Cost Curve ماڈیول ایک پریمیم روٹنگ ٹائر ہے اور اس کے اصول مخلوط پیچیدگی کے کام انجام دینے والے تمام ایجنٹوں پر لاگو ہوتے ہیں۔

شرطیں

انڈیکس

  1. ہر چیز کے لیے کلاڈ کو کال کرنے کا مسئلہ

  2. لاگت وکر کی تفصیل

  3. پروجیکٹ کی ترتیبات

  4. پرت 1: ڈیٹرمنسٹک ازگر

  5. ٹائر 2: مبہم مقدمات کے لیے کلاڈ ہائیکو

  6. ٹائر 3: سیمنٹک ججمنٹ کے لیے کلاڈ کے سونیٹ

  7. راؤٹر: audit_url()

  8. خوبصورت متبادل

  9. لاگت وکر ٹیسٹنگ

  10. اس پیٹرن کو اپنے ایجنٹ پر لاگو کریں۔

ہر چیز کے لیے کلاڈ کو کال کرنے کا مسئلہ

زیادہ تر ایجنٹ کوڈ اس طرح لگتا ہے:

def audit_url(snapshot: dict) -> dict:
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        messages=[{"role": "user", "content": build_prompt(snapshot)}]
    )
    return parse_response(response)

یہ کام کرتا ہے۔ یہ فہرست میں ہر یو آر ایل کے لیے سونیٹ کو بھی کال کرتا ہے۔ اگر عنوان 142 حروف لمبا ہے اور کوئی ماڈل شامل نہیں ہے، تو اس میں ایک URL ہوتا ہے جہاں جواب یقینی طور پر فیل ہے۔

Claude Sonnet 4 کی قیمت 3 فی ملین ان پٹ ٹوکن اور 15 فی ملین آؤٹ پٹ ٹوکن ہے۔ ایک عام صفحہ کا سنیپ شاٹ تقریباً 500 ان پٹ ٹوکنز کا ہوتا ہے۔ یہ \(0.0015 فی یو آر ایل صرف آؤٹ پٹ ٹوکن سے پہلے ان پٹ کے لیے ہے۔ 20 یو آر ایل کے ہفتہ وار آڈٹ میں، کل تقریباً \)0.12 ہے۔ یہ مہنگا نہیں ہے۔ تاہم، زیادہ تر صفحات میں مکینیکل SEO کے مسائل ہوتے ہیں، جیسے گمشدہ تفصیل، 60 حروف سے زیادہ عنوانات، اور کوئی کیننیکل ٹیگز نہیں۔ کردار کی گنتی یہ سب کچھ حاصل کرتی ہے۔ کسی ماڈل کی ضرورت نہیں ہے۔

لاگت کے منحنی خطوط اس مسئلے کو روٹنگ کے ذریعے حل کرتے ہیں اس کی بنیاد پر کہ کام کی اصل میں کیا ضرورت ہے، بجائے اس کے کہ ماڈل کس قابل ہے۔

لاگت وکر کی تفصیل

لاگت کے منحنی خطوط میں تین درجے، تین ٹولز، اور تین قیمت پوائنٹس ہیں۔

ٹائر 1 – ڈیٹرمنسٹک ازگر۔ لاگت: $0۔ عنوان کی لمبائی، تفصیل کی لمبائی، H1 شمار، اور رسمی وجود کو چیک کریں۔ یہ فیصلہ کال نہیں ہے۔ یہ ایک سٹرنگ آپریشن ہے۔ اگر عنوان کی لمبائی 60 سے زیادہ ہے تو ناکام ہو جاتا ہے۔ کسی ماڈل کی ضرورت نہیں ہے۔

ٹائر 2 – کلاڈ ہائیکو۔ لاگت: ~$0.0001 فی کال۔ ایک عنوان ہے، لیکن یہ 4 حروف طویل ہے۔ ایک تفصیل ہے، لیکن یہ صرف 30 حروف کی ہو سکتی ہے۔ اسٹیٹس کوڈ ری ڈائریکٹ ہے۔ اس نے مکینیکل آڈٹ پاس کیا، لیکن کچھ گڑبڑ ہے۔ ہائیکو تیز اور سستا ہے، اس لیے مشکوک کیسز کو بڑھانا جھوٹے مثبت کو ڈیبگ کرنے کے وقت سے کم خرچ کرتا ہے۔

ٹائر 3 – کلاڈ کے سونیٹ۔ لاگت: ~$0.006 فی کال۔ صفحات ہائیکو اس بات کی نشاندہی کرتے ہیں کہ معنوی فیصلوں کی ضرورت ہے۔ "یہ عنوان لمبا ہے، لیکن نیویگیشن لیبل کی طرح پڑھتا ہے۔” "یہ تفصیل عنوان کی نقل ہے۔” سونیٹ واقعی مشکل معاملات کے لیے پیسہ کماتا ہے، فہرست میں موجود ہر یو آر ایل کے لیے نہیں۔

روٹنگ کے فیصلے API کالز سے پہلے ہوتے ہیں۔ اس سے قطع نظر کہ کس درجے نے درخواست پر کارروائی کی ہے، نتیجہ خیز اسکیما ایک ہی ہے۔

پروجیکٹ کی ترتیبات

mkdir cost-curve-demo && cd cost-curve-demo
pip install anthropic

اپنی API کلید ترتیب دیں۔

# macOS/Linux
export ANTHROPIC_API_KEY="sk-ant-..."

# Windows PowerShell
$env:ANTHROPIC_API_KEY = "sk-ant-..."

بنانا cost_curve.py – آپ اس ماڈیول کو مرحلہ وار بنائیں گے۔

پرت 1: ڈیٹرمنسٹک ازگر

ٹائر 1 تمام URLs پر پہلے چلتا ہے۔ صرف Python سٹرنگ آپریشنز کا استعمال کرتے ہوئے چار فیلڈز کو چیک کریں۔ کوئی API کال نہیں، کوئی تاخیر نہیں، کوئی قیمت نہیں۔

import json
import logging
import os
import re
from datetime import datetime, timezone

import anthropic

logger = logging.getLogger(__name__)

REDIRECT_CODES = {301, 302, 307, 308}

# Fields that trigger Tier 2 escalation
# Title or description present but suspiciously short
AMBIGUOUS_TITLE_MAX = 10   # chars — present but too short to be real
AMBIGUOUS_DESC_MAX = 50    # chars — present but too short to be useful


def _now_iso() -> str:
    return datetime.now(timezone.utc).isoformat()


def _build_result(snapshot: dict, method: str) -> dict:
    """Base result skeleton — same schema regardless of tier."""
    return {
        "url": snapshot.get("final_url", ""),
        "final_url": snapshot.get("final_url", ""),
        "status_code": snapshot.get("status_code"),
        "title": {"value": None, "length": 0, "status": "PASS"},
        "description": {"value": None, "length": 0, "status": "PASS"},
        "h1": {"count": 0, "value": None, "status": "PASS"},
        "canonical": {"value": None, "status": "PASS"},
        "flags": [],
        "human_review": False,
        "audited_at": _now_iso(),
        "method": method,
        "needs_tier3": False,
    }


def tier1_check(snapshot: dict) -> dict:
    """
    Pure Python SEO checks. Zero API calls.

    Returns a result dict with method="deterministic".
    Sets needs_tier3=False always — Tier 1 never escalates to Tier 3 directly.
    Escalation to Tier 2 is decided by the router, not here.
    """
    result = _build_result(snapshot, "deterministic")

    title = snapshot.get("title") or ""
    description = snapshot.get("meta_description") or ""
    h1s = snapshot.get("h1s") or []
    canonical = snapshot.get("canonical") or ""

    # Title check
    result["title"]["value"] = title or None
    result["title"]["length"] = len(title)
    if not title or len(title) > 60:
        result["title"]["status"] = "FAIL"
        msg = "Title is missing" if not title else f"Title is {len(title)} characters (max 60)"
        result["flags"].append(msg)

    # Description check
    result["description"]["value"] = description or None
    result["description"]["length"] = len(description)
    if not description or len(description) > 160:
        result["description"]["status"] = "FAIL"
        msg = "Meta description is missing" if not description else f"Meta description is {len(description)} characters (max 160)"
        result["flags"].append(msg)

    # H1 check
    result["h1"]["count"] = len(h1s)
    result["h1"]["value"] = h1s[0] if h1s else None
    if len(h1s) == 0:
        result["h1"]["status"] = "FAIL"
        result["flags"].append("H1 tag is missing")
    elif len(h1s) > 1:
        result["h1"]["status"] = "FAIL"
        result["flags"].append(f"Multiple H1 tags found ({len(h1s)})")

    # Canonical check
    result["canonical"]["value"] = canonical or None
    if not canonical:
        result["canonical"]["status"] = "FAIL"
        result["flags"].append("Canonical tag is missing")

    return result

کلیدی ڈیزائن فیصلے: tier1_check() آپ یہ فیصلہ نہیں کرتے کہ بڑھنا ہے یا نہیں۔ بس چیک چلائیں اور اسے واپس کریں۔ راؤٹر نتائج کی بنیاد پر اضافہ کا تعین کرتا ہے۔

ٹائر 2: مبہم مقدمات کے لیے کلاڈ ہائیکو

ٹائر 2 کو اس وقت متحرک کیا جاتا ہے جب ٹائر 1 کو کسی میکانیکل مسئلہ کا پتہ چلتا ہے لیکن نتائج کو دو بار چیک کرنے کی ضرورت ہوتی ہے۔ اس کا چار حرفی عنوان ہے، لیکن یہ واضح طور پر غلط ہے۔ یہ 30 حروف کی تفصیل ہے جو تکنیکی طور پر درست ہے، لیکن بیکار ہے۔ ری ڈائریکشن کی حالت جس کے لیے انسانی پڑھنے کے قابل وضاحت درکار ہے۔

ہائیکو یہاں ایک مناسب نمونہ ہے۔ یہ تیز، سستا ہے (\(1 ان پٹ/\)5 آؤٹ پٹ فی ملین ٹوکنز) اور درجہ بندی کی سطح کے تعین کے لیے کافی ہے۔ پرامپٹ ایک تنگ سوال پوچھتا ہے۔ کیا یہ ایک سانیٹ کی ضرورت کے لیے کافی مبہم ہے؟

def tier2_check(snapshot: dict) -> dict:
    """
    Claude Haiku call for ambiguous cases.

    Returns result with method="haiku".
    Sets needs_tier3=True if Haiku determines the case needs semantic judgment.
    Falls back to Tier 1 result on API error.
    """
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if not api_key:
        raise OSError("ANTHROPIC_API_KEY is not set.")

    client = anthropic.Anthropic(api_key=api_key)

    title = snapshot.get("title") or ""
    description = snapshot.get("meta_description") or ""
    status_code = snapshot.get("status_code")

    prompt = f"""You are an SEO auditor doing a quick triage check.

Page data:
- Title: {repr(title)} ({len(title)} chars)
- Meta description: {repr(description)} ({len(description)} chars)
- Status code: {status_code}

Answer these two questions with only "yes" or "no":
1. Does this page need semantic judgment beyond simple length/presence checks? 
   (e.g. title is present but clearly wrong, description is present but meaningless)
2. Is the status code a redirect that needs investigation?

Respond in this exact JSON format and nothing else:
{{"needs_tier3": true_or_false, "reason": "one sentence explanation"}}"""

    try:
        response = client.messages.create(
            model="claude-haiku-4-5-20251001",
            max_tokens=150,
            messages=[{"role": "user", "content": prompt}],
        )
        raw = response.content[0].text.strip()
        # Strip markdown fences if present
        if raw.startswith("```"):
            lines = raw.splitlines()
            raw = "\n".join(lines[1:-1] if lines[-1].strip() == "```" else lines[1:])
        parsed = json.loads(raw)

        result = _build_result(snapshot, "haiku")
        # Copy Tier 1 field checks — Haiku doesn't redo those
        t1 = tier1_check(snapshot)
        result["title"] = t1["title"]
        result["description"] = t1["description"]
        result["h1"] = t1["h1"]
        result["canonical"] = t1["canonical"]
        result["flags"] = t1["flags"]
        result["needs_tier3"] = parsed.get("needs_tier3", False)
        if result["needs_tier3"]:
            result["flags"].append(f"Escalated to Tier 3: {parsed.get('reason', '')}")

        return result

    except Exception as exc:
        logger.warning("[tier2] Haiku API error: %s — falling back to Tier 1 result", exc)
        fallback = tier1_check(snapshot)
        fallback["method"] = "haiku-fallback"
        return fallback

فال بیک ایک اہم حصہ ہے۔ اگر ہائیکو ناکام ہوجاتا ہے (شرح کی حد، نیٹ ورک کی خرابی، غلط جواب)، فنکشن کریش کے بجائے ٹائر 1 کا نتیجہ لوٹاتا ہے۔ شکر گزاری جاری ہے۔ URL اس طرح نظر آئے گا: method="haiku-fallback" تاکہ آپ بعد میں اس کی شناخت کر سکیں۔

ٹائر 3: سیمنٹک ججمنٹ کے لیے کلاڈ کے سونیٹ

ٹائر 3 وہ جگہ ہے جہاں مکمل نکالنے کا اشارہ چلتا ہے۔ یہ وہی کال ہے جو سادہ عمل درآمد کرے گی۔ فرق یہ ہے کہ URLs کا صرف ایک چھوٹا حصہ اس پرت تک پہنچتا ہے۔

def tier3_check(snapshot: dict) -> dict:
    """
    Claude Sonnet call for semantic judgment.

    Returns result with method="sonnet".
    This is the full extraction prompt — same as calling the model directly.
    """
    api_key = os.environ.get("ANTHROPIC_API_KEY")
    if not api_key:
        raise OSError("ANTHROPIC_API_KEY is not set.")

    client = anthropic.Anthropic(api_key=api_key)

    prompt = f"""You are an SEO auditor. Analyze this page snapshot and return ONLY a JSON object.
No prose. No explanation. No markdown fences. Raw JSON only.

Page data:
- URL: {snapshot.get('final_url')}
- Status code: {snapshot.get('status_code')}
- Title: {snapshot.get('title')}
- Meta description: {snapshot.get('meta_description')}
- H1 tags: {snapshot.get('h1s')}
- Canonical: {snapshot.get('canonical')}

Return this exact schema:
{{
  "url": "string",
  "final_url": "string",
  "status_code": number,
  "title": {{"value": "string or null", "length": number, "status": "PASS or FAIL"}},
  "description": {{"value": "string or null", "length": number, "status": "PASS or FAIL"}},
  "h1": {{"count": number, "value": "string or null", "status": "PASS or FAIL"}},
  "canonical": {{"value": "string or null", "status": "PASS or FAIL"}},
  "flags": ["array of strings describing specific issues"],
  "human_review": false,
  "audited_at": "ISO timestamp"
}}

PASS/FAIL rules:
- title: FAIL if null or length > 60 characters, or if present but clearly not a real title
- description: FAIL if null or length > 160 characters, or if present but meaningless
- h1: FAIL if count is 0 or count > 1
- canonical: FAIL if null
- audited_at: use current UTC time"""

    try:
        response = client.messages.create(
            model="claude-sonnet-4-20250514",
            max_tokens=1000,
            messages=[{"role": "user", "content": prompt}],
        )
        raw = response.content[0].text.strip()
        if raw.startswith("```"):
            lines = raw.splitlines()
            raw = "\n".join(lines[1:-1] if lines[-1].strip() == "```" else lines[1:])

        result = json.loads(raw)
        result["method"] = "sonnet"
        result["needs_tier3"] = False
        return result

    except Exception as exc:
        logger.warning("[tier3] Sonnet API error: %s — falling back to Tier 1 result", exc)
        fallback = tier1_check(snapshot)
        fallback["method"] = "sonnet-fallback"
        return fallback

ٹائر 3 میں ایک پرامپٹ کا اضافہ نوٹ کریں جو ٹائر 1 میں موجود نہیں ہے۔ "or if present but clearly not a real title" اور "or if present but meaningless". یہ ہائیکو کا ایک معنوی فیصلہ ہے جسے ضروری سمجھا گیا۔ ٹائر 3 اس پر ایکشن لیتا ہے۔

راؤٹر: audit_url()

روٹر ایک عوامی انٹرفیس ہے۔ باقی سب کچھ نفاذ کی تفصیلات ہیں۔

def audit_url(snapshot: dict, tiered: bool = False) -> dict:
    """
    Route a page snapshot through the appropriate audit tier.

    Args:
        snapshot: Page data from browser.py — must contain final_url,
                  status_code, title, meta_description, h1s, canonical.
        tiered: If False, delegates directly to Tier 3 (Sonnet).
                If True, routes through the cost curve.

    Returns:
        Audit result dict with method field indicating which tier ran.
    """
    if not tiered:
        # Non-tiered mode: call Sonnet directly, same as v1 behavior
        return tier3_check(snapshot)

    # Tier 1: always runs first
    t1_result = tier1_check(snapshot)

    # Check if escalation to Tier 2 is warranted
    title = snapshot.get("title") or ""
    description = snapshot.get("meta_description") or ""
    status_code = snapshot.get("status_code")

    needs_tier2 = (
        # Title present but suspiciously short
        (title and len(title) < AMBIGUOUS_TITLE_MAX) or
        # Description present but suspiciously short
        (description and len(description) < AMBIGUOUS_DESC_MAX) or
        # Redirect status — may need explanation
        (status_code in REDIRECT_CODES)
    )

    if not needs_tier2:
        # Tier 1 result is definitive — return without any API call
        return t1_result

    # Tier 2: Haiku triage
    t2_result = tier2_check(snapshot)

    if not t2_result.get("needs_tier3", False):
        # Haiku determined no semantic judgment needed
        return t2_result

    # Tier 3: Sonnet for semantic judgment
    return tier3_check(snapshot)

راؤٹر منطق واضح اور پڑھنے میں آسان ہے۔ ہر فیصلہ نقطہ ایک نامزد شرط ہے۔ جب tiered=Falseطرز عمل v1 کے سادہ نفاذ سے مماثل ہے۔ یہ پسماندہ مطابقت کو یقینی بناتا ہے، موجودہ آڈٹ میں خلل ڈالے بغیر لاگت کے منحنی خطوط کو بتدریج شامل کرنے کی اجازت دیتا ہے۔

خوبصورت متبادل

متبادل پیٹرن ٹائر 2 اور ٹائر 3 دونوں میں ظاہر ہوتا ہے۔ یہ بتانے کے قابل ہے:

# Pattern used in both tier2_check() and tier3_check()
except Exception as exc:
    logger.warning("[tierN] API error: %s — falling back to Tier 1 result", exc)
    fallback = tier1_check(snapshot)
    fallback["method"] = "tierN-fallback"
    return fallback

یہ فنکشن تین چیزیں کرتا ہے:

  1. بعد میں ڈیبگنگ کے لیے کافی سیاق و سباق کے ساتھ غلطیوں کو لاگ کریں۔

  2. ایک درست نتیجہ لوٹاتا ہے۔ ٹائر 1 کے تعین کی جانچ ہمیشہ اس سے قطع نظر چلتی ہے۔

  3. اپنے نتائج کو متبادل طریقے سے ٹیگ کریں تاکہ آپ انہیں اپنی رپورٹس میں فلٹر کر سکیں۔

API کی خرابی کی وجہ سے کریش ہونے والا ایجنٹ پروڈکشن کے لیے تیار نہیں ہے۔ وہ ایجنٹ جو خوبصورتی سے تنزلی اور جاری رکھتے ہیں:

لاگت وکر ٹیسٹنگ

بنانا test_cost_curve.py ریئل ٹائم API کال کیے بغیر روٹنگ کے رویے کو چیک کرنے کے لیے:

import json
from unittest import mock

from cost_curve import audit_url, tier1_check


def make_snapshot(title="Normal Title Under 60 Chars",
                  description="A normal meta description that is under 160 characters and describes the page content well.",
                  h1s=["Single H1"],
                  canonical="https://example.com/page",
                  status_code=200,
                  final_url="https://example.com/page"):
    return {
        "title": title,
        "meta_description": description,
        "h1s": h1s,
        "canonical": canonical,
        "status_code": status_code,
        "final_url": final_url,
    }


def test_clean_page_returns_tier1_no_api_calls():
    """Clean page: all checks pass deterministically — no API call."""
    snapshot = make_snapshot()
    with mock.patch("anthropic.Anthropic") as mock_client:
        result = audit_url(snapshot, tiered=True)
        assert result["method"] == "deterministic"
        mock_client.assert_not_called()
    print("PASS: clean page → Tier 1, zero API calls")


def test_long_title_returns_tier1_fail_no_api_call():
    """Title >60 chars: FAIL from Tier 1, no API call."""
    snapshot = make_snapshot(title="A" * 70)
    with mock.patch("anthropic.Anthropic") as mock_client:
        result = audit_url(snapshot, tiered=True)
        assert result["method"] == "deterministic"
        assert result["title"]["status"] == "FAIL"
        mock_client.assert_not_called()
    print("PASS: title >60 → Tier 1 FAIL, zero API calls")


def test_suspiciously_short_title_escalates_to_tier2():
    """Title present but 4 chars: escalates to Tier 2."""
    snapshot = make_snapshot(title="SEO")  # 3 chars — under AMBIGUOUS_TITLE_MAX
    mock_response = mock.MagicMock()
    mock_response.content = [mock.MagicMock(
        text="{"needs_tier3": false, "reason": "title is short but not ambiguous"}"
    )]
    with mock.patch("anthropic.Anthropic") as mock_client:
        mock_client.return_value.messages.create.return_value = mock_response
        result = audit_url(snapshot, tiered=True)
        assert result["method"] == "haiku"
        assert mock_client.return_value.messages.create.call_count == 1
    print("PASS: short title → Tier 2 (Haiku called once)")


def test_tiered_false_calls_sonnet_directly():
    """tiered=False: Sonnet called regardless of snapshot content."""
    snapshot = make_snapshot()  # clean page, would be Tier 1 in tiered mode
    mock_response = mock.MagicMock()
    mock_response.content = [mock.MagicMock(text=json.dumps({
        "url": "https://example.com/page",
        "final_url": "https://example.com/page",
        "status_code": 200,
        "title": {"value": "Normal Title Under 60 Chars", "length": 27, "status": "PASS"},
        "description": {"value": "desc", "length": 4, "status": "PASS"},
        "h1": {"count": 1, "value": "Single H1", "status": "PASS"},
        "canonical": {"value": "https://example.com/page", "status": "PASS"},
        "flags": [],
        "human_review": False,
        "audited_at": "2026-04-01T00:00:00+00:00",
    }))]
    with mock.patch("anthropic.Anthropic") as mock_client:
        mock_client.return_value.messages.create.return_value = mock_response
        result = audit_url(snapshot, tiered=False)
        assert result["method"] == "sonnet"
        assert mock_client.return_value.messages.create.call_count == 1
    print("PASS: tiered=False → Sonnet called directly")


def test_haiku_api_failure_falls_back_to_tier1():
    """Haiku failure: falls back to Tier 1 result, no crash."""
    snapshot = make_snapshot(title="SEO")  # triggers Tier 2
    with mock.patch("anthropic.Anthropic") as mock_client:
        mock_client.return_value.messages.create.side_effect = Exception("rate limit")
        result = audit_url(snapshot, tiered=True)
        assert result["method"] == "haiku-fallback"
    print("PASS: Haiku failure → fallback to Tier 1, no crash")


if __name__ == "__main__":
    test_clean_page_returns_tier1_no_api_calls()
    test_long_title_returns_tier1_fail_no_api_call()
    test_suspiciously_short_title_escalates_to_tier2()
    test_tiered_false_calls_sonnet_directly()
    test_haiku_api_failure_falls_back_to_tier1()
    print("\nAll tests passed.")

چلائیں:

python test_cost_curve.py

متوقع پیداوار:

PASS: clean page → Tier 1, zero API calls
PASS: title >60 → Tier 1 FAIL, zero API calls
PASS: short title → Tier 2 (Haiku called once)
PASS: tiered=False → Sonnet called directly
PASS: Haiku failure → fallback to Tier 1, no crash

اس پیٹرن کو اپنے ایجنٹ پر لاگو کریں۔

لاگت کا وکر SEO تک محدود نہیں ہے۔ مخلوط پیچیدگی کے کام کرنے والا کوئی بھی ایجنٹ اسے استعمال کرسکتا ہے۔

اصول: یہ فیصلہ کرنے سے پہلے کہ کس ماڈل کو کال کرنا ہے، آپ کو درحقیقت ضرورت کے مطابق کاموں کی درجہ بندی کریں۔

کسٹمر سپورٹ رابطہ:

  • ٹائر 1: مطلوبہ الفاظ معلوم اکثر پوچھے گئے سوالات کے عنوانات سے مماثل ہیں - کوئی ماڈل نہیں۔

  • پرت 2: مبہم سوالات کے لیے ارادے کی درجہ بندی کے لیے ہائیکو۔

  • ٹائر 3: پیچیدہ شکایات کے لیے سونیٹ جن میں فیصلے کی ضرورت ہوتی ہے۔

کوڈ کا جائزہ لینے والا:

  • ٹائر 1: لنٹ کے قواعد، نحو کی جانچ - کوئی ماڈل نہیں۔

  • ٹائر 2: عام پیٹرن کا پتہ لگانے کے لیے ہائیکو

  • ٹائر 3: آرکیٹیکچرل ریویو کے لیے سونیٹ

مواد ماڈریشن ایجنٹ:

  • ٹائر 1: بلاک لسٹ میچ - کوئی ماڈل نہیں۔

  • ٹائر 2: بارڈر لائن کیسز کے لیے ہائیکس

  • ٹائر 3: حالات کے فیصلے کے لیے سونیٹ

عمل درآمد کا طریقہ تینوں صورتوں کے لیے یکساں ہے۔ کہ audit_url() راؤٹر ہے۔ route_task(). درجہ بندی کی خصوصیت اشارے اور اضافے کے حالات کو تبدیل کرتی ہے۔ فال بیک منطق وہی رہتی ہے۔

ایجنٹ کوڈ لکھنے سے پہلے پوچھنا ایک اہم سوال یہ ہے کہ ان پٹ کا کتنا حصہ میکانکی طور پر حل کیا جا سکتا ہے۔ وہ حصہ ٹائر 1 میں جائے گا اور باقی کو بڑھا دیا جائے گا۔ لاگت کا وکر باقی سب کچھ رکھتا ہے۔

ختم

اس ماڈیول کو پیداوار میں استعمال کرنے کے لیے SEO آڈٹ ایجنٹ سمیت مکمل عمل درآمد، dannwaneri/seo-agent پر دستیاب ہے۔ کہ core/ ڈائریکٹری MIT لائسنس یافتہ ہے۔ پرتوں والی روٹنگ ہے۔ premium/cost_curve.py.

یہ ٹیوٹوریل ایک ساتھی حصہ ہے جس کے لیے: میں SEO آڈٹ کے لیے فی یو آر ایل 0.006\)0 ادا کر رہا تھا یہاں تک کہ مجھے احساس ہوا کہ مجھے اس کی سب سے زیادہ ضرورت ہے\)0 DEV.to لاگت کے وکر کے پیچھے تعمیراتی فیصلوں کا احاطہ کرتا ہے۔

Scroll to Top