Maison développement back-end Golang Appeler LangChain depuis Go (Partie 1)

Appeler LangChain depuis Go (Partie 1)

Jan 02, 2025 pm 09:29 PM

Calling LangChain from Go (Part 1)

Motivation

Suite à mes tests « vacances » (posts précédents…) sur l'utilisation de Golang et des LLM, je cherchais un moyen simple d'implémenter les appels LangChain en Go, et de préférence en utilisant watsonx.ai.

Heureusement, j'ai trouvé le référentiel Github suivant : https://github.com/tmc/langchaingo (révérence à Travis Cline https://github.com/tmc).

Dans son dépôt, il y a ce dossier spécifique : https://github.com/tmc/langchaingo/blob/main/examples/watsonx-llm-example/watsonx_example.go qui a retenu mon attention !

Alors comme d'habitude j'ai construit un projet et j'ai essayé de le mettre en œuvre et j'ai aussi mis mes propres idées (à ma sauce ?).

Mise en œuvre

Comme d'habitude comme il y a un besoin en variables d'environnement, j'ai mis en place un fichier .env qui est ensuite utilisé dans l'application.

export WATSONX_API_KEY="your-watsonx-api-key"
export WATSONX_PROJECT_ID="your-watsonx-projectid"
# I used the US-SOUTH, could be any other region of IBM Cloud
export SERVICE_URL="https://us-south.ml.cloud.ibm.com" 
Copier après la connexion

Dans un article précédent, j'ai mentionné avoir essayé de compter le nombre de jetons envoyés et reçus d'un LLM. Ce travail est encore en cours, j'ai donc utilisé directement la bibliothèque « tiktoken-go » dans mon application avec l'idée d'y apporter quelques modifications (dans un futur proche ?). Quoi qu'il en soit, dans le cas de mon état d'avancement actuel, cela ne fonctionne pas vraiment, mais c'est là.

Pour l'application elle-même, j'ai utilisé le code de Travis de son référentiel presque tel quel, et je l'ai ajouté et enveloppé avec les fonctionnalités suivantes ;

  • utiliser une boîte de dialogue pour la saisie rapide (? J'adore les boîtes de dialogue ?)
  • «tentative» de compter le nombre de «jetons» envoyés et reçus en retour du LLM. Le code en lui-même est le suivant ;
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "os/exec"
    "runtime"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/dialog"
    "fyne.io/fyne/v2/widget"

    "github.com/joho/godotenv"
    "github.com/pkoukk/tiktoken-go"
    "github.com/tmc/langchaingo/llms"
    "github.com/tmc/langchaingo/llms/watsonx"
)

const (
    _tokenApproximation = 4
)

const (
    _gpt35TurboContextSize   = 4096
    _gpt432KContextSize      = 32768
    _gpt4ContextSize         = 8192
    _textDavinci3ContextSize = 4097
    _textBabbage1ContextSize = 2048
    _textAda1ContextSize     = 2048
    _textCurie1ContextSize   = 2048
    _codeDavinci2ContextSize = 8000
    _codeCushman1ContextSize = 2048
    _textBisonContextSize    = 2048
    _chatBisonContextSize    = 2048
    _defaultContextSize      = 2048
)

// nolint:gochecknoglobals
var modelToContextSize = map[string]int{
    "gpt-3.5-turbo":    _gpt35TurboContextSize,
    "gpt-4-32k":        _gpt432KContextSize,
    "gpt-4":            _gpt4ContextSize,
    "text-davinci-003": _textDavinci3ContextSize,
    "text-curie-001":   _textCurie1ContextSize,
    "text-babbage-001": _textBabbage1ContextSize,
    "text-ada-001":     _textAda1ContextSize,
    "code-davinci-002": _codeDavinci2ContextSize,
    "code-cushman-001": _codeCushman1ContextSize,
}

var tokens int

func runCmd(name string, arg ...string) {
    cmd := exec.Command(name, arg...)
    cmd.Stdout = os.Stdout
    cmd.Run()
}

func ClearTerminal() {
    switch runtime.GOOS {
    case "darwin":
        runCmd("clear")
    case "linux":
        runCmd("clear")
    case "windows":
        runCmd("cmd", "/c", "cls")
    default:
        runCmd("clear")
    }
}

