aidoc.uz

5-qism · AI muhandisi uchun Python·23-bob

HTTP va LLM API: Python'dan Claude bilan ishlash

HTTP asoslari va httpx, REST API'ni qo'lda chaqirish, Anthropic Python SDK: so'rov va javob tuzilmasi, suhbat tarixi, streaming, xatolar va retry, tokenlar va narx, prompt caching, Pydantic bilan structured output, tool use (agent sikli), rasmlar va xavfsizlik.

Bu bob — kursning cho'qqisi: oldingi 22 bobda o'rgangan hamma narsa (satrlar, lug'atlar, funksiyalar, klasslar, xatolar, typing, Pydantic, async, fayllar) shu yerda LLM bilan ishlaydigan haqiqiy kodga aylanadi. Misollar Anthropic Claude API'sida, lekin g'oyalar (HTTP, JSON, streaming, tool use, structured output) barcha LLM provayderlari uchun bir xil.

▶ Video dars· pixegami· 20:01· ingliz tilida
Claude 3.5 API in Python • Explore AWESOME Use Cases!

Claude API'ni Python'dan chaqirish va amaliy misollar. Video eskiroq model (Claude 3.5) bilan yozilgan — SDK asoslari bir xil, lekin joriy model nomlari va parametrlar uchun bobga tayaning.

YouTube'da ochish ↗

1. HTTP — veb-API'larning tili#

Har bir LLM API — bu HTTP so'rov: sizning dasturingiz serverga xabar yuboradi, server javob qaytaradi.

So'rov (request)
POST /v1/messages + sarlavhalar + JSON tana
Server
kalitni tekshiradi, modelni ishga tushiradi
Javob (response)
status kodi + sarlavhalar + JSON tana
QismNimaMisol
MetodAmal turiGET (o'qish), POST (yaratish/yuborish), PUT, PATCH, DELETE
URLManzilhttps://api.anthropic.com/v1/messages
Sarlavhalar (headers)Metama'lumotcontent-type: application/json, autentifikatsiya kaliti
Tana (body)Ma'lumot (odatda JSON){"model": "...", "messages": [...]}
Status kodiNatija200 OK, 400, 401, 404, 429, 500...

Status kodlari#

KodMa'nosiNima qilish kerak
2xxMuvaffaqiyat—
400So'rov noto'g'ri (parametr, format)Kodni tuzating — qayta urinish foydasiz
401 / 403Kalit noto'g'ri / ruxsat yo'qKalitni tekshiring
404Topilmadi (noto'g'ri URL yoki model nomi)Tuzating
408 / 429Vaqt tugadi / juda ko'p so'rovKutib qayta urinish (backoff)
5xxServer xatosiKutib qayta urinish

Qoida: 4xx — sizning xatoingiz (429 dan tashqari), 5xx — server xatosi. Retry faqat vaqtinchalik xatolarda (408, 429, 5xx, tarmoq) ma'noli.

httpx bilan so'rovlar#

uv add httpx
import httpx
 
resp = httpx.get(
    "https://api.github.com/search/repositories",
    params={"q": "language:python stars:>50000", "per_page": 3},   # URL'ga ?q=...&per_page=3
    headers={"Accept": "application/vnd.github+json"},
    timeout=10.0,                                                   # HAR DOIM timeout
)
resp.raise_for_status()          # 4xx/5xx bo'lsa — httpx.HTTPStatusError
for repo in resp.json()["items"]:
    print(repo["full_name"], repo["stargazers_count"])

Ko'p so'rov yuboradigan kodda klient obyektini qayta ishlating — ulanishlar saqlanadi va tezroq ishlaydi:

with httpx.Client(base_url="https://api.example.com", timeout=10, headers={"Authorization": f"Bearer {token}"}) as client:
    users = client.get("/users").json()
    client.post("/events", json={"type": "login", "user_id": 42})    # json= — avtomatik serializatsiya

Async versiyasi — httpx.AsyncClient (17-bob). requests kutubxonasi ham mashhur va deyarli bir xil API'ga ega, lekin async'ni qo'llamaydi.

2. LLM API'ni qo'lda chaqirish#

SDK nima qilishini tushunish uchun avval xom HTTP so'rov:

import os
 
import httpx
 
resp = httpx.post(
    "https://api.anthropic.com/v1/messages",
    headers={
        "x-api-key": os.environ["ANTHROPIC_API_KEY"],
        "anthropic-version": "2023-06-01",
        "content-type": "application/json",
    },
    json={
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "Python'da list va tuple farqi nima? Qisqa."}],
    },
    timeout=60,
)
resp.raise_for_status()
data = resp.json()
print(data["content"][0]["text"])
print(data["usage"])          # {'input_tokens': ..., 'output_tokens': ...}

