GoでChatGPT
terminalから呼び出せるGPTクライアントをgolangで作成します。
main関数
main.go
package main
import (
"bufio"
"fmt"
"os"
"./gpt"
)
func main() {
for {
fmt.Print("> ")
scanner := bufio.NewScanner(os.Stdin)
if scanner.Scan() {
input := scanner.Text()
if input == "exit" {
fmt.Println("exit!")
break
}
gpt.Call(input)
}
}
}
exitと入力したら終了します。
gpt/call.go
package gpt
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
"github.com/joho/godotenv"
)
var messages []Message
type GPT struct {
apiKey string
endpoint string
}
func NewGPT() *GPT {
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
return &GPT{
apiKey: os.Getenv("OPENAI_API_KEY"),
endpoint: "https://api.openai.com/v1/chat/completions",
}
}
func Call(question string) string {
g := NewGPT()
messages = append(messages, Message{
Role: "user",
Content: question,
})
response := g.getOpenAIResponse(g.apiKey)
fmt.Println(response.Choices[0].Messages.Content)
print("\n")
return response.Choices[0].Messages.Content
}
func (g GPT) getOpenAIResponse(apiKey string) OpenaiResponse {
requestBody := OpenaiRequest{
Model: "gpt-3.5-turbo",
Messages: messages,
}
requestJSON, _ := json.Marshal(requestBody)
req, err := http.NewRequest("POST", g.endpoint, bytes.NewBuffer(requestJSON))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer func(Body io.ReadCloser) {
err := Body.Close()
if err != nil {
panic(err)
}
}(resp.Body)
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
var response OpenaiResponse
err = json.Unmarshal(body, &response)
if err != nil {
println("Error: ", err.Error())
return OpenaiResponse{}
}
messages = append(messages, Message{
Role: "assistant",
Content: response.Choices[0].Messages.Content,
})
return response
}
type OpenaiRequest struct {
Model string `json:"model"`
Messages []Message `json:"messages"`
}
type OpenaiResponse struct {
ID string `json:"id"`
Object string `json:"object"`
Created int `json:"created"`
Choices []Choice `json:"choices"`
Usages Usage `json:"usage"`
}
type Choice struct {
Index int `json:"index"`
Messages Message `json:"message"`
FinishReason string `json:"finish_reason"`
}
type Message struct {
Role string `json:"role"`
Content string `json:"content"`
}
type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
過去のやり取りを与えるといった実装はしていません。
あまり良いライブラリがなかったので、標準のnet/http
でAPIを叩くようにしました。
使用しているサードパーティ製ライブラリは環境変数を.env
から取得するための
"github.com/joho/godotenv"
だけです。
go get "github.com/joho/godotenv"
実行
$ go run main.go
> おはよう
おはようございます!朝から元気ですか?何かお手伝いできることはありますか?
>
よさそうです。
> golangで.envファイルから環境変数を取得するにはどうしたらいいですか?
golangで.envファイルから環境変数を取得するには、`godotenv`というパッケージを使用するのが一般的です。以下の手順に従って実装してみてください。
1. `go get github.com/joho/godotenv`コマンドを実行して、`godotenv`パッケージをインストールします。
2. コード内で`godotenv`パッケージをインポートします。
```go
import (
"github.com/joho/godotenv"
"log"
"os"
)
-
.env
ファイルを読み込む前にgodotenv.Load()
関数を呼び出します。err := godotenv.Load() if err != nil { log.Fatal("Error loading .env file") }
-
環境変数を使用したい場所で
os.Getenv()
関数を使用してアクセスします。dbUser := os.Getenv("DB_USER") dbPassword := os.Getenv("DB_PASSWORD")
.env
ファイルには以下のように環境変数と値を設定します。DB_USER=your_db_user DB_PASSWORD=your_db_password
このようにすることで、.env
ファイルから環境変数を取得できます。ただし、godotenv
は開発時に便利ですが、本番環境ではセキュリティリスクとなる可能性があるため、適切に管理する必要があります。
CLI化
どこのディレクトリからでも使いたいので、ビルドして、パスが通ったディレクトリへ移動させます。
$ go build -o gpt-client
$ mv gpt-client /usr/local/bin/
$ which gpt-client
/usr/local/bin/gpt-client
$ gpt-client
>
よさそうです。
参考