بلاگ پر واپس جائیں

API اور SDKگائیڈ

LLM API سے درست JSON حاصل کریں: response_format اور دوبارہ کوششیں

ایک کاپی کرنے کے قابل Python درخواست جو پارس کے قابل JSON واپس کرتی ہے، ایک json.loads ریپر جو خالی یا کٹے ہوئے جوابات سنبھالتا ہے، اور JSON ٹوٹنے کی وجوہات کی چیک لسٹ۔

از CheapTokens Teamشائع شدہ 6 منٹ کا مطالعہ

ایک ٹرمینل جو response_format json_object کے ساتھ چیٹ کمپلیشن درخواست دکھا رہا ہے
اس صفحہ پر
  1. کام: ایک ای میل اندر، ایک قطار باہر
  2. فلیگ سے زیادہ مثال کیوں اہم ہے
  3. محفوظ طریقے سے پارس کریں: خالی، کٹا ہوا، یا صرف ٹوٹا ہوا
  4. صرف نحو نہیں، شکل چیک کریں
  5. ای میلز کے ایک بیچ کی لاگت
  6. فوری جانچ

چیٹ ماڈل سے JSON حاصل کرنے کے لیے تین کام کریں: response_format={"type": "json_object"} پاس کریں، پرامپٹ میں لفظ "json" اور ساخت کی ایک مثال ڈالیں، اور max_tokens کو پورے آبجیکٹ کے لیے کافی زیادہ رکھیں۔ پھر جواب پر کبھی آنکھ بند کر کے بھروسا نہ کریں: چیک کریں کہ یہ خالی نہیں ہے، finish_reason چیک کریں، اور صرف اس کے بعد json.loads کال کریں۔

یہ مختصر ورژن ہے۔ اس گائیڈ کا باقی حصہ ایک بہت عام کام کے لیے ایک مکمل اسکرپٹ ہے: ای میل سے فیلڈز نکالنا۔ مثالیں base URL https://api.cheaptokens.dev/v1 اور ماڈل id deepseek-ai/DeepSeek-V4-Flash-0731 استعمال کرتی ہیں (docs)۔

کام: ایک ای میل اندر، ایک قطار باہر#

فرض کریں آپ کی اسکرپٹ سپورٹ ای میلز پڑھتی ہے اور ہر ایک کو ایک ریکارڈ میں بدلنا ہے: بھیجنے والا، تاریخ، رقم، اور بھیجنے والا کیا چاہتا ہے۔ یہ لیں:

ہائے، میں Lumen Ltd سے Anna Petrova ہوں۔ 14 اکتوبر کو میں نے انوائس #3381 کی 1,250 EUR ادائیگی کی، لیکن رسید اب بھی اسے غیر ادا شدہ دکھاتی ہے۔ براہ کرم جمعہ سے پہلے اسے ٹھیک کریں۔

آپ یہ واپس چاہتے ہیں، اور کچھ نہیں:

json
{"sender": "Anna Petrova", "date": "2026-10-14", "amount": 1250, "currency": "EUR", "action": "fix receipt status"}

ایک سادہ "فیلڈز نکالیں" پرامپٹ آپ کو ایک دوستانہ جملہ، ایک کوڈ فینس، یا دونوں دے سکتا ہے۔ آپ کا json.loads پہلے بیک ٹک پر ہی اٹک جاتا ہے۔ یہی وہ مسئلہ ہے جسے response_format اور ایک اچھا پرامپٹ مل کر حل کرتے ہیں۔

Python اور curl میں وہی درخواست

Python

python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)
MODEL = "deepseek-ai/DeepSeek-V4-Flash-0731"

SYSTEM = """Extract fields from the email and answer with json only.
Example of the json format:
{"sender": "Jane Roe", "date": "2026-01-31", "amount": 99.5, "currency": "USD", "action": "short phrase"}
Use null for a field that is not in the email."""

resp = client.chat.completions.create(
    model=MODEL,
    messages=[
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": email_text},
    ],
    response_format={"type": "json_object"},
    max_tokens=1000,
    temperature=0,
)
print(resp.choices[0].message.content)

curl

bash
curl https://api.cheaptokens.dev/v1/chat/completions \
  -H "Authorization: Bearer $CHEAPTOKENS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-ai/DeepSeek-V4-Flash-0731",
    "messages": [
      {"role": "system", "content": "Extract fields from the email and answer with json only. Example: {\"sender\": \"Jane Roe\", \"amount\": 99.5}"},
      {"role": "user", "content": "Hi, this is Anna Petrova from Lumen Ltd. I paid invoice #3381 for 1,250 EUR..."}
    ],
    "response_format": {"type": "json_object"},
    "max_tokens": 1000
  }'