Hammasi tanish: JSON lug'atlar, muhit o'zgaruvchisidagi kalit, timeout, raise_for_status. Amalda esa rasmiy SDK ishlatiladi: u tiplar, retry, streaming, xatolar klasslari va yordamchi funksiyalarni beradi.

3. Anthropic Python SDK#

uv add anthropic

API kalitini console.anthropic.com da yarating va muhit o'zgaruvchisiga qo'ying (9-bob):

# .env
ANTHROPIC_API_KEY=sk-ant-...
import anthropic
 
client = anthropic.Anthropic()        # kalitni ANTHROPIC_API_KEY'dan o'zi o'qiydi
 
message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Python'da list va tuple farqi nima? Qisqa."}],
)
 
for block in message.content:
    if block.type == "text":
        print(block.text)

Javob tuzilmasi#

message.id             # 'msg_01...'
message.model          # 'claude-opus-5-5'
message.stop_reason    # 'end_turn' | 'max_tokens' | 'tool_use' | 'refusal' | ...
message.usage          # input_tokens, output_tokens, cache_read_input_tokens, ...
message.content        # bloklar ro'yxati: text, thinking, tool_use...

content — ro'yxat, satr emas: javobda bir nechta turdagi bloklar bo'lishi mumkin (matn, model "fikrlashi", asbob chaqiruvi). Har doim block.typeni tekshiring — 4-bobdagi match aynan shu uchun qulay edi.

stop_reasonni tekshiring#

