Askit est un plugin linguistique pour TypeScript qui vous permet de tirer parti des capacités d'un modèle grand langage (LLM), comme GPT-4, directement dans votre environnement de programmation, aucune API complexe nécessaire. La vaste gamme d'applications d'Askit comprend:
Construit sur l'API OpenAI, ASKIT fournit une interface conviviale pour l'incorporation de LLMS dans vos applications. Vous pouvez utiliser Askit non seulement dans TypeScript, mais aussi dans JavaScript et Python.
Pour intégrer ASKIT avec JavaScript, veuillez vous référer à la section JavaScript correspondante.
Si Python est votre langue préférée, vous pouvez en savoir plus sur la façon d'utiliser ASKIT en visitant notre page Askit (Pyaskit) dédiée.
Contrôle de sortie guidé par le type: Obtenez une réponse dans le type spécifié.
Définition des fonctions basées sur le modèle: Définissez les fonctions à l'aide d'un modèle d'invite.
Génération de code: générer des fonctions à partir de l'interface unifiée. Voir la génération de code avec ASKIT pour plus de détails.
Programmation par exemple (PBE): Définissez les fonctions à l'aide d'exemples. Voir la programmation par exemple avec Askit pour plus de détails.
Avant de commencer, assurez-vous que Node.js et NPM sont installés sur votre système. Ensuite, exécutez la commande suivante:
npm install ts-askit Ce package repose sur ts-patch . Pour installer ts-patch , exécutez:
npx ts-patch install Ajoutez l'extrait suivant à votre tsconfig.json :
"compilerOptions" : {
"plugins" : [{ "transform" : " ts-askit/transform " }]
} Cette modification permet au compilateur TypeScript de prendre en charge les paramètres de type pour les API ask et define dans ASKIT.
Le package ts-patch est crucial pour libérer le plein potentiel d'Askit, car il étend le compilateur TypeScript pour intégrer pleinement le système de type Askit. Bien qu'Askit puisse être utilisé sans ts-patch , cette intégration offre une expérience plus riche en fonctionnalités.
Avant d'utiliser Askit , vous devez définir votre touche API OpenAI comme variable d'environnement OPENAI_API_KEY :
export OPENAI_API_KEY= < your OpenAI API key > <your OpenAI API key> est une chaîne qui ressemble à ceci: sk-<your key> . Vous pouvez trouver votre clé API dans le tableau de bord Openai.
Vous pouvez également spécifier le nom du modèle en tant que variable d'environnement ASKIT_MODEL :
export ASKIT_MODEL= < model name > <model name> est le nom du modèle que vous souhaitez utiliser. Le dernier ASKIT est testé avec gpt-4 et gpt-3.5-turbo-16k . Vous pouvez trouver la liste des modèles disponibles dans la documentation de l'API OpenAI.
Voici quelques exemples d'introduction:
import { ask } from 'ts-askit' ;
ask < string > ( 'Paraphrase "Hello World!"' ) . then ( ( result ) => {
console . log ( result ) ;
} ) ; Dans cet exemple, ask est une fonction API qui permet à votre programme de poser des requêtes à un modèle de langage grand (LLM). Le paramètre de type représente le type de sortie attendu du LLM. Ici, le type de sortie est string . L'invite est transmise comme un argument en langage naturel, décrivant la tâche pour le LLM pour effectuer. ask est asynchrone, renvoyant une Promise du type de sortie spécifié. L'extrait de code ci-dessus devrait imprimer quelque chose comme ceci:
Greetings, Universe!
Pour une invite avec des paramètres, vous pouvez utiliser l'API define comme suit:
import { define } from 'ts-askit' ;
const paraphrase = define < string > ( 'Paraphrase {{text}}' ) ;
paraphrase ( { text : 'Hello World!' } ) . then ( ( result ) => {
console . log ( result ) ;
} ) ; define est une fonction API qui vous permet de définir une fonction personnalisée. Son paramètre de type indique le type de sortie du LLM et, par conséquent, la valeur de retour de la fonction. La fonction reçoit un modèle de chaîne comme argument, servant d'invite de tâche de LLM. Le modèle peut inclure des paramètres enfermés en accolades à double boucle. Dans l'exemple ci-dessus, text est un paramètre dans le modèle, et il peut s'agir de n'importe quel identifiant JavaScript valide.
Une fois la fonction définie, elle peut être invoquée comme toute autre fonction. Cette fonction accepte un objet comme un argument, qui mappe aux valeurs des paramètres de modèle. Dans ce cas, text correspond à la chaîne «Hello World!».
Askit est apte à générer du code à partir de descriptions de langage naturel. Voici un exemple:
import { define } from 'ts-askit' ;
const sort = define < number [ ] , { numbers : number [ ] } > (
'Sort {{numbers}} in ascending order'
) ; Cet exemple présente une fonction qui trie un tableau de nombres dans l'ordre croissant, en utilisant l'API define pour demander au LLM de définir la fonction. Bien que efficace dans le concept, cette méthode peut sembler lourde en calcul car chaque appel de fonction nécessite une nouvelle tâche LLM.
Pour rationaliser ce processus, nous pouvons tirer parti du LLM pour générer le code de la fonction de tri, plutôt que de recourir au LLM pour chaque tâche de tri. Cela optimise la fonction sans nécessiter de modifications dans son implémentation, grâce aux capacités de génération de code d'Askit .
Le code de la fonction susmentionnée peut être généré en trois étapes:
tsc . L'analyseur Askit analyse le code et génère un fichier JSONL contenant des détails sur les appels API define et ask .npx askgen < jsonl file >tsc . Cette fois, les appels API define et ask sont remplacés par les références et les appels à la fonction nouvellement générée, respectivement, grâce à la fonction de remplacement automatique d' Askit . Askit vous permet de tirer parti de la puissance de la programmation par l'exemple (PBE). PBE simplifie le processus de programmation en vous permettant de définir les fonctionnalités à travers des exemples plutôt qu'une logique codée en dur. L'exemple suivant illustre cela en vous montrant comment ajouter deux nombres binaires à l'aide de PBE avec ASKIT .
import { define , Example } from 'ts-askit' ;
const trainingExamples : Example [ ] = [
{ input : { x : '1' , y : '0' } , output : '1' } ,
{ input : { x : '1' , y : '1' } , output : '10' } ,
{ input : { x : '101' , y : '11' } , output : '1000' } ,
{ input : { x : '1001' , y : '110' } , output : '1111' } ,
{ input : { x : '1111' , y : '1' } , output : '10000' } ,
] ;
const testExamples = [
{ input : { x : '0' , y : '1' } , output : '1' } ,
{ input : { x : '10' , y : '0' } , output : '10' } ,
{ input : { x : '110' , y : '10' } , output : '1000' } ,
] ;
const addInBase2 = define < string , { x : string ; y : string } > (
'Add {{x}} and {{y}}' ,
trainingExamples ,
testExamples
) ;
async function doit ( ) {
console . log ( await addInBase2 ( { x : '101' , y : '11' } ) ) ;
}
doit ( ) ; Dans cet exemple, nous définissons une fonction addInBase2 qui prend deux nombres binaires (représentés sous forme de chaînes) et les ajoute. La fonction define est invoquée avec une invite et deux tableaux d'exemples: des exemples de formation et des exemples de test. Les exemples de formation se reflètent dans l'invite d'une manière d'apprentissage à petit coup. D'un autre côté, les exemples de test sont utilisés pour valider l'exactitude de la fonction générée. Les exemples de test ne sont pas requis si vous ne générez pas de code pour la fonction.
Le résultat est une fonctionnalité puissante vous permettant de demander au LLM d'effectuer des opérations complexes, comme l'addition binaire, en utilisant que des exemples. Cette approche vous permet de développer rapidement des fonctionnalités complexes et avec une logique moins explicite.
Une fois la fonction addInBase2 définie, vous pouvez l'appeler avec des chaînes de numéro binaires pour effectuer l'ajout dans la base 2. Comme avec les appels de fonction traditionnels, ask opération ASKIT a renvoie une promesse qui résout avec le résultat calculé.
Les développeurs JavaScript peuvent exploiter pleinement le potentiel du contrôle de sortie guidé de type offert par Askit . Tout comme son dactylographie de frère, JavaScript incorpore la méthode API ask pour y parvenir. La fonction ask prend deux paramètres: un type et une invite.
Voici un éventail d'exemples démontrant son utilisation:
const ai = require ( 'ts-askit' )
const t = require ( 'ts-askit/types' )
ai . ask ( t . number , 'What is the third prime number?' ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . string , "What is the month number of 'January'?" ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . array ( t . number ) , "What are the month numbers in the second quarter?" ) ;
const monthType = t . type ( {
name : t . string ,
number : t . number
} )
ai . ask ( monthType , "What is the month number of 'October'?" ) . then ( ( answer ) => { console . log ( answer ) } ) ;
ai . ask ( t . array ( monthType ) , "What are the months in the second quarter?" ) . then ( ( answer ) => { console . log ( answer ) } ) ; Dans l'extrait de code ci-dessus, la fonction ask est invoquée avec un type et une invite. Le paramètre de type sert à informer Askit sur le format et la structure de la sortie souhaitée. Cela devient extrêmement pratique lorsque vous avez affaire à des structures de données complexes.
Avec Askit , les développeurs JavaScript ont la capacité de définir des fonctions à l'aide de modèles faciles à comprendre. La méthode define est le héros dans les coulisses ici, car il aide à créer des fonctions en fonction du modèle de tâche fourni. Une fois créées, ces fonctions peuvent être appelées avec n'importe quel objet qui fournit des valeurs pour les espaces réservés dans le modèle.
Voici un exemple de la façon dont c'est fait:
const ai = require ( 'ts-askit' )
const t = require ( 'ts-askit/types' )
let f = ai . define ( t . string , 'Translate {{text}} into {{language}}' ) ;
f ( { text : 'Hello' , language : 'French' } ) . then ( ( answer ) => { console . log ( answer ) } ) ; Dans le code ci-dessus, la méthode define est utilisée pour établir une fonction f à l'aide d'un modèle de tâche 'traduire {{text}} en {{langage}}'. La fonction f est ensuite invoquée avec un objet qui fournit des valeurs pour text et language .
Le module 'ts-askit/types' est un trésor de types que vous pouvez utiliser pour guider la sortie d' Askit . Voici une table pour vous aider à saisir rapidement ces types:
| Taper | Description | Type Exemple | Exemple de valeur |
|---|---|---|---|
NumberType | Type numérique | t.number | 123 |
StringType | Type de chaîne | t.string | "Bonjour le monde!" |
BooleanType | Type booléen | t.boolean | vrai |
LiteralType | Type de valeur littérale | t.literal(123) | 123 |
ArrayType | Type de tableau | t.array(t.number) | [1, 2, 3] |
UnionType | Type d'union (plusieurs valeurs possibles) | t.union([t.literal('yes'), t.literal('no')]) | "Oui" ou "Non" |
InterfaceType | Type d'interface / dictionnaire | t.type({a: t.number, b: t.number}) | {a: 1, b: 2} |
CodeType | Type de code | t.code('python') | "Def hello_world (): print ('bonjour, monde!')" |
Chaque type a des propriétés spécifiques qu'Askit utilise pour comprendre la tâche à accomplir et formater correctement la sortie.
Au moment de la rédaction, la fonction de génération de code est exclusivement disponible dans TypeScript. Cependant, les efforts battent leur plein pour étendre cette fonctionnalité puissante au domaine de JavaScript. Si vos exigences appellent pour l'utilisation de la génération de code dans l'intervalle, nous vous recommandons d'utiliser TypeScript jusqu'à d'autres mises à jour.
Pour plus de détails sur notre code de conduite et le processus de soumission des demandes de traction, veuillez vous référer à contribution.md.
Ce projet est autorisé sous la licence du MIT. Pour plus d'informations, consultez le fichier de licence.
@misc { okuda2023askit ,
title = { AskIt: Unified Programming Interface for Programming with Large Language Models } ,
author = { Katsumi Okuda and Saman Amarasinghe } ,
year = { 2023 } ,
eprint = { 2308.15645 } ,
archivePrefix = { arXiv } ,
primaryClass = { cs.PL }
}