JSON Output کے لیے DeepSeek API ریفرنس (27 اکتوبر 2026 کو چیک کیا گیا؛ صفحے پر کوئی اشاعت کی تاریخ نہیں ہے) ان قواعد کو بیان کرتا ہے جن کی یہ درخواست پیروی کرتی ہے: response_format کو json_object پر سیٹ کریں، سسٹم یا یوزر پرامپٹ میں کہیں لفظ "json"، اور ہدف کی ساخت کی ایک مثال۔ مثال کے بغیر ماڈل کو آپ کے فیلڈ ناموں کا اندازہ لگانا پڑتا ہے، اور وہ اگلی ای میل پر مختلف اندازہ لگائے گا۔

فلیگ سے زیادہ مثال کیوں اہم ہے#

response_format API سے JSON آبجیکٹ واپس کرنے کو کہتا ہے۔ یہ ماڈل کو نہیں بتاتا کہ کون سا آبجیکٹ۔ اسے ایسے سمجھیں جیسے کسی ساتھی سے کہیں "مجھے ایک اسپریڈشیٹ بھیجیں" بغیر یہ بتائے کہ کون سے کالم۔ آپ کو ایک اسپریڈشیٹ ملتی ہے، بس آپ کی نہیں۔

پرامپٹ میں مثال کالم ہیڈر کی قطار ہے۔ دو عادات اسے بہتر بناتی ہیں:

  • اصل شکل دکھائیں، بشمول اقسام: 1250 ایک نمبر ہے، "2026-10-14" ایک مقررہ تاریخ فارمیٹ میں ایک سٹرنگ ہے۔
  • بتائیں کہ جب کوئی فیلڈ غائب ہو تو کیا کرنا ہے (اوپر null)۔ ورنہ ماڈل خلا بھرنے کے لیے ایک قدر ایجاد کر لیتا ہے۔

response_format کو ایک مضبوط اشارہ سمجھیں، ضمانت نہیں۔ ماڈلز کبھی کبھی پھر بھی خالی سٹرنگ واپس کرتے ہیں، یا آبجیکٹ کو نثر میں لپیٹ دیتے ہیں۔ اسی لیے اگلا حصہ موجود ہے۔

محفوظ طریقے سے پارس کریں: خالی، کٹا ہوا، یا صرف ٹوٹا ہوا#

عملی طور پر تین ناکامیاں سامنے آتی ہیں، اور ہر ایک مختلف نشان چھوڑتی ہے:

  • خالی مواد۔ DeepSeek دستاویزات کہتی ہیں کہ JSON موڈ کبھی کبھار خالی مواد واپس کر سکتا ہے اور پرامپٹ کو دوبارہ لکھنے کا مشورہ دیتی ہیں۔ آپ کی طرف یہ message.content کے "" یا None ہونے، اور json.loads("") کے Expecting value: line 1 column 1 (char 0) اٹھانے کی صورت میں نظر آتا ہے۔
  • کٹا ہوا۔ max_tokens آبجیکٹ کے بیچ میں ختم ہو گیا۔ finish_reason length ہے، اور متن سٹرنگ کے بیچ میں ختم ہوتا ہے۔ اس بارے میں مزید AI جواب جملے کے بیچ میں کیوں رک جاتا ہے میں۔
  • JSON نہیں۔ آبجیکٹ سے پہلے ایک جملہ، یا اس کے گرد ایک فینس۔
خالی جواب پر json.loads JSONDecodeError اٹھاتا ہے
Python میں خالی JSON-موڈ جواب کیسا لگتا ہے

پہلی اور تیسری کا حل زیادہ پختہ پرامپٹ کے ساتھ دوبارہ کوشش ہے۔ دوسری کے لیے، اسی حد کے ساتھ دوبارہ کوشش کچھ نہیں بدلتی، اس لیے ریپر اٹھتا ہے اور آپ کو max_tokens بڑھانے کو کہتا ہے:

python
def ask_json(email_text: str, retries: int = 1) -> dict:
    user = email_text
    for attempt in range(retries + 1):
        resp = client.chat.completions.create(
            model=MODEL,
            messages=[
                {"role": "system", "content": SYSTEM},
                {"role": "user", "content": user},
            ],
            response_format={"type": "json_object"},
            max_tokens=1000,
            temperature=0,
        )
        choice = resp.choices[0]
        if choice.finish_reason == "length":
            raise ValueError("JSON cut off by max_tokens: raise the limit")
        text = (choice.message.content or "").strip()
        if text:
            try:
                return json.loads(text)
            except json.JSONDecodeError:
                pass
        # empty or not JSON: ask again, more firmly
        user = email_text + "\n\nReply with one json object only, in the format of the example."
    raise ValueError("no valid JSON after retry")

ایک اسکرپٹ کے لیے ایک دوبارہ کوشش کافی ہے۔ اگر یہ دو بار ناکام ہو، ای میل id لاگ کریں اور آگے بڑھیں؛ تیسری یکساں درخواست شاذ و نادر ہی مدد کرتی ہے۔

جوڑے ملائیں

