मुख्य बिंदु
- ChatOpenAI बिना किसी बदलाव के काम करता है: base_url, api_key और मॉडल को
uncensoredपर सेट करें। - API फ़ंक्शन कॉलिंग का समर्थन करता है, इसलिए bind_tools और प्रीबिल्ट एजेंट दोनों काम करते हैं।
- लूप इटरेशन को सीमित करें और टूल आर्ग्यूमेंट्स की जांच करें; ओपन-वेट मॉडल कभी-कभी उन्हें गलत समझते हैं।
- जब आप एजेंट्स को समानांतर चलाते हैं तो पूर्ण कुंजी पर 8 समानांतर अनुरोधों की सीमा का ध्यान रखें।
शुरू करने से पहले आपको क्या चाहिए
आपको Python 3.10 या उससे नया, एक API कुंजी, और कुछ पैकेजों की आवश्यकता है। कुंजी API कुंजी पृष्ठ से आती है: Google या ईमेल और पासवर्ड से साइन अप करें, फिर एक क्लिक से $0.50 का मुफ़्त ट्रायल क्रेडिट क्लेम करें। ट्रायल कुंजी 2 समानांतर अनुरोध और प्रति मिनट 60 की अनुमति देती है, जो यदि आप एक समय में एक एजेंट चलाते हैं तो इस लेख में सब कुछ के लिए पर्याप्त है।
pip install langchain-openai langchain-core langgraph
export API_KEY="paste-your-key-here"API POST /v1/chat/completions और GET /v1/models एक्सपोज़ करता है। LangChain को केवल पहले की आवश्यकता है। मॉडल एक अकेला ओपन-वेट मॉडल है जिसे वयस्कों के कानूनी उपयोग के लिए, कंटेंट अस्वीकार किए बिना जवाब देने के लिए ट्यून्ड किया गया है; इसे एक स्वतंत्र प्रदाता द्वारा चलाया जाता है और यह किसी भी मॉडल विक्रेता की आधिकारिक API नहीं है। दस्तावेज़ हेडर और लिमिट्स सूचीबद्ध करता है यदि आप उन्हें अपने एडिटर के पास चाहते हैं।
हिस्से API से कैसे मैप होते हैं
यह जानना मददगार है कि LangChain नेटवर्क पर क्या करता है। एक HumanMessage role user के साथ एक संदेश बन जाता है। एक AIMessage assistant बन जाता है, और जब यह tool calls वहन करता है, तो वे असिस्टेंट संदेश में एक tool_calls सरणी के रूप में प्रकट होते हैं। एक ToolMessage role tool बन जाता है जिसमें मेल खाने वाला कॉल ID होता है। सिस्टम प्रॉम्प्ट पहले role system के साथ जाता है।
यह मैपिंग डिबगिंग के लिए महत्वपूर्ण है। यदि कोई एजेंट अजीब व्यवहार करता है, तो प्रत्येक कॉल से पहले संदेश सूची प्रिंट करें और इसे एक ट्रांसक्रिप्ट की तरह पढ़ें। आप आमतौर पर एक मिनट के भीतर समस्या पहचान लेंगे: एक टूल रिजल्ट जो खाली है, एक कॉल आईडी जो मेल नहीं खाती, या एक हिस्ट्री जो आपकी उम्मीद से कहीं ज्यादा लंबी हो गई है। शब्द एजेंटिक इसे जादू जैसा बना सकता है, लेकिन हर कदम एक साधारण चैट कंप्लीशन अनुरोध है।
चरण 1: ChatOpenAI कनेक्ट करें
पूरी इंटीग्रेशन तीन आर्गुमेंट्स पर निर्भर है। LangChain मानक OpenAI-शैली के अनुरोध बनाता है, इसलिए सर्वर अंतर नहीं बता सकता।
import os
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.uncensoredvideo.cc/v1",
api_key=os.environ["API_KEY"],
temperature=0.7,
max_retries=2,
)
print(llm.invoke("Name three beats of a heist scene, one line each.").content)यदि यह तीन लाइनें प्रिंट करता है, तो प्लंबिंग काम कर रही है। यदि आपको 401 मिलता है, तो कुंजी की जाँच करें। यदि आपको 404 मिलता है, तो जाँच करें कि URL /v1 पर समाप्त होता है और इसमें कोई अतिरिक्त पाथ नहीं है। max_retries एक क्लाइंट विकल्प है, और यह Retry-After: 5 वाले अस्थायी 429 प्रतिक्रियाओं के साथ मदद करता है।
स्ट्रीमिंग उसी तरीके से काम करती है जिससे आप किसी भी OpenAI मॉडल के साथ इसका उपयोग करेंगे: llm.stream(...) कॉल करें और इटरेट करें। अंतिम चंक उपयोग की जानकारी लेकर आता है, इसलिए आप प्रत्येक कॉल के लिए टोकन गणना लॉग कर सकते हैं।
चरण 2: टूल्स परिभाषित करें
एक एजेंट एक लूप है: मॉडल कन्वर्सेशन पढ़ता है, या तो जवाब देता है या टूल का अनुरोध करता है, आपका कोड टूल चलाता है, और परिणाम वापस मॉडल को जाता है। नीचे दिए गए टूल्स सादे Python फ़ंक्शन हैं। वे जानबूझकर बोरिंग हैं, क्योंकि उद्देश्य मैकेनिक्स देखना है।
from langchain_core.tools import tool
@tool
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
@tool
def spoken_minutes(words: int, words_per_minute: int = 150) -> float:
"""Estimate how many minutes a script takes to read aloud."""
return round(words / words_per_minute, 2)
tools = [word_count, spoken_minutes]डॉकस्ट्रिंग और टाइप हिंट्स मॉडल द्वारा देखे जाने वाले टूल विवरण और स्कीमा बन जाते हैं। उन्हें इस तरह लिखें जैसे आप किसी सहकर्मी को ब्रीफिंग दे रहे हों। एक अस्पष्ट डॉकस्ट्रिंग एजेंट द्वारा गलत टूल चुनने का सबसे आम कारण है। यदि आप वीडियो के लिए स्क्रिप्ट लिखते हैं, तो एक ही पैटर्न शॉट लिस्ट खोजने या लेंथ बजेट की जाँच करने वाले टूल्स तक स्केल करता है, जिसका विवरण Sora 2 स्क्रिप्ट जनरेटर पेज पर दिया गया है।
चरण 3: एजेंट लूप को हाथ से चलाएं
प्रीबिल्ट हेल्पर्स लूप को छुपाते हैं। इसे एक बार स्वयं लिखने से आगे की हर बग ढूँढना आसान हो जाता है।
from langchain_core.messages import HumanMessage, ToolMessage
by_name = {t.name: t for t in tools}
llm_tools = llm.bind_tools(tools)
messages = [HumanMessage(
"Here is a draft: 'The vault door hums. Nina counts to three, "
"then cuts the power.' How many words is it, and how long is it read aloud?"
)]
for step in range(6):
ai = llm_tools.invoke(messages)
messages.append(ai)
if not ai.tool_calls:
break
for call in ai.tool_calls:
result = by_name[call["name"]].invoke(call["args"])
messages.append(ToolMessage(content=str(result), tool_call_id=call["id"]))
print(messages[-1].content)तीन बातें महत्वपूर्ण हैं। range(6) कैप एक भ्रमित मॉडल को अनंत लूप से रोकता है, और यह आपके खर्च को भी कैप करता है। tool_call_id को उस कॉल से मेल खाना चाहिए जिसका जवाब दिया जा रहा है। और मॉडल एक ही रिप्लाई में कई टूल्स का अनुरोध कर सकता है, इसलिए भीतरी लूप एक लिस्ट को हैंडल करता है।
अंदर से, अनुरोध में tools ऐरे होता है और रिप्लाई में tool_calls होता है, जिसमें परिणाम role: "tool" वाले संदेशों के रूप में लौटाए जाते हैं। आप tool_choice के साथ एक विशिष्ट टूल फोर्स कर सकते हैं, जिसे LangChain bind_tools को एक आर्गुमेंट के रूप में एक्सपोज़ करता है।
चरण 4: प्रीबिल्ट LangGraph एजेंट का उपयोग करें
जब मैनुअल लूप समझ में आ जाता है, तो प्रीबिल्ट एजेंट लाइन्स बचाता है। यह उसी मॉडल और उसी टूल्स को लेता है।
import os
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(
model="uncensored",
base_url="https://api.uncensoredvideo.cc/v1",
api_key=os.environ["API_KEY"],
)
agent = create_react_agent(llm, tools)
out = agent.invoke({"messages": [("user", "How long is a 450 word script read aloud?")]})
print(out["messages"][-1].content)LangChain और LangGraph अपने API रिलीज के बीच बदलते हैं, और कुछ हेल्पर्स को नाम बदल दिए गए हैं या स्थानांतरित कर दिए गए हैं। यदि कोई इम्पोर्ट फेल होता है, तो समकक्ष एजेंट कन्स्ट्रक्टर के लिए वर्तमान LangChain दस्तावेज़ीकरण की जाँच करें। कनेक्शन भाग, ChatOpenAI एक बेस URL के साथ, वही रहता है।
लूप और ग्राफ के बीच चयन करना
हाथ से लिखा गया लूप उन एजेंट्स के लिए पर्याप्त है जो कुछ टूल्स में से चुनते हैं और रुक जाते हैं। यह पढ़ने में आसान है, लॉग करने में आसान है और इसमें फ्रेमवर्क की कोई हैरानी नहीं है। जब आपको स्टेट पर निर्भर शाखाओं की आवश्यकता हो तो LangGraph पर जाएं: एक रिव्यू स्टेप जो काम को फिर से पास करने के लिए वापस भेजता है, एक रिस्की टूल चलने से पहले एक मानवीय अनुमोदन, या कई विशेषज्ञ सब-एजेंट जो परिणाम एक-दूसरे को पास करते हैं।
आप जो भी चुनते हैं, प्रत्येक नोड को छोटा रखें और उसे एक काम दें। एक प्लानिंग नोड जो JSON में एक छोटी नंबर लिस्ट आउटपुट करता है, एक एक्जीक्यूशन नोड जो टूल्स चलाता है, और एक राइटिंग नोड जो अंतिम टेक्स्ट तैयार करता है, एक विशाल प्रॉम्प्ट की तुलना में टेस्ट करने में आसान हैं। वे आपको अलग-अलग टेम्परेचर का उपयोग करने की भी अनुमति देते हैं: प्लानिंग और टूल उपयोग के लिए कम, और राइटिंग स्टेप के लिए अधिक। चूंकि हर नोड एक सामान्य चैट कंप्लीशन कॉल है, वही कुंजी, URL और मॉडल नाम उन सभी को सर्व करता है, और लागत बस कॉल्स का योग है।
एक आखिरी आदत: रनिंग टोकन टोटल प्रिंट करें। डेमो में सस्ते दिखने वाले एजेंट एक अस्त-व्यस्त असली टास्क पर दस गुना ज्यादा खर्च कर सकते हैं, और हर रिस्पॉन्स पर उपयोग आंकड़े इसे पहले रन पर दिखाते हैं, इससे पहले कि यह आपके बैलेंस पर एक हैरानी बन जाए।
मेमोरी, टेस्टिंग और स्ट्रक्चर्ड आउटपुट
ऊपर वाला लूप स्क्रिप्ट खत्म होने पर सब कुछ भूल जाता है। सबसे सरल मेमोरी संदेश सूची स्वयं है: इसे यूजर टर्न्स के बीच रखें, हर नए सवाल को एपेंड करें, और जब यह लंबा हो जाए तो सबसे पुराने संदेशों को ट्रिम करें। लंबे सत्रों के लिए, पुराने संदेशों को मॉडल द्वारा लिखे गए एक छोटे सारांश से बदल दें। चूंकि इनपुट प्रति टोकन के लिए बिल किया जाता है, एक 500-टोकन सारांश खर्च और फोकस दोनों में 20,000 टोकन की रॉ हिस्ट्री से बेहतर है।
एजेंट्स की टेस्टिंग मुख्य रूप से उन व्यवहारों की जाँच करने के बारे में है जिन्हें आप देख सकते हैं। टेम्परेचर को 0 पर सेट करें या एक तय seed पास करें, जिसे API पास कर देता है, ताकि रन अधिक रिपीटेबल हों। फिर कुछ सवाल लिखें जहां आप जानते हैं कि कौन सा टूल कॉल होना चाहिए, और जवाब के सटीक शब्दों पर नहीं, बल्कि संदेश सूची में टूल नामों और आर्गुमेंट्स पर असर्ट करें। प्रॉम्प्ट या टूल विवरण में हर बदलाव के बाद इन्हें चलाएँ। एक डॉकस्ट्रिंग बदलने से मॉडल द्वारा चुना गया टूल बदल सकता है, और टेस्ट नोटिस करने का सबसे सस्ता तरीका है।
हर रन के लिए तीन चीजें लॉग करें: स्टेप्स की संख्या, उनके आर्गुमेंट्स के साथ टूल कॉल्स, और टोकन उपयोग। जब एक रन गलत होता है, तो वे तीन लाइनें आपको बताती हैं कि क्या मॉडल ने गलत चयन किया, क्या टूल फेल हुआ, या लूप स्टेप्स से बाहर हो गया।
स्ट्रक्चर्ड आउटपुट और JSON मोड
एजेंट्स को अक्सर टेक्स्ट के बजाय डेटा वापस करना होता है। API response_format: {"type":"json_object"} के माध्यम से JSON मोड सपोर्ट करता है। LangChain में आप llm.bind(response_format={"type": "json_object"}) के साथ इसे मांग सकते हैं। प्रॉम्प्ट में मॉडल को बताएं कि जवाब एक JSON ऑब्जेक्ट होना चाहिए और उन कीज को नाम दें जिन्हें आप उम्मीद करते हैं, फिर स्ट्रिंग को पार्स करें और Pydantic के साथ उसे वैलिडेट करें। पार्स स्टेप पर हमेशा सफल होने का भरोसा न करें; इसे एक रेट्री में लपेटें जो एरर टेक्स्ट को मॉडल को एक बार वापस भेजता है।
चूक और उन्हें ठीक करने के तरीके
- खराब टूल तर्क। एक ओपन-वेट मॉडल कभी-कभी उस जगह पर स्ट्रिंग भेजता है जहाँ आपने इंटिजर घोषित किया था। तर्कों की जाँच करें, टूल से एक छोटा एरर मैसेज लौटाएँ, और अगले चरण पर मॉडल को स्वयं सुधारने दें।
- अनियंत्रित लूप। हमेशा इटेरेशन को सीमित करें। डेवलप करते समय हर चरण को लॉग करें।
- समानांतर एजेंट। एक फुल कुंजी 8 समानांतर अनुरोधों की अनुमति देती है। यदि आप एक बैच चला रहे हैं, तो
config={"max_concurrency": 4}llm.batchपर सेट करें ताकि गुंजाइश बनी रहे। लिमिट से अधिक होने पर 429 कोडconcurrencyके साथ लौटाया जाता है; प्रति मिनट 300 अनुरोधों से अधिक होने परrate_limitedलौटाया जाता है। - स्ट्रीमिंग और टूल्स का मिश्रण। एक स्ट्रीम किए गए अनुरोध में कॉन्करेंसी स्लॉट स्ट्रीम खत्म होने तक बना रहता है, इसलिए ट्रायल कुंजी पर स्ट्रीम हैंडलर के अंदर नए कॉल शुरू न करें।
- बढ़ती हुई हिस्ट्री। हर चरण पर पूर्ण मैसेज लिस्ट फिर से भेजी जाती है। कॉन्टेक्स्ट विंडो 100,000 टोकन की है, लेकिन हर कॉल पर आपको इनपुट के लिए भुगतान करना पड़ता है।
एजेंट रन का खर्च
एक साधारण एजेंट लें जो एक टास्क पूरा करने के लिए 4 मॉडल कॉल करता है, जिसमें औसत प्रॉम्प्ट 3,000 टोकन और हर कॉल पर 200 आउटपुट टोकन होते हैं। इनपुट: 4 x 3,000 = 12,000 टोकन, जो 12,000 x $0.15 / 1,000,000 = $0.0018 है। आउटपुट: 4 x 200 = 800 टोकन, जो $0.0004 है। एक रन का खर्च $0.0022 आता है, इसलिए 1,000 रन का खर्च $2.20 आता है। $0.50 का ट्रायल क्रेडिट लगभग 227 ऐसे रन कवर करता है। विफल या अस्वीकृत अनुरोधों के लिए चार्ज नहीं किया जाता है, और क्रेडिट कभी एक्सपायर नहीं होता है। टॉप-अप राशि और बोनस के लिए कीमतें देखें। यह साइट केवल क्रिप्टो लेती है, TRC20 पर USDT या Base पर USDC।