QiymatMa'nosiReaksiya
end_turnModel javobni tugatdiNormal
max_tokensmax_tokens limitiga yetdi — javob kesilganLimitni oshiring yoki foydalanuvchiga bildiring
tool_useModel asbob chaqirmoqchiAsbobni bajarib, natijani qaytaring (8-bo'lim)
refusalXavfsizlik filtri javobni to'xtatdicontentga tayanmang, foydalanuvchiga tushunarli xabar

Asosiy parametrlar#

ParametrMa'nosi
modelModel ID'si: claude-opus-5-5 (eng kuchli, standart), claude-sonnet-5-5 (tez va arzonroq), claude-haiku-4-5 (eng tez va arzon)
max_tokensJavob uzunligining yuqori chegarasi (majburiy)
messagesSuhbat: user va assistant rollari navbatma-navbat
systemTizim ko'rsatmasi: rol, uslub, qoidalar
output_config={"effort": ...}Qancha "o'ylash" — low / medium / high / xhigh / max: sifat, tezlik va narx muvozanati
stop_sequencesShu matn chiqsa — to'xtash
toolsModel chaqira oladigan funksiyalar (8-bo'lim)

4. System prompt va suhbat tarixi#

API holatsiz (stateless): har bir so'rovda butun suhbat tarixini yuborasiz. Model avvalgi xabarlarni "eslab qolmaydi" — siz ularni qayta yuborasiz:

SYSTEM = (
    "Sen tajribali Python o'qituvchisisan. O'zbek tilida, qisqa va aniq javob ber. "
    "Har javobda bitta kichik kod misoli bo'lsin."
)
 
history: list[dict] = []
 
 
def ask(question: str) -> str:
    history.append({"role": "user", "content": question})
    msg = client.messages.create(
        model="claude-opus-5-5",
        max_tokens=2048,
        system=SYSTEM,
        messages=history,
    )
    answer = "".join(b.text for b in msg.content if b.type == "text")
    history.append({"role": "assistant", "content": answer})
    return answer
 
 
ask("Dekorator nima?")
ask("Parametrli versiyasini ko'rsat")     # model oldingi savolni "biladi" — chunki tarix yuborildi

Oqibatlari: suhbat uzaygan sari har so'rov qimmatlashadi (har safar butun tarix input token sifatida hisoblanadi) va oxir-oqibat kontekst oynasiga sig'maydi. Yechimlar: oxirgi N ta xabarni saqlash (5-bob last_turns), eski qismni xulosa qilish, prompt caching (6-bo'lim).

5. Streaming — javobni token-token olish#

Uzun javobni to'liq tayyor bo'lishini kutish — foydalanuvchi uchun bir necha soniya "o'lik" ekran. Streaming bilan matn yozilishi bilan ko'rinadi:

with client.messages.stream(
    model="claude-opus-5-5",
    max_tokens=4096,
    messages=[{"role": "user", "content": "Python'dagi GIL haqida tushuntir"}],
) as stream:
    for text in stream.text_stream:          # generator (7-bob!) — har bo'lak kelishi bilan
        print(text, end="", flush=True)
    final = stream.get_final_message()       # to'liq Message obyekti: usage, stop_reason
 
print()
print(final.usage.output_tokens, final.stop_reason)

Bu yerda 7-bob (generatorlar) va 14-bob (kontekst menejer) birlashdi: with ulanishni to'g'ri yopadi, text_stream — iterator. Veb-ilovada xuddi shu bo'laklar brauzerga uzatiladi (24-bob) — aidoc.uz'dagi "Claude'dan so'rang" maydoni ham aynan shunday ishlaydi.

Katta max_tokens bilan ishlaganda streaming tavsiya etiladi — bitta uzun so'rov HTTP timeout'ga uchramasligi uchun.

6. Tokenlar, narx va prompt caching#

LLM narxi tokenlar bo'yicha hisoblanadi — kiruvchi (input) va chiquvchi (output) alohida:

ModelInput, $ / 1M tokenOutput, $ / 1M token
Claude Opus 5.54.0020.00
Claude Sonnet 5.52.0010.00
Claude Haiku 4.51.005.00

(2026-yil oktabr holati — narxlar o'zgarishi mumkin, rasmiy sahifani tekshiring.)

def cost_usd(usage, price_in: float = 4.0, price_out: float = 20.0) -> float:
    return (usage.input_tokens * price_in + usage.output_tokens * price_out) / 1_000_000
 
cost_usd(message.usage)       # masalan, 0.0042

Yuborishdan oldin tokenlarni aniq sanash:

count = client.messages.count_tokens(
    model="claude-opus-5-5",
    messages=[{"role": "user", "content": long_document}],
)
count.input_tokens

3-bobda aytilganidek, len(text) yoki boshqa provayderlarning tokenizatorlari Claude tokenlarini to'g'ri bermaydi — o'zbekcha matnda farq ayniqsa katta.

Prompt caching#

Agar har so'rovda bir xil katta qism takrorlansa (uzun tizim ko'rsatmasi, hujjat, kitob bobi), uni keshlash mumkin — keyingi so'rovlarda o'sha qism ~10 baravar arzon va tezroq o'qiladi:

response = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=2048,
    system=[
        {"type": "text", "text": "Sen hujjat bo'yicha savollarga javob beruvchi yordamchisan."},
        {"type": "text", "text": big_document, "cache_control": {"type": "ephemeral"}},   # shu yergacha keshlanadi
    ],
    messages=[{"role": "user", "content": question}],
)
response.usage.cache_creation_input_tokens   # birinchi marta — keshga yozildi
response.usage.cache_read_input_tokens       # keyingi so'rovlarda — keshdan o'qildi

Kesh prefiks bo'yicha ishlaydi: o'zgarmas qismlar oldinda, o'zgaruvchi (savol) — oxirida. Tizim ko'rsatmasiga datetime.now() qo'shsangiz, har so'rovda prefiks o'zgaradi va kesh hech qachon ishlamaydi.

7. Xatolar va retry#

10-bobdagi istisnolar ierarxiyasi amalda:

import anthropic
 
client = anthropic.Anthropic(max_retries=4, timeout=60.0)   # SDK 408/429/5xx va tarmoq xatolarida o'zi qayta urinadi
 
try:
    message = client.messages.create(model="claude-opus-5-5", max_tokens=1024, messages=msgs)
except anthropic.AuthenticationError:
    raise SystemExit("API kaliti noto'g'ri — ANTHROPIC_API_KEY'ni tekshiring")
except anthropic.BadRequestError as e:
    log.error("So'rov noto'g'ri: %s", e.message)        # qayta urinish foydasiz — kodni tuzating
    raise
except anthropic.RateLimitError:
    log.warning("Limit — SDK retry'lari ham yordam bermadi")
    raise
except anthropic.APIStatusError as e:
    log.error("API xatosi %s: %s", e.status_code, e.message)
    raise
except anthropic.APIConnectionError:
    log.error("Tarmoq xatosi")
    raise

Tartib muhim: aniqroq klasslar oldin (RateLimitError → APIStatusError vorisi → APIError vorisi). O'z retry siklingizni yozishdan oldin SDK'ning max_retries parametridan foydalaning — u to'g'ri backoff va retry-after sarlavhasini hisobga oladi.

8. Structured output — Pydantic bilan#

15-bobda Pydantic'ni shu lahza uchun o'rgangan edik. Modeldan aniq sxemadagi ma'lumot olish:

from typing import Literal
 
import anthropic
from pydantic import BaseModel, Field
 
 
class Review(BaseModel):
    sentiment: Literal["positive", "negative", "neutral"]
    topics: list[str] = Field(description="Sharhda tilga olingan mavzular, masalan: yetkazib berish, narx")
    summary: str = Field(description="Bir gaplik xulosa, o'zbek tilida")
 
 
client = anthropic.Anthropic()
 
response = client.messages.parse(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": "Sharhni tahlil qil: 'Telefon zo'r, lekin yetkazib berish 2 hafta davom etdi.'",
    }],
    output_format=Review,
)
 