کون سی علامت کس وجہ کی طرف اشارہ کرتی ہے؟

  • finish_reason "length" ہےmax_tokens آبجیکٹ کے لیے بہت کم ہے
  • content ایک خالی سٹرنگ ہےJSON موڈ نے کچھ واپس نہیں کیا؛ پرامپٹ دوبارہ لکھیں اور دوبارہ کوشش کریں
  • بیک ٹک والے حرف پر JSONDecodeErrorماڈل نے JSON کو کوڈ فینس میں لپیٹ دیا
  • ای میلز کے درمیان فیلڈ نام مختلف ہیںپرامپٹ میں ساخت کی کوئی مثال نہیں ہے

صرف نحو نہیں، شکل چیک کریں#

json.loads صرف یہ ثابت کرتا ہے کہ متن درست JSON ہے۔ یہ ثابت نہیں کرتا کہ اس میں وہ فیلڈز ہیں جو آپ نے مانگے تھے۔ پارس کرنے کے فوراً بعد ایک سستا چیک شامل کریں:

python
REQUIRED = {"sender", "date", "amount", "currency", "action"}

data = ask_json(email_text)
missing = REQUIRED - data.keys()
if missing:
    raise ValueError(f"missing fields: {sorted(missing)}")

یہاں سے ڈکٹ سیدھا ڈیٹا بیس کی قطار یا اسپریڈشیٹ میں جاتا ہے۔ اگر آپ کو ماڈل سے اپنے فنکشنز کال کروانے ہیں بجائے ایک مقررہ ریکارڈ بھرنے کے، تو یہ ایک مختلف ٹول ہے: Python میں فنکشن کالنگ دیکھیں۔

ای میل سے چیک شدہ ریکارڈ تک کا راستہ: مثال کے ساتھ پرامپٹ، json_object، پارس، فیلڈ چیک
پانچ مراحل میں پورا راستہ

ای میلز کے ایک بیچ کی لاگت#

مختصر اخراج سستی قسم کی درخواست ہے: چند سو ٹوکن اندر، چند درجن باہر۔ فرض کریں روزانہ 1,000 ای میلز تقریباً 400 ان پٹ ٹوکنز (پرامپٹ، مثال اور ای میل) اور تقریباً 80 آؤٹ پٹ ٹوکنز (JSON) کے ساتھ۔ DeepSeek-V4-Flash پر یہ روزانہ $0.014 ہے، اور جدول دیگر ماڈلز پر وہی بوجھ دکھاتا ہے:

ماڈل فی درخواست 1,000 درخواستیں OpenRouter، 1,000 درخواستیں
GLM-5.3-Flash $0.000011 $0.0112 $0.0226
DeepSeek-V4-Flash $0.000014 $0.014 $0.0315
MiniMax-M2.7 $0.000032 $0.032 $0.216

فی درخواست 400 ان پٹ اور 80 آؤٹ پٹ ٹوکنز۔ فی 1M ٹوکنز کی قیمتیں موجودہ ہیں اور ہمارے ٹیرف کے ساتھ تبدیل ہوتی ہیں؛ OpenRouter کالم اسی ورک لوڈ کے لیے حوالہ جاتی قیمتیں دکھاتا ہے۔

مجموعی طور پر، ان پٹ اور آؤٹ پٹ کو ملا کر، DeepSeek-V4-Flash اس بوجھ کے لیے OpenRouter کی حوالہ قیمت سے سستا نکلتا ہے۔ یہ فی جواب 32,768 آؤٹ پٹ ٹوکنز تک کی بھی اجازت دیتا ہے، لہٰذا لائن آئٹمز کی لمبی فہرست اس طرح نہیں کٹے گی جیسے چھوٹی حد کے ساتھ ہوتی، اور قیمت کسی بھی گھنٹے میں یکساں ہے۔ GLM-5.3-Flash (zai-org/GLM-5.3-Flash) اسی API ایڈریس پر ایک اور آپشن ہے: 8,192 آؤٹ پٹ ٹوکنز تک، جو فی ای میل ایک ریکارڈ کے لیے کافی ہے۔ موجودہ قیمتیں قیمتوں کے صفحے پر ہیں؛ DeepSeek ماڈل صفحہ پر یہاں استعمال ہونے والے ماڈل کی تفصیلات ہیں۔

فوری جانچ#

فوری جانچ

آپ کا JSON ایک سٹرنگ کے بیچ میں کٹا ہوا ہے۔ آپ سب سے پہلے کیا دیکھتے ہیں؟

جواب دکھائیں

جواب: finish_reason اور max_tokens

کٹا ہوا آبجیکٹ finish_reason کے length پر سیٹ ہونے کے ساتھ ختم ہوتا ہے۔ حد تک پہنچ گئی، اس لیے max_tokens بڑھائیں؛ temperature یا ایڈریس بدلنے سے مدد نہیں ملتی۔

اگر آپ نے ابھی تک کوئی درخواست نہیں بھیجی، تو اپنی پہلی API درخواست سے شروع کریں، پھر واپس آ کر اوپر کا کوڈ استعمال کریں۔