এতে কোন সন্দেহ নেই যে OpenAI এর ChatGPT ব্যতিক্রমী বুদ্ধিমান — এটি আইনজীবীর বার পরীক্ষায় উত্তীর্ণ হয়েছে, এটি একজন ডাক্তারের মতো জ্ঞানের অধিকারী, এবং কিছু পরীক্ষায় এর আইকিউ 155 হয়েছে । যাইহোক, এটি অজ্ঞতা স্বীকার করার পরিবর্তে তথ্য জাল করার প্রবণতা রাখে। এই প্রবণতা, 2021 সালে এর জ্ঞান বন্ধ হওয়ার সাথে সাথে, GPT API ব্যবহার করে বিশেষ পণ্য তৈরিতে চ্যালেঞ্জ তৈরি করে।
কিভাবে আমরা এই বাধা অতিক্রম করতে পারি? কিভাবে আমরা GPT-3 এর মত মডেলে নতুন জ্ঞান দিতে পারি? আমার লক্ষ্য হল পাইথন, ওপেনএআই এপিআই এবং ওয়ার্ড এম্বেডিং নিযুক্ত করে একটি প্রশ্ন-উত্তরকারী বট তৈরি করে এই প্রশ্নগুলির সমাধান করা।
আমি এমন একটি বট তৈরি করতে চাই যা একটি প্রম্পট থেকে ক্রমাগত ইন্টিগ্রেশন পাইপলাইন তৈরি করে, যা আপনি জানেন যে, সেমাফোর সিআই/সিডিতে YAML দিয়ে তৈরি করা হয়েছে ।
এখানে কর্মরত বটটির একটি উদাহরণ রয়েছে:
চলমান প্রোগ্রামের স্ক্রিনশট। স্ক্রিনে, python query.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub"
কার্যকর করা হয় এবং প্রোগ্রামটি একটি CI পাইপলাইনের সাথে সম্পর্কিত YAML প্রিন্ট করে যা অনুরোধ করা ক্রিয়া সম্পাদন করে।
DocsGPT , My AskAI , এবং Libraria- এর মতো প্রকল্পের স্পিরিট অনুযায়ী আমি GPT-3 মডেলটিকে Semaphore এবং কীভাবে পাইপলাইন কনফিগারেশন ফাইল তৈরি করতে হয় সে সম্পর্কে "শিক্ষা" দেওয়ার পরিকল্পনা করছি। আমি বিদ্যমান ডকুমেন্টেশন ব্যবহার করে এটি অর্জন করব।
আমি বট বিল্ডিংয়ের পূর্বে জ্ঞান গ্রহণ করব না এবং পরিষ্কার কোড বজায় রাখব যাতে আপনি এটিকে আপনার প্রয়োজনীয়তার সাথে মানিয়ে নিতে পারেন।
এই টিউটোরিয়ালটি অনুসরণ করার জন্য আপনার বট কোডিং করার অভিজ্ঞতা বা নিউরাল নেটওয়ার্কের জ্ঞানের প্রয়োজন নেই। যাইহোক, আপনার প্রয়োজন হবে:
ChatGPT, বা আরও সঠিকভাবে, GPT-3 এবং GPT-4, বৃহৎ ভাষা মডেলগুলি (LLM) তাদের শক্তি প্রদান করে, সেপ্টেম্বর 2021 এর কাছাকাছি কাটঅফ তারিখ সহ একটি বিশাল ডেটাসেটে প্রশিক্ষণ দেওয়া হয়েছে।
মোটকথা, GPT-3 সেই তারিখের পরের ঘটনা সম্পর্কে খুব কমই জানে। আমরা একটি সহজ প্রম্পট দিয়ে এটি যাচাই করতে পারি:
2022 সালের বিশ্বকাপ কে জিতেছে তা ChatGPT জানে না।
যদিও কিছু ওপেনএআই মডেল ফাইন-টিউনিং এর মধ্য দিয়ে যেতে পারে, আরও উন্নত মডেল, যেমন যেগুলি আগ্রহী, তা পারে না; আমরা তাদের প্রশিক্ষণের তথ্য বাড়াতে পারি না।
আমরা কিভাবে GPT-3 এর প্রশিক্ষণ ডেটার বাইরে উত্তর পেতে পারি? একটি পদ্ধতিতে এর পাঠ্য বোঝার ক্ষমতাকে কাজে লাগানো জড়িত; প্রাসঙ্গিক প্রসঙ্গের সাথে প্রম্পট উন্নত করে, আমরা সম্ভবত সঠিক উত্তর পেতে পারি।
নীচের উদাহরণে, আমি FIFA এর অফিসিয়াল সাইট থেকে প্রসঙ্গ সরবরাহ করছি এবং প্রতিক্রিয়া উল্লেখযোগ্যভাবে আলাদা:
সরবরাহ করা প্রসঙ্গে, ChatGPT সঠিকভাবে উত্তর দিতে পারে।
আমরা অনুমান করতে পারি যে পর্যাপ্ত প্রাসঙ্গিক প্রসঙ্গ দেওয়া হলে মডেলটি যেকোনো প্রম্পটে সাড়া দিতে পারে। প্রশ্নটি রয়ে গেছে: একটি নির্বিচারে প্রম্পট দেওয়া প্রাসঙ্গিক কী তা আমরা কীভাবে জানতে পারি? এটি মোকাবেলা করার জন্য, আমাদের অন্বেষণ করতে হবে কি শব্দ এমবেডিং ।
ভাষার মডেলের পরিপ্রেক্ষিতে, একটি এম্বেডিং হল শব্দ, বাক্য বা সম্পূর্ণ নথিকে ভেক্টর বা সংখ্যার তালিকা হিসাবে উপস্থাপন করার একটি উপায়।
এম্বেডিং গণনা করতে, আমাদের একটি নিউরাল নেটওয়ার্কের প্রয়োজন হবে যেমন word2vec বা text-embeding-ada-002 । এই নেটওয়ার্কগুলিকে প্রচুর পরিমাণে পাঠ্যের উপর প্রশিক্ষিত করা হয়েছে এবং প্রশিক্ষণের ডেটাতে নির্দিষ্ট প্যাটার্নগুলি যে ফ্রিকোয়েন্সিগুলির সাথে প্রদর্শিত হয় তা বিশ্লেষণ করে শব্দগুলির মধ্যে সম্পর্ক খুঁজে পেতে পারে৷
ধরা যাক আমাদের নিম্নলিখিত শব্দ রয়েছে:
কল্পনা করুন আমরা প্রতিটি শব্দের ভেক্টর গণনা করতে এই এমবেডিং নেটওয়ার্কগুলির মধ্যে একটি ব্যবহার করি। উদাহরণ স্বরূপ:
শব্দ | ভেক্টর | প্রসঙ্গ |
---|---|---|
বিড়াল | [০.১, ০.২, ০.৩, ০.৪, ০.৫] | প্রাণী, বস্তু, ছোট জিনিস |
কুকুর | [০.৬, ০.৭, ০.৮, ০.৯, ১.০] | প্রাণী, বস্তু, বড় জিনিস |
বল | [০.২, ০.৪, ০.৬, ০.৮, ১.০] | বস্তু, খেলনা, ছোট জিনিস |
গৃহ | [০.৩, ০.৬, ০.৯, ১.২, ১.৫] | বিল্ডিং, বাড়ি, বড় জিনিস |
একবার আমাদের কাছে প্রতিটি শব্দের ভেক্টর আছে, আমরা পাঠ্যের অর্থ উপস্থাপন করতে সেগুলি ব্যবহার করতে পারি। উদাহরণস্বরূপ, "বিড়াল বল তাড়া করেছে" বাক্যটিকে ভেক্টর [0.1, 0.2, 0.3, 0.4, 0.5] + [0.2, 0.4, 0.6, 0.8, 1.0] = [0.3, 0.6, 0.9, 1.2] হিসাবে উপস্থাপন করা যেতে পারে , 1.5]। এই ভেক্টরটি এমন একটি বাক্যকে উপস্থাপন করে যা একটি প্রাণীকে একটি বস্তুকে তাড়া করে।
শব্দ এমবেডিংগুলিকে বহুমাত্রিক স্থান হিসাবে কল্পনা করা যেতে পারে যেখানে একই অর্থ সহ শব্দ বা বাক্যগুলি একসাথে কাছাকাছি থাকে। যেকোন ইনপুট টেক্সটের অনুরূপ অর্থ খুঁজতে আমরা ভেক্টরের মধ্যে "দূরত্ব" গণনা করতে পারি।
ভেক্টর স্পেস হিসাবে এমবেডিংয়ের 3D উপস্থাপনা। বাস্তবে, এই স্থানগুলির শত শত বা হাজার হাজার মাত্রা থাকতে পারে। সূত্র: মিট এআই এর মাল্টিটুল: ভেক্টর এমবেডিংস
এই সব পিছনে প্রকৃত গণিত এই নিবন্ধের সুযোগের বাইরে. যাইহোক, মূল টেকঅ্যাওয়ে হল যে ভেক্টর অপারেশনগুলি আমাদেরকে গণিত ব্যবহার করে অর্থ পরিবর্তন বা নির্ধারণ করতে দেয় । "রাণী" শব্দটিকে উপস্থাপন করে এমন ভেক্টরটি নিন, এটি থেকে "নারী" ভেক্টর বিয়োগ করুন এবং "পুরুষ" ভেক্টর যোগ করুন। ফলাফল "রাজা" এর আশেপাশে একটি ভেক্টর হওয়া উচিত। আমরা যদি "পুত্র" যোগ করি তবে আমাদের "রাজপুত্র" এর কাছাকাছি কোথাও যাওয়া উচিত।
এ পর্যন্ত, আমরা শব্দকে ইনপুট হিসেবে এবং সংখ্যাকে আউটপুট হিসেবে গ্রহণ করে নিউরাল নেটওয়ার্ক এম্বেড করার বিষয়ে আলোচনা করেছি। যাইহোক, অনেক আধুনিক নেটওয়ার্ক শব্দ প্রক্রিয়াকরণ থেকে টোকেন প্রক্রিয়াকরণে চলে গেছে।
একটি টোকেন পাঠ্যের ক্ষুদ্রতম একক যা মডেল দ্বারা প্রক্রিয়া করা যেতে পারে। টোকেন শব্দ, অক্ষর, বিরাম চিহ্ন, চিহ্ন বা শব্দের অংশ হতে পারে।
ওপেনএআই অনলাইন টোকেনাইজারের সাথে পরীক্ষা করে আমরা দেখতে পারি কিভাবে শব্দগুলিকে টোকেনে রূপান্তর করা হয়, যা টেক্সটকে টোকেনে রূপান্তর করতে বাইট-পেয়ার এনকোডিং (BPE) ব্যবহার করে এবং প্রতিটিকে একটি সংখ্যা দিয়ে উপস্থাপন করে:
টোকেন এবং শব্দের মধ্যে প্রায়ই 1-থেকে-1 সম্পর্ক থাকে। বেশিরভাগ টোকেন শব্দ এবং একটি অগ্রণী স্থান অন্তর্ভুক্ত করে। যাইহোক, "এম্বেডিং" এর মতো বিশেষ ক্ষেত্রে রয়েছে যা দুটি টোকেন নিয়ে গঠিত, "এম্বেড" এবং "ডিং" বা "ক্ষমতা" যা চারটি টোকেন নিয়ে গঠিত। আপনি যদি "টোকেন আইডি" ক্লিক করেন, আপনি প্রতিটি টোকেনের মডেলের সাংখ্যিক উপস্থাপনা দেখতে পাবেন।
এমবেডিংগুলি কী তা এখন আমরা বুঝতে পেরেছি, পরবর্তী প্রশ্ন হল: কীভাবে তারা আমাদের একটি স্মার্ট বট তৈরি করতে সাহায্য করতে পারে?
প্রথমে, আসুন আমরা সরাসরি GPT-3 API ব্যবহার করলে কী ঘটে তা বিবেচনা করা যাক। ব্যবহারকারী একটি প্রম্পট জারি করে, এবং মডেলটি তার ক্ষমতার সর্বোত্তম সাড়া দেয়।
যাইহোক, যখন আমরা সমীকরণে প্রসঙ্গ যোগ করি, তখন জিনিসগুলি পরিবর্তিত হয়। উদাহরণস্বরূপ, প্রসঙ্গ দেওয়ার পরে যখন আমি ChatGPT কে বিশ্বকাপ বিজয়ী সম্পর্কে জিজ্ঞাসা করি, তখন এটি সমস্ত পার্থক্য তৈরি করে।
সুতরাং, একটি স্মার্ট বট তৈরি করার পরিকল্পনাটি নিম্নরূপ:
ডাটাবেস ডিজাইন করে বেশিরভাগ প্রকল্পের মতই শুরু করা যাক।
আমাদের প্রসঙ্গ ডাটাবেস মূল ডকুমেন্টেশন এবং তাদের নিজ নিজ ভেক্টর অন্তর্ভুক্ত করা আবশ্যক. নীতিগতভাবে, আমরা এই কাজের জন্য যেকোনো ধরনের ডাটাবেস নিয়োগ করতে পারি, কিন্তু একটি ভেক্টর ডাটাবেস হল কাজের জন্য সর্বোত্তম হাতিয়ার।
ভেক্টর ডাটাবেসগুলি হল বিশেষ ডেটাবেস যা উচ্চ-মাত্রিক ভেক্টর ডেটা সংরক্ষণ এবং পুনরুদ্ধারের জন্য ডিজাইন করা হয়েছে। অনুসন্ধানের জন্য এসকিউএল-এর মতো একটি কোয়েরি ভাষা ব্যবহার করার পরিবর্তে, আমরা একটি ভেক্টর সরবরাহ করি এবং N নিকটতম প্রতিবেশীদের অনুরোধ করি।
ভেক্টর তৈরি করতে, আমরা OpenAI থেকে টেক্সট-এম্বেডিং-ada-002 ব্যবহার করব, কারণ এটি তাদের অফার করা সবচেয়ে দ্রুত এবং সবচেয়ে সাশ্রয়ী মডেল। মডেলটি ইনপুট টেক্সটকে টোকেনে রূপান্তর করে এবং তাদের সম্পর্ক শেখার জন্য ট্রান্সফরমার নামে পরিচিত একটি মনোযোগ প্রক্রিয়া ব্যবহার করে। এই নিউরাল নেটওয়ার্কের আউটপুট হল পাঠ্যের অর্থ প্রতিনিধিত্বকারী ভেক্টর।
একটি প্রসঙ্গ ডাটাবেস তৈরি করতে, আমি করব:
প্রথমে, আমাকে OpenAI API কী দিয়ে একটি পরিবেশ ফাইল শুরু করতে হবে। এই ফাইলটি কখনই সংস্করণ নিয়ন্ত্রণে প্রতিশ্রুতিবদ্ধ হওয়া উচিত নয়, কারণ API কীটি ব্যক্তিগত এবং আপনার অ্যাকাউন্টের সাথে সংযুক্ত৷
export OPENAI_API_KEY=YOUR_API_KEY
পরবর্তী, আমি আমার পাইথন অ্যাপ্লিকেশনের জন্য একটি ভার্চুয়ালেনভ তৈরি করব:
$ virtualenv venv $ source venv/bin/activate $ source .env
এবং OpenAI প্যাকেজ ইনস্টল করুন:
```bash $ pip install openai numpy
আসুন "ডকার কন্টেইনার" স্ট্রিংটির জন্য এমবেডিং গণনা করার চেষ্টা করি। আপনি এটি পাইথন REPL বা পাইথন স্ক্রিপ্ট হিসাবে চালাতে পারেন:
$ python >>> import openai >>> embeddings = openai.Embedding.create(input="Docker Containers", engine="text-embedding-ada-002") >>> embeddings JSON: { "data": [ { "embedding": [ -0.00530336843803525, 0.0013223182177171111, ... 1533 more items ..., -0.015645816922187805 ], "index": 0, "object": "embedding" } ], "model": "text-embedding-ada-002-v2", "object": "list", "usage": { "prompt_tokens": 2, "total_tokens": 2 } }
আপনি দেখতে পাচ্ছেন, OpenAI-এর মডেল 1536টি আইটেম ধারণকারী একটি embedding
তালিকার সাথে প্রতিক্রিয়া জানায় — টেক্সট-এমবেডিং-এডা-002-এর ভেক্টর আকার।
যদিও বেছে নেওয়ার জন্য একাধিক ভেক্টর ডাটাবেস ইঞ্জিন রয়েছে, যেমন Chroma যা ওপেন-সোর্স, আমি পাইনেকোনকে বেছে নিয়েছি কারণ এটি একটি মুক্ত স্তর সহ একটি পরিচালিত ডাটাবেস, যা জিনিসগুলিকে সহজ করে তোলে। তাদের স্টার্টার প্ল্যানটি আমার প্রয়োজনীয় সমস্ত ডেটা পরিচালনা করতে সক্ষম।
আমার Pinecone অ্যাকাউন্ট তৈরি করার পরে এবং আমার API কী এবং পরিবেশ পুনরুদ্ধার করার পরে, আমি আমার .env
ফাইলে উভয় মান যোগ করি।
এখন .env
আমার Pinecone এবং OpenAI গোপনীয়তা থাকা উচিত।
export OPENAI_API_KEY=YOUR_API_KEY # Pinecone secrets export PINECONE_API_KEY=YOUR_API_KEY export PINECONE_ENVIRONMENT=YOUR_PINECONE_DATACENTER
তারপর, আমি পাইথনের জন্য পাইনকোন ক্লায়েন্ট ইনস্টল করি:
$ pip install pinecone-client
আমি একটি ডাটাবেস আরম্ভ করতে হবে; এগুলি হল db_create.py
স্ক্রিপ্টের বিষয়বস্তু:
# db_create.py import pinecone import openai import os index_name = "semaphore" embed_model = "text-embedding-ada-002" api_key = os.getenv("PINECONE_API_KEY") env = os.getenv("PINECONE_ENVIRONMENT") pinecone.init(api_key=api_key, environment=env) embedding = openai.Embedding.create( input=[ "Sample document text goes here", "there will be several phrases in each batch" ], engine=embed_model ) if index_name not in pinecone.list_indexes(): print("Creating pinecone index: " + index_name) pinecone.create_index( index_name, dimension=len(embedding['data'][0]['embedding']), metric='cosine', metadata_config={'indexed': ['source', 'id']} )
স্ক্রিপ্টটি ডাটাবেস তৈরি করতে কয়েক মিনিট সময় নিতে পারে।
$ python db_create.py
এর পরে, আমি টিকটকেন প্যাকেজটি ইনস্টল করব। উৎস নথিতে কতগুলি টোকেন আছে তা গণনা করতে আমি এটি ব্যবহার করব। এটি গুরুত্বপূর্ণ কারণ এমবেডিং মডেল শুধুমাত্র 8191 টোকেন পর্যন্ত পরিচালনা করতে পারে।
$ pip install tiktoken
প্যাকেজ ইনস্টল করার সময়, আসুন একটি সুন্দর-সুদর্শন অগ্রগতি বার তৈরি করতে tqdm
ইনস্টল করি।
$ pip install tqdm
এখন আমাকে ডাটাবেসে নথিগুলি আপলোড করতে হবে। এর জন্য স্ক্রিপ্ট বলা হবে index_docs.py
। আসুন প্রয়োজনীয় মডিউলগুলি আমদানি করে এবং কিছু ধ্রুবক সংজ্ঞায়িত করে শুরু করি:
# index_docs.py # Pinecone db name and upload batch size index_name = 'semaphore' upsert_batch_size = 20 # OpenAI embedding and tokenizer models embed_model = "text-embedding-ada-002" encoding_model = "cl100k_base" max_tokens_model = 8191
পরবর্তী, টোকেন গণনা করার জন্য আমাদের একটি ফাংশন প্রয়োজন হবে। OpenAI পৃষ্ঠায় একটি টোকেন কাউন্টার উদাহরণ রয়েছে:
import tiktoken def num_tokens_from_string(string: str) -> int: """Returns the number of tokens in a text string.""" encoding = tiktoken.get_encoding(encoding_model) num_tokens = len(encoding.encode(string)) return num_tokens
অবশেষে, মূল নথিটিকে ব্যবহারযোগ্য উদাহরণে রূপান্তর করতে আমার কিছু ফিল্টারিং ফাংশন দরকার। ডকুমেন্টেশনের বেশিরভাগ উদাহরণ কোড বেড়ার মধ্যে, তাই আমি প্রতিটি ফাইল থেকে সমস্ত YAML কোড বের করব:
import re def extract_yaml(text: str) -> str: """Returns list with all the YAML code blocks found in text.""" matches = [m.group(1) for m in re.finditer("```yaml([\w\W]*?)```", text)] return matches
আমি ফাংশন সঙ্গে সম্পন্ন করছি. এর পরে, এটি মেমরিতে ফাইলগুলি লোড করবে এবং উদাহরণগুলি বের করবে:
from tqdm import tqdm import sys import os import pathlib repo_path = sys.argv[1] repo_path = os.path.abspath(repo_path) repo = pathlib.Path(repo_path) markdown_files = list(repo.glob("**/*.md")) + list( repo.glob("**/*.mdx") ) print(f"Extracting YAML from Markdown files in {repo_path}") new_data = [] for i in tqdm(range(0, len(markdown_files))): markdown_file = markdown_files[i] with open(markdown_file, "r") as f: relative_path = markdown_file.relative_to(repo_path) text = str(f.read()) if text == '': continue yamls = extract_yaml(text) j = 0 for y in yamls: j = j+1 new_data.append({ "source": str(relative_path), "text": y, "id": f"github.com/semaphore/docs/{relative_path}[{j}]" })
এই মুহুর্তে, সমস্ত YAMLs new_data
তালিকায় সংরক্ষণ করা উচিত। চূড়ান্ত পদক্ষেপ হল Pinecone এ এমবেডিংগুলি আপলোড করা।
import pinecone import openai api_key = os.getenv("PINECONE_API_KEY") env = os.getenv("PINECONE_ENVIRONMENT") pinecone.init(api_key=api_key, enviroment=env) index = pinecone.Index(index_name) print(f"Creating embeddings and uploading vectors to database") for i in tqdm(range(0, len(new_data), upsert_batch_size)): i_end = min(len(new_data), i+upsert_batch_size) meta_batch = new_data[i:i_end] ids_batch = [x['id'] for x in meta_batch] texts = [x['text'] for x in meta_batch] embedding = openai.Embedding.create(input=texts, engine=embed_model) embeds = [record['embedding'] for record in embedding['data']] # clean metadata before upserting meta_batch = [{ 'id': x['id'], 'text': x['text'], 'source': x['source'] } for x in meta_batch] to_upsert = list(zip(ids_batch, embeds, meta_batch)) index.upsert(vectors=to_upsert)
একটি রেফারেন্স হিসাবে, আপনি ডেমো সংগ্রহস্থলে সম্পূর্ণ index_docs.py ফাইলটি খুঁজে পেতে পারেন
ডাটাবেস সেটআপের সাথে শেষ করতে সূচী স্ক্রিপ্টটি চালাই:
$ git clone https://github.com/semaphoreci/docs.git /tmp/docs $ source .env $ python index_docs.py /tmp/docs
Pinecone ড্যাশবোর্ডের ডাটাবেসে ভেক্টর দেখাতে হবে।
আমরা নিম্নলিখিত কোড সহ ডাটাবেস অনুসন্ধান করতে পারি, যা আপনি স্ক্রিপ্ট হিসাবে বা পাইথন REPL-এ সরাসরি চালাতে পারেন:
$ python >>> import os >>> import pinecone >>> import openai # Compute embeddings for string "Docker Container" >>> embeddings = openai.Embedding.create(input="Docker Containers", engine="text-embedding-ada-002") # Connect to database >>> index_name = "semaphore" >>> api_key = os.getenv("PINECONE_API_KEY") >>> env = os.getenv("PINECONE_ENVIRONMENT") >>> pinecone.init(api_key=api_key, environment=env) >>> index = pinecone.Index(index_name) # Query database >>> matches = index.query(embeddings['data'][0]['embedding'], top_k=1, include_metadata=True) >>> matches['matches'][0] {'id': 'github.com/semaphore/docs/docs/ci-cd-environment/docker-authentication.md[3]', 'metadata': {'id': 'github.com/semaphore/docs/docs/ci-cd-environment/docker-authentication.md[3]', 'source': 'docs/ci-cd-environment/docker-authentication.md', 'text': '\n' '# .semaphore/semaphore.yml\n' 'version: v1.0\n' 'name: Using a Docker image\n' 'agent:\n' ' machine:\n' ' type: e1-standard-2\n' ' os_image: ubuntu1804\n' '\n' 'blocks:\n' ' - name: Run container from Docker Hub\n' ' task:\n' ' jobs:\n' ' - name: Authenticate docker pull\n' ' commands:\n' ' - checkout\n' ' - echo $DOCKERHUB_PASSWORD | docker login ' '--username "$DOCKERHUB_USERNAME" --password-stdin\n' ' - docker pull /\n' ' - docker images\n' ' - docker run /\n' ' secrets:\n' ' - name: docker-hub\n'}, 'score': 0.796259582, 'values': []}
আপনি দেখতে পাচ্ছেন, প্রথম ম্যাচটি একটি সেমাফোর পাইপলাইনের জন্য YAML যা একটি ডকার ইমেজ টানে এবং এটি চালায়। এটি একটি ভাল শুরু কারণ এটি আমাদের "ডকার কন্টেইনার" অনুসন্ধান স্ট্রিংয়ের সাথে প্রাসঙ্গিক।
আমাদের কাছে ডেটা আছে, এবং আমরা জানি কিভাবে এটি অনুসন্ধান করতে হয়। এর বট কাজ করা যাক.
প্রম্পট প্রক্রিয়াকরণের পদক্ষেপগুলি হল:
যথারীতি, আমি complete.py
এ কিছু ধ্রুবক সংজ্ঞায়িত করে শুরু করব, বটের প্রধান স্ক্রিপ্ট:
# complete.py # Pinecone database name, number of matched to retrieve # cutoff similarity score, and how much tokens as context index_name = 'semaphore' context_cap_per_query = 30 match_min_score = 0.75 context_tokens_per_query = 3000 # OpenAI LLM model parameters chat_engine_model = "gpt-3.5-turbo" max_tokens_model = 4096 temperature = 0.2 embed_model = "text-embedding-ada-002" encoding_model_messages = "gpt-3.5-turbo-0301" encoding_model_strings = "cl100k_base" import pinecone import os # Connect with Pinecone db and index api_key = os.getenv("PINECONE_API_KEY") env = os.getenv("PINECONE_ENVIRONMENT") pinecone.init(api_key=api_key, environment=env) index = pinecone.Index(index_name)
এর পরে, আমি OpenAI উদাহরণে দেখানো টোকেন গণনা করার জন্য ফাংশন যোগ করব। প্রথম ফাংশনটি একটি স্ট্রিং-এ টোকেন গণনা করে, যখন দ্বিতীয়টি বার্তাগুলিতে টোকেন গণনা করে। আমরা একটু পরে বিস্তারিত বার্তা দেখতে পাব. আপাতত, আসুন শুধু বলি এটি একটি কাঠামো যা কথোপকথনের অবস্থাকে মেমরিতে রাখে।
import tiktoken def num_tokens_from_string(string: str) -> int: """Returns the number of tokens in a text string.""" encoding = tiktoken.get_encoding(encoding_model_strings) num_tokens = len(encoding.encode(string)) return num_tokens def num_tokens_from_messages(messages): """Returns the number of tokens used by a list of messages. Compatible with model """ try: encoding = tiktoken.encoding_for_model(encoding_model_messages) except KeyError: encoding = tiktoken.get_encoding(encoding_model_strings) num_tokens = 0 for message in messages: num_tokens += 4 # every message follows {role/name}\n{content}\n for key, value in message.items(): num_tokens += len(encoding.encode(value)) if key == "name": # if there's a name, the role is omitted num_tokens += -1 # role is always required and always 1 token num_tokens += 2 # every reply is primed with assistant return num_tokens
নিম্নলিখিত ফাংশন GPT-3 এর জন্য একটি সমৃদ্ধ প্রম্পট ফেরত দিতে আসল প্রম্পট এবং প্রসঙ্গ স্ট্রিং নেয়:
def get_prompt(query: str, context: str) -> str: """Return the prompt with query and context.""" return ( f"Create the continuous integration pipeline YAML code to fullfil the requested task.\n" + f"Below you will find some context that may help. Ignore it if it seems irrelevant.\n\n" + f"Context:\n{context}" + f"\n\nTask: {query}\n\nYAML Code:" )
get_message
ফাংশন প্রম্পটটিকে API এর সাথে সামঞ্জস্যপূর্ণ একটি বিন্যাসে ফর্ম্যাট করে:
def get_message(role: str, content: str) -> dict: """Generate a message for OpenAI API completion.""" return {"role": role, "content": content}
মডেলটি কীভাবে প্রতিক্রিয়া দেখায় তা প্রভাবিত করে এমন তিনটি ধরণের ভূমিকা রয়েছে:
এখন আকর্ষক অংশ জন্য. get_context
ফাংশন প্রম্পট নেয়, ডাটাবেসকে জিজ্ঞাসা করে এবং এই শর্তগুলির মধ্যে একটি পূরণ না হওয়া পর্যন্ত একটি প্রসঙ্গ স্ট্রিং তৈরি করে:
context_tokens_per_query
ছাড়িয়ে গেছে, আমি প্রসঙ্গটির জন্য যে স্থান সংরক্ষিত করেছি।match_min_score
নিচে একটি মিল আছে এমন ম্যাচগুলি উপেক্ষা করা হয়। import openai def get_context(query: str, max_tokens: int) -> list: """Generate message for OpenAI model. Add context until hitting `context_token_limit` limit. Returns prompt string.""" embeddings = openai.Embedding.create( input=[query], engine=embed_model ) # search the database vectors = embeddings['data'][0]['embedding'] embeddings = index.query(vectors, top_k=context_cap_per_query, include_metadata=True) matches = embeddings['matches'] # filter and aggregate context usable_context = "" context_count = 0 for i in range(0, len(matches)): source = matches[i]['metadata']['source'] if matches[i]['score'] < match_min_score: # skip context with low similarity score continue context = matches[i]['metadata']['text'] token_count = num_tokens_from_string(usable_context + '\n---\n' + context) if token_count < context_tokens_per_query: usable_context = usable_context + '\n---\n' + context context_count = context_count + 1 print(f"Found {context_count} contexts for your query") return usable_context
পরবর্তী এবং চূড়ান্ত ফাংশন, complete
, OpenAI-তে API অনুরোধ জারি করে এবং মডেলের প্রতিক্রিয়া প্রদান করে।
def complete(messages): """Query the OpenAI model. Returns the first answer. """ res = openai.ChatCompletion.create( model=chat_engine_model, messages=messages, temperature=temperature ) return res.choices[0].message.content.strip()
এখানেই শেষ; এখন আমাকে শুধুমাত্র কমান্ড লাইন আর্গুমেন্টের সাথে মোকাবিলা করতে হবে এবং ফাংশনগুলিকে সঠিক ক্রমে কল করতে হবে:
import sys query = sys.argv[1] context = get_context(query, context_tokens_per_query) prompt = get_prompt(query, context) # initialize messages list to send to OpenAI API messages = [] messages.append(get_message('user', prompt)) messages.append(get_message('system', 'You are a helpful assistant that writes YAML code for Semaphore continuous integration pipelines and explains them. Return YAML code inside code fences.')) if num_tokens_from_messages(messages) >= max_tokens_model: raise Exception('Model token size limit reached') print("Working on your query... ") answer = complete(messages) print("Answer:\n") print(answer) messages.append(get_message('assistant', answer))
স্ক্রিপ্টটি চালানোর এবং এটির ভাড়া কেমন তা দেখার সময় এসেছে:
$ python complete.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub"
ফলাফল হলো:
version: v1.0 name: Docker Build and Push agent: machine: type: e1-standard-2 os_image: ubuntu1804 blocks: - name: "Build and Push Docker Image" task: jobs: - name: "Docker Build and Push" commands: - checkout - docker build -t /: . - echo "$DOCKERHUB_PASSWORD" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin - docker push /: promotions: - name: Deploy to production pipeline_file: deploy-production.yml auto_promote: when: "result = 'passed' and branch = 'master'"
এটি প্রথম ভাল ফলাফল। আমরা প্রদত্ত প্রসঙ্গ উদাহরণ থেকে মডেলটি সিনট্যাক্স অনুমান করেছে।
মনে রাখবেন যে আমি একটি শালীন লক্ষ্য নিয়ে শুরু করেছি: YAML পাইপলাইন লেখার জন্য একজন সহকারী তৈরি করা। আমার ভেক্টর ডাটাবেসে সমৃদ্ধ বিষয়বস্তু সহ, আমি সেমাফোর (অথবা যে কোনও পণ্য - ডক্সকে /tmp
এ ক্লোন করা মনে রাখবেন?) সম্পর্কে যেকোনো প্রশ্নের উত্তর দিতে বটটিকে সাধারণীকরণ করতে পারি।
ভালো উত্তর পাওয়ার চাবিকাঠি হল — আশ্চর্যজনকভাবে — মানের প্রসঙ্গ। শুধুমাত্র ভেক্টর ডাটাবেসে প্রতিটি নথি আপলোড করলে ভালো ফলাফল পাওয়া যায় না। প্রসঙ্গ ডাটাবেস কিউরেট করা উচিত, বর্ণনামূলক মেটাডেটা দিয়ে ট্যাগ করা উচিত এবং সংক্ষিপ্ত হওয়া উচিত। অন্যথায়, আমরা অপ্রাসঙ্গিক প্রসঙ্গ সহ প্রম্পটে টোকেন কোটা পূরণ করার ঝুঁকি নিয়ে থাকি।
সুতরাং, এক অর্থে, আমাদের প্রয়োজন মেটানোর জন্য বটটিকে সূক্ষ্ম-টিউন করার সাথে জড়িত একটি শিল্প — এবং প্রচুর পরীক্ষা এবং ত্রুটি রয়েছে৷ আমরা প্রসঙ্গ সীমা নিয়ে পরীক্ষা করতে পারি, নিম্নমানের সামগ্রী সরাতে পারি, সারসংক্ষেপ করতে পারি এবং মিলের স্কোর সামঞ্জস্য করে অপ্রাসঙ্গিক প্রসঙ্গ ফিল্টার করতে পারি।
আপনি হয়তো লক্ষ্য করেছেন যে আমার বট আমাদের ChatGPT-এর মতো প্রকৃত কথোপকথন করতে সক্ষম করে না। আমরা একটি প্রশ্ন জিজ্ঞাসা করি এবং একটি উত্তর পাই।
বটটিকে একটি পূর্ণাঙ্গ চ্যাটবটে রূপান্তর করা, নীতিগতভাবে, খুব বেশি চ্যালেঞ্জিং নয়। আমরা প্রতিটি API অনুরোধের সাথে মডেলে পূর্ববর্তী প্রতিক্রিয়াগুলি পুনরায় প্রেরণ করে কথোপকথন বজায় রাখতে পারি। পূর্ববর্তী GPT-3 উত্তরগুলি "সহকারী" ভূমিকার অধীনে ফেরত পাঠানো হয়। উদাহরণ স্বরূপ:
messages = [] while True: query = input('Type your prompt:\n') context = get_context(query, context_tokens_per_query) prompt = get_prompt(query, context) messages.append(get_message('user', prompt)) messages.append(get_message('system', 'You are a helpful assistant that writes YAML code for Semaphore continuous integration pipelines and explains them. Return YAML code inside code fences.')) if num_tokens_from_messages(messages) >= max_tokens_model: raise Exception('Model token size limit reached') print("Working on your query... ") answer = complete(messages) print("Answer:\n") print(answer) # remove system message and append model's answer messages.pop() messages.append(get_message('assistant', answer))
দুর্ভাগ্যবশত, এই বাস্তবায়ন বরং প্রাথমিক। এটি বর্ধিত কথোপকথন সমর্থন করবে না কারণ প্রতিটি ইন্টারঅ্যাকশনের সাথে টোকেন সংখ্যা বৃদ্ধি পায়। শীঘ্রই, আমরা GPT-3-এর জন্য 4096-টোকেন সীমাতে পৌঁছব, আরও সংলাপ রোধ করব।
সুতরাং, আমাদের অনুরোধটি টোকেন সীমার মধ্যে রাখার কিছু উপায় খুঁজে বের করতে হবে। কয়েকটি কৌশল অনুসরণ করে:
শব্দ এমবেডিং এবং একটি ভাল প্রসঙ্গ ডেটাবেসের মাধ্যমে বটের প্রতিক্রিয়াগুলিকে উন্নত করা সম্ভব। এটি অর্জন করতে, আমাদের ভাল মানের ডকুমেন্টেশন প্রয়োজন। একটি বট তৈরিতে যথেষ্ট পরিমাণে ট্রায়াল এবং ত্রুটি জড়িত যা আপাতদৃষ্টিতে বিষয়বস্তুর একটি উপলব্ধি রাখে।
আমি আশা করি শব্দ এম্বেডিং এবং বৃহৎ ভাষার মডেলগুলির এই গভীর অন্বেষণ আপনাকে আপনার প্রয়োজনীয়তা অনুসারে কাস্টমাইজ করা আরও শক্তিশালী বট তৈরি করতে সহায়তা করবে৷
শুভ বিল্ডিং!
এছাড়াও এখানে প্রকাশিত.