review = response.parsed_output       # Review obyekti — tiplar tekshirilgan
review.sentiment                      # masalan, 'neutral'
review.topics                         # masalan, ['telefon sifati', 'yetkazib berish']

messages.parse Pydantic modelini JSON Schema'ga aylantiradi, modelni sxemaga mos javob berishga majburlaydi va natijani qaytadan Pydantic obyektiga aylantiradi. 11-bobdagi extract_json kabi "mo'rt" usullarga ehtiyoj qolmaydi. Natijani baribir mantiqan tekshiring: sxemaga mos JSON ham noto'g'ri ma'noga ega bo'lishi mumkin.

9. Tool use — model funksiyalaringizni chaqiradi#

Tool use (function calling) — agentlarning asosi. Siz modelga funksiyalar ro'yxatini (nom, tavsif, parametrlar sxemasi) berasiz; model kerak bo'lganda "shu funksiyani shu argumentlar bilan chaqir" deydi; siz funksiyani bajarib, natijani qaytarasiz; model natijadan foydalanib javob beradi.

Foydalanuvchi: Samarqandda havo qanday?
Model: tool_use get_weather(city=Samarqand)
Sizning kodingiz: funksiyani bajaradi → +21°C
Model: Samarqandda hozir +21°C, quyoshli.

Mexanizmni tushunish uchun — qo'lda yozilgan agent sikli:

import json
 
import anthropic
 
client = anthropic.Anthropic()
 
