Calling LangChain from Go (Part 1)
Motivation
Following my “holiday” tests (previous posts…) on using Golang and LLMs, I was looking for an easy way to implement LangChain calling in Go, and preferably using watsonx.ai.
Luckily I found the following Github repository: https://github.com/tmc/langchaingo (curtsy to Travis Cline https://github.com/tmc).
In his repository, there is this specific folder: https://github.com/tmc/langchaingo/blob/main/examples/watsonx-llm-example/watsonx_example.go which caught my attention!
So as usual I built a project and tried to implement it and also put my own ideas (à ma sauce ?).
Implementation
As usual as there is a need on environment variables, I set up an .env file which is later used in the app.
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"
In a previous post I mentioned trying to count the number of tokens sent to and received from a LLM. That work is still WIP, so I used directly the “tiktoken-go” library inside my app with an idea of making some changes to it (in a near future?). Anyways, in the case of my current state of progress it does not really work, but it is there.
For the app by itself, I used Travis’ code from his repository almost as is, and added and wrapped it with the following features;
- using a dialog box for the prompt input (? I love dialog-boxes ?)
- “attempt” to count the number of “tokens” sent to and received back from the LLM. The code by itself is the following;
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") }
Which works fine as the output is shown below.
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
Voilà!
Next steps
I would implement the following features for the version 0.2;
- Proposing the model the user wants to use,
- A more accurate way to determine the # of tokens,
- Some real LangChain implementation.
Conclusion
This is a very simple reflection of my work around calling LangChain from a Go application.
Stay tuned for more to come ?
The above is the detailed content of Calling LangChain from Go (Part 1). For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

OpenSSL, as an open source library widely used in secure communications, provides encryption algorithms, keys and certificate management functions. However, there are some known security vulnerabilities in its historical version, some of which are extremely harmful. This article will focus on common vulnerabilities and response measures for OpenSSL in Debian systems. DebianOpenSSL known vulnerabilities: OpenSSL has experienced several serious vulnerabilities, such as: Heart Bleeding Vulnerability (CVE-2014-0160): This vulnerability affects OpenSSL 1.0.1 to 1.0.1f and 1.0.2 to 1.0.2 beta versions. An attacker can use this vulnerability to unauthorized read sensitive information on the server, including encryption keys, etc.

The library used for floating-point number operation in Go language introduces how to ensure the accuracy is...

Queue threading problem in Go crawler Colly explores the problem of using the Colly crawler library in Go language, developers often encounter problems with threads and request queues. �...

Backend learning path: The exploration journey from front-end to back-end As a back-end beginner who transforms from front-end development, you already have the foundation of nodejs,...

The difference between string printing in Go language: The difference in the effect of using Println and string() functions is in Go...

Under the BeegoORM framework, how to specify the database associated with the model? Many Beego projects require multiple databases to be operated simultaneously. When using Beego...

The problem of using RedisStream to implement message queues in Go language is using Go language and Redis...

This article introduces a variety of methods and tools to monitor PostgreSQL databases under the Debian system, helping you to fully grasp database performance monitoring. 1. Use PostgreSQL to build-in monitoring view PostgreSQL itself provides multiple views for monitoring database activities: pg_stat_activity: displays database activities in real time, including connections, queries, transactions and other information. pg_stat_replication: Monitors replication status, especially suitable for stream replication clusters. pg_stat_database: Provides database statistics, such as database size, transaction commit/rollback times and other key indicators. 2. Use log analysis tool pgBadg
