我最近使用 Golang 建立了一個名為 GenCLI 的人工智慧驅動的 CLI,您可以從中以文字格式提出問題,或者給它一個圖像並從終端詢問有關它的詳細資訊。如果您覺得這很有趣,那麼這個部落格適合您。在此,我們完全從頭開始建立 CLI,並使用 Google 的 Gemini API 為其賦予 AI 功能。如果您想查看我的 GenCLI,請點擊連結是的,它是開源的。
讓我們一步一步來了解每個過程。
建立一個資料夾並在您最喜歡的 IDE/編輯器中開啟它。我正在使用 VS Code 並將資料夾命名為 go-ai。現在透過執行指令 go mod init
go mod init github.com/Pradumnasaraf/go-ai
完成後,將會建立一個 go.mod。
儘管我們可以手動建立並完成建置 CLI 的所有操作。但 Cobra Package 的優點在於它有 CLI,可以為 CLI 產生結構、產生檔案和安裝套件。這將幫助我們加快流程並減少錯誤。若要安裝 Cobra CLI 工具,請使用下列指令:
go install github.com/spf13/cobra-cli@latest
完成此操作後,您可以透過在終端機中綁定 cobra-cli 來檢查該工具是否已安裝,您將獲得可用清單。現在執行 cobra-cli init 來設定專案。運行後會自動建立cmd資料夾、go.sum和main.go檔案。若要測試它是否正常執行,請執行 main.go。您將在終端機中看到有關 CLI 的輸出(如下面的螢幕截圖)
要通訊並使用 Google 的 Gemini API,首先我們需要安裝 Gemini Golang SKD 套件,為此請執行以下指令。
go get github.com/google/generative-ai-go
現在就像其他 API 一樣,我們需要一個 API 金鑰。要得到這個頭在這裡 https://aistudio.google.com/app/apikey 並得到它。它是免費的,您可以在 30 秒內獲得它。一旦你獲得了 API 金鑰集,就可以透過執行以下命令來設定環境變數:
export GEMINI_API_KEY=<YOUR_API_KEY>
此方法的問題是環境變數僅在當前會話中存在,當您關閉終端時它就會消失。為了避免此問題,請將 export 命令新增至 shell 設定檔中,例如 .bashrc、.bash_profile 或 .zshrc(取決於您的 shell)。這樣,您就可以從系統中的任何位置存取 CLI。
現在,是時候為 CLI 建立一個子命令,而不是直接將邏輯寫入 root.go。這樣做的原因是,如果將來我們想要包含更多功能和更多子命令,我們可以簡單地透過添加更多子命令來添加,而不是阻止根命令。如果你不明白這一點,別擔心,繼續往下看,事情就會清楚的。
要建立子指令,Cobra CLI 提供了一個 add 指令來建立它。為此,請執行以下命令。這裡search將成為一個子命令。你可以選擇任何你喜歡的。
cobra-cli add search
執行後,將在 cmd 目錄下建立一個新文件,其中包含所有這些預先填入的程式碼。在程式碼中,我們將變數 searchCmd 初始化為指向 cobra.Command 結構的指針,並為子命令名稱、用途等欄位提供值。每當我們執行子命令時,Run: 中的函數就會被觸發。命令。另外,如果您看到我們在 init 函數中為 root 命令新增了一個命令(子命令)。完整的程式碼應該是這樣的。
package cmd import ( "fmt" "github.com/spf13/cobra" ) // searchCmd represents the search command var searchCmd = &cobra.Command{ Use: "search", Short: "A brief description of your command", Long: `A longer description that spans multiple lines and likely contains examples`, Run: func(cmd *cobra.Command, args []string) { fmt.Println("search called") }, } func init() { rootCmd.AddCommand(searchCmd) }
要檢查子命令“search”是否按預期工作,現在使用“search”命令運行 CLI,您將在終端中看到“search called”列印。
go run main.go search
現在,讓我們處理 API 方面的工作。讓我們匯入 Google Gemini API 的套件以及日誌記錄和作業系統層級任務所需的其他套件。這是完整的清單。
import ( "context" "log" "os" "github.com/google/generative-ai-go/genai" "github.com/spf13/cobra" "google.golang.org/api/option" )
然後讓我們新增一個名為 getResponse 的函式。該函數將幫助我們與 Gemini API 進行通信,獲取回應並列印它。另外,如果您看到我們對提示文字進行了硬編碼 - “寫一個關於人工智能和魔法的故事”,請不要擔心,我們會更改它,但首先讓我們讓它發揮作用:)。這是一個完整的函數程式碼,將其新增到您的 init 函數下方。您將在 Gemini 網站上找到相同的啟動程式碼。
func getResponse() { ctx := context.Background() client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY"))) if err != nil { log.Fatal(err) } defer client.Close() model := client.GenerativeModel("gemini-1.5-flash") resp, err := model.GenerateContent(ctx, genai.Text("Write a story about a AI and magic")) if err != nil { log.Fatal(err) } fmt.Println(resp.Candidates[0].Content.Parts[0]) }
Now let's add getResponse function to the in the field Run: function. So that when we run the sun command it will call getResponse function. Now the code will look like this.
package cmd import ( "context" "fmt" "log" "os" "github.com/google/generative-ai-go/genai" "github.com/spf13/cobra" "google.golang.org/api/option" ) // searchCmd represents the search command var searchCmd = &cobra.Command{ Use: "search", Short: "A brief description of your command", // Added the getResponse() function Run: func(cmd *cobra.Command, args []string) { getResponse() }, } func init() { rootCmd.AddCommand(searchCmd) } func getResponse() { ctx := context.Background() client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY"))) if err != nil { log.Fatal(err) } defer client.Close() model := client.GenerativeModel("gemini-1.5-flash") resp, err := model.GenerateContent(ctx, genai.Text("Write a story about a AI and magic")) if err != nil { log.Fatal(err) } fmt.Println(resp.Candidates[0].Content.Parts[0]) }
If you getting a red squiggly line under the imported package names run go mod tidy. It will install the missing package and do a cleanup. Now, again execute the go run main.go search. This time you will get a response from the API for the Prompt we hardcoded, i.e, "Write a story about a AI and magic"
In case you are encountering the below error check if your environment variable is set properly with the right name. You can check by executing the printenv command in your terminal and see if it's present there or not.
Once everything is working, let’s make the prompt dynamic so that we don’t have to hardcode the prompt directly into the code and we provide it via the terminal.
To do that, add an ARG: field to the searchCmd struct so that the user at least needs to enter an argument after the sub-command. Also, we will modify the getResponse function to accept a slice of data because args will be in the slice format, and we will use the strings package to convert it into a sentence.
Lastly, replace the hardcoded text in genai.Text() with the userArgs variable we created to convert the slice into a sentence. This is how the complete code will look like; I have commented above on the changes we have to make for better understanding.
package cmd import ( "context" "fmt" "log" "os" "strings" // import strings package "github.com/google/generative-ai-go/genai" "github.com/spf13/cobra" "google.golang.org/api/option" ) var searchCmd = &cobra.Command{ Use: "search", Short: "A brief description of your command", Args: cobra.MinimumNArgs(1), // Minimum 1 arg required Run: func(cmd *cobra.Command, args []string) { getResponse(args) }, } func init() { rootCmd.AddCommand(searchCmd) } // Function can now accept slice parameter func getResponse(args []string) { // Creating a sentence out of a slice userArgs := strings.Join(args[0:], " ") ctx := context.Background() client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY"))) if err != nil { log.Fatal(err) } defer client.Close() model := client.GenerativeModel("gemini-1.5-flash") // change the hardcoded text to userArgs variable resp, err := model.GenerateContent(ctx, genai.Text(userArgs)) if err != nil { log.Fatal(err) } fmt.Println(resp.Candidates[0].Content.Parts[0]) }
If you execute the go run main search now, it will give you an error message in the terminal saying at least one arg is required. This means our code is working perfectly.
Now let's execute the command the right way giving it an argument - a prompt/question.
As you can see, it provided us with the answer. We pass the prompt in quotes so that we can add special characters like "?", ".", etc. So here it is, a fully functional AI-powered CLI.
Now, if you want to publish the package so that your CLI can directly execute commands and be used from anywhere in the system, it’s very simple to do that. First, push your changes to GitHub and then head over to the URL https://pkg.go.dev/github.com/
Once it’s live, you can simply download the CLI by using the go install command:
go install <repo-url> go install github.com/Pradumnasaraf/go-ai@latest
And directly use the CLI with commands like go-ai, go-ai search, etc. If you encounter the error saying command not found: go-ai after running it, you need to add $GOPATH/bin to your $PATH environment variable. Refer to this guide for that.
That's it for this blog. This was a little longer than the blogs I usually write. I'm glad you're still reading and made it to the end—thank you so much for your support. I sometimes share tips on Twitter. You can connect with me there.
以上是使用 Golang 和 Google Gemini 建立 AI 支援的 CLI的詳細內容。更多資訊請關注PHP中文網其他相關文章!