TOOLS = [
    {
        "name": "get_weather",
        "description": "Berilgan shahar uchun joriy ob-havoni qaytaradi.",
        "input_schema": {
            "type": "object",
            "properties": {"city": {"type": "string", "description": "Shahar nomi, masalan: Toshkent"}},
            "required": ["city"],
        },
    },
    {
        "name": "convert_currency",
        "description": "Summani bir valyutadan boshqasiga o'tkazadi.",
        "input_schema": {
            "type": "object",
            "properties": {
                "amount": {"type": "number"},
                "from_currency": {"type": "string", "enum": ["UZS", "USD", "EUR"]},
                "to_currency": {"type": "string", "enum": ["UZS", "USD", "EUR"]},
            },
            "required": ["amount", "from_currency", "to_currency"],
        },
    },
]
 
RATES = {"USD": 12_650.0, "EUR": 13_900.0, "UZS": 1.0}       # soxta kurslar
 
 
def get_weather(city: str) -> dict:
    return {"city": city, "temp_c": 21, "condition": "quyoshli"}      # haqiqiy loyihada — API chaqiruvi
 
 
def convert_currency(amount: float, from_currency: str, to_currency: str) -> dict:
    result = amount * RATES[from_currency] / RATES[to_currency]
    return {"result": round(result, 2), "currency": to_currency}
 
 
HANDLERS = {"get_weather": get_weather, "convert_currency": convert_currency}
 
 
def run_tool(name: str, args: dict) -> tuple[str, bool]:
    """Asbobni bajaradi. (natija_json, xatomi) qaytaradi."""
    try:
        return json.dumps(HANDLERS[name](**args), ensure_ascii=False), False
    except Exception as e:                       # xatoni modelga qaytaramiz — u tuzatishga urinadi
        return f"Xato: {e!r}", True
 
 
def agent(question: str, max_steps: int = 10) -> str:
    messages = [{"role": "user", "content": question}]
    for _ in range(max_steps):                   # cheksiz sikldan himoya
        response = client.messages.create(
            model="claude-opus-5-5", max_tokens=4096, tools=TOOLS, messages=messages,
        )
        messages.append({"role": "assistant", "content": response.content})
 
        if response.stop_reason != "tool_use":
            return "".join(b.text for b in response.content if b.type == "text")
 
        results = []
        for block in response.content:
            if block.type == "tool_use":
                output, is_error = run_tool(block.name, block.input)
                results.append({
                    "type": "tool_result",
                    "tool_use_id": block.id,         # qaysi chaqiruvga javob ekanini bog'laydi
                    "content": output,
                    "is_error": is_error,
                })
        messages.append({"role": "user", "content": results})    # BARCHA natijalar bitta xabarda
    raise RuntimeError("Agent qadamlar limitiga yetdi")
 
 
print(agent("Samarqandda havo qanday? Va 250 dollar necha so'm bo'ladi?"))

Muhim nuqtalar:

  • model bir javobda bir nechta asbobni chaqirishi mumkin — hammasini bajarib, natijalarni bitta user xabarida qaytaring;
  • tool_use_id — har bir natijani o'z chaqiruviga bog'laydi;
  • asbob xatosini yashirmang — is_error: True bilan qaytaring, model ko'pincha argumentni tuzatib qayta urinadi;
  • max_steps — cheksiz sikldan himoya (agentlar ba'zan "aylanib" qoladi).

SDK'ning tool runner'i#

Amalda bu siklni qo'lda yozish shart emas — SDK funksiyaning type hint'lari va docstring'idan (14 va 15-boblar!) sxemani o'zi yasaydi va siklni o'zi boshqaradi:

from anthropic import beta_tool
 
 
@beta_tool
def get_weather(city: str) -> str:
    """Berilgan shahar uchun joriy ob-havoni qaytaradi.
 
    Args:
        city: Shahar nomi, masalan: Toshkent.
    """
    return json.dumps({"city": city, "temp_c": 21, "condition": "quyoshli"}, ensure_ascii=False)
 
 
runner = client.beta.messages.tool_runner(
    model="claude-opus-5-5",
    max_tokens=4096,
    tools=[get_weather],
    messages=[{"role": "user", "content": "Buxoroda havo qanday?"}],
)
for message in runner:             # har qadamda Message; asboblar avtomatik bajariladi
    for block in message.content:
        if block.type == "text":
            print(block.text)

14-bobdagi @tool ro'yxatga oluvchi dekoratorni eslang — g'oya aynan shu, faqat to'liq va ishlab chiqarishga tayyor.

10. Rasmlar (vision)#

import base64
from pathlib import Path
 
image_b64 = base64.standard_b64encode(Path("chek.jpg").read_bytes()).decode()
 
message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{
        "role": "user",
        "content": [
            {"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": image_b64}},
            {"type": "text", "text": "Chekdagi jami summa va sanani ayt."},
        ],
    }],
)

