OpenAI'nin ChatGPT'sinin son derece akıllı olduğuna şüphe yok; geçmiş, sahip ve bazı testler . Ancak cehaleti kabul etmek yerine eğilimindedir. Bu eğilim, bilgi birikiminin 2021'de sona ereceği gerçeğiyle birleştiğinde, GPT API'yi kullanarak özel ürünler oluşturma konusunda zorluklar ortaya çıkarıyor. avukatlık sınavını doktor benzeri bilgiye IQ'sunun 155 olduğunu gösteriyor bilgiyi uydurma Bu engelleri nasıl aşabiliriz? GPT-3 gibi bir modele yeni bilgileri nasıl aktarabiliriz? Amacım Python, OpenAI API ve sözcük yerleştirmeleri kullanan bir soru yanıtlayan bot oluşturarak bu soruları yanıtlamak. Ne İnşa Edeceğim Bildiğiniz gibi Semaphore CI/CD'de bir istemden ardışık düzenleri oluşturan bir bot oluşturmayı düşünüyorum. YAML ile biçimlendirilmiş sürekli entegrasyon İşte botun çalışırken bir örneği: Çalışan programın ekran görüntüsü. Ekranda yürütülür ve program, istenen eylemi gerçekleştiren bir CI işlem hattına karşılık gelen YAML'yi yazdırır. python query.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub" , ve gibi projelerin ruhuna uygun olarak, GPT-3 modelini Semaphore ve ardışık düzen yapılandırma dosyalarının nasıl oluşturulacağı hakkında "öğretmeyi" planlıyorum. Bunu yararlanarak başaracağım. DocsGPT My AskAI Libraria mevcut belgelerden Bot oluşturma konusunda önceden bilgi sahibi olduğumu varsaymayacağım ve gereksinimlerinize uyarlayabilmeniz için temiz kodu koruyacağım. Önkoşullar Bu öğreticiyi takip etmek için bir bot kodlama deneyimine veya sinir ağları bilgisine ihtiyacınız yoktur. Ancak ihtiyacınız olacak: Piton 3. Bir Çam Kozalağı hesabı ( ücretsiz kaydolun). Başlangıç planına OpenAI API Anahtarı ( ); yeni kullanıcılar ilk 3 ay boyunca 5 ABD doları değerinde ücretsiz krediyi deneyebilir. ücretlidir, kredi kartı gerektirir Ama ChatGPT Öğrenemez, Değil mi? ChatGPT veya daha doğrusu GPT-3 ve GPT-4, onları destekleyen Büyük Dil Modelleri (LLM), Eylül 2021 civarında sonlanma tarihi olan devasa bir veri kümesi üzerinde eğitildi. Aslında GPT-3 bu tarihin ötesindeki olaylar hakkında çok az şey biliyor. Bunu basit bir istemle doğrulayabiliriz: ChatGPT, 2022'de Dünya Kupasını kimin kazandığını bilmiyor. Bazı OpenAI modelleri geçebilirken, ilgilenilenler gibi daha gelişmiş modeller bunu yapamaz; onların eğitim verilerini artıramayız. ince ayardan GPT-3'ten eğitim verilerinin ötesinde nasıl yanıt alabiliriz? Yöntemlerden biri metni anlama yeteneklerinden yararlanmayı içerir; Bilgi istemini ilgili bağlamla zenginleştirerek muhtemelen doğru cevabı elde edebiliriz. Aşağıdaki örnekte, bağlamı aktarıyorum ve yanıtlar önemli ölçüde farklılık gösteriyor: FIFA'nın resmi sitesinden Sağlanan bağlamla ChatGPT doğru yanıt verebilir. Yeterince ilgili bağlam verildiğinde modelin herhangi bir soruya yanıt verebileceği sonucunu çıkarabiliriz. Soru hala ortada: Keyfi bir istemle neyin alakalı olduğunu nasıl bilebiliriz? Bu sorunu çözmek için ne olduğunu araştırmamız gerekiyor. kelime yerleştirmelerin Kelime Gömmeleri Nelerdir? Dil modelleri bağlamında gömme, kelimeleri, cümleleri veya tüm belgeleri vektörler veya sayı listeleri olarak temsil etmenin bir yoludur. Gömmeleri hesaplamak için veya gibi bir sinir ağına ihtiyacımız olacak. Bu ağlar çok büyük miktarda metin üzerinde eğitilmiştir ve eğitim verilerinde belirli kalıpların görünme sıklığını analiz ederek kelimeler arasındaki ilişkileri bulabilirler. word2vec text-embedding-ada-002 Diyelim ki elimizde şu kelimeler var: Kedi Köpek Top Ev Her kelimenin vektörlerini hesaplamak için bu yerleştirme ağlarından birini kullandığımızı hayal edin. Örneğin: Kelime Vektör Bağlam Kedi [0,1, 0,2, 0,3, 0,4, 0,5] Hayvanlar, nesneler, küçük şeyler Köpek [0,6, 0,7, 0,8, 0,9, 1,0] Hayvanlar, nesneler, büyük şeyler Top [0,2, 0,4, 0,6, 0,8, 1,0] Nesneler, oyuncaklar, küçük şeyler Ev [0,3, 0,6, 0,9, 1,2, 1,5] Binalar, evler, büyük şeyler Her kelimenin vektörlerini aldıktan sonra bunları metnin anlamını temsil etmek için kullanabiliriz. Örneğin, "Kedi topu kovaladı" cümlesi şu şekilde gösterilebilir: [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]. Bu vektör bir nesneyi kovalayan bir hayvanla ilgili bir cümleyi temsil ediyor. Kelime gömmeleri, benzer anlamlara sahip kelime veya cümlelerin birbirine yakın olduğu çok boyutlu alanlar olarak görselleştirilebilir. Herhangi bir girdi metnine benzer anlamlar bulmak için vektörler arasındaki "mesafeyi" hesaplayabiliriz. Gömmelerin vektör uzayları olarak 3 boyutlu gösterimi. Gerçekte bu uzayların yüzlerce ya da binlerce boyutu olabilir. Kaynak: Yapay Zekanın Çok Amaçlı Aracıyla Tanışın: Vektör Yerleştirmeleri Tüm bunların ardındaki gerçek matematik bu makalenin kapsamı dışındadır. Bununla birlikte, önemli çıkarım . “Kraliçe” kelimesini temsil eden vektörü alın, “kadın” vektörünü bundan çıkarın ve “erkek” vektörünü ekleyin. Sonuç “kral”ın yakınında bir vektör olmalıdır. “Oğul”u eklersek “prens”e yakın bir yere gelmeliyiz. , vektör işlemlerinin matematiği kullanarak anlamı değiştirmemize veya belirlememize olanak sağlamasıdır Sinir Ağlarını Belirteçlerle Yerleştirme Şu ana kadar kelimeleri girdi, sayıları da çıktı olarak alan sinir ağlarının yerleştirilmesini tartıştık. Ancak birçok modern ağ, kelimeleri işlemekten jetonları işlemeye geçti. , model tarafından işlenebilen en küçük metin birimidir. Belirteçler sözcükler, karakterler, noktalama işaretleri, semboller veya sözcük parçaları olabilir. Belirteç Metni belirteçlere dönüştürmek ve her birini bir sayıyla temsil etmek için (BPE) kullanan deneyerek kelimelerin nasıl belirteçlere dönüştürüldüğünü görebiliriz: Bayt Çifti Kodlama OpenAI çevrimiçi belirteç oluşturucuyu Belirteçler ve kelimeler arasında genellikle 1'e 1 ilişki vardır. Çoğu jeton, kelimeyi ve baştaki boşluğu içerir. Bununla birlikte, "embed" ve "ding" olmak üzere iki jetondan oluşan "gömme" veya dört jetondan oluşan "yetenekler" gibi özel durumlar da vardır. "Jeton Kimlikleri"ne tıklarsanız modelin her bir jetonun sayısal temsilini görebilirsiniz. Gömmeleri Kullanarak Daha Akıllı Bir Bot Tasarlamak Artık yerleştirmelerin ne olduğunu anladığımıza göre bir sonraki soru şu: Daha akıllı bir bot oluşturmamıza nasıl yardımcı olabilirler? Öncelikle GPT-3 API'sini doğrudan kullandığımızda ne olacağına bakalım. Kullanıcı bir istem gönderir ve model, yeteneğinin en iyisine yanıt verir. Ancak denkleme bağlam eklediğimizde işler değişiyor. Örneğin, bağlamı sağladıktan sonra ChatGPT'ye Dünya Kupası'nın galibi hakkında soru sorduğumda büyük fark yarattı. Yani daha akıllı bir bot oluşturma planı şu şekildedir: Kullanıcının istemini durdurun. Bu istemin yerleştirmelerini hesaplayarak bir vektör elde edin. Başlangıçtaki bilgi istemiyle anlamsal olarak alakalı olmaları gerektiğinden, vektörün yakınındaki belgeler için bir veritabanında arama yapın. Orijinal istemi ilgili bağlamla birlikte GPT-3'e gönderin. GPT-3'ün yanıtını kullanıcıya iletin. Çoğu projede olduğu gibi veritabanını tasarlayarak başlayalım. Gömmelerle Bilgi Veritabanı Oluşturma Bağlam veritabanımız orijinal belgeleri ve bunların ilgili vektörlerini içermelidir. Prensip olarak bu görev için her tür veritabanını kullanabiliriz ancak bu iş için en uygun araçtır. vektör veritabanı Vektör veritabanları, yüksek boyutlu vektör verilerini depolamak ve almak için tasarlanmış özel veritabanlarıdır. Arama için SQL gibi bir sorgu dili kullanmak yerine bir vektör sağlıyoruz ve en yakın N komşuyu talep ediyoruz. Vektörleri oluşturmak için OpenAI'nin kullanacağız çünkü bu, sundukları en hızlı ve en uygun maliyetli modeldir. Model, giriş metnini belirteçlere dönüştürür ve aralarındaki ilişkileri öğrenmek için olarak bilinen bir dikkat mekanizmasını kullanır. Bu sinir ağının çıktısı metnin anlamını temsil eden vektörlerdir. text-embedding-ada-002'sini Transformer Bir bağlam veritabanı oluşturmak için şunları yapacağım: Tüm kaynak belgelerini toplayın. İlgisiz belgeleri filtreleyin. Her belge için yerleştirmeleri hesaplayın. Vektörleri, orijinal metni ve diğer ilgili meta verileri veritabanında saklayın. Belgeleri Vektörlere Dönüştürme Öncelikle OpenAI API anahtarıyla bir ortam dosyasını başlatmalıyım. API anahtarı özel olduğundan ve hesabınıza bağlı olduğundan bu dosya hiçbir zaman sürüm kontrolüne alınmamalıdır. export OPENAI_API_KEY=YOUR_API_KEY Daha sonra Python uygulamam için bir virtualenv oluşturacağım: $ virtualenv venv $ source venv/bin/activate $ source .env Ve OpenAI paketini yükleyin: ```bash $ pip install openai numpy "Docker Container" dizisinin yerleştirmesini hesaplamayı deneyelim. Bunu Python REPL'de veya Python betiği olarak çalıştırabilirsiniz: $ 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 } } Gördüğünüz gibi, OpenAI'nin modeli 1536 öğe içeren bir listesiyle yanıt veriyor - metin yerleştirme-ada-002'nin vektör boyutu. embedding Gömmelerin Çam Kozalağı'nda saklanması Açık kaynaklı gibi seçilebilecek birden fazla vektör veritabanı motoru olmasına rağmen, seçtim çünkü bu, ücretsiz katmana sahip yönetilen bir veritabanı, bu da işleri kolaylaştırıyor. ihtiyaç duyacağım tüm verileri fazlasıyla karşılayabilecek kapasitede. Chroma Pinecone'u Başlangıç planları Pinecone hesabımı oluşturup API anahtarımı ve ortamımı aldıktan sonra her iki değeri de dosyama ekliyorum. .env Artık benim Pinecone ve OpenAI sırlarımı içermeli. .env export OPENAI_API_KEY=YOUR_API_KEY # Pinecone secrets export PINECONE_API_KEY=YOUR_API_KEY export PINECONE_ENVIRONMENT=YOUR_PINECONE_DATACENTER Daha sonra Python için Pinecone istemcisini kuruyorum: $ pip install pinecone-client Bir veritabanını başlatmam gerekiyor; betiğinin içeriği şunlardır: 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']} ) Komut dosyasının veritabanını oluşturması birkaç dakika sürebilir. $ python db_create.py Daha sonra paketini kuracağım. Kaynak belgelerin kaç jetona sahip olduğunu hesaplamak için kullanacağım. Bu önemlidir çünkü yerleştirme modeli yalnızca 8191 jetona kadar işleyebilir. tiktoken $ pip install tiktoken Paketleri kurarken güzel görünümlü bir ilerleme çubuğu oluşturmak için de kuralım. tqdm $ pip install tqdm Şimdi belgeleri veritabanına yüklemem gerekiyor. Bunun betiğine adı verilecek. Gerekli modülleri içe aktararak ve bazı sabitleri tanımlayarak başlayalım: 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 Daha sonra jetonları saymak için bir fonksiyona ihtiyacımız olacak. OpenAI sayfasında bir var: jeton sayacı örneği 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 Son olarak orijinal belgeyi kullanılabilir örneklere dönüştürmek için bazı filtreleme işlevlerine ihtiyacım olacak. Belgelerdeki örneklerin çoğu kod sınırları arasındadır, bu nedenle tüm YAML kodunu her dosyadan çıkaracağım: 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 Fonksiyonlarla işim bitti. Daha sonra bu, dosyaları belleğe yükleyecek ve örnekleri çıkaracaktır: 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}]" }) Bu noktada tüm YAML'lerin listesinde saklanması gerekir. Son adım, yerleştirmeleri Çam Kozalağı'na yüklemektir. new_data 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) Referans olarak dosyasının tamamını demo deposunda bulabilirsiniz. index_docs.py Veritabanı kurulumunu tamamlamak için indeks betiğini çalıştıralım: $ git clone https://github.com/semaphoreci/docs.git /tmp/docs $ source .env $ python index_docs.py /tmp/docs Veritabanını test etme Çam kozalağı kontrol paneli veritabanındaki vektörleri göstermelidir. Veritabanını, komut dosyası olarak veya doğrudan Python REPL'de çalıştırabileceğiniz aşağıdaki kodla sorgulayabiliriz: $ 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': []} Gördüğünüz gibi ilk eşleşme, Docker görüntüsünü çeken ve çalıştıran Semafor hattının YAML'sidir. "Docker Konteynerleri" arama dizemizle alakalı olduğundan bu iyi bir başlangıç. Botu oluşturma Veriler elimizde ve onu nasıl sorgulayacağımızı biliyoruz. Bunu botta çalıştıralım. İstemi işlemeye yönelik adımlar şunlardır: Kullanıcının istemini alın. Vektörünü hesaplayın. Veritabanından ilgili bağlamı alın. Kullanıcının istemini bağlamla birlikte GPT-3'e gönderin. Modelin yanıtını kullanıcıya iletin. Her zamanki gibi, botun ana betiği dosyasında bazı sabitleri tanımlayarak başlayacağım: 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) Daha sonra, gösterildiği gibi jetonları saymak için işlevler ekleyeceğim. İlk işlev bir dizedeki belirteçleri sayarken, ikincisi mesajlardaki belirteçleri sayar. Mesajları birazdan detaylı olarak göreceğiz. Şimdilik konuşmanın durumunu hafızada tutan bir yapı olduğunu söyleyelim. OpenAI örneklerinde 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 Aşağıdaki işlev, GPT-3 için zenginleştirilmiş bir bilgi istemi döndürmek üzere orijinal bilgi istemini ve bağlam dizelerini alır: 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:" ) işlevi istemi API ile uyumlu bir biçimde biçimlendirir: get_message def get_message(role: str, content: str) -> dict: """Generate a message for OpenAI API completion.""" return {"role": role, "content": content} Modelin nasıl tepki vereceğini etkileyen üç tür rol vardır: : Kullanıcının orijinal istemi için. Kullanıcı : asistanın davranışını ayarlamaya yardımcı olur. Etkinliği konusunda olsa da mesaj listesinin sonunda gönderildiğinde daha etkili olduğu görülüyor. Sistem bazı tartışmalar : modelin geçmiş yanıtlarını temsil eder. OpenAI API'nin bir "belleği" yoktur; bunun yerine, konuşmayı sürdürmek için her etkileşim sırasında modelin önceki yanıtlarını geri göndermeliyiz. Asistan Şimdi ilgi çekici kısım için. işlevi istemi alır, veritabanını sorgular ve şu koşullardan biri karşılanana kadar bir bağlam dizesi oluşturur: get_context Metnin tamamı, bağlam için ayırdığım alan olan alanını aşıyor. context_tokens_per_query Arama fonksiyonu istenen tüm eşleşmeleri alır. Benzerlik puanı altında olan eşleşmeler dikkate alınmaz. 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 Bir sonraki ve son işlev olan , API isteğini OpenAI'ye gönderir ve modelin yanıtını döndürür. complete 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() Bu kadar; şimdi sadece komut satırı argümanlarıyla ilgilenmem ve fonksiyonları doğru sırayla çağırmam gerekiyor: 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)) Komut dosyasını çalıştırmanın ve nasıl çalıştığını görmenin zamanı geldi: $ python complete.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub" Sonuç: 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'" Bu ilk iyi sonuçtur. Model, sözdizimini sunduğumuz bağlam örneklerinden çıkarmıştır. Botun Yeteneklerini Genişletmeye İlişkin Düşünceler Mütevazı bir hedefle başladığımı unutmayın: YAML işlem hatlarını yazacak bir asistan yaratmak. Vektör veritabanımdaki daha zengin içerik sayesinde botu, Semaphore (veya herhangi bir ürün) hakkındaki her soruyu yanıtlayacak şekilde genelleştirebilirim; dokümanları içine kopyalamayı unutmayın. /tmp İyi yanıtlar almanın anahtarı - şaşırtıcı olmayan bir şekilde - kaliteli bağlamdır. Her belgenin yalnızca vektör veri tabanına yüklenmesinin iyi sonuçlar vermesi pek mümkün değildir. Bağlam veritabanı düzenlenmeli, açıklayıcı meta verilerle etiketlenmeli ve kısa ve öz olmalıdır. Aksi takdirde, istemdeki belirteç kotasını alakasız bağlamla doldurma riskiyle karşı karşıya kalırız. Yani, bir bakıma, ihtiyaçlarımızı karşılayacak şekilde botun ince ayarını yapmak bir sanat ve çok sayıda deneme yanılma içeriyor. Benzerlik puanını ayarlayarak bağlam sınırıyla denemeler yapabilir, düşük kaliteli içeriği kaldırabilir, özetleyebilir ve alakasız bağlamı filtreleyebiliriz. Uygun Bir Chatbot Uygulamak Botumun ChatGPT gibi gerçek sohbetler yapmamıza izin vermediğini fark etmiş olabilirsiniz. Bir soru soruyoruz ve bir cevap alıyoruz. Botu tam teşekküllü bir chatbot'a dönüştürmek prensipte çok zor değil. Her API isteğinde modele verilen önceki yanıtları yeniden göndererek konuşmayı sürdürebiliriz. Önceki GPT-3 yanıtları "asistan" rolü altında geri gönderilir. Örneğin: 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)) Ne yazık ki, bu uygulama oldukça ilkeldir. Her etkileşimde belirteç sayısı arttığından, genişletilmiş konuşmaları desteklemeyecektir. Çok yakında GPT-3 için 4096 jeton sınırına ulaşacağız ve bu da daha fazla diyaloğu önleyecek. Bu nedenle, isteği belirteç sınırları dahilinde tutmanın bir yolunu bulmalıyız. Birkaç strateji takip ediyor: Eski mesajları silin. Bu en basit çözüm olsa da, konuşmanın "hafızasını" yalnızca en son mesajlarla sınırlandırır. Önceki mesajları özetleyin. Daha önceki mesajları yoğunlaştırmak ve bunları orijinal soru ve yanıtların yerine koymak için "Modele sor" seçeneğini kullanabiliriz. Bu yaklaşım maliyeti ve sorgular arasındaki gecikmeyi artırsa da geçmiş mesajların silinmesine kıyasla daha üstün sonuçlar üretebilir. Etkileşim sayısına katı bir sınır koyun. Hem daha akıllı hem de çift token kapasitesine sahip olan GPT-4 API'nin genel kullanılabilirliğini bekleyin. "gpt-3.5-turbo-16k" gibi daha yeni bir model kullanın. 16 bin token'a kadar işlem yapabilen Çözüm Botun yanıtlarını geliştirmek, kelime yerleştirmeler ve iyi bir bağlam veri tabanı ile mümkündür. Bunu başarmak için kaliteli belgelere ihtiyacımız var. Görünüşte konuyu kavrayabilen bir bot geliştirmede önemli miktarda deneme yanılma söz konusudur. Kelime yerleştirmelerin ve büyük dil modellerinin bu derinlemesine incelenmesinin, gereksinimlerinize göre özelleştirilmiş daha güçlü bir bot oluşturmanıza yardımcı olacağını umuyorum. Mutlu bina! da yayınlandı. Burada