यह पायथन एसडीके का उपयोग करके ओपनएआई के सहायक एपीआई के साथ एजेंटों के निर्माण पर एक बहु-भाग श्रृंखला में पहला भाग है। एजेंट क्या हैं? जिस तरह से मैं इसे देखना पसंद करता हूं, एक एजेंट वास्तव में एलएलएम (बड़े भाषा मॉडल) का लाभ उठाने वाले सॉफ्टवेयर का एक टुकड़ा है और मानव व्यवहार की नकल करने की कोशिश कर रहा है। इसका मतलब है कि यह न केवल बातचीत कर सकता है और भाषा को समझ सकता है, बल्कि यह ऐसे कार्य भी कर सकता है जिनका वास्तविक दुनिया पर प्रभाव पड़ता है। इन क्रियाओं को आम तौर पर उपकरण कहा जाता है। इस ब्लॉग पोस्ट में, हम यह पता लगाएंगे कि ओपनएआई के असिस्टेंट एपीआई का उपयोग करके उनके पायथन एसडीके का उपयोग करके एक एजेंट कैसे बनाया जाए। भाग 1 सहायक का ढाँचा मात्र होगा। यानी सिर्फ बातचीत का हिस्सा. मैंने फ़्रेमवर्क अज्ञेयवादी होने के उद्देश्य से एक सीएलआई ऐप बनाने का निर्णय लिया। हम जानबूझकर अपने कार्यान्वयन को एक एजेंट कहेंगे और दोनों के बीच आसानी से अंतर करने के लिए ओपनएआई एसडीके कार्यान्वयन को एक सहायक के रूप में संदर्भित करेंगे। जब उन कार्यों की बात आती है जिन्हें एजेंट कॉल करने में सक्षम होता है तो मैं और का परस्पर उपयोग करता हूं। भाग 2 में फ़ंक्शन कॉलिन को अधिक विस्तार से कवर किया जाएगा। टूल फ़ंक्शन शब्दों आवश्यक शर्तें इस ट्यूटोरियल का अनुसरण करने के लिए, आपको निम्नलिखित की आवश्यकता होगी: आपकी मशीन पर Python3 स्थापित है एक OpenAI API कुंजी पायथन प्रोग्रामिंग का बुनियादी ज्ञान OpenAI सहायक अवधारणाएँ : असिस्टेंट एपीआई में एक असिस्टेंट उपयोगकर्ता संदेशों का जवाब देने के लिए कॉन्फ़िगर की गई एक इकाई है। यह कार्यों के साथ बातचीत करने और उत्तर प्रदान करने के लिए निर्देशों, एक चुने हुए मॉडल और टूल का उपयोग करता है। असिस्टेंट : असिस्टेंट एपीआई में एक थ्रेड एक वार्तालाप या संवाद का प्रतिनिधित्व करता है। यह प्रत्येक उपयोगकर्ता इंटरैक्शन के लिए बनाया गया है और इसमें कई संदेश शामिल हो सकते हैं, जो चल रही बातचीत के लिए एक कंटेनर के रूप में काम करेंगे। थ्रेड : एक संदेश एक थ्रेड में संचार की एक इकाई है। इसमें टेक्स्ट (और भविष्य में संभावित फ़ाइलें) शामिल हैं और इसका उपयोग थ्रेड के भीतर उपयोगकर्ता प्रश्नों या सहायक प्रतिक्रियाओं को व्यक्त करने के लिए किया जाता है। संदेश : रन असिस्टेंट द्वारा थ्रेड को प्रोसेस करने का एक उदाहरण है। इसमें थ्रेड को पढ़ना, टूल को कॉल करना है या नहीं, यह तय करना और थ्रेड के संदेशों की मॉडल की व्याख्या के आधार पर प्रतिक्रियाएं उत्पन्न करना शामिल है। रन विकास परिवेश की स्थापना पहला कदम उपयोग करके एक आभासी वातावरण बनाना और उसे सक्रिय करना है। यह सुनिश्चित करेगा कि हमारी निर्भरताएँ सिस्टम पायथन इंस्टालेशन से अलग हैं: venv python3 -m venv venv source venv/bin/activate आइए अपनी एकमात्र निर्भरता स्थापित करें: पैकेज: openai pip install openai एक फ़ाइल बनाएँ। आइए हमारे सीएलआई ऐप के लिए कुछ बुनियादी रनटाइम तर्क को शामिल करें: main.py while True: user_input = input("User: ") if user_input.lower() == 'exit': print("Exiting the assistant...") break print(f"Assistant: You said {user_input}") इसे चलाकर आज़माएँ: python3 main.py python3 main.py User: hi Assistant: You said hi जैसा कि आप देख सकते हैं, सीएलआई एक उपयोगकर्ता संदेश को इनपुट के रूप में स्वीकार करता है, और हमारे जीनियस असिस्टेंट के पास अभी तक दिमाग नहीं है इसलिए वह संदेश को तुरंत दोहरा देता है। अभी इतना स्मार्ट नहीं हूं. एजेंट अब, मज़ा 😁 (या सिरदर्द 🤕) शुरू होता है। मैं अभी अंतिम कक्षा के लिए आवश्यक सभी आयात प्रदान करूंगा, ताकि आप अपना दिमाग इस बात पर न लगाएं कि चीजें कहां से आ रही हैं क्योंकि मैंने संक्षिप्तता के लिए आयात को कोड नमूनों से बाहर रखा है। आइए एक नई फ़ाइल में क्लास बनाकर शुरुआत करें: agent.py Agent import time import openai from openai.types.beta.threads.run import Run class Agent: def __init__(self, name: str, personality: str): self.name = name self.personality = personality self.client = openai.OpenAI(api_key="sk-*****") self.assistant = self.client.beta.assistants.create( name=self.name, model="gpt-4-turbo-preview" ) क्लास कंस्ट्रक्टर में, हम अपनी ओपनएआई एपीआई कुंजी पास करके ओपनएआई क्लाइंट को क्लास प्रॉपर्टी के रूप में प्रारंभ करते हैं। इसके बाद, हम एक क्लास प्रॉपर्टी बनाते हैं जो हमारे नव निर्मित असिस्टेंट से मैप होती है। हम बाद में उपयोग के लिए और वर्ग गुणों के रूप में संग्रहीत करते हैं। assistant name personality क्रिएट मेथड में हम तर्क दे रहे हैं, वह केवल ओपनएआई डैशबोर्ड में असिस्टेंट की पहचान करने के लिए है, और एआई को वास्तव में इस बिंदु पर इसकी जानकारी नहीं है। आपको वास्तव में को नाम देना होगा जिसे हम बाद में देखेंगे। name instructions असिस्टेंट बनाते समय आप पहले से ही सेट कर सकते हैं, लेकिन यह वास्तव में आपके असिस्टेंट को गतिशील परिवर्तनों के प्रति कम लचीला बना देगा। instructions आप पर कॉल करके असिस्टेंट को अपडेट कर सकते हैं, लेकिन गतिशील मूल्यों को पारित करने के लिए एक बेहतर जगह है जिसे हम रन पर पहुंचने पर देखेंगे। client.beta.assistants.update ध्यान दें कि यदि आप रन बनाते समय यहां बार-बार पारित करते हैं, तो सहायक के रन के से अधिलेखित हो जाएंगे। वे एक-दूसरे के पूरक नहीं हैं, इसलिए अपनी आवश्यकताओं के आधार पर एक चुनें: स्थिर निर्देशों के लिए सहायक स्तर या गतिशील निर्देशों के लिए रन स्तर। instructions instructions instructions मॉडल के लिए, मैंने मॉडल चुना ताकि हम इस श्रृंखला के भाग 2 में फ़ंक्शन कॉलिंग जोड़ सकें। यदि आप उपकरण लागू करते समय अपने आप को शुद्ध हताशा का माइग्रेन देते हुए पैसे का कुछ अंश बचाना चाहते हैं तो आप उपयोग कर सकते हैं। gpt-4-turbo-preview gpt-3.5-turbo जीपीटी 3.5 कॉलिंग टूल्स में भयानक है; इससे निपटने की कोशिश में मैंने जो घंटे गँवाए हैं, वे मुझे यह कहने की अनुमति देते हैं। 😝 मैं इसे यहीं छोड़ दूँगा, और इस पर बाद में और अधिक जानकारी दूंगा। एक थ्रेड बनाना, संदेश जोड़ना, और अंतिम संदेश पुनः प्राप्त करना एक एजेंट बनाने के बाद, हमें एक वार्तालाप सूत्र शुरू करने की आवश्यकता होगी। class Agent: # ... (rest of code) def create_thread(self): self.thread = self.client.beta.threads.create() और हम उस थ्रेड में संदेश जोड़ने का एक तरीका चाहेंगे: class Agent: # ... (rest of code) def add_message(self, message): self.client.beta.threads.messages.create( thread_id=self.thread.id, role="user", content=message ) ध्यान दें कि फिलहाल, केवल भूमिका के साथ संदेश जोड़ना संभव है। मेरा मानना है कि ओपनएआई भविष्य के रिलीज में इसे बदलने की योजना बना रहा है क्योंकि यह काफी सीमित है। user अब, हम थ्रेड में अंतिम संदेश प्राप्त कर सकते हैं: class Agent: # ... (rest of code) def get_last_message(self): return self.client.beta.threads.messages.list( thread_id=self.thread.id ).data[0].content[0].text.value इसके बाद, हमारे पास अब तक क्या है इसका परीक्षण करने के लिए हम एक प्रवेश बिंदु विधि बनाते हैं। वर्तमान में, विधि केवल थ्रेड में अंतिम संदेश लौटाती है। यह वास्तव में रन नहीं करता है। यह अभी भी बुद्धिहीन है. run_agent run_agent class Agent: # ... (rest of code) def run_agent(self): message = self.get_last_message() return message वापस में, हम एजेंट और अपना पहला थ्रेड बनाते हैं। हम थ्रेड में एक संदेश जोड़ते हैं। फिर वही संदेश उपयोगकर्ता को वापस लौटाएं, लेकिन इस बार, उस लाइव थ्रेड से आ रहा है। main.py from agent import Agent agent = Agent(name="Bilbo Baggins", personality="You are the accomplished and renowned adventurer from The Hobbit. You act like you are a bit of a homebody, but you are always up for an adventure. You worry a bit too much about breakfast.") agent.create_thread() while True: user_input = input("User: ") if user_input.lower() == 'exit': print("Exiting the agent...") break agent.add_message(user_input) answer = agent.run_agent() print(f"Assistant: {answer}") आइए इसे चलाएँ: python3 main.py User: hi Assistant: hi अभी भी बहुत स्मार्ट नहीं है. हॉबिट की तुलना में तोते के अधिक करीब। अगले भाग में असली मज़ा शुरू होता है। एक रन बनाना और मतदान करना जब आप एक रन बनाते हैं, तो आपको रन की स्थिति की जांच करने के लिए समय-समय पर ऑब्जेक्ट को पुनः प्राप्त करने की आवश्यकता होती है। इसे मतदान कहते हैं, और यह बेकार है। आपके एजेंट को आगे क्या करना चाहिए यह निर्धारित करने के लिए आपको मतदान करने की आवश्यकता है। OpenAI ने इसे सरल बनाने के लिए स्ट्रीमिंग के लिए समर्थन जोड़ने की योजना बनाई है। इस बीच, मैं आपको दिखाऊंगा कि इस अगले भाग में मतदान कैसे स्थापित किया जाए। Run निम्नलिखित विधि नामों पर नोट करें जो कि पायथन में यह इंगित करने के लिए मानक है कि विधि आंतरिक उपयोग के लिए है और इसे सीधे बाहरी कोड द्वारा एक्सेस नहीं किया जाना चाहिए। _ सबसे पहले, आइए बनाने के लिए एक सहायक विधि बनाएं, और इस विधि को कॉल करने के लिए अपडेट करें: Run _create_run run_agent class Agent: # ... (rest of code) def get_breakfast_count_from_db(self): return 1 def _create_run(self): count = self.get_breakfast_count_from_db() return self.client.beta.threads.runs.create( thread_id=self.thread.id, assistant_id=self.assistant.id, instructions=f""" Your name is: {self.name} Your personality is: {self.personality} Metadata related to this conversation: {{ "breakfast_count": {count} }} """, ) def run_agent(self): run = self._create_run() # add this line message = self.get_last_message() return message ध्यान दें कि रन बनाने के लिए हम और कैसे पास करते हैं। thread.id assistant.id याद रखें कि मैंने शुरुआत में कैसे कहा था कि गतिशील निर्देश और डेटा भेजने के लिए एक बेहतर जगह है? रन बनाते समय वह पैरामीटर होगा। हमारे मामले में, हम नाश्ते की एक डेटाबेस से प्राप्त कर सकते हैं। यह आपको हर बार जब आप कोई उत्तर देना चाहते हैं तो विभिन्न प्रासंगिक गतिशील डेटा को आसानी से पारित करने की अनुमति देगा। instructions count अब, आपका एजेंट अपने चारों ओर बदल रही दुनिया से अवगत है और उसके अनुसार कार्य कर सकता है। मुझे अपने निर्देशों में एक मेटाडेटा JSON ऑब्जेक्ट रखना पसंद है जो प्रासंगिक गतिशील संदर्भ रखता है। यह मुझे कम क्रियाशीलता के साथ और ऐसे प्रारूप में डेटा भेजने की अनुमति देता है जिसे एलएलएम वास्तव में अच्छी तरह से समझता है। इसे अभी तक न चलाएं; यह काम नहीं करेगा क्योंकि हम अंतिम संदेश प्राप्त होने पर रन पूरा होने की प्रतीक्षा नहीं कर रहे हैं, इसलिए यह अभी भी अंतिम उपयोगकर्ता संदेश होगा। आइए अपना मतदान तंत्र बनाकर इसका समाधान करें। सबसे पहले, हमें एक रन को बार-बार और आसानी से पुनः प्राप्त करने के लिए एक तरीके की आवश्यकता होगी, तो आइए एक विधि जोड़ें: _retrieve_run class Agent: # ... (rest of code) def _retrieve_run(self, run: Run): return self.client.beta.threads.runs.retrieve( run_id=run.id, thread_id=self.thread.id) ध्यान दें कि किसी विशिष्ट रन को खोजने के लिए हमें और दोनों को कैसे पास करना होगा। run.id thread.id हमारे एजेंट वर्ग में विधि जोड़ें: _poll_run class Agent: # ... (rest of code) def _cancel_run(self, run: Run): self.client.beta.threads.runs.cancel( run_id=run.id, thread_id=self.thread.id) def _poll_run(self, run: Run): status = run.status start_time = time.time() while status != "completed": if status == 'failed': raise Exception(f"Run failed with error: {run.last_error}") if status == 'expired': raise Exception("Run expired.") time.sleep(1) run = self._retrieve_run(run) status = run.status elapsed_time = time.time() - start_time if elapsed_time > 120: # 2 minutes self._cancel_run(run) raise Exception("Run took longer than 2 minutes.") 🥵 ओह, यह बहुत है... चलो इसे खोलो। एक ऑब्जेक्ट को तर्क के रूप में प्राप्त करता है और वर्तमान रन निकालता है। सभी उपलब्ध स्थितियाँ OpenAI में पाई जा सकती हैं। हम बस उनमें से कुछ का उपयोग करेंगे जो हमारे वर्तमान उद्देश्य के अनुरूप हों। _poll_run Run status डॉक्स अब हम कुछ त्रुटि परिदृश्यों को संभालते हुए पूर्ण स्थिति की जांच करने के लिए थोड़ी देर का लूप चलाते हैं। असिस्टेंट एपीआई की वास्तविक बिलिंग थोड़ी अस्पष्ट है, इसलिए सुरक्षित रहने के लिए, मैंने 2 मिनट के बाद अपने रन रद्द करने का विकल्प चुना। हालाँकि, जब OpenAI 10 मिनट के बाद चलता है तो इसकी समय सीमा है। यदि एक दौड़ में 2 मिनट से अधिक समय लगता है, तो संभवतः आपको कोई समस्या है। expired चूँकि मैं भी हर कुछ मिलीसेकंड में मतदान नहीं करना चाहता, इसलिए मैं अपने अनुरोध को केवल हर 1 सेकंड में मतदान करके दबा देता हूँ जब तक कि मैं 2 मिनट के निशान तक नहीं पहुँच जाता और अपनी दौड़ रद्द नहीं कर देता। आप इसे अपनी इच्छानुसार समायोजित कर सकते हैं। देरी के बाद प्रत्येक पुनरावृत्ति, हम रन स्थिति फिर से लाते हैं। अब, आइए उन सभी को हमारी विधि में प्लग करें। आप देखेंगे कि हम पहले के साथ रन बनाते हैं, फिर हम के साथ पोल करते हैं जब तक कि हमें कोई उत्तर नहीं मिलता है या कोई त्रुटि सामने नहीं आती है, और अंत में जब पोलिंग समाप्त हो जाती है, तो हम थ्रेड से अंतिम संदेश प्राप्त करते हैं जो अब एजेंट से होगा। run_agent _create_run _poll_run फिर हम संदेश को अपने रनटाइम लूप पर लौटाते हैं, ताकि इसे उपयोगकर्ता को वापस भेजा जा सके। class Agent: # ... (rest of code) def run_agent(self): run = self._create_run() self._poll_run(run) # add this line message = self.get_last_message() return message वोइला, अब जब आप अपना एजेंट दोबारा चलाएंगे, तो आपको हमारे मित्रवत एजेंट से उत्तर मिलेगा: python3 main.py User: hi Assistant: Hello there! What adventure can we embark on today? Or perhaps, before we set out, we should think about breakfast. Have you had yours yet? I've had mine, of course – can't start the day without a proper breakfast, you know. User: how many breakfasts have you had? Assistant: Ah, well, I've had just 1 breakfast today. But the day is still young, and there's always room for a second, isn't there? What about you? How can I assist you on this fine day? भाग 2 में, हम अपने एजेंट के लिए टूल को कॉल करने की क्षमता जोड़ेंगे। आप पूरा कोड मेरे पर पा सकते हैं। GitHub आपके पढ़ने के लिए धन्यवाद. टिप्पणियों में कोई भी विचार और प्रतिक्रिया सुनकर खुशी हुई। इस तरह की अधिक सामग्री के लिए लिंक्डइन पर मुझे फ़ॉलो करें: https://www.linkedin.com/in/jean-marie-dalmasso-1b5473141/