content satr o'rniga bloklar ro'yxati bo'lishi mumkin — matn, rasm, hujjat (PDF) aralash. Rasm matndan oldin bo'lgani ma'qul. Bu yerni messages.parse bilan birlashtirsangiz — cheklardan tuzilmali ma'lumot ajratib oluvchi tizim tayyor.

11. Async va ko'p so'rov#

17-bobdagi naqsh: AsyncAnthropic + Semaphore:

import asyncio
 
from anthropic import AsyncAnthropic
 
 
async def summarize_all(texts: list[str], concurrency: int = 8) -> list[str]:
    sem = asyncio.Semaphore(concurrency)
    async with AsyncAnthropic() as client:
 
        async def one(text: str) -> str:
            async with sem:
                msg = await client.messages.create(
                    model="claude-opus-5-5",
                    max_tokens=300,
                    output_config={"effort": "low"},      # oddiy vazifa — kam "o'ylash", tezroq va arzonroq
                    messages=[{"role": "user", "content": f"Bir gapda xulosa qil:\n\n{text}"}],
                )
            return "".join(b.text for b in msg.content if b.type == "text")
 
        return await asyncio.gather(*(one(t) for t in texts))

Natijalar darhol kerak bo'lmasa — Message Batches API (client.messages.batches): so'rovlar paketi 24 soat ichida ~50% arzon narxda bajariladi.

12. Amaliyot: terminalda streaming chat#

Hamma narsani bitta dasturga yig'amiz — 4-bobdagi chatbot skeletining haqiqiy versiyasi:

"""chat.py — terminalda Claude bilan streaming suhbat."""
 
import os
import sys
 
import anthropic
 
MODEL = os.environ.get("MODEL", "claude-opus-5-5")
SYSTEM = "Sen Python bo'yicha yordamchisan. O'zbek tilida, aniq va qisqa javob ber."
MAX_TURNS = 20
PRICE_IN, PRICE_OUT = 4.0, 20.0
 
 
def main() -> None:
    client = anthropic.Anthropic(max_retries=3)
    history: list[dict] = []
    total_cost = 0.0
    print(f"{MODEL} bilan suhbat. Chiqish: Ctrl+D yoki 'chiq'.\n")
 
    while True:
        try:
            user = input("Siz: ").strip()
        except (EOFError, KeyboardInterrupt):
            break
        if not user:
            continue
        if user.lower() in {"chiq", "exit"}:
            break
 
        history.append({"role": "user", "content": user})
        print("Claude: ", end="", flush=True)
        try:
            with client.messages.stream(
                model=MODEL, max_tokens=4096, system=SYSTEM, messages=history[-2 * MAX_TURNS:],
            ) as stream:
                for text in stream.text_stream:
                    print(text, end="", flush=True)
                final = stream.get_final_message()
        except anthropic.APIError as e:
            history.pop()                                  # muvaffaqiyatsiz savolni tarixdan olib tashlaymiz
            print(f"\n[xato: {type(e).__name__}] qayta urinib ko'ring.", file=sys.stderr)
            continue
 
        answer = "".join(b.text for b in final.content if b.type == "text")
        if final.stop_reason == "max_tokens":
            print("\n[javob uzunlik limitida kesildi]", end="")
        history.append({"role": "assistant", "content": answer})
 
        u = final.usage
        cost = (u.input_tokens * PRICE_IN + u.output_tokens * PRICE_OUT) / 1e6
        total_cost += cost
        print(f"\n  [{u.input_tokens}→{u.output_tokens} token, ${cost:.4f}]\n")
 
    print(f"\nJami: ${total_cost:.4f}")
 
 
