Rationalisez votre vie à l'aide de l'incidencetools.jl, le package Julia qui simplifie l'interaction avec les grands modèles de langage.
Incmingtools.jl n'est pas destiné à construire des systèmes à grande échelle. C'est censé être l'outil incontournable de votre environnement mondial qui vous fera économiser 20 minutes par jour!
Conseil
Sauter aux documents
@ai_str et Templage facile Prendre le début de l'incidencetools.jl est aussi simple que d'importer le package et d'utiliser la macro @ai_str pour vos questions.
Remarque: vous devrez définir votre clé API OpenAI en tant que variable d'environnement avant d'utiliser IncitetTools.jl (voir la section Création de la clé API OpenAI ci-dessous).
Après l'introduction de la facturation prépayée, vous devrez acheter des crédits pour commencer (5 $ minimum). Pour un démarrage rapide, définissez-le simplement via ENV["OPENAI_API_KEY"] = "your-api-key"
Installer IncitingTools:
using Pkg
Pkg . add ( " PromptingTools " )Et nous sommes prêts à partir!
using PromptingTools
ai " What is the capital of France? "
# [ Info: Tokens: 31 @ Cost: $0.0 in 1.5 seconds --> Be in control of your spending!
# AIMessage("The capital of France is Paris.") L'objet retourné est un emballage léger avec un message généré dans le domaine :content (par exemple, ans.content ) pour un traitement supplémentaire en aval.
Conseil
Si vous souhaitez répondre au message précédent, ou continuez simplement la conversation, utilisez @ai!_str (Remarquez le bang ! ):
ai! " And what is the population of it? "Vous pouvez facilement injecter toutes les variables avec une interpolation de chaîne:
country = " Spain "
ai " What is the capital of $ (country)? "
# [ Info: Tokens: 32 @ Cost: $0.0001 in 0.5 seconds
# AIMessage("The capital of Spain is Madrid.") Conseil
Utilisez des plate-forme après strict pour sélectionner le modèle à appeler, par exemple, ai"What is the capital of France?"gpt4 (utilisez gpt4t pour le nouveau modèle GPT-4 Turbo). Idéal pour ces questions très difficiles!
Pour des modèles d'invite plus complexes, vous pouvez utiliser des modèles de style guidon et fournir des variables comme arguments de mots clés:
msg = aigenerate ( " What is the capital of {{country}}? Is the population larger than {{population}}? " , country = " Spain " , population = " 1M " )
# [ Info: Tokens: 74 @ Cost: $0.0001 in 1.3 seconds
# AIMessage("The capital of Spain is Madrid. And yes, the population of Madrid is larger than 1 million. As of 2020, the estimated population of Madrid is around 3.3 million people.") Conseil
Utilisez asyncmap pour exécuter plusieurs tâches alimentées en AI simultanément.
Conseil
Si vous utilisez des modèles lents (comme GPT-4), vous pouvez utiliser la version asynchrone de @ai_str -> @aai_str pour éviter de bloquer le REPT, par exemple, aai"Say hi but slowly!"gpt4 (similaire @ai!_str -> @aai!_str pour les conversations multipus).
Pour des exemples plus pratiques, consultez les examples/ dossiers et la section Exemples avancés ci-dessous.
@ai_str et Templage facileai*airetry!aigenerate ( api_kwargs )L'ingénierie rapide n'est ni rapide ni facile. De plus, différents modèles et leurs fins peuvent nécessiter des formats et des astuces rapides différents, ou peut-être que les informations avec lesquelles vous travaillez nécessitent des modèles spéciaux. IncmingTools.jl est destiné à unifier les invites pour différents backends et à rendre les tâches courantes (comme les invites des modèles) aussi simples que possible.
Certaines fonctionnalités:
aigenerate : Simplifier les modèles d'invite avec le guidon (par exemple, {{variable}} ) et les arguments de mots clés@ai_str : Enregistrez les touches avec une macro de chaîne pour les invites simplesai... pour une meilleure découverteai* Fonctions remarquables: aigenerate , aiembed , aiclassify , aiextract , aiscan , aiimage , aitemplates
Toutes les fonctions ai* ont la même structure de base:
ai*(<optional schema>,<prompt or conversation>; <optional keyword arguments>) ,
Mais ils diffèrent dans le but:
aigenerate est la fonction générale pour générer une réponse de texte avec des LLM, c'est-à-dire qu'il renvoie AIMessage avec le champ :content contenant le texte généré (par exemple, ans.content isa AbstractString )aiembed est conçu pour extraire des intégres de la réponse du modèle AI, c'est-à-dire qu'il renvoie DataMessage avec un champ :content contenant les intégres (par exemple, ans.content isa AbstractArray )aiextract est conçu pour extraire des données structurées de la réponse du modèle AI et les renvoyer en tant que Julia Struct (par exemple, si nous fournissons return_type=Food , nous obtenons ans.content isa Food ). Vous devez d'abord définir le type de retour, puis le fournir comme un argument de mot-clé.aitools est conçu pour les flux de travail agentiques avec un mélange d'appels d'outils et d'entrées utilisateur. Il peut fonctionner avec des fonctions simples et les exécuter.aiclassify est conçu pour classer le texte d'entrée (ou simplement répondre à l'intérieur) d'un ensemble de choices discrets fournis par l'utilisateur. Il peut être très utile en tant que juge LLM ou routeur pour les systèmes de chiffon, car il utilise le "Trick Logit Bias" et génère exactement 1 jeton. Il renvoie AIMessage avec Field :content , mais le :content ne peut être que l'un des choices fournis (par exemple, ans.content in choices )aiscan est destiné à travailler avec des images et des modèles compatibles avec la vision (comme une entrée), mais il renvoie AIMessage avec le champ :content contenant le texte généré (par exemple, ans.content isa AbstractString ) similaire à aigenerate .aiimage est pour générer des images (par exemple, avec Openai Dall-E 3). Il renvoie un DataMessage , où le champ :content peut contenir l'URL pour télécharger l'image ou l'image codée de base64 en fonction de l' api_kwargs.response_format fournie par l'utilisateur.aitemplates est une fonction d'assistance pour découvrir les modèles disponibles et voir leurs détails (par exemple, aitemplates("some keyword") ou aitemplates(:AssistantAsk) ) Si vous utilisez un model connu, vous n'avez pas besoin de fournir un schema (le premier argument).
Les arguments de mots clés facultatifs dans ai* ont tendance à être:
model::String - quel modèle vous souhaitez utiliserverbose::Bool - si vous êtes allé voir les journaux d'informations sur les coûts d'IAreturn_all::Bool - que vous vouliez toute la conversation ou simplement la réponse IA (c'est-à-dire que vous souhaitiez inclure vos entrées / invite dans la sortie)api_kwargs::NamedTuple - Paramètres spécifiques pour le modèle, par exemple, temperature=0.0 pour ne pas être créatif (et avoir une sortie plus similaire dans chaque cycle)http_kwargs::NamedTuple - Paramètres du package http.jl, par exemple, readtimeout = 120 à Time Out en 120 secondes si aucune réponse n'a été reçue.Expérimental: agenttools
En plus de la liste ci-dessus des fonctions ai* , vous pouvez également utiliser les homologues "paresseux" de ces fonctions du module expérimental AgentTools.
using PromptingTools . Experimental . AgentTools Par exemple, AIGenerate() créera une instance paresseuse d' aigenerate . Il s'agit d'une instance d' AICall avec aigenerate comme fonction AI. Il utilise exactement les mêmes arguments et arguments de mots clés que aigenerate (voir ?aigenerate pour plus de détails).
"Lazy" fait référence au fait qu'il ne génère aucune sortie lorsqu'elle est instanciée (uniquement lors de run! est appelée).
Ou dit différemment, la structure AICall et toutes ses saveurs ( AIGenerate , ...) sont conçues pour faciliter un modèle d'exécution différé (évaluation paresseuse) pour les fonctions d'IA qui interagissent avec un modèle d'apprentissage des langues (LLM). Il stocke les informations nécessaires à un appel AI et exécute la fonction AI sous-jacente uniquement lorsqu'elle est fournie avec un UserMessage ou lorsque la run! la méthode est appliquée. Cela nous permet de nous souvenir des entrées de l'utilisateur et de déclencher l'appel LLM à plusieurs reprises si nécessaire, ce qui permet la fixation automatique (voir ?airetry! ).
Si vous souhaitez un puissant flux de travail de fixation automatique, vous pouvez utiliser airetry! , qui exploite la recherche d'arbres Monte-Carlo pour choisir la trajectoire optimale de la conversation en fonction de vos besoins.
Expérimental: Ragtools
Enfin, nous fournissons un ensemble d'outils pour créer des applications de chiffon (récupérer, répondre, générer).
Il peut être aussi simple que deux appels: build_index et airag (récupérer, répondre, générer).
Si vous utilisez alors une imprimée assez imprimée avec PromptingTools.pprint , nous mettons en évidence le texte généré par rapport au texte provocateur du contexte et nous noons la force de la réponse générée prise en charge par le contexte. De plus, nous annotons chaque morceau généré avec une référence à laquelle le document source d'où il provient probablement (y compris le score de confiance entre 0 et 1).
Google Search est génial, mais c'est un commutateur de contexte. Vous devez souvent ouvrir quelques pages et lire la discussion pour trouver la réponse dont vous avez besoin. Idem avec le site Web de Chatgpt.
Imaginez que vous êtes dans VScode, en modifiant votre fichier .gitignore . Comment ignorer à nouveau un fichier dans tous les sous-dossiers?
Tout ce que vous avez à faire est de taper: aai"What to write in .gitignore to ignore file XYZ in any folder or subfolder?"
Avec aai"" (par opposition à ai"" ), nous passons un appel non bloquant au LLM pour ne pas vous empêcher de poursuivre votre travail. Lorsque la réponse est prête, nous la enregistrons à partir de l'arrière-plan:
[ Info: Tokens: 102 @ Cost: $0.0002 in 2.7 seconds ┌ Info: AIMessage> To ignore a file called "XYZ" in any folder or subfolder, you can add the following line to your .gitignore file: │ │
│ **/XYZ ││ └ This pattern uses the double asterisk (**) to match any folder or subfolder, and then specifies the name of the file you want ignorer.
Vous avez probablement enregistré 3 à 5 minutes sur cette tâche et probablement 5 à 10 minutes, en raison de l'interrupteur / distraction de contexte que vous avez évité. C'est une petite victoire, mais cela s'additionne rapidement.
Vous pouvez utiliser la fonction aigenerate pour remplacer les variables de guidon (par exemple, {{name}} ) via des arguments de mots clés.
msg = aigenerate ( " Say hello to {{name}}! " , name = " World " ) Les invites les plus complexes sont effectivement une conversation (un ensemble de messages), où vous pouvez avoir des messages de trois entités: système, utilisateur, AIASSSISTANT. Nous fournissons les types correspondants pour chacun d'eux: SystemMessage , UserMessage , AIMessage .
using PromptingTools : SystemMessage, UserMessage
conversation = [
SystemMessage ( " You're master Yoda from Star Wars trying to help the user become a Jedi. " ),
UserMessage ( " I have feelings for my {{object}}. What should I do? " )]
msg = aigenerate (conversation; object = " old iPhone " )Aimessage ("Ah, un dilemme, vous avez. L'attachement émotionnel peut assombrir votre chemin pour devenir un Jedi. Pour être attaché aux biens matériels, vous ne devez pas. L'iPhone n'est qu'un outil, rien de plus. Lâchez prise, vous devez.
Cherchez le détachement, Young Padawan. Réfléchissez à l'impermanence de toutes choses. Appréciez les souvenirs qu'il vous a donnés, et vous séparez avec gratitude. En son absence, trouvez de nouvelles expériences pour grandir et devenir une avec la force. Ce n'est qu'alors, un vrai Jedi, vous deviendrez. ")
Vous pouvez également l'utiliser pour créer des conversations, par exemple,
new_conversation = vcat (conversation ... ,msg, UserMessage ( " Thank you, master Yoda! Do you have {{object}} to know what it feels like? " ))
aigenerate (new_conversation; object = " old iPhone " )Aimesage ("Hmm, possédez un vieil iPhone, je ne le fais pas. Mais l'expérience avec les pièces jointes, j'ai. Détachement, j'ai appris. Véritable puissance et liberté, ça apporte ...")
Avec les LLM, la qualité / robustesse de vos résultats dépend de la qualité de vos invites. Mais l'écriture d'invites est difficile! C'est pourquoi nous proposons un système de modèles pour vous faire gagner du temps et des efforts.
Pour utiliser un modèle spécifique (par exemple, `` pour demander une langue Julia):
msg = aigenerate ( :JuliaExpertAsk ; ask = " How do I add packages? " ) Ce qui précède équivaut à une version plus verbale qui utilise explicitement la répartition sur AITemplate :
msg = aigenerate ( AITemplate ( :JuliaExpertAsk ); ask = " How do I add packages? " ) Trouvez des modèles disponibles avec aitemplates :
tmps = aitemplates ( " JuliaExpertAsk " )
# Will surface one specific template
# 1-element Vector{AITemplateMetadata}:
# PromptingTools.AITemplateMetadata
# name: Symbol JuliaExpertAsk
# description: String "For asking questions about Julia language. Placeholders: `ask`"
# version: String "1"
# wordcount: Int64 237
# variables: Array{Symbol}((1,))
# system_preview: String "You are a world-class Julia language programmer with the knowledge of the latest syntax. Your commun"
# user_preview: String "# Questionnn{{ask}}"
# source: String ""Ce qui précède vous donne une bonne idée de ce qu'est le modèle, quels espaces réservés sont disponibles et combien il en coûterait pour l'utiliser (= WordCount).
Recherchez tous les modèles liés à Julia:
tmps = aitemplates ( " Julia " )
# 2-element Vector{AITemplateMetadata}... -> more to come later! Si vous êtes sur VScode, vous pouvez tirer parti d'un bel affichage tabulaire avec vscodedisplay :
using DataFrames
tmps = aitemplates ( " Julia " ) |> DataFrame |> vscodedisplay J'ai mon modèle sélectionné, comment puis-je l'utiliser? Utilisez simplement le "nom" dans aigenerate ou aiclassify comme vous le voyez dans le premier exemple!
Vous pouvez inspecter n'importe quel modèle en le «rendant» (c'est ce que le LLM verra):
julia > AITemplate ( :JudgeIsItTrue ) |> PromptingTools . renderVoir plus d'exemples dans les exemples / dossier.
Vous pouvez tirer parti de asyncmap pour exécuter plusieurs tâches alimentées par AI simultanément, en améliorant les performances des opérations par lots.
prompts = [ aigenerate ( " Translate 'Hello, World!' to {{language}} " ; language) for language in [ " Spanish " , " French " , " Mandarin " ]]
responses = asyncmap (aigenerate, prompts)Conseil
Vous pouvez limiter le nombre de tâches simultanées avec le mot-clé asyncmap(...; ntasks=10) .
Certaines tâches nécessitent des modèles plus puissants. Toutes les fonctions orientées utilisateur ont un model d'argument de mot-clé qui peut être utilisé pour spécifier le modèle à utiliser. Par exemple, vous pouvez utiliser model = "gpt-4-1106-preview" pour utiliser le dernier modèle GPT-4 Turbo. Cependant, personne ne veut taper ça!
Nous proposons un ensemble d'alias modèles (par exemple, "gpt3", "gpt4", "gpt4t" -> le turbo GPT-4 ci-dessus, etc.) qui peut être utilisé à la place.
Chaque ai... appelle d'abord le nom du modèle fourni dans le dictionnaire PromptingTools.MODEL_ALIASES , afin que vous puissiez facilement étendre avec vos propres alias!
const PT = PromptingTools
PT . MODEL_ALIASES[ " gpt4t " ] = " gpt-4-1106-preview " Ces alias peuvent également être utilisés comme drapeaux dans la macro @ai_str , par exemple, ai"What is the capital of France?"gpt4t (GPT-4 Turbo a un coup sûr des connaissances en avril 2023, il est donc utile pour des questions plus contemporaines).
Utilisez la fonction aiembed pour créer des intégres via le modèle OpenAI par défaut qui peut être utilisé pour la recherche sémantique, le regroupement et les flux de travail AI plus complexes.
text_to_embed = " The concept of artificial intelligence. "
msg = aiembed (text_to_embed)
embedding = msg . content # 1536-element Vector{Float64}Si vous prévoyez de calculer la distance en cosinus entre les intérêts, vous pouvez d'abord les normaliser:
using LinearAlgebra
msg = aiembed ([ " embed me " , " and me too " ], LinearAlgebra . normalize)
# calculate cosine distance between the two normalized embeddings as a simple dot product
msg . content ' * msg . content[:, 1 ] # [1.0, 0.787] Vous pouvez utiliser la fonction aiclassify pour classer toute instruction fournie comme vrai / false / inconnu. Ceci est utile pour la vérification des faits, l'hallucination ou les contrôles NLI, la modération, le filtrage, l'analyse des sentiments, l'ingénierie des fonctionnalités et plus encore.
aiclassify ( " Is two plus two four? " )
# trueLes invites du système et les modèles de meilleure qualité peuvent être utilisés pour des tâches plus complexes, notamment en sachant quand s'en remettre à un humain:
aiclassify ( :JudgeIsItTrue ; it = " Is two plus three a vegetable on Mars? " , model = " gpt4t " )
# unknown Dans l'exemple ci-dessus, nous avons utilisé un modèle d'invite :JudgeIsItTrue , qui se développe automatiquement à l'invite système suivante (et une invite utilisateur distincte):
"Vous êtes un juge d'IA impartial évaluant si la déclaration fournie est" vraie "ou" fausse ". Répondre" inconnu "si vous ne pouvez pas décider".
Pour plus d'informations sur les modèles, consultez la section des invites à modèle.
aiclassify peut également être utilisé pour la classification dans un ensemble de catégories définies (maximum 20), nous pouvons donc l'utiliser pour le routage.
De plus, si vous fournissez les choix sous forme de tuples ( (label, description) ), le modèle utilisera les descriptions pour décider, mais il renverra les étiquettes.
Exemple:
choices = [( " A " , " any animal or creature " ), ( " P " , " for any plant or tree " ), ( " O " , " for everything else " )]
input = " spider "
aiclassify ( :InputClassifier ; choices, input) # -> returns "A" for any animal or creature
# Try also with:
input = " daphodil " # -> returns "P" for any plant or tree
input = " castle " # -> returns "O" for everything elseSous le capot, nous utilisons l'astuce "biais logit" pour forcer seulement 1 jeton généré - cela signifie que c'est très bon marché et très rapide!
Êtes-vous fatigué d'extraire des données avec Regex? Vous pouvez utiliser LLMS pour extraire des données structurées à partir de texte!
Tout ce que vous avez à faire est de définir la structure des données que vous souhaitez extraire et le LLM fera le reste.
Définissez un return_type avec struct. Fournir des docstrings si nécessaire (améliore les résultats et aide à la documentation).
Commençons par une tâche difficile - extraire la météo actuelle dans un endroit donné:
@enum TemperatureUnits celsius fahrenheit
""" Extract the current weather in a given location
# Arguments
- `location`: The city and state, e.g. "San Francisco, CA"
- `unit`: The unit of temperature to return, either `celsius` or `fahrenheit`
"""
struct CurrentWeather
location :: String
unit :: Union{Nothing,TemperatureUnits}
end
# Note that we provide the TYPE itself, not an instance of it!
msg = aiextract ( " What's the weather in Salt Lake City in C? " ; return_type = CurrentWeather)
msg . content
# CurrentWeather("Salt Lake City, UT", celsius)Mais vous pouvez l'utiliser même pour des tâches plus complexes, comme l'extraction de nombreuses entités d'un texte:
" Person's age, height, and weight. "
struct MyMeasurement
age :: Int
height :: Union{Int,Nothing}
weight :: Union{Nothing,Float64}
end
struct ManyMeasurements
measurements :: Vector{MyMeasurement}
end
msg = aiextract ( " James is 30, weighs 80kg. He's 180cm tall. Then Jack is 19 but really tall - over 190! " ; return_type = ManyMeasurements)
msg . content . measurements
# 2-element Vector{MyMeasurement}:
# MyMeasurement(30, 180, 80.0)
# MyMeasurement(19, 190, nothing) Il y a même un wrapper pour vous aider à assister aux erreurs avec des explications utiles sur les raisons pour lesquelles l'analyse a échoué. Voir ?PromptingTools.MaybeExtract pour plus d'informations.
Avec la fonction aiscan , vous pouvez interagir avec des images comme s'ils étaient du texte.
Vous pouvez simplement décrire une image fournie:
msg = aiscan ( " Describe the image " ; image_path = " julia.png " , model = " gpt4v " )
# [ Info: Tokens: 1141 @ Cost: $0.0117 in 2.2 seconds
# AIMessage("The image shows a logo consisting of the word "julia" written in lowercase") Ou vous pouvez faire un OCR d'une capture d'écran. Transcrivons du code SQL à partir d'une capture d'écran (plus de rétinération!), Nous utilisons un modèle :OCRTask :
# Screenshot of some SQL code
image_url = " https://www.sqlservercentral.com/wp-content/uploads/legacy/8755f69180b7ac7ee76a69ae68ec36872a116ad4/24622.png "
msg = aiscan ( :OCRTask ; image_url, model = " gpt4v " , task = " Transcribe the SQL code in the image. " , api_kwargs = (; max_tokens = 2500 ))
# [ Info: Tokens: 362 @ Cost: $0.0045 in 2.5 seconds
# AIMessage("```sql
# update Orders <continue>Vous pouvez ajouter une mise en évidence de la syntaxe des sorties via Markdown
using Markdown
msg . content |> Markdown . parseairetry!Il s'agit d'une fonctionnalité expérimentale, vous devez donc l'importer explicitement:
using PromptingTools . Experimental . AgentTools Ce module propose des homologues "paresseux" aux fonctions ai... , vous pouvez donc les utiliser de manière plus contrôlée, par exemple, aigenerate -> AIGenerate (remarquez le camelcase), qui a exactement les mêmes arguments sauf qu'il génère uniquement lorsqu'il run! est appelé.
Par exemple:
out = AIGenerate ( " Say hi! " ; model = " gpt4t " )
run! (out) Comment est-ce utile? Nous pouvons utiliser les mêmes «entrées» pour les appels répétés, par exemple, lorsque nous voulons valider ou régénérer certaines sorties. Nous avons une fonction airetry pour nous aider.
La signature de l' airetry! IS airetry!(condition_function, aicall::AICall, feedback_function) . Il évalue la condition condition_function sur l'objet aicall (par exemple, nous évaluons f_cond(aicall) -> Bool ). S'il échoue, nous appelons feedback_function sur l'objet aicall pour fournir des commentaires pour le modèle AI (par exemple, f_feedback(aicall) -> String ) et répéter le processus jusqu'à ce qu'il passe ou jusqu'à ce que la valeur max_retries soit dépassée.
Nous pouvons prendre des échecs d'API (aucun commentaire nécessaire, donc aucun n'est fourni)
# API failure because of a non-existent model
# RetryConfig allows us to change the "retry" behaviour of any lazy call
out = AIGenerate ( " say hi! " ; config = RetryConfig (; catch_errors = true ),
model = " NOTEXIST " )
run! (out) # fails
# we ask to wait 2s between retries and retry 2 times (can be set in `config` in aicall as well)
airetry! (isvalid, out; retry_delay = 2 , max_retries = 2 )Ou nous pouvons valider certaines sorties (par exemple, son format, son contenu, etc.)
Nous jouerons un jeu de devinettes en couleur (je pense "jaune"):
# Notice that we ask for two samples (`n_samples=2`) at each attempt (to improve our chances).
# Both guesses are scored at each time step, and the best one is chosen for the next step.
# And with OpenAI, we can set `api_kwargs = (;n=2)` to get both samples simultaneously (cheaper and faster)!
out = AIGenerate (
" Guess what color I'm thinking. It could be: blue, red, black, white, yellow. Answer with 1 word only " ;
verbose = false ,
config = RetryConfig (; n_samples = 2 ), api_kwargs = (; n = 2 ))
run! (out)
# # Check that the output is 1 word only, third argument is the feedback that will be provided if the condition fails
# # Notice: functions operate on `aicall` as the only argument. We can use utilities like `last_output` and `last_message` to access the last message and output in the conversation.
airetry! (x -> length ( split ( last_output (x), r" | \ . " )) == 1 , out,
" You must answer with 1 word only. " )
# Note: you could also use the do-syntax, eg,
airetry! (out, " You must answer with 1 word only. " ) do aicall
length ( split ( last_output (aicall), r" | \ . " )) == 1
end Vous pouvez placer plusieurs airetry! appelle dans une séquence. Ils continueront à réessayer jusqu'à ce qu'ils mangent des appels AI maximaux autorisés ( max_calls ) ou des tentatives maximales ( max_retries ).
Voir les documents pour des exemples plus complexes et des conseils d'utilisation ( ?airetry ). Nous tirons parti de la recherche sur les arbres Monte Carlo (MCTS) pour optimiser la séquence des tentatives, il s'agit donc d'un outil très puissant pour construire des flux de travail IA robustes (inspiré par le papier de recherche d'arbre des agents linguistiques et par du papier Assertions DSPy).
Olllama.ai est un outil incroyablement simple qui vous permet d'exécuter plusieurs modèles de langage grand (LLM) sur votre ordinateur. Il convient particulièrement lorsque vous travaillez avec des données sensibles qui ne doivent être envoyées nulle part.
Supposons que vous ayez installé Olllama, téléchargé un modèle et qu'il fonctionne en arrière-plan.
Nous pouvons l'utiliser avec la fonction aigenerate :
const PT = PromptingTools
schema = PT . OllamaSchema () # notice the different schema!
msg = aigenerate (schema, " Say hi! " ; model = " openhermes2.5-mistral " )
# [ Info: Tokens: 69 in 0.9 seconds
# AIMessage("Hello! How can I assist you today?") Pour les modèles communs qui ont été enregistrés (voir ?PT.MODEL_REGISTRY ), vous n'avez pas besoin de fournir explicitement le schéma:
msg = aigenerate ( " Say hi! " ; model = " openhermes2.5-mistral " ) Et nous pouvons également utiliser la fonction aiembed :
msg = aiembed (schema, " Embed me " , copy; model = " openhermes2.5-mistral " )
msg . content # 4096-element JSON3.Array{Float64...
msg = aiembed (schema, [ " Embed me " , " Embed me " ]; model = " openhermes2.5-mistral " )
msg . content # 4096×2 Matrix{Float64}: Vous pouvez désormais également utiliser aiscan pour fournir des images aux modèles Olllama! Voir les documents pour plus d'informations.
Si vous obtenez des erreurs, vérifiez que Olllama est en cours d'exécution - consultez le guide de configuration de la section Olllama ci-dessous.
Les modèles Mistral dominent depuis longtemps l'espace open-source. Ils sont désormais disponibles via leur API, vous pouvez donc les utiliser avec IncitStools.jl!
msg = aigenerate ( " Say hi! " ; model = " mistral-tiny " ) Tout fonctionne, car nous avons enregistré les modèles dans le PromptingTools.MODEL_REGISTRY ! Il existe actuellement 4 modèles disponibles: mistral-tiny , mistral-small , mistral-medium , mistral-embed .
Sous le capot, nous utilisons un schéma dédié MistralOpenAISchema qui tire parti de la majeure partie de la base de code spécifique à l'Openai, vous pouvez donc toujours fournir cela explicitement comme premier argument:
const PT = PromptingTools
msg = aigenerate (PT . MistralOpenAISchema (), " Say Hi! " ; model = " mistral-tiny " , api_key = ENV [ " MISTRAL_API_KEY " ]) Comme vous pouvez le voir, nous pouvons charger votre clé API à partir de l'env ou via le mécanisme préférences.jl (voir ?PREFERENCES pour plus d'informations).
Mais Mistralai ne sont pas les seuls! Il existe de nombreux autres fournisseurs passionnants, par exemple, perplexité.ai, feux d'artifice.ai. Tant qu'ils sont compatibles avec l'API OpenAI (par exemple, envoyant messages avec des clés role et content ), vous pouvez les utiliser avec Incitetools.jl en utilisant schema = CustomOpenAISchema() :
# Set your API key and the necessary base URL for the API
api_key = " ... "
prompt = " Say hi! "
msg = aigenerate (PT . CustomOpenAISchema (), prompt; model = " my_model " , api_key, api_kwargs = (; url = " http://localhost:8081 " ))Comme vous pouvez le voir, il fonctionne également pour tous les modèles locaux que vous pourriez avoir exécutés sur votre ordinateur!
Remarque: Pour le moment, nous ne soutenons que les fonctions aigenerate et aiembed pour Mistralai et d'autres API compatibles OpenAI. Nous prévoyons d'étendre le soutien à l'avenir.
Assurez-vous que la variable d'environnement ANTHROPIC_API_KEY est définie sur votre clé API.
# cladeuh is alias for Claude 3 Haiku
ai " Say hi! " claudeh Les alias modèles prédéfinis sont claudeo , claudes et claudeh , pour Claude 3 Opus, Sonnet et Haiku, respectivement.
Le schéma correspondant est AnthropicSchema .
Il existe plusieurs modèles rapides avec XML dans le nom, ce qui suggère qu'ils utilisent le formatage XML adapté à l'anthropique pour séparer les sections. Trouvez-les avec aitemplates("XML") .
# cladeo is alias for Claude 3 Opus
msg = aigenerate (
:JuliaExpertAskXML , ask = " How to write a function to convert Date to Millisecond? " ,
model = " cladeo " )TBU ...
Trouvez plus d'exemples dans les exemples / dossier.
Le package est construit autour de trois éléments clés:
aigenerate , aiembed , aiclassify ) Pourquoi cette conception? Différentes API nécessitent des formats rapides différents. Par exemple, l'API d'Openai nécessite un tableau de dictionnaires avec des champs role et content , tandis que l'API d'Olllama pour le modèle Zephyr-7B nécessite un schéma ChatML avec une grande chaîne et des séparateurs comme <|im_start|>usernABC...<|im_end|>user . Pour séparer les sections dans votre invite, OpenAI préfère les en-têtes de marques ( ##Response ) vs Anthropic fonctionne mieux avec les balises HTML ( <text>{{TEXT}}</text> ).
Ce package est fortement inspiré par l'instructeur et son utilisation intelligente de l'appel de fonction.
Schémas rapides
Le type de clé utilisé pour la personnalisation de la logique de préparation des entrées pour les LLM et les appelle (via plusieurs répartitions).
Tous sont des sous-types d' AbstractPromptSchema et chaque fonction de tâche a une signature générique avec un schéma dans la première position foo(schema::AbstractPromptSchema,...)
La répartition est définie à la fois pour le "rendu" des invites ( render ) et pour appeler les API ( aigenerate ).
Idéalement, chaque nouvelle interface serait définie dans un fichier séparé llm_<interface>.jl (par exemple, llm_openai.jl ).
Messages
Les invites sont effectivement une conversation à terminer.
Les conversations ont tendance à avoir trois acteurs clés: le système (pour les instructions globales), l'utilisateur (pour les entrées / données) et l'assistant AI (pour les sorties). Nous fournissons des types de SystemMessage , UserMessage et AIMessage pour chacun d'eux.
Compte tenu d'un schéma rapide et d'un ou plusieurs messages, vous pouvez render l'objet résultant à intégrer l'API du modèle. Par exemple, pour Openai
using PromptingTools : render, SystemMessage, UserMessage
PT = PromptingTools
schema = PT . OpenAISchema () # also accessible as the default schema `PT.PROMPT_SCHEMA`
conversation = conversation = [
SystemMessage ( " Act as a helpful AI assistant. Provide only the information that is requested. " ),
UserMessage ( " What is the capital of France? " )]
messages = render (schema, conversation)
# 2-element Vector{Dict{String, String}}:
# Dict("role" => "system", "content" => "Act as a helpful AI assistant. Provide only the information that is requested.")
# Dict("role" => "user", "content" => "What is the capital of France?")Cet objet peut être fourni directement à l'API OpenAI.
Fonctions axées sur les tâches
L'aspiration consiste à fournir un ensemble de fonctions faciles à rappeler pour les tâches communes, par conséquent, tout commence par ai... Toutes les fonctions doivent renvoyer un emballage léger avec des réponses résultantes. À l'heure actuelle, il ne peut s'agir que AIMessage (pour toute réponse textuelle) ou d'un DataMessage générique (pour des données structurées comme les incorporations).
Étant donné les différences dans les API du modèle et leurs paramètres (par exemple, API OpenAI vs olllama), les fonctions de tâche sont envoyées sur schema::AbstractPromptSchema comme premier argument.
Voir src/llm_openai.jl pour un exemple d'implémentation. Chaque nouvelle interface serait définie dans un fichier distinct llm_<interface>.jl .
Les modèles d'Openai sont à l'avant-garde de la recherche sur l'IA et fournissent des capacités robustes et de pointe pour de nombreuses tâches.
Il y aura des situations qui ne peuvent pas l'utiliser (par exemple, la confidentialité, le coût, etc.). Dans ce cas, vous pouvez utiliser des modèles locaux (par exemple, olllama) ou d'autres API (par exemple, anthropique).
Remarque: Pour commencer avec Ollama.ai, voir le guide de configuration de la section Olllama ci-dessous.
Il existe de nombreuses alternatives:
Au moment de la rédaction du moment de la rédaction, Openai n'utilise pas les appels de l'API pour former leurs modèles.
API
OpenAI n'utilise pas de données soumises et générées par notre API pour former des modèles OpenAI ou améliorer l'offre de services d'OpenAI. Afin de soutenir l'amélioration continue de nos modèles, vous pouvez remplir ce formulaire pour vous opter pour partager vos données avec nous. - comment vos données sont utilisées pour améliorer nos modèles
Vous pouvez toujours revérifier les dernières informations sur la façon d'Openai comment nous utilisons votre page de données.
Ressources:
Vous pouvez obtenir votre clé API depuis OpenAI en vous inscrivant à un compte et en accédant à la section API du site Web OpenAI.
Ressources:
Conseil
Réglez toujours les limites de dépenses!
OpenAI vous permet de fixer des limites de dépenses directement sur le tableau de bord de votre compte pour éviter les coûts inattendus.
Un bon début pourrait être une limite douce de 5 $ et une limite dure de 10 $ - vous pouvez toujours l'augmenter plus tard dans le mois.
Ressources:
Si vous utilisez un modèle local (par exemple, avec Olllama), c'est gratuit. Si vous utilisez des API commerciales (par exemple, OpenAI), vous paierez probablement par "jeton" (une unité de sous-mot).
Par exemple, une demande simple avec une question simple et une réponse de 1 phrase en retour ("est la déclaration xyz un commentaire positif") vous coûtera ~ 0,0001 $ (c'est-à-dire un centième de cent)
Cela vaut-il la peine de payer?
Genai est un moyen d'acheter du temps! Vous pouvez payer des cents pour économiser des dizaines de minutes chaque jour.
Poursuivant l'exemple ci-dessus, imaginez que vous avez un tableau avec 200 commentaires. Maintenant, vous pouvez analyser chacun d'eux avec un LLM pour les fonctionnalités / vérifications dont vous avez besoin. En supposant que le prix par appel était de 0,0001 $, vous paieriez 2 cents pour le travail et économisez 30 à 60 minutes de votre temps!
Ressources:
Il s'agit d'un guide pour la clé API d'Openai, mais il fonctionne pour toute autre clé API dont vous pourriez avoir besoin (par exemple, MISTRAL_API_KEY pour API Mistralai).
Pour utiliser l'API OpenAI avec IncitStools.jl, définissez votre clé API comme variable d'environnement:
ENV [ " OPENAI_API_KEY " ] = " your-api-key "En tant que ponctuel, vous pouvez:
export OPENAI_API_KEY = <your key>setup.jl (assurez-vous de ne pas le commettre à GitHub!) Assurez-vous de démarrer Julia à partir de la même fenêtre de terminal où vous définissez la variable. Vérifiez facile dans Julia, exécutez ENV["OPENAI_API_KEY"] et vous devriez voir votre clé!
Une meilleure façon:
~/.zshrc ). Il sera automatiquement chargé chaque fois que vous lancez le terminal Nous prenons également en charge les préférences.jl, afin que vous puissiez simplement exécuter: PromptingTools.set_preferences!("OPENAI_API_KEY"=>"your-api-key") et il sera persisté à travers les sessions. Pour voir les préférences actuelles, exécutez PromptingTools.get_preferences("OPENAI_API_KEY") .
Faites attention à ne pas commettre LocalPreferences.toml à github, car il montrerait votre clé d'API au monde!
Ressources:
aigenerate ( api_kwargs )Voir la référence de l'API OpenAI pour plus d'informations.
Pour un accès facile de n'importe où, ajoutez des incit-tools dans votre startup.jl (peut être trouvé dans ~/.julia/config/startup.jl ).
Ajouter l'extrait suivant:
using PromptingTools
const PT = PromptingTools # to access unexported functions and types
Maintenant, vous pouvez simplement utiliser ai"Help me do X to achieve Y" à partir de n'importe quelle session de REP!
L'éthique de l'incidencetools.jl est de vous permettre d'utiliser le modèle que vous souhaitez, qui comprend des LLM open source. Le plus populaire et le plus facile à configurer est Ollama.ai - voir ci-dessous pour plus d'informations.
Ollama exécute un service d'arrière-plan hébergeant des LLMS auxquels vous pouvez accéder via une API simple. Il est particulièrement utile lorsque vous travaillez avec des données sensibles qui ne doivent être envoyées nulle part.
L'installation est très facile, il suffit de télécharger la dernière version ici.
Une fois que vous l'avez installé, lancez simplement l'application et vous êtes prêt à partir!
Pour vérifier s'il fonctionne, accédez à votre navigateur et ouvrez 127.0.0.1:11434 . Vous devriez voir le message "Olllama est en cours d'exécution". Alternativement, vous pouvez exécuter ollama serve dans votre terminal et vous recevrez un message qu'il fonctionne déjà.
Il existe de nombreux modèles disponibles dans la bibliothèque Ollama, notamment LLAMA2, Codellama, SQLCoder ou My Personal préféré openhermes2.5-mistral .
Téléchargez de nouveaux modèles avec ollama pull <model_name> (par exemple, ollama pull openhermes2.5-mistral ).
Afficher les modèles actuellement disponibles avec ollama list .
Voir olllama.ai pour plus d'informations.
Le réglage fin est une technique puissante pour adapter un modèle à votre cas d'utilisation spécifique (principalement le format / syntaxe / tâche). Il nécessite un ensemble de données d'exemples, que vous pouvez désormais générer facilement avec IncitStools.jl!
Vous pouvez enregistrer n'importe quelle conversation (vecteur de messages) dans un fichier avec PT.save_conversation("filename.json", conversation) .
Une fois le temps de financement, créez un bundle de conversations à forme de sharegpt (format de fintuning commun) dans un seul fichier .jsonl . Utilisez PT.save_conversations("dataset.jsonl", [conversation1, conversation2, ...]) (remarquez que les "conversations" plurielles dans le nom de la fonction).
Pour un exemple de processus de finotuning de bout en bout, consultez notre projet de sœur Juliallmleaderboard Finetuning Experiment. Il montre le processus de finetuning pour un demi-dollar avec JarvisLabs.ai et Axolotl.
Ceci est une liste de fonctionnalités que j'aimerais voir à l'avenir (sans ordre particulier):
Pour plus d'informations, de contributions ou de questions, veuillez visiter le référentiel Github Incivttools.jl.
Veuillez noter que bien que le CrimingTools.jl vise à offrir une expérience fluide, il s'appuie sur des API externes qui peuvent changer. Restez à l'écoute du référentiel pour les mises à jour et les nouvelles fonctionnalités.
Merci d'avoir choisi Inciblittools.jl pour autonomiser vos applications avec l'IA!