Il ne fait aucun doute que le ChatGPT d'OpenAI est exceptionnellement intelligent - il a réussi le test du barreau de l'avocat , il possède des connaissances proches de celles d'un médecin et certains tests ont montré son QI à 155 . Cependant, il a tendance à fabriquer des informations au lieu de concéder l'ignorance. Cette tendance, associée au fait que ses connaissances cessent en 2021, pose des défis dans la création de produits spécialisés utilisant l'API GPT.
Comment pouvons-nous surmonter ces obstacles ? Comment pouvons-nous transmettre de nouvelles connaissances à un modèle comme GPT-3 ? Mon objectif est de répondre à ces questions en construisant un bot de réponse aux questions utilisant Python, l'API OpenAI et des incorporations de mots.
J'ai l'intention de créer un bot qui génère des pipelines d'intégration continue à partir d'une invite, qui, comme vous le savez peut-être, sont formatés avec YAML dans Semaphore CI/CD.
Voici un exemple du bot en action :
Capture d'écran du programme en cours d'exécution. Sur l'écran, la commande python query.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub"
est exécutée, et le programme imprime YAML correspondant à un pipeline CI qui effectue l'action demandée.
Dans l'esprit de projets comme DocsGPT , My AskAI et Libraria , je prévois "d'enseigner" le modèle GPT-3 sur Semaphore et comment générer des fichiers de configuration de pipeline. J'y parviendrai en m'appuyant sur la documentation existante .
Je ne supposerai pas une connaissance préalable de la construction de bots et maintiendrai un code propre afin que vous puissiez l'adapter à vos besoins.
Vous n'avez pas besoin d'expérience dans le codage d'un bot ou de connaissances en réseaux de neurones pour suivre ce tutoriel. Cependant, vous aurez besoin de :
ChatGPT, ou plus précisément, GPT-3 et GPT-4, les grands modèles de langage (LLM) qui les alimentent, ont été formés sur un ensemble de données massif avec une date limite autour de septembre 2021.
Essentiellement, GPT-3 en sait très peu sur les événements au-delà de cette date. Nous pouvons le vérifier avec une simple invite :
ChatGPT ne sait pas qui a remporté la Coupe du monde en 2022.
Alors que certains modèles OpenAI peuvent subir des ajustements , les modèles les plus avancés, tels que ceux qui nous intéressaient, ne le peuvent pas ; nous ne pouvons pas augmenter leurs données de formation.
Comment pouvons-nous obtenir des réponses de GPT-3 au-delà de ses données d'entraînement ? Une méthode consiste à exploiter ses capacités de compréhension de texte ; en améliorant l'invite avec un contexte pertinent, nous pouvons probablement obtenir la bonne réponse.
Dans l'exemple ci-dessous, je fournis le contexte du site officiel de la FIFA , et la réponse diffère considérablement :
Avec le contexte fourni, ChatGPT peut répondre avec précision.
Nous pouvons en déduire que le modèle peut répondre à n'importe quelle invite s'il dispose d'un contexte suffisamment pertinent. La question demeure : comment pouvons-nous savoir ce qui est pertinent à partir d'une invite arbitraire ? Pour résoudre ce problème, nous devons explorer ce que sont les incorporations de mots .
Dans le contexte des modèles de langage, une incorporation est un moyen de représenter des mots, des phrases ou des documents entiers sous forme de vecteurs ou de listes de nombres.
Pour calculer les intégrations, nous aurons besoin d'un réseau de neurones tel que word2vec ou text-embedding-ada-002 . Ces réseaux ont été formés sur des quantités massives de texte et peuvent trouver des relations entre les mots en analysant les fréquences avec lesquelles des modèles spécifiques apparaissent dans les données de formation.
Disons que nous avons les mots suivants :
Imaginez que nous utilisions l'un de ces réseaux d'intégration pour calculer les vecteurs de chaque mot. Par exemple:
Mot | Vecteur | Contexte |
---|---|---|
Chat | [0.1, 0.2, 0.3, 0.4, 0.5] | Animaux, objets, petites choses |
Chien | [0,6, 0,7, 0,8, 0,9, 1,0] | Animaux, objets, grandes choses |
Balle | [0,2, 0,4, 0,6, 0,8, 1,0] | Objets, jouets, petites choses |
Loger | [0,3, 0,6, 0,9, 1,2, 1,5] | Bâtiments, maisons, grandes choses |
Une fois que nous avons les vecteurs pour chaque mot, nous pouvons les utiliser pour représenter le sens du texte. Par exemple, la phrase "Le chat a chassé la balle" peut être représentée par le vecteur [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]. Ce vecteur représente une phrase qui parle d'un animal poursuivant un objet.
Les incorporations de mots peuvent être visualisées comme des espaces multidimensionnels où des mots ou des phrases ayant des significations similaires sont proches les uns des autres. Nous pouvons calculer la "distance" entre les vecteurs pour trouver des significations similaires pour tout texte d'entrée.
Représentation 3D des plongements sous forme d'espaces vectoriels. En réalité, ces espaces peuvent avoir des centaines ou des milliers de dimensions. Source : Découvrez le multi-outil d'IA : intégrations vectorielles
Les mathématiques réelles derrière tout cela dépassent la portée de cet article. Cependant, le point clé à retenir est que les opérations vectorielles nous permettent de manipuler ou de déterminer le sens à l'aide des mathématiques . Prenez le vecteur qui représente le mot « reine », soustrayez-en le vecteur « femme » et ajoutez le vecteur « homme ». Le résultat devrait être un vecteur proche de "king". Si nous ajoutons "fils", nous devrions nous rapprocher de "prince".
Jusqu'à présent, nous avons discuté de l'intégration de réseaux de neurones prenant des mots comme entrées et des nombres comme sorties. Cependant, de nombreux réseaux modernes sont passés du traitement des mots au traitement des jetons.
Un jeton est la plus petite unité de texte pouvant être traitée par le modèle. Les jetons peuvent être des mots, des caractères, des signes de ponctuation, des symboles ou des parties de mots.
Nous pouvons voir comment les mots sont convertis en jetons en expérimentant le tokenizer en ligne OpenAI , qui utilise le Byte-Pair Encoding (BPE) pour convertir le texte en jetons et représenter chacun par un nombre :
Il existe souvent une relation de 1 à 1 entre les jetons et les mots. La plupart des jetons incluent le mot et un espace au début. Cependant, il existe des cas particuliers tels que "embedding", qui se compose de deux jetons, "embed" et "ding", ou "capabilities", qui se compose de quatre jetons. Si vous cliquez sur "ID de jeton", vous pouvez voir la représentation numérique du modèle de chaque jeton.
Maintenant que nous comprenons ce que sont les intégrations, la question suivante est : comment peuvent-elles nous aider à créer un bot plus intelligent ?
Considérons d'abord ce qui se passe lorsque nous utilisons directement l'API GPT-3. L'utilisateur émet une invite et le modèle répond au mieux de ses capacités.
Cependant, lorsque nous ajoutons du contexte à l'équation, les choses changent. Par exemple, lorsque j'ai interrogé ChatGPT sur le vainqueur de la Coupe du monde après avoir fourni le contexte, cela a fait toute la différence.
Ainsi, le plan pour construire un bot plus intelligent est le suivant :
Commençons comme la plupart des projets, par la conception de la base de données.
Notre base de données de contexte doit inclure la documentation originale et leurs vecteurs respectifs. En principe, nous pouvons utiliser n'importe quel type de base de données pour cette tâche, mais une base de données vectorielle est l'outil optimal pour le travail.
Les bases de données vectorielles sont des bases de données spécialisées conçues pour stocker et récupérer des données vectorielles de grande dimension. Au lieu d'employer un langage de requête tel que SQL pour la recherche, nous fournissons un vecteur et demandons les N voisins les plus proches.
Pour générer les vecteurs, nous utiliserons text-embedding-ada-002 d'OpenAI, car c'est le modèle le plus rapide et le plus rentable qu'ils proposent. Le modèle convertit le texte d'entrée en jetons et utilise un mécanisme d'attention appelé Transformer pour apprendre leurs relations. La sortie de ce réseau de neurones est constituée de vecteurs représentant la signification du texte.
Pour créer une base de données de contexte, je vais :
Tout d'abord, je dois initialiser un fichier d'environnement avec la clé API OpenAI. Ce fichier ne doit jamais être validé pour le contrôle de version, car la clé API est privée et liée à votre compte.
export OPENAI_API_KEY=YOUR_API_KEY
Ensuite, je vais créer un virtualenv pour mon application Python :
$ virtualenv venv $ source venv/bin/activate $ source .env
Et installez le package OpenAI :
```bash $ pip install openai numpy
Essayons de calculer l'intégration de la chaîne "Docker Container". Vous pouvez l'exécuter sur le REPL Python ou en tant que script Python :
$ 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 } }
Comme vous pouvez le voir, le modèle d'OpenAI répond avec une liste embedding
contenant 1536 éléments - la taille du vecteur pour text-embedding-ada-002.
Bien qu'il existe plusieurs moteurs de base de données vectorielles parmi lesquels choisir, comme Chroma qui est open-source, j'ai choisi Pinecone car c'est une base de données gérée avec un niveau gratuit, ce qui simplifie les choses. Leur plan Starter est plus que capable de gérer toutes les données dont j'aurai besoin.
Après avoir créé mon compte Pinecone et récupéré ma clé API et mon environnement, j'ajoute les deux valeurs à mon fichier .env
.
Maintenant .env
devrait contenir mes secrets Pinecone et OpenAI.
export OPENAI_API_KEY=YOUR_API_KEY # Pinecone secrets export PINECONE_API_KEY=YOUR_API_KEY export PINECONE_ENVIRONMENT=YOUR_PINECONE_DATACENTER
Ensuite, j'installe le client Pinecone pour Python :
$ pip install pinecone-client
J'ai besoin d'initialiser une base de données ; voici le contenu du script 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']} )
Le script peut prendre quelques minutes pour créer la base de données.
$ python db_create.py
Ensuite, je vais installer le package tiktoken . Je vais l'utiliser pour calculer le nombre de jetons des documents source. Ceci est important car le modèle d'intégration ne peut gérer que jusqu'à 8191 jetons.
$ pip install tiktoken
Lors de l'installation des packages, installons également tqdm
pour produire une belle barre de progression.
$ pip install tqdm
Maintenant, je dois télécharger les documents dans la base de données. Le script pour cela s'appellera index_docs.py
. Commençons par importer les modules requis et définissons quelques constantes :
# 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
Ensuite, nous aurons besoin d'une fonction pour compter les jetons. Il y a un exemple de compteur de jetons sur la page 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
Enfin, j'aurai besoin de quelques fonctions de filtrage pour convertir le document original en exemples utilisables. La plupart des exemples de la documentation se situent entre les clôtures de code, je vais donc extraire tout le code YAML de chaque fichier :
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
J'en ai fini avec les fonctions. Ensuite, cela va charger les fichiers en mémoire et extraire les exemples :
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}]" })
À ce stade, tous les YAML doivent être stockés dans la liste new_data
. La dernière étape consiste à télécharger les intégrations dans 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)
À titre de référence, vous pouvez trouver le fichier index_docs.py complet dans le référentiel de démonstration
Exécutons le script d'index pour terminer la configuration de la base de données :
$ git clone https://github.com/semaphoreci/docs.git /tmp/docs $ source .env $ python index_docs.py /tmp/docs
Le tableau de bord Pinecone doit afficher les vecteurs dans la base de données.
Nous pouvons interroger la base de données avec le code suivant, que vous pouvez exécuter en tant que script ou directement dans le REPL Python :
$ 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': []}
Comme vous pouvez le voir, la première correspondance est le YAML pour un pipeline Semaphore qui extrait une image Docker et l'exécute. C'est un bon début car il est pertinent pour notre chaîne de recherche "Docker Containers".
Nous avons les données et nous savons comment les interroger. Mettons-le au travail dans le bot.
Les étapes de traitement de l'invite sont :
Comme d'habitude, je commencerai par définir quelques constantes dans complete.py
, le script principal du bot :
# 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)
Ensuite, j'ajouterai des fonctions pour compter les jetons comme indiqué dans les exemples OpenAI . La première fonction compte les jetons dans une chaîne, tandis que la seconde compte les jetons dans les messages. Nous verrons les messages en détail dans un instant. Pour l'instant, disons simplement que c'est une structure qui garde en mémoire l'état de la conversation.
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
La fonction suivante utilise l'invite d'origine et les chaînes de contexte pour renvoyer une invite enrichie pour 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:" )
La fonction get_message
formate l'invite dans un format compatible avec l'API :
def get_message(role: str, content: str) -> dict: """Generate a message for OpenAI API completion.""" return {"role": role, "content": content}
Il existe trois types de rôles qui affectent la façon dont le modèle réagit :
Maintenant, pour la partie engageante. La fonction get_context
prend l'invite, interroge la base de données et génère une chaîne de contexte jusqu'à ce que l'une de ces conditions soit remplie :
context_tokens_per_query
, l'espace que j'ai réservé pour le contexte.match_min_score
sont ignorées. 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
La fonction suivante et finale, complete
, envoie la requête API à OpenAI et renvoie la réponse du modèle.
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()
C'est tout; maintenant, je n'ai plus qu'à gérer les arguments de la ligne de commande et appeler les fonctions dans le bon ordre :
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))
Il est temps d'exécuter le script et de voir comment il se comporte :
$ python complete.py "Create a CI pipeline that builds and uploads a Docker image to Docker Hub"
Le résultat est:
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'"
C'est le premier bon résultat. Le modèle a déduit la syntaxe des exemples de contexte que nous avons fournis.
Rappelez-vous que j'ai commencé avec un objectif modeste : créer un assistant pour écrire des pipelines YAML. Avec un contenu plus riche dans ma base de données vectorielle, je peux généraliser le bot pour répondre à toute question sur Semaphore (ou tout autre produit — rappelez-vous de cloner les docs dans /tmp
?).
La clé pour obtenir de bonnes réponses est — sans surprise — un contexte de qualité. Il est peu probable que le simple téléchargement de chaque document dans la base de données vectorielle donne de bons résultats. La base de données contextuelle doit être organisée, étiquetée avec des métadonnées descriptives et être concise. Sinon, nous risquons de remplir le quota de jetons dans l'invite avec un contexte non pertinent.
Donc, dans un sens, il y a un art - et beaucoup d'essais et d'erreurs - impliqués dans le réglage fin du bot pour répondre à nos besoins. Nous pouvons expérimenter la limite de contexte, supprimer le contenu de mauvaise qualité, résumer et filtrer le contexte non pertinent en ajustant le score de similarité.
Vous avez peut-être remarqué que mon bot ne nous permet pas d'avoir une conversation réelle comme ChatGPT. Nous posons une question et obtenons une réponse.
Convertir le bot en un chatbot à part entière n'est, en principe, pas trop difficile. Nous pouvons maintenir la conversation en renvoyant les réponses précédentes au modèle avec chaque requête API. Les réponses GPT-3 précédentes sont renvoyées sous le rôle "assistant". Par exemple:
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))
Malheureusement, cette implémentation est assez rudimentaire. Il ne prendra pas en charge les conversations prolongées car le nombre de jetons augmente à chaque interaction. Bientôt, nous atteindrons la limite de 4096 jetons pour GPT-3, empêchant la poursuite du dialogue.
Nous devons donc trouver un moyen de maintenir la demande dans les limites des jetons. Quelques stratégies suivent :
Améliorer les réponses du bot est possible avec des incorporations de mots et une bonne base de données de contexte. Pour y parvenir, nous avons besoin d'une documentation de bonne qualité. Il y a une quantité importante d'essais et d'erreurs impliqués dans le développement d'un bot qui possède apparemment une compréhension du sujet.
J'espère que cette exploration approfondie des incorporations de mots et des grands modèles de langage vous aidera à créer un bot plus puissant, adapté à vos besoins.
Bonne construction !
Également publié ici .