golang集成OpenAI ChatGPT、DALL·E和Whisper API功能插件库go-openai的使用
Go OpenAI 库使用指南
这个库提供了非官方的Go客户端来访问OpenAI API。支持以下功能:
- ChatGPT 4o, o1
- GPT-3, GPT-4
- DALL·E 2, DALL·E 3, GPT Image 1
- Whisper
安装
go get github.com/sashabaranov/go-openai
当前go-openai需要Go 1.18或更高版本。
使用示例
ChatGPT基础示例
package main
import (
"context"
"fmt"
openai "github.com/sashabaranov/go-openai"
)
func main() {
client := openai.NewClient("your token")
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: "Hello!",
},
},
},
)
if err != nil {
fmt.Printf("ChatCompletion error: %v\n", err)
return
}
fmt.Println(resp.Choices[0].Message.Content)
}
获取OpenAI API密钥
- 访问OpenAI网站
- 如果没有账号,点击"Sign Up"创建。如果有账号,点击"Log In"
- 登录后,导航到API密钥管理页面
- 点击"Create new secret key"
- 输入新密钥的名称,然后点击"Create secret key"
- 新API密钥将显示。使用此密钥与OpenAI API交互
注意:您的API密钥是敏感信息。不要与任何人分享。
其他示例
ChatGPT流式响应
package main
import (
"context"
"errors"
"fmt"
"io"
openai "github.com/sashabaranov/go-openai"
)
func main() {
c := openai.NewClient("your token")
ctx := context.Background()
req := openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
MaxTokens: 20,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: "Lorem ipsum",
},
},
Stream: true,
}
stream, err := c.CreateChatCompletionStream(ctx, req)
if err != nil {
fmt.Printf("ChatCompletionStream error: %v\n", err)
return
}
defer stream.Close()
fmt.Printf("Stream response: ")
for {
response, err := stream.Recv()
if errors.Is(err, io.EOF) {
fmt.Println("\nStream finished")
return
}
if err != nil {
fmt.Printf("\nStream error: %v\n", err)
return
}
fmt.Printf(response.Choices[0].Delta.Content)
}
}
GPT-3补全
package main
import (
"context"
"fmt"
openai "github.com/sashabaranov/go-openai"
)
func main() {
c := openai.NewClient("your token")
ctx := context.Background()
req := openai.CompletionRequest{
Model: openai.GPT3Babbage002,
MaxTokens: 5,
Prompt: "Lorem ipsum",
}
resp, err := c.CreateCompletion(ctx, req)
if err != nil {
fmt.Printf("Completion error: %v\n", err)
return
}
fmt.Println(resp.Choices[0].Text)
}
语音转文本(Whisper)
package main
import (
"context"
"fmt"
openai "github.com/sashabaranov/go-openai"
)
func main() {
c := openai.NewClient("your token")
ctx := context.Background()
req := openai.AudioRequest{
Model: openai.Whisper1,
FilePath: "recording.mp3",
}
resp, err := c.CreateTranscription(ctx, req)
if err != nil {
fmt.Printf("Transcription error: %v\n", err)
return
}
fmt.Println(resp.Text)
}
DALL·E 2图像生成
package main
import (
"bytes"
"context"
"encoding/base64"
"fmt"
openai "github.com/sashabaranov/go-openai"
"image/png"
"os"
)
func main() {
c := openai.NewClient("your token")
ctx := context.Background()
// 通过链接获取示例图像
reqUrl := openai.ImageRequest{
Prompt: "Parrot on a skateboard performs a trick, cartoon style, natural light, high detail",
Size: openai.CreateImageSize256x256,
ResponseFormat: openai.CreateImageResponseFormatURL,
N: 1,
}
respUrl, err := c.CreateImage(ctx, reqUrl)
if err != nil {
fmt.Printf("Image creation error: %v\n", err)
return
}
fmt.Println(respUrl.Data[0].URL)
// 示例图像作为base64
reqBase64 := openai.ImageRequest{
Prompt: "Portrait of a humanoid parrot in a classic costume, high detail, realistic light, unreal engine",
Size: openai.CreateImageSize256x256,
ResponseFormat: openai.CreateImageResponseFormatB64JSON,
N: 1,
}
respBase64, err := c.CreateImage(ctx, reqBase64)
if err != nil {
fmt.Printf("Image creation error: %v\n", err)
return
}
imgBytes, err := base64.StdEncoding.DecodeString(respBase64.Data[0].B64JSON)
if err != nil {
fmt.Printf("Base64 decode error: %v\n", err)
return
}
r := bytes.NewReader(imgBytes)
imgData, err := png.Decode(r)
if err != nil {
fmt.Printf("PNG decode error: %v\n", err)
return
}
file, err := os.Create("example.png")
if err != nil {
fmt.Printf("File creation error: %v\n", err)
return
}
defer file.Close()
if err := png.Encode(file, imgData); err != nil {
fmt.Printf("PNG encode error: %v\n", err)
return
}
fmt.Println("The image was saved as example.png")
}
配置代理
config := openai.DefaultConfig("token")
proxyUrl, err := url.Parse("http://localhost:{port}")
if err != nil {
panic(err)
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
}
config.HTTPClient = &http.Client{
Transport: transport,
}
c := openai.NewClientWithConfig(config)
结构化输出
package main
import (
"context"
"fmt"
"log"
"github.com/sashabaranov/go-openai"
"github.com/sashabaranov/go-openai/jsonschema"
)
func main() {
client := openai.NewClient("your token")
ctx := context.Background()
type Result struct {
Steps []struct {
Explanation string `json:"explanation"`
Output string `json:"output"`
} `json:"steps"`
FinalAnswer string `json:"final_answer"`
}
var result Result
schema, err := jsonschema.GenerateSchemaForType(result)
if err != nil {
log.Fatalf("GenerateSchemaForType error: %v", err)
}
resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
Model: openai.GPT4oMini,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: "You are a helpful math tutor. Guide the user through the solution step by step.",
},
{
Role: openai.ChatMessageRoleUser,
Content: "how can I solve 8x + 7 = -23",
},
},
ResponseFormat: &openai.ChatCompletionResponseFormat{
Type: openai.ChatCompletionResponseFormatTypeJSONSchema,
JSONSchema: &openai.ChatCompletionResponseFormatJSONSchema{
Name: "math_reasoning",
Schema: schema,
Strict: true,
},
},
})
if err != nil {
log.Fatalf("CreateChatCompletion error: %v", err)
}
err = schema.Unmarshal(resp.Choices[0].Message.Content, &result)
if err != nil {
log.Fatalf("Unmarshal schema error: %v", err)
}
fmt.Println(result)
}
常见问题
为什么在温度设为0时,相同问题会得到不同答案?
即使在温度字段设为0时,也不能保证总是得到相同的响应。有几个因素会影响结果:
- Go OpenAI行为:当在Go OpenAI中将温度字段设为0时,omitempty标签会导致该字段从请求中移除。因此,OpenAI API会应用默认值1。
- 输入/输出的令牌数量:如果输入和输出中有大量令牌,即使温度设为0,仍可能出现非确定性行为。特别是当使用约32k令牌时,即使温度为0,非确定性行为的可能性也最高。
解决方法:
- 使用新的seed参数与system_fingerprint响应字段,结合温度管理。
- 尝试使用math.SmallestNonzeroFloat32:在温度字段中指定math.SmallestNonzeroFloat32而不是0,可以模拟设为0的行为。
- 限制令牌数量:通过限制输入和输出中的令牌数量,特别是避免接近32k令牌的大型请求,可以降低非确定性行为的风险。
Go OpenAI是否提供令牌计数方法?
不,Go OpenAI不提供令牌计数功能,并且未来也没有计划提供此功能。但是,如果有一种零依赖的方式实现令牌计数功能,可能会将其合并到Go OpenAI中。否则,更适合在专用库或存储库中实现它。
贡献
遵循贡献指南,我们希望确保您的贡献能够顺利高效地进行。
致谢
我们要向该项目的贡献者和赞助商表示最深切的感谢。
更多关于golang集成OpenAI ChatGPT、DALL·E和Whisper API功能插件库go-openai的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang集成OpenAI ChatGPT、DALL·E和Whisper API功能插件库go-openai的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用go-openai库集成OpenAI API功能
go-openai是一个优秀的Golang库,可以方便地集成OpenAI的各种API功能,包括ChatGPT、DALL·E和Whisper。下面我将详细介绍如何使用这个库。
安装
首先安装go-openai库:
go get github.com/sashabaranov/go-openai
初始化客户端
package main
import (
"context"
"fmt"
"os"
openai "github.com/sashabaranov/go-openai"
)
func main() {
// 从环境变量获取API密钥
apiKey := os.Getenv("OPENAI_API_KEY")
if apiKey == "" {
fmt.Println("请设置OPENAI_API_KEY环境变量")
return
}
// 创建OpenAI客户端
client := openai.NewClient(apiKey)
// 使用各种API功能...
}
1. ChatGPT API 使用示例
基本聊天功能
func chatWithGPT(client *openai.Client, prompt string) (string, error) {
resp, err := client.CreateChatCompletion(
context.Background(),
openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: prompt,
},
},
},
)
if err != nil {
return "", err
}
return resp.Choices[0].Message.Content, nil
}
流式响应
func streamChatWithGPT(client *openai.Client, prompt string) error {
req := openai.ChatCompletionRequest{
Model: openai.GPT3Dot5Turbo,
Messages: []openai.ChatCompletionMessage{{Role: openai.ChatMessageRoleUser, Content: prompt}},
Stream: true,
}
stream, err := client.CreateChatCompletionStream(context.Background(), req)
if err != nil {
return err
}
defer stream.Close()
for {
response, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
return err
}
fmt.Printf(response.Choices[0].Delta.Content)
}
return nil
}
2. DALL·E API 使用示例
生成图像
func generateImage(client *openai.Client, prompt string) (string, error) {
req := openai.ImageRequest{
Prompt: prompt,
Size: openai.CreateImageSize1024x1024,
ResponseFormat: openai.CreateImageResponseFormatURL,
N: 1,
}
resp, err := client.CreateImage(context.Background(), req)
if err != nil {
return "", err
}
return resp.Data[0].URL, nil
}
图像编辑
func editImage(client *openai.Client, imagePath, maskPath, prompt string) (string, error) {
image, err := os.Open(imagePath)
if err != nil {
return "", err
}
defer image.Close()
mask, err := os.Open(maskPath)
if err != nil {
return "", err
}
defer mask.Close()
req := openai.ImageEditRequest{
Image: image,
Mask: mask,
Prompt: prompt,
N: 1,
Size: openai.CreateImageSize1024x1024,
}
resp, err := client.CreateEditImage(context.Background(), req)
if err != nil {
return "", err
}
return resp.Data[0].URL, nil
}
3. Whisper API 使用示例
语音转文字
func transcribeAudio(client *openai.Client, audioPath string) (string, error) {
audio, err := os.Open(audioPath)
if err != nil {
return "", err
}
defer audio.Close()
req := openai.AudioRequest{
Model: openai.Whisper1,
FilePath: audioPath,
Reader: audio,
}
resp, err := client.CreateTranscription(context.Background(), req)
if err != nil {
return "", err
}
return resp.Text, nil
}
翻译音频
func translateAudio(client *openai.Client, audioPath string) (string, error) {
audio, err := os.Open(audioPath)
if err != nil {
return "", err
}
defer audio.Close()
req := openai.AudioRequest{
Model: openai.Whisper1,
FilePath: audioPath,
Reader: audio,
}
resp, err := client.CreateTranslation(context.Background(), req)
if err != nil {
return "", err
}
return resp.Text, nil
}
高级功能
自定义配置
// 创建自定义配置的客户端
config := openai.DefaultConfig("your-api-key")
config.BaseURL = "https://your-proxy.com/v1" // 如果有代理
client := openai.NewClientWithConfig(config)
错误处理
resp, err := client.CreateChatCompletion(ctx, req)
if err != nil {
var apiErr *openai.APIError
if errors.As(err, &apiErr) {
fmt.Printf("OpenAI API错误: %s, 状态码: %d\n", apiErr.Message, apiErr.HTTPStatusCode)
} else {
fmt.Printf("请求错误: %v\n", err)
}
return
}
总结
go-openai库提供了简单易用的接口来访问OpenAI的各种API功能。通过上述示例,你可以轻松集成ChatGPT的对话能力、DALL·E的图像生成和编辑功能,以及Whisper的语音识别和翻译功能到你的Golang应用中。
记得在实际使用时:
- 妥善管理API密钥
- 处理可能出现的错误
- 根据需求调整各种参数
- 注意API的调用频率和配额限制