if __name__ == "__main__":
    main()
terminal
uv run chat.py
claude-opus-5-5 bilan suhbat. Chiqish: Ctrl+D yoki 'chiq'. Siz: Generator nima, bir gapda? Claude: Generator — qiymatlarni yield orqali bittalab, faqat so'ralganda ishlab chiqaradigan funksiya; u butun ketma-ketlikni xotirada saqlamaydi. [41→38 token, $0.0009]

(Javob matni har safar biroz farq qiladi — LLM deterministik emas.)

Nima noto'g'ri ketishi mumkin#

XatoOqibatTuzatish
Kalit koddaSizib chiqadi, pul o'g'irlanadiMuhit o'zgaruvchisi / .env (9-bob)
Timeout yo'qOsilib qolgan so'rovKlient timeout=; uzun javoblar uchun streaming
content[0].textthinking yoki tool_use bloki birinchi bo'lsa — xatoblock.type == "text" bo'yicha filtrlang
stop_reason tekshirilmaydiKesilgan/rad etilgan javob to'liq deb qabul qilinadiend_turn, max_tokens, refusalni ajrating
400'da retryFoydasiz so'rovlarFaqat 408/429/5xx/tarmoq; SDK max_retries
Tarix cheksiz o'sadiNarx o'sadi, kontekst to'ladiOxirgi N ta, xulosa, caching
Tizim promptida o'zgaruvchan qismKesh ishlamaydiO'zgarmas qism oldinda
temperature eng yangi modelda400 xatoeffort
Model JSON'iga json.loads + ishonishKalit yo'q, tip noto'g'rimessages.parse + Pydantic
Asbob argumentlariga ko'r-ko'rona ishonishXavfsizlik teshigiValidatsiya, cheklovlar, inson tasdig'i
Tool natijalarini alohida xabarlarda yuborishAPI xatosi yoki model chalkashadiBitta user xabarida hammasi
Amaliy topshiriq

1. Xom HTTP va SDK

Bir xil savolni (a) httpx bilan xom HTTP orqali, (b) SDK orqali yuboring. Ikkala javobdagi usageni chiqaring. Keyin ataylab xato qiling: noto'g'ri kalit, mavjud bo'lmagan model nomi, max_tokens=5 — har birida qanday status kodi/istisno va stop_reason chiqishini jadvalga yozing.

Maslahatni ko'rsatish

httpx.post bilan bir xil so'rovni yuboring; javob JSON'idagi usage va SDK'dagi message.usage ni solishtiring.

Amaliy topshiriq

2. Token narxi kalkulyatori

Bir xil ma'noli inglizcha va o'zbekcha 500 so'zlik matnni count_tokens bilan sanang (3-bob mashqining davomi). O'zbekcha matn necha foiz ko'proq token? 10 000 ta shunday hujjatni Opus 5.5 va Haiku 4.5 bilan qayta ishlash narxini hisoblang.

Maslahatni ko'rsatish

count_tokens bilan ikkala matnni sanang; narx = tokens * price / 1e6.

Amaliy topshiriq

3. Structured extraction

15-bob mashqidagi ish e'loni sxemasini messages.parse bilan ishlating: 5 ta turli e'lon matnidan ma'lumot ajratib, Pandas DataFrame'ga yig'ing va CSV'ga saqlang. Model maosh oralig'ini topa olmagan holatlarni qanday qayta ishlaysiz?

