“क्या यह मॉडल टूल कॉल सपोर्ट करता है?” — यह मॉडल के बारे में सवाल लगता है। लेकिन है नहीं। यह सवाल मॉडल और उस एंडपॉइंट के बारे में है जिस पर आप उसे कॉल करते हैं — और वही मॉडल एक पर हाँ और दूसरे पर ना कह सकता है। यह पेज बताता है कि ऐसा क्यों है, और Entity Enricher किसी कैटलॉग पर भरोसा करने के बजाय इसे मापकर इस सवाल का निपटारा कैसे करता है।
OpenAI के gpt-6 परिवार को क्लासिक /v1/chat/completions एंडपॉइंट पर फ़ंक्शन टूल के साथ रिक्वेस्ट भेजें और रिक्वेस्ट सीधे अस्वीकार हो जाती है:
400 Bad Request Function tools with reasoning_effort are not supported. Use /v1/responses or set reasoning_effort to 'none'.
वही मॉडल, वही टूल और वही प्रॉम्प्ट /v1/responses पर भेजें और वह सामान्य रूप से जवाब देता है — दोनों स्ट्रक्चर्ड-आउटपुट चैनलों पर, रीज़निंग एफ़र्ट के साथ या उसके बिना। मॉडल में कुछ नहीं बदला। सिर्फ़ पता बदला।
इसका नतीजा
क्षमता केवल मॉडल की विशेषता नहीं है। यह (मॉडल, एंडपॉइंट) जोड़े की विशेषता है। इसलिए हर वह कैटलॉग जो प्रति मॉडल एक ही true/false रखता है, ऐसे सवाल का जवाब दे रहा है जिसे वह वास्तव में देख ही नहीं सकता।
रूट बस वह एंडपॉइंट है जिस पर रिक्वेस्ट भेजी जाती है। वही प्रोवाइडर, वही मॉडल, वही API की — लेकिन अलग वायर फ़ॉर्मैट, अलग रिक्वेस्ट संरचना, और इस बारे में अलग नियम कि क्या-क्या साथ मिलाया जा सकता है। OpenAI इनमें से दो देता है, और इंडस्ट्री के बड़े हिस्से ने पुराने वाले की कॉपी कर ली।
| रूट | आदान-प्रदान का स्वरूप | कौन इसे बोलता है |
|---|---|---|
Chat Completions /v1/chat/completions2023 | स्टेटलेस: आप मैसेज की पूरी सूची भेजते हैं, आपको अगला मैसेज वापस मिलता है। कॉल के बीच सर्वर पर कुछ भी नहीं रखा जाता। | OpenAI, और वह वास्तविक इंडस्ट्री मानक जिसे लगभग बाकी सबने अपनाया है — xAI, DeepSeek, Alibaba, Groq, Together, Ollama और ज़्यादातर OpenAI-संगत गेटवे। |
Responses API /v1/responses2025 | टाइप्ड आइटम की एक सूची लौटाता है — एक रीज़निंग आइटम, एक मैसेज, एक फ़ंक्शन-टूल कॉल, एक होस्टेड-टूल कॉल — स्टेट सर्वर-साइड रखता है, और रीज़निंग को एक टर्न से अगले टर्न तक ले जा सकता है। | सिर्फ़ OpenAI। Chat Completions जैसा स्वरूप बोलने वाला कोई मिलता-जुलता एंडपॉइंट अपने आप इसे सर्व नहीं करता। |
इसीलिए आज “the OpenAI API” कहना अस्पष्ट है: वे दो हैं, वे एक-दूसरे से ओवरलैप करते हैं, और वे एक जैसे नियम लागू नहीं करते।
रीज़निंग मॉडलों ने मैसेज मॉडल को तोड़ दिया। किसी मॉडल की आंतरिक रीज़निंग कोई मैसेज नहीं है: न वह कुछ है जो उसने आपसे कहा, न वह जो आपने उससे कहा। Chat Completions के पास सिर्फ़ मैसेज की एक सूची है, इसलिए रीज़निंग रखने की उसमें कोई जगह नहीं — और जिसे वह दर्शा नहीं सकता, उसे वह एक टर्न से दूसरे टर्न के बीच गिरा देता है।
Responses API को इसी कमी को ध्यान में रखकर बनाया गया था। लौटाई गई सूची में reasoning एक प्रथम-श्रेणी आइटम है; यह एन्क्रिप्टेड रूप में वापस आ सकता है और अगली बारी में दोबारा भेजा जा सकता है, जिससे मॉडल अपनी सोच को फिर से गढ़ने की बजाय उसी से आगे चलता है।
फ़ंक्शन-टूल कॉल एक राउंड ट्रिप है: मॉडल किसी टूल की मांग करता है, आपका कोड जवाब देता है, मॉडल आगे बढ़ता है। Chat Completions पर उस राउंड ट्रिप के दौरान रीज़निंग रखने की कोई जगह नहीं है, इसलिए कॉन्टिन्यूएशन चुपचाप उसके बिना फिर शुरू हो जाएगा — मॉडल को वह सोच दोबारा करनी पड़ेगी जिसका आपने पहले ही भुगतान किया था, और संभवतः वह उसे अलग तरह से दोहराएगा।
इसलिए प्रोवाइडर चुपचाप गुणवत्ता घटाने के बजाय इस संयोजन को मना कर देता है। एरर मैसेज मॉडल की सीमा नहीं है; यह पुराने API का यह मानना है कि यह मॉडल जो पैदा करता है, उसके लिए उसके पास कोई जगह ही नहीं है।
अगर हर क्षमता एक ही एंडपॉइंट को पसंद करती, तो रूट एक ऐसा इम्प्लीमेंटेशन विवरण होता जिसके बारे में किसी को सोचना ही न पड़ता। पर ऐसा है नहीं।
टूल चैनल के ज़रिए स्ट्रक्चर्ड आउटपुट ठीक वही संयोजन है जिसे Chat Completions किसी रीज़निंग मॉडल पर मना करता है, और प्रोवाइडर-होस्टेड वेब-सर्च टूल सिर्फ़ वहीं स्वीकार किया जाता है।
रॉ ऑडियो बाइट्स अटैच करना Responses API पथ नहीं संभाल सकता, इसलिए ऑडियो-सक्षम मॉडल केवल पुराने एंडपॉइंट से पहुँच में आता है।
एक मॉडल, दो क्षमताएँ, दो अलग एंडपॉइंट। कोई एक true/false ऐसा नहीं जो दोनों के बारे में ईमानदार हो — इसीलिए Entity Enricher प्रति रूट क्षमता मैप दर्ज करता है, और इसीलिए जिस रन को दो अलग रूट पर बसी दो क्षमताएँ चाहिए, उसे चुपचाप एक क्षमता गँवाने के बजाय साफ़ शब्दों में मना कर दिया जाता है।
क्षमता प्रोब कोई बनावटी, हाथ से लिखी रिक्वेस्ट नहीं भेजती। यह असली एजेंट पथ चलाती है — वही कोड जिससे कोई एनरिचमेंट रन गुज़रता है — जाँची जा रही क्षमता को ज़बरदस्ती चालू करके, और फ़ैसला प्रोवाइडर के जवाब पर छोड़ देती है। इसलिए जो मापा जाता है वह यह है कि एप्लिकेशन वास्तव में क्या कर सकता है, न कि यह कि API सैद्धांतिक रूप से क्या स्वीकार कर सकता है।
पूरी सीढ़ी — स्ट्रक्चर्ड-आउटपुट चैनल, विज़न, PDF, ऑडियो, web search, reasoning और उसका प्रति-अनुरोध effort नियंत्रण — राउटर जो भी रूट चुन सकता है, उसके लिए एक बार चलती है। लगभग हर प्रोवाइडर के लिए वह एक ही रूट होता है, और प्रोब की लागत बिलकुल वही रहती है जो हमेशा थी; केवल OpenAI-आकार के वे प्रोवाइडर, जिन तक वाकई दो तरीकों से पहुँचा जा सकता है, दो बार मापे जाते हैं।
जो रूट अपनी पहली प्लेन-टेक्स्ट कॉल का जवाब नहीं देता, उसे बस मापा ही नहीं जाता, और प्रोब किए गए मॉडल को फिर केवल उन रूट्स पर भेजा जाता है जिन्होंने जवाब दिया — किसी दूसरे एंडपॉइंट पर फ़ॉलबैक नहीं होता, न चयन के समय और न रन फ़ेल होने पर। जिस मॉडल के लिए कोई रूट जवाब नहीं देता, उसे हटा दिया जाता है, और उसे भी जिसके रूट्स पर कोई भी स्ट्रक्चर्ड-आउटपुट चैनल नहीं है: टेक्स्ट कभी फ़ॉलबैक नहीं होता, इसलिए ऐसा मॉडल एक भी एनरिचमेंट पूरी नहीं कर सकता। उसे केवल कोई बाद वाला प्रोब ही वापस लाता है जो किसी चैनल को साबित कर दे। रन फ़ेल होने की वजह से क्षमताएँ कभी नहीं बदली जातीं — उन्हें मापने वाली एकमात्र चीज़ प्रोब है।
अनुरोध स्वीकार हुआ और मॉडल ने अपेक्षित प्रकार का उत्तर दिया।
उस रूट के लिए मापे गए true के रूप में दर्ज — और यह हर स्क्रैप किए गए दावे पर भारी पड़ता है।
प्रोवाइडर ने क्षमता को स्पष्ट रूप से अस्वीकार कर दिया, या क्लाइंट ने अनुरोध बनाने से ही इनकार कर दिया।
केवल यही परिणाम false लिखने की अनुमति पाता है। अस्वीकृति भी निःशुल्क है: उसका कभी बिल नहीं बनता।
इसके अलावा कुछ भी: रेट लिमिट, अनुपलब्ध एक्सेस टियर, टाइमआउट, प्रोवाइडर 5xx, कोई अपरिचित एरर।
कुछ भी दर्ज नहीं होता, और अगली प्रोब इसका निपटारा कर सकती है।
दोनों गलतियों की कीमत बराबर नहीं है। गलत unknown की कीमत एक री-प्रोब है: क्षमता को बाद में फिर से माप लिया जाता है। गलत no चुपचाप और स्थायी होता है — यह मॉडल को हर जगह नीचे गिरा देता है, उसे पिकर्स से और रूटिंग के निर्णय से हटा देता है, और किसी को कभी पता नहीं चलता कि क्यों। इसलिए कोई अपरिचित विफलता कुछ भी सिद्ध नहीं करती, और उसे कुछ भी सिद्ध न करने वाली मानकर दर्ज किया जाता है।
HTTP 200 यह साबित करता है कि रिक्वेस्ट स्वीकार हुई। यह साबित नहीं करता कि मॉडल ने अटैचमेंट वास्तव में पढ़ा — कोई प्रोवाइडर आराम से इमेज स्वीकार कर उसे ऐसे मॉडल को दे सकता है जो उसे कभी देखता ही नहीं। इसलिए पेलोड ले जाने वाला हर प्रोब ऐसा पेलोड ले जाता है जिसका जवाब जाँचा जा सके:
| क्षमता | भेजा गया पेलोड | पूछा गया सवाल |
|---|---|---|
| विज़न | एक ठोस लाल इमेज | “इसमें कौन-सा रंग प्रमुख है?” |
| PDF इनपुट | ठीक एक शब्द वाला PDF | “डॉक्यूमेंट में कौन-सा शब्द है?” |
| ऑडियो इनपुट | गिनी जा सकने वाली टोन की संख्या वाली एक ऑडियो फ़ाइल | “कितनी अलग-अलग बीप?” |
दो अलग-अलग परिणाम, जान-बूझकर
कंटेंट का जवाब वर्डिक्ट के साथ दर्ज होता है और क्षमता फ़्लैग को कभी नहीं पलटता। कोई छोटा मॉडल अगर लाल वर्ग को गलत पढ़ ले, तब भी वह विज़न सपोर्ट करता है — ट्रांसपोर्ट ने काम किया, मोडैलिटी पहुँचाई गई, मॉडल बस कमज़ोर था। “नहीं कर सकता” और “खराब किया” को एक मान लेना एक गलत शब्द की वजह से चुपचाप एक काम करती क्षमता मिटा देगा; उन्हें अलग रखने से आपको दोनों बातें एक साथ पता चलती हैं।
LiteLLM या PricePerToken जैसे सार्वजनिक मॉडल कैटलॉग क्षमताओं को मॉडल के बारे में एक सपाट तथ्य के रूप में बताते हैं, बिना किसी एंडपॉइंट के। यह लापरवाही नहीं है — इसके लिए उनके पास कोई फ़ील्ड ही नहीं है। पर इसका मतलब है कि कोई दावा आम तौर पर बिल्कुल सही हो सकता है और फिर भी उस एंडपॉइंट के लिए गलत हो सकता है जिसे आपका रन इस्तेमाल करता है।
“यह मॉडल टूल कॉल सपोर्ट करता है।” कहीं न कहीं सही। कहाँ, इस पर चुप। ऐसे मॉडल के लिए शुरुआती बिंदु के रूप में उपयोगी जिसे अभी किसी ने प्रोब नहीं किया है।
“इस एंडपॉइंट पर, इस मॉडल ने इस क्षण टूल कॉल स्वीकार किए।” यह अपने रूट का नाम बताता है, जिससे इसकी तुलना उस रूट से की जा सकती है जिसे कोई रन वास्तव में लेगा।
रूट का नाम दर्ज करना ही किसी माप को समय के साथ ईमानदार बनाए रखता है। जिस एंडपॉइंट को मॉडल अब इस्तेमाल ही नहीं करता, उस पर लिया गया वर्डिक्ट किसी दावे से बेहतर सबूत नहीं है — वह किसी और चीज़ का सबूत है। अगर उसके साथ रूट दर्ज न हो, तो पुराना माप मौजूदा माप से अलग ही नहीं दिखेगा और गलत एंडपॉइंट के लिए कैटलॉग पर भारी पड़ जाएगा। रूट दर्ज होने पर वह बस लागू नहीं होता, और जब तक सही एंडपॉइंट पर लिया गया माप उसकी जगह नहीं लेता, दावा ही मान्य रहता है।
ऐप के अंदर वाला मॉडल कैटलॉग और सार्वजनिक मॉडल कैटलॉग, दोनों में फ़िल्टर के पास एक Route सेलेक्टर होता है। यह बदलता है कि हर पंक्ति के क्षमता आइकन किस रूट के लिए जवाब दे रहे हैं।
हर पंक्ति उस एंडपॉइंट के लिए जवाब देती है जिस पर वह मॉडल वास्तव में सर्व किया जाता है। यही वह व्यू है जो एनरिचमेंट चलाने पर मिलने वाले नतीजे से मेल खाता है, और जब तक आप किसी विशिष्ट एंडपॉइंट की जाँच नहीं कर रहे, पढ़ने लायक यही है।
पूरी टेबल को एक एंडपॉइंट पर पिन कर दें और आइकन सिर्फ़ उसी एंडपॉइंट के लिए जवाब देंगे — इसी तरह आप एंडपॉइंट बदलते हुए किसी क्षमता को प्रकट या गायब होते देख पाते हैं, और इसी तरह दो मॉडलों की बराबरी पर तुलना कर पाते हैं।
जिस मॉडल का केवल एक ही पहुँच-योग्य रूट है, उसके लिए कोई सेलेक्टर नहीं दिखता: चुनने के लिए कुछ नहीं है, और उसके आइकन पहले से ही उसके एकमात्र एंडपॉइंट के लिए जवाब दे रहे हैं। सेलेक्टर ठीक तब दिखता है जब अस्पष्टता वास्तविक होती है।
ज़्यादातर मौकों पर कुछ नहीं — और यही तो बात है। आप कभी रूट नहीं चुनते। आप एक मॉडल चुनते हैं और अपने रन का विवरण देते हैं, और राउटर वह एंडपॉइंट चुनता है जो रन की ज़रूरत को उठा सके: टूल और वेब सर्च वहाँ जाते हैं जहाँ वे स्वीकार किए जाते हैं, ऑडियो अटैचमेंट वहाँ जाता है जहाँ ऑडियो ले जाया जा सके।
आपको जो एक स्थिति दिखाई देगी वह वास्तविक टकराव है — उदाहरण के लिए, उसी OpenAI मॉडल से web search माँगना और साथ ही एक ऑडियो फ़ाइल अटैच करना, क्योंकि कोई एक एंडपॉइंट दोनों को नहीं देता। ऐसे रन को स्पष्ट रूप से अस्वीकार किया जाता है — दोनों क्षमताओं का नाम लेते हुए और यह बताते हुए कि हर रूट क्या ले जा सकता है — बजाय इसके कि रन चले और चुपचाप उनमें से एक छोड़ दी जाए। कोई एक आवश्यकता हटा दें, या दोनों देने वाला मॉडल चुनें, और यह आगे बढ़ जाएगा।
और जब कोई क्षमता आइकन आपको चौंकाए, तो Route सेलेक्टर ही उसकी व्याख्या है: आप लगभग हमेशा ऐसे मॉडल को देख रहे होते हैं जिसका जवाब इस पर निर्भर करता है कि सवाल कहाँ पूछा गया था।