func promptEntryDialog() string {

    var promptEntry string

    // Create a new Fyne application
    myApp := app.New()
    myWindow := myApp.NewWindow("Prompt Entry Dialog")

    // Variable to store user input
    var userInput string

    // Button to show the dialog
    button := widget.NewButton("Click to Enter your prompt's text", func() {
        entry := widget.NewEntry()
        dialog.ShowCustomConfirm("Input Dialog", "OK", "Cancel", entry, func(confirm bool) {
            if confirm {
                userInput = entry.Text
                promptEntry = userInput
                fmt.Println("User Input:", userInput) // Print to the console
                myWindow.Close()
            }
        }, myWindow)
    })

    // Add the button to the window
    myWindow.SetContent(container.NewVBox(
        widget.NewLabel("Click the button below to enter text:"),
        button,
    ))

    // Set the window size and run the application
    myWindow.Resize(fyne.NewSize(400, 200))
    myWindow.ShowAndRun()
    return promptEntry
}

func CountTokens(model, text string, inorout string) int {
    var txtLen int
    e, err := tiktoken.EncodingForModel(model)
    if err != nil {
        e, err = tiktoken.GetEncoding("gpt2")
        if err != nil {
            log.Printf("[WARN] Failed to calculate number of tokens for model, falling back to approximate count")
            txtLen = len([]rune(text))

            fmt.Println("Guessed tokens for the "+inorout+" text:", txtLen/_tokenApproximation)

            return txtLen
        }
    }
    return len(e.Encode(text, nil, nil))
}

func GetModelContextSize(model string) int {
    contextSize, ok := modelToContextSize[model]
    if !ok {
        return _defaultContextSize
    }
    return contextSize
}

func CalculateMaxTokens(model, text string) int {
    return GetModelContextSize(model) - CountTokens(model, text, text)
}

func main() {
    var prompt, model string

    // read the '.env' file
    err := godotenv.Load()
    if err != nil {
        log.Fatal("Error loading .env file")
    }

    ApiKey := os.Getenv("WATSONX_API_KEY")
    if ApiKey == "" {
        log.Fatal("WATSONX_API_KEY environment variable is not set")
    }
    ServiceURL := os.Getenv("SERVICE_URL")
    if ServiceURL == "" {
        log.Fatal("SERVICE_URL environment variable is not set")
    }
    ProjectID := os.Getenv("WATSONX_PROJECT_ID")
    if ProjectID == "" {
        log.Fatal("WATSONX_PROJECT_ID environment variable is not set")
    }

    // LLM from watsonx.ai
    model = "ibm/granite-13b-instruct-v2"
    // model = "meta-llama/llama-3-70b-instruct"

    llm, err := watsonx.New(
        model,
        //// Optional parameters: to be implemented if needed - Not used at this stage but all ready
        // wx.WithWatsonxAPIKey(ApiKey),
        // wx.WithWatsonxProjectID("YOUR WATSONX PROJECT ID"),
    )

    if err != nil {
        log.Fatal(err)
    }
    ctx := context.Background()

    prompt = promptEntryDialog()

    // for the output visibility on the consol - getting rid of system messages
    ClearTerminal()

    // Use the entry variable here
    fmt.Println("Calling the llm with the user's prompt:", prompt)

    tokens = CountTokens(model, prompt, "input")

    completion, err := llms.GenerateFromSinglePrompt(
        ctx,
        llm,
        prompt,
        llms.WithTopK(10),
        llms.WithTopP(0.95),
        llms.WithSeed(25),
    )
    // Check for errors
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(completion)

    tokens = CountTokens(model, completion, "output")

}

Copier après la connexion

Ce qui fonctionne bien car le résultat est affiché ci-dessous.

Calling the llm with the user's prompt: What is the distance in Kilmometers from Earth to Moon?
2024/12/31 11:08:04 [WARN] Failed to calculate number of tokens for model, falling back to approximate count
Guessed tokens for the input text: 13
The distance from Earth to the Moon is about 384,400 kilometers.
2024/12/31 11:08:04 [WARN] Failed to calculate number of tokens for model, falling back to approximate count
Guessed tokens for the output text: 16

#####


Calling the llm with the user's prompt: What is the name of the capital city of France?
2024/12/31 11:39:28 [WARN] Failed to calculate number of tokens for model, falling back to approximate count
Guessed tokens for the input text: 11
Paris
2024/12/31 11:39:28 [WARN] Failed to calculate number of tokens for model, falling back to approximate count
Guessed tokens for the output text: 1
Copier après la connexion

Voilà !

Prochaines étapes