Maslahatni ko'rsatish

class JobPost(BaseModel) — 15-bob mashqidagi sxema; messages.parse(output_format=JobPost); natijalarni pandas DataFrame'ga.

Amaliy topshiriq

4. Kichik agent

Tool use siklini kengaytiring: (a) search_docs(query) — 11-bobdagi JSONL fayldan kalit so'z bo'yicha qidiradi; (b) calculator(expression) — faqat sonlar va +-*/() belgilariga ruxsat beradi (eval emas! ast moduli bilan xavfsiz hisoblang). Har bir asbob chaqiruvini 14-bobdagi span bilan logga yozing. Agent "hujjatlarda nechta buyurtma bor va ularning o'rtacha narxi qancha?" kabi savolga javob bera oladimi?

Yodda saqlang
  • 01HTTP: metod, URL, sarlavhalar, JSON tana, status kodlari; 4xx — sizniki (429 dan tashqari), 5xx — serverniki.
  • 02httpx: timeout har doim, raise_for_status, klient obyektini qayta ishlating.
  • 03SDK: client.messages.create; content — bloklar ro'yxati, block.type'ni tekshiring; stop_reason'ni tekshiring.
  • 04API holatsiz: suhbat tarixini har safar yuborasiz — narx va kontekst o'sadi.
  • 05Streaming: with client.messages.stream(...) as s: for text in s.text_stream.
  • 06Narx tokenlar bo'yicha; count_tokens bilan sanang; o'zgarmas katta qismni prompt caching bilan keshlang.
  • 07Structured output: messages.parse(output_format=PydanticModel).
  • 08Tool use: model so'raydi → siz bajarasiz → tool_result qaytarasiz; max_steps va xavfsizlik cheklovlari.

Mustahkamlash

Test va amaliy masalalar

Avval testni ishlang — har javobdan keyin izoh chiqadi. Keyin masalalarni shu yerning o'zida yechib, brauzerdagi haqiqiy Python bilan avtomatik tekshiring. Natijalaringiz kurs progressi sahifasida jamlanadi.

Test: topshirilmaganMasalalar: 0/3

Bilimni tekshirish

Bob bo'yicha test

12 ta savol · har javobdan keyin to'g'ri yoki xatoligi va izoh ko'rsatiladi · oxirida natija foizda.

Amaliy masalalar

Kodni yozing va «Tekshirish»ni bosing (yoki Ctrl/⌘ + Enter). Kodingiz shu brauzerda saqlanib turadi.

01Javobdan matn va asboblar

split_content(content) — API javobidagi bloklar ro'yxatidan (lug'atlar) (matn, asboblar) qaytarsin: matn — barcha text bloklarining birlashmasi ("" bilan), asboblar — tool_use bloklaridan (name, input) ro'yxati. Boshqa bloklar (thinking va h.k.) e'tiborsiz.

02Agent sikli (soxta klient bilan)

run_agent(client, tools, question, max_steps=5) — client.create(messages) javob lug'atini qaytaradi: {"stop_reason": ..., "content": [...]}. stop_reason != "tool_use" bo'lsa — matnni qaytaring. Aks holda javobni assistant xabari sifatida qo'shing, har tool_use uchun tools[name](**input) ni bajarib (xato bo'lsa is_error: True va xato matni), barcha natijalarni bitta user xabarida ({"type": "tool_result", "tool_use_id": id, "content": str(natija), "is_error": bool}) qo'shing. Qadamlar tugasa — RuntimeError.

03Xarajat kalkulyatori

cost_usd(usage, model) — usage lug'ati (input_tokens, output_tokens, ixtiyoriy cache_read_input_tokens) va narxlar jadvali bo'yicha dollar narxini 6 xona yaxlitlab qaytarsin. Narxlar ($/1M): claude-opus-5-5 — 4 / 20, kesh o'qish 0.20; claude-haiku-4-5 — 1 / 5, kesh o'qish 0.10. Noma'lum model — KeyError.