AI ایپس میں وینڈر لاک اِن عموماً یکبارگی نہیں ہوتا۔ یہ آہستہ آہستہ در آتا ہے — کہیں براہِ راست import openai، کہیں ہارڈ کوڈڈ ماڈل نام، کہیں ایسا رسپانس فیلڈ جسے آپ یہ دیکھے بغیر پارس کرتے ہیں کہ دوسرے فراہم کنندگان بھی وہی چیز لوٹاتے ہیں یا نہیں۔ چھ ماہ بعد، فراہم کنندہ بدلنا آپ کے بیک اینڈ کا آدھا حصہ دوبارہ لکھنے کے مترادف ہو جاتا ہے۔
لاک اِن ہونے کے چار طریقے
زیادہ تر ڈویلپرز سمجھتے ہیں کہ لاک اِن کا مطلب ہے "میں OpenAI SDK استعمال کر رہا ہوں۔" یہ سب سے کم خطرناک قسم ہے۔ حقیقی جال زیادہ باریک ہوتے ہیں:
| لاک اِن کی قسم | یہ کیسے ہوتا ہے | نتیجہ |
|---|---|---|
| SDK لاک اِن | ہر جگہ from openai import OpenAI | SDK بدلنا ہر فائل کو چھونا پڑتا ہے |
| ماڈل نام لاک اِن | کاروباری منطق میں model="gpt-4o" ہارڈ کوڈڈ | ہر ماڈل تبدیلی ایک کوڈ تبدیلی بن جاتی ہے |
| پیرامیٹر لاک اِن | logprobs, n>1, یا reasoning_effort کا استعمال | یہ Claude یا Gemini پر موجود نہیں |
| رسپانس فارمیٹ لاک اِن | فراہم کنندہ-مخصوص رسپانس فیلڈز کو پارس کرنا | مختلف فراہم کنندگان مختلف ساختیں لوٹاتے ہیں |
مقصد ان سب کو مکمل ختم کرنا نہیں — کچھ قابلِ قبول سمجھوتے ہیں۔ مقصد یہ جاننا ہے کہ آپ کون سے لاک اِن شعوری طور پر قبول کر رہے ہیں۔
اپنے ابسٹریکشن لیئر کے طور پر OpenAI-مطابق اینڈ پوائنٹ استعمال کریں
SDK لاک اِن سے بچنے کا سب سے صاف طریقہ یہ ہے کہ ایک واحد OpenAI-مطابق اینڈ پوائنٹ استعمال کریں جو متعدد فراہم کنندگان تک روٹنگ کرے۔ آپ OpenAI SDK برقرار رکھتے ہیں، مگر بیک اینڈ کوئی بھی فراہم کنندہ ہو سکتا ہے۔
CometAPI یہ کام کرتی ہے — ایک اینڈ پوائنٹ، ایک key، OpenAI، Anthropic، Google، DeepSeek، xAI، اور دیگر کے 500+ ماڈلز:
import osfrom openai import OpenAIfrom dotenv import load_dotenvload_dotenv()api_key = os.environ.get("AI_API_KEY")if not api_key: raise ValueError("AI_API_KEY ماحولاتی ویریایبل سیٹ نہیں ہے")client = OpenAI( base_url=os.environ.get("AI_BASE_URL", "https://api.cometapi.com/v1"), api_key=api_key,)
GPT سے Claude پھر Gemini پر جانا ایک لائن کی تبدیلی ہے:
# پہلےresponse = client.chat.completions.create(model="gpt-5.4", messages=[...])# بعد میں — کوڈ وہی، ماڈل مختلـفresponse = client.chat.completions.create(model="claude-sonnet-4-6", messages=[...])
نوٹ: gpt-5.4 اور claude-sonnet-4-6 جیسے ماڈل نام CometAPI کے پلیٹ فارم identifiers ہیں — یہ صرف https://api.cometapi.com/v1 کے ذریعے کام کرتے ہیں، براہِ راست OpenAI یا Anthropic کی APIs کے ذریعے نہیں۔ مکمل کیٹلاگ اور قیمتوں کے لیے full model list دیکھیں۔
اپنے کاروباری لاجک سے ماڈل نام الگ رکھیں
آپ کے کوڈ میں جگہ جگہ ماڈل نام بکھرے ہونا لاک اِن کی سب سے عام شکل ہے۔ حل یہ ہے کہ ایک مرکزی کنفیگ رکھیں جو محیطی ویریایبلز سے پڑھے:
# config.py — ماڈل اسائنمنٹس بدلنے کی ایک ہی جگہimport osMODEL_CONFIG = { "summarize": os.environ.get("MODEL_SUMMARIZE", "claude-opus-4-7"), "code": os.environ.get("MODEL_CODE", "gpt-5.4"), "classify": os.environ.get("MODEL_CLASSIFY", "claude-haiku-4-5"), "chat": os.environ.get("MODEL_CHAT", "gpt-5.4-mini"),}# اسٹارٹ اپ پر توثیق کریں — غیر واضح API غلطیوں کے بجائے فوراً ناکام ہوںfor task, model in MODEL_CONFIG.items(): if not model: raise ValueError(f"'{task}' کے لیے ماڈل کنفیگ سیٹ نہیں ہے")
آپ کی کاروباری منطق کبھی براہِ راست ماڈل نام حوالہ نہیں دیتی:
from config import MODEL_CONFIGdef summarize(text: str) -> str: response = client.chat.completions.create( model=MODEL_CONFIG["summarize"], messages=[{"role": "user", "content": f"خلاصہ بنائیں: {text}"}], max_tokens=300 # پروڈکشن میں اسے کنفیگ میں منتقل کریں ) return response.choices[0].message.content
پوری ایپ میں سمریزیشن ماڈل بدلنے کے لیے ایک محیطی ویریایبل بدل دیں۔ نہ grep، نہ find-and-replace۔
رسپانس کو اس طرح ریپ کریں کہ کوڈ فراہم کنندہ-مخصوص فیلڈز پر منحصر نہ رہے
مختلف فراہم کنندگان ہلکے فرق کے ساتھ رسپانس کی ساخت لوٹاتے ہیں۔ اگر آپ اپنے کوڈ بیس میں ہر جگہ خام API رسپانسز پارس کرتے ہیں، تو آپ اسی فراہم کنندہ کے فارمیٹ کے لاک اِن میں ہیں۔
اسے نارملائزڈ dataclass میں لپیٹیں:
from dataclasses import dataclassfrom typing import Optionalfrom openai import OpenAI, APIStatusError, APIConnectionError, APITimeoutErrorfrom openai.types.chat import ChatCompletionimport logging@dataclassclass AIResponse: content: str model: str input_tokens: int output_tokens: intdef call_model(task: str, messages: list, **kwargs) -> AIResponse: """ تمام LLM کالز کے لیے واحد انٹری پوائنٹ۔ چاہے جو بھی ماڈل ہینڈل کرے، نارملائزڈ AIResponse لوٹاتا ہے۔ 4xx (کلائنٹ غلطیاں) پر استثنا اٹھاتا ہے۔ 5xx/نیٹ ورک غلطیوں پر لوگ کرتا ہے اور دوبارہ اٹھاتا ہے۔ """ model = MODEL_CONFIG.get(task, "gpt-5.4-mini") if not model: raise ValueError(f"ٹاسک '{task}' کے لیے کوئی ماڈل کنفیگر نہیں ہے") try: response: ChatCompletion = client.chat.completions.create( model=model, messages=messages, **kwargs ) except APIStatusError as e: logging.error(f"ٹاسک={task} ماڈل={model} کے لیے API خرابی: {e.status_code} {e.message}") raise except (APIConnectionError, APITimeoutError) as e: logging.error(f"نیٹ ورک خرابی ٹاسک={task} ماڈل={model}: {e}") raise # جب ماڈل متن دینے کے بجائے ٹول کال ٹرگر کرے تو content None ہوتا ہے content = response.choices[0].message.content or "" # اسٹریمنگ موڈ میں usage None ہوتا ہے — دستیاب نہ ہو تو 0 رکھیں usage = response.usage input_tokens = usage.prompt_tokens if usage else 0 output_tokens = usage.completion_tokens if usage else 0 logging.info( f"ٹاسک={task} ماڈل={model} ان پٹ_ٹوکنز={input_tokens} آؤٹ پٹ_ٹوکنز={output_tokens}" ) return AIResponse( content=content, model=response.model, input_tokens=input_tokens, output_tokens=output_tokens, )
اب آپ کی کاروباری منطق خام API رسپانسز نہیں بلکہ AIResponse آبجیکٹس کے ساتھ کام کرتی ہے۔ اگر کسی فراہم کنندہ نے رسپانس فارمیٹ بدلا تو آپ ایک ہی جگہ پر درستگی کریں گے۔
ریپر میں اسٹریمنگ سپورٹ شامل کریں
چیٹ انٹرفیسز کے لیے اسٹریمنگ درکار ہو گی۔ ریپر اسے الگ راستے کے طور پر ہینڈل کرتا ہے:
from typing import Iteratordef stream_model(task: str, messages: list, **kwargs) -> Iterator[str]: """ روٹڈ ماڈل سے ٹوکنز اسٹریم کریں۔ نوٹ: اسٹریمنگ میں usage ڈیٹا واپس نہیں ملتا۔ فالبیک اسٹریمنگ موڈ میں سپورٹڈ نہیں — آپ مکمل درخواست کی کامیابی جانے سے پہلے ہی ٹوکنز دینا شروع کر چکے ہوتے ہیں۔ """ model = MODEL_CONFIG.get(task, "gpt-5.4-mini") if not model: raise ValueError(f"ٹاسک '{task}' کے لیے کوئی ماڈل کنفیگر نہیں ہے") stream = client.chat.completions.create( model=model, messages=messages, stream=True, **kwargs ) for chunk in stream: delta = chunk.choices[0].delta.content if delta: yield delta# استعمالfor token in stream_model("chat", [{"role": "user", "content": "ہیلو"}]): print(token, end="", flush=True)
جانیں کون سے پیرامیٹرز لاک اِن پیدا کرتے ہیں
کچھ پیرامیٹرز صرف مخصوص فراہم کنندگان پر موجود ہیں۔ ان کا استعمال ٹھیک ہے — بس شعوری انتخاب کے طور پر کریں:
| پیرامیٹر | کہاں کام کرتا ہے | لاک اِن کا خدشہ |
|---|---|---|
| logprobs | صرف GPT | زیادہ — Claude یا Gemini پر کوئی متبادل نہیں |
| n > 1 | GPT، Gemini (Claude پر نہیں) | درمیانہ — Claude میں لوپ درکار |
| reasoning_effort | صرف GPT o-series | زیادہ — کہیں اور متبادل نہیں |
| temperature > 1.0 | GPT، Gemini (Claude پر نہیں) | کم — Claude کی حد 1.0 ہے |
| tools | تمام بڑے فراہم کنندگان | کوئی نہیں — استعمال کے لیے محفوظ |
| response_format | تمام بڑے فراہم کنندگان | کم — معمولی اسکیم فرق |
اگر آپ اعتماد اسکورنگ کے لیے logprobs استعمال کر رہے ہیں تو اس فیچر کے لیے آپ GPT کے لاک اِن میں ہیں۔ یہ معقول سمجھوتہ ہے — بس اسے دستاویزی بنائیں تاکہ اگلا ڈویلپر وجہ جان سکے۔
فراہم کنندہ اینڈ پوائنٹ کو کنفیگریبل بنائیں
base_url="https://api.cometapi.com/v1" ہارڈ کوڈ کرنا بھی لاک اِن کی ایک شکل ہے۔ اسے محیطی ویریایبل بنائیں:
# .env — CometAPI کا استعمالAI_BASE_URL=https://api.cometapi.com/v1AI_API_KEY=your_cometapi_key# براہِ راست OpenAI پر جانے کے لیے یہ دو لائنیں بدل دیں:# AI_BASE_URL=https://api.openai.com/v1# AI_API_KEY=your_openai_key
مرحلہ 1 سے کلائنٹ initialization پہلے ہی ان ویریایبلز سے پڑھتا ہے۔ CometAPI اور کسی براہِ راست فراہم کنندہ کے درمیان سوئچ کرنا اب کوڈ نہیں، کنفیگ تبدیلی ہے۔
Node.js ورژن
import OpenAI from 'openai';const apiKey = process.env.AI_API_KEY;if (!apiKey) throw new Error('AI_API_KEY سیٹ نہیں ہے');const client = new OpenAI({ baseURL: process.env.AI_BASE_URL ?? 'https://api.cometapi.com/v1', apiKey,});// ماڈل IDs، CometAPI کے پلیٹ فارم identifiers ہیں — دیکھیے cometapi.com/modelsconst MODEL_CONFIG = { summarize: process.env.MODEL_SUMMARIZE ?? 'claude-opus-4-7', code: process.env.MODEL_CODE ?? 'gpt-5.4', classify: process.env.MODEL_CLASSIFY ?? 'claude-haiku-4-5', chat: process.env.MODEL_CHAT ?? 'gpt-5.4-mini',};// اسٹارٹ اپ پر توثیق کریںfor (const [task, model] of Object.entries(MODEL_CONFIG)) { if (!model) throw new Error(`'${task}' کے لیے ماڈل کنفیگ سیٹ نہیں ہے`);}/** * تمام LLM کالز کے لیے واحد انٹری پوائنٹ۔ * نارملائزڈ رسپانس لوٹاتا ہے۔ 4xx پر استثنا اٹھاتا ہے، 5xx/نیٹ ورک پر لوگ کر کے دوبارہ اٹھاتا ہے۔ */async function callModel(task, messages, options = {}) { const model = MODEL_CONFIG[task] ?? 'gpt-5.4-mini'; let response; try { response = await client.chat.completions.create({ model, messages, ...options, }); } catch (err) { // غلطیوں کو نگلیں نہیں — لوگ کریں اور دوبارہ اٹھائیں console.error(`API خرابی ٹاسک=${task} ماڈل=${model}:`, err.message); throw err; } // جب ماڈل ٹول کال ٹرگر کرے تو content null ہوتا ہے const content = response.choices[0].message.content ?? ''; // بعض کنفیگریشنز میں usage غیر موجود ہو سکتا ہے const inputTokens = response.usage?.prompt_tokens ?? 0; const outputTokens = response.usage?.completion_tokens ?? 0; console.log(`ٹاسک=${task} ماڈل=${model} ان پٹ=${inputTokens} آؤٹ پٹ=${outputTokens}`); return { content, model: response.model, inputTokens, outputTokens };}/** * روٹڈ ماڈل سے ٹوکنز اسٹریم کریں۔ * اسٹریمنگ موڈ میں usage ڈیٹا دستیاب نہیں ہوتا۔ */async function* streamModel(task, messages, options = {}) { const model = MODEL_CONFIG[task] ?? 'gpt-5.4-mini'; const stream = await client.chat.completions.create({ model, messages, stream: true, ...options, }); for await (const chunk of stream) { const delta = chunk.choices[0]?.delta?.content; if (delta) yield delta; }}// استعمال — بلاکنگconst result = await callModel('classify', [ { role: 'user', content: 'مثبت یا منفی؟ "بہت پسند آیا!"' }]);console.log(result.content);// استعمال — اسٹریمنگfor await (const token of streamModel('chat', [ { role: 'user', content: 'ہیلو' }])) { process.stdout.write(token);}
کون سا لاک اِن قابلِ قبول ہے
- Using the OpenAI SDK — یہ de facto معیار ہے۔ زیادہ تر فراہم کنندگان اسے سپورٹ کرتے ہیں۔ کم خطرے کا لاک اِن۔
- وہ فراہم کنندہ-مخصوص فیچرز جن کی آپ کو واقعی ضرورت ہے — اگر آپ کو
logprobsچاہیے تو استعمال کریں۔ اس کوڈ کو isolate رکھیں تاکہ بعد میں تلاش اور تبدیل کرنا آسان رہے۔ - Fine-tuned ماڈلز — ایک فائن ٹیونڈ ماڈل فطری طور پر ایک فراہم کنندہ سے بندھا ہوتا ہے۔ یہ متوقع ہے۔
وہ لاک اِن جس سے بچنا چاہیے وہ غیر ارادی ہے — کاروباری منطق میں ماڈل نام، مختلف فائلوں میں پھیلا ہوا خام رسپانس پارسنگ، سورس میں ہارڈ کوڈڈ API keys۔
آگے کیا ہے
اب آپ کے پاس ایک ابسٹریکشن لیئر ہے جو آپ کی کاروباری منطق سے فراہم کنندہ کی تفصیلات کو باہر رکھتی ہے۔ اس سلسلے کے آخری مضمون میں یہ ہوگا کہ جب چیزیں غلط ہوں تو کیا ہوتا ہے: ناکام جنریشنز کو کیسے ڈیبگ کریں، ایرر کوڈز کی تشریح، اور ایسا ایرر ہینڈلنگ بنانا جو واقعی بتائے کہ کیا ٹوٹا۔
اگلا: AI API جنریشنز کی ناکامی کو کیسے ڈیبگ کریں
سوالات
سوال: SDK لاک اِن اور ماڈل لاک اِن میں کیا فرق ہے؟
SDK لاک اِن کا مطلب ہے آپ کا کوڈ ایک مخصوص لائبریری امپورٹ کرتا ہے اور اگر آپ SDK بدلیں تو کوڈ بدلنا پڑے گا۔ ماڈل لاک اِن کا مطلب ہے ماڈل نام آپ کی کاروباری منطق میں بکھرے ہوئے ہیں۔ SDK لاک اِن کم خطرناک ہے کیونکہ زیادہ تر فراہم کنندگان اب OpenAI SDK فارمیٹ سپورٹ کرتے ہیں۔ ماڈل لاک اِن زیادہ پریشان کن ہے کیونکہ اسے ڈھونڈنا اور ٹھیک کرنا مشکل ہوتا ہے۔
سوال: اگر میں CometAPI استعمال کروں تو کیا میں صرف OpenAI لاک اِن کے بدلے CometAPI لاک اِن لے رہا ہوں؟
کچھ حد تک۔ آپ براہِ راست فراہم کنندہ لاک اِن کے بدلے ایک پراکسی لیئر لے رہے ہیں۔ فائدہ: ایک key، ایک اینڈ پوائنٹ، ماڈل سوئچ کرنا آسان۔ خطرہ: اگر CometAPI میں آؤٹیج ہوا تو آپ کے تمام فراہم کنندگان ایک ساتھ بند ہو سکتے ہیں۔ تدارک اوپر کے کوڈ میں ہے — AI_BASE_URL ایک محیطی ویریایبل ہے۔ اگر آپ کو CometAPI کو بائی پاس کر کے براہِ راست فراہم کنندہ کو کال کرنا ہو تو یہ کنفیگ تبدیلی ہے، کوڈ تبدیلی نہیں۔
سوال: کیا میں Claude کی extended thinking یا OpenAI کی reasoning_effort کو اس پیٹرن کے ذریعے استعمال کر سکتا/سکتی ہوں؟
ہاں، انہیں call_model میں **kwargs کے طور پر پاس کریں۔ بس یاد رہے کہ اگر آپ اس ٹاسک کو کسی اور ماڈل کی طرف روٹ کریں تو یہ پیرامیٹرز نظرانداز ہو جائیں گے یا ایرر دیں گے۔ ان ٹاسکس کو دستاویزی بنائیں جو فراہم کنندہ-مخصوص فیچرز استعمال کرتے ہیں تاکہ اگلا ڈویلپر وجہ جان سکے۔
سوال: Claude کی temperature حد 1.0 کو Claude اور GPT****?** کے درمیان روٹنگ کرتے وقت کیسے ہینڈل کروں؟
temperature کو 1.0 یا اس سے کم رکھیں تاکہ دونوں کے لیے محفوظ حد میں رہیں۔ اگر آپ کو خاص طور پر GPT پر تخلیقی ٹاسکس کے لیے زیادہ temperature چاہیے تو ان ٹاسکس کو MODEL_CONFIG میں واضح طور پر GPT پر روٹ کریں، بجائے اس کے کہ انہیں عمومی روٹر پر چھوڑ دیں۔
سوال: کیا مجھے امیج اور ویڈیو جنریشن APIs کو بھی اسی طرح abstract کرنا چاہیے؟
وہی اصول لاگو ہوتے ہیں — مرکزی کنفیگ، نارملائزڈ رسپانس ریپر، کاروباری منطق میں فراہم کنندہ-مخصوص فیلڈز نہ ہوں۔ امیج اور ویڈیو APIs میں ساختی فرق زیادہ ہوتے ہیں (async بمقابلہ sync، مختلف پیرامیٹر سیٹس) اس لیے ابسٹراکشن لیئر میں زیادہ کام لگتا ہے۔ پہلے ٹیکسٹ سے شروع کریں، پھر ڈھانچے کے ثابت ہونے پر پیٹرن کو بڑھائیں۔
سوال: ماڈلز کے درمیان context window کے فرق کا کیا کریں؟
یہ روٹنگ کے وقت حقیقی خطرہ ہے۔ GPT-5.5 کا context window 1M ٹوکن ہے، Claude ماڈلز 200K تک سپورٹ کرتے ہیں، اور Gemini 3.5 Flash 1M تک سپورٹ کرتا ہے۔ اگر آپ کسی لمبے ڈاکیومنٹ کے ٹاسک کو کم context window والے ماڈل کی طرف روٹ کریں تو ان پٹ خاموشی سے truncate ہو جاتا ہے۔ اگر آپ کے ٹاسکس میں لمبا ان پٹ شامل ہے تو روٹنگ سے پہلے context لمبائی چیک شامل کریں — یا ہمیشہ لمبے context والے ٹاسکس کو MODEL_CONFIG میں کسی مخصوص ماڈل کی طرف روٹ کریں، بجائے اس کے کہ انہیں ڈیفالٹ پر گرنے دیں۔