J'implémenterais les fonctionnalités suivantes pour la version 0.2 ;

  • Proposer le modèle que l'utilisateur souhaite utiliser,
  • Une façon plus précise de déterminer le nombre de jetons,
  • Une véritable implémentation de LangChain.

Conclusion

Ceci est un reflet très simple de mon travail autour de l'appel de LangChain à partir d'une application Go.

Restez à l'écoute pour en savoir plus à venir ?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Quelles sont les vulnérabilités de Debian OpenSSL Quelles sont les vulnérabilités de Debian OpenSSL Apr 02, 2025 am 07:30 AM

OpenSSL, en tant que bibliothèque open source largement utilisée dans les communications sécurisées, fournit des algorithmes de chiffrement, des clés et des fonctions de gestion des certificats. Cependant, il existe des vulnérabilités de sécurité connues dans sa version historique, dont certaines sont extrêmement nocives. Cet article se concentrera sur les vulnérabilités et les mesures de réponse communes pour OpenSSL dans Debian Systems. DebianopenSSL CONNUTS Vulnérabilités: OpenSSL a connu plusieurs vulnérabilités graves, telles que: la vulnérabilité des saignements cardiaques (CVE-2014-0160): cette vulnérabilité affecte OpenSSL 1.0.1 à 1.0.1F et 1.0.2 à 1.0.2 Versions bêta. Un attaquant peut utiliser cette vulnérabilité à des informations sensibles en lecture non autorisées sur le serveur, y compris les clés de chiffrement, etc.

Comment spécifier la base de données associée au modèle de Beego ORM? Comment spécifier la base de données associée au modèle de Beego ORM? Apr 02, 2025 pm 03:54 PM

Dans le cadre du cadre de beegoorm, comment spécifier la base de données associée au modèle? De nombreux projets Beego nécessitent que plusieurs bases de données soient opérées simultanément. Lorsque vous utilisez Beego ...

Transformant du développement frontal au développement back-end, est-il plus prometteur d'apprendre Java ou Golang? Transformant du développement frontal au développement back-end, est-il plus prometteur d'apprendre Java ou Golang? Apr 02, 2025 am 09:12 AM

Chemin d'apprentissage du backend: le parcours d'exploration du front-end à l'arrière-end en tant que débutant back-end qui se transforme du développement frontal, vous avez déjà la base de Nodejs, ...

Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Comment résoudre le problème de conversion de type user_id lors de l'utilisation du flux redis pour implémenter les files d'attente de messages dans le langage Go? Apr 02, 2025 pm 04:54 PM

Le problème de l'utilisation de Redessstream pour implémenter les files d'attente de messages dans le langage GO consiste à utiliser le langage GO et redis ...

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Apr 02, 2025 pm 05:09 PM

Que dois-je faire si les étiquettes de structure personnalisées à Goland ne sont pas affichées? Lorsque vous utilisez Goland pour le développement du langage GO, de nombreux développeurs rencontreront des balises de structure personnalisées ...

Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Quelles bibliothèques sont utilisées pour les opérations du numéro de point flottantes en Go? Apr 02, 2025 pm 02:06 PM

La bibliothèque utilisée pour le fonctionnement du numéro de point flottante dans le langage go présente comment s'assurer que la précision est ...

Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Quel est le problème avec le fil de file d'attente dans GO's Crawler Colly? Apr 02, 2025 pm 02:09 PM

Problème de threading de file d'attente dans Go Crawler Colly explore le problème de l'utilisation de la bibliothèque Crawler Crawler dans le langage Go, les développeurs rencontrent souvent des problèmes avec les threads et les files d'attente de demande. � ...

Comment configurer l'expansion automatique de MongoDB sur Debian Comment configurer l'expansion automatique de MongoDB sur Debian Apr 02, 2025 am 07:36 AM

Cet article présente comment configurer MongoDB sur Debian System pour réaliser une expansion automatique. Les étapes principales incluent la configuration de l'ensemble de répliques MongoDB et de la surveillance de l'espace disque. 1. Installation de MongoDB Tout d'abord, assurez-vous que MongoDB est installé sur le système Debian. Installez à l'aide de la commande suivante: SudoaptupDaSudoaptInstall-myongoDB-Org 2. Configuration de la réplique MongoDB Ensemble de répliques MongoDB assure la haute disponibilité et la redondance des données, ce qui est la base de la réalisation d'une expansion de capacité automatique. Démarrer le service MongoDB: Sudosystemctlstartmongodsudosys

See all articles