go-openai

GitHub
10.6k 1.7k 非常简单 1 次阅读 今天Apache-2.0插件语言模型音频
AI 解读 由 AI 自动生成,仅供参考

go-openai 是一款专为 Go 语言开发者打造的非官方 OpenAI API 客户端库。它旨在简化 Go 应用与 OpenAI 强大人工智能模型的集成过程,让开发者无需从零构建复杂的 HTTP 请求和响应解析逻辑,即可轻松调用各类前沿 AI 能力。

该工具全面支持 ChatGPT(包括 GPT-4o、o1 等最新模型)、GPT-3.5/4、DALL·E 2/3、GPT Image 1 以及 Whisper 语音识别等核心接口。无论是需要实现智能对话机器人、生成创意图像,还是进行语音转文字处理,go-openai 都能提供稳定且类型安全的代码支持。其独特的技术亮点在于对流式输出(Streaming)的完善支持,允许应用实时接收并展示模型生成的内容,显著提升用户交互体验;同时,它紧跟 Go 语言特性,要求 Go 1.18 及以上版本,确保了代码的现代性与执行效率。

go-openai 非常适合熟悉或正在使用 Go 语言的软件工程师、后端开发人员以及 AI 应用研究者。如果你希望在 Go 项目中快速接入 OpenAI 生态,构建高效、可靠的智能应用,这款轻量级且社区活跃的库将是你的理想选择。通过简单的安装和直观的 API 设计,它能帮助你专注于业务逻辑创新,而非底层通信细节。

使用场景

某电商平台的后端团队正在用 Go 语言重构其智能客服系统,需要快速集成大模型能力以自动回答用户关于订单状态和退货政策的咨询。

没有 go-openai 时

  • 开发人员必须手动封装复杂的 HTTP 请求,逐行处理鉴权头、JSON 序列化及错误码映射,代码冗余且极易出错。
  • 实现流式回复(Streaming)功能极其困难,需底层处理 SSE 协议解析,导致用户等待首字响应时间过长,体验卡顿。
  • 切换不同模型(如从 GPT-3.5 升级至 GPT-4o)或尝试 Whisper 语音转文字时,需要重写大量接口适配逻辑,维护成本高昂。
  • 缺乏统一的类型定义,团队成员对 API 参数结构理解不一致,导致联调阶段频繁出现格式错误。

使用 go-openai 后

  • 仅需几行代码即可初始化客户端并调用 CreateChatCompletion,库内部自动处理所有 HTTP 细节与错误重试,开发效率提升数倍。
  • 直接调用 CreateChatCompletionStream 接口即可轻松实现打字机效果的流式输出,显著降低用户感知延迟,交互更流畅。
  • 通过简单的常量替换(如 openai.GPT4o)即可无缝切换模型,或一键启用 Whisper 接口处理用户上传的语音投诉,扩展性极强。
  • 利用库中预定义的强类型结构体(如 ChatCompletionRequest),编译器能自动检查参数合法性,大幅减少运行时异常。

go-openai 将繁琐的 API 对接工作转化为标准的 Go 函数调用,让团队能专注于业务逻辑而非底层通信协议。

运行环境要求

操作系统
  • Linux
  • macOS
  • Windows
GPU

未说明

内存

未说明

依赖
notes这是一个 Go 语言客户端库,用于调用 OpenAI API,本身不运行 AI 模型,因此无需本地 GPU 或大内存。运行需安装 Go 1.18 及以上版本,并配置有效的 OpenAI API Key。支持通过代理配置访问网络。
python不适用 (Go 语言库)
Go >= 1.18
go-openai hero image

快速开始

Go OpenAI

Go Reference Go Report Card codecov

本库为 OpenAI API 提供非官方的 Go 客户端。我们支持以下功能:

  • 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 密钥:

  1. 访问 OpenAI 官网:https://platform.openai.com/account/api-keys
  2. 如果您还没有账号,请点击“Sign Up”创建一个;如果您已有账号,请点击“Log In”登录。
  3. 登录后,进入您的 API 密钥管理页面。
  4. 点击“Create new secret key”。
  5. 为您的新密钥命名,然后点击“Create secret key”。
  6. 您的新 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("流式响应:")
	for {
		response, err := stream.Recv()
		if errors.Is(err, io.EOF) {
			fmt.Println("\n流式结束")
			return
		}

		if err != nil {
			fmt.Printf("\n流式错误:%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)
}
GPT-3 流式完成
package main

import (
	"errors"
	"context"
	"fmt"
	"io
	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",
		Stream:    true,
	}
	stream, err := c.CreateCompletionStream(ctx, req)
	if err != nil {
		fmt.Printf("CompletionStream error: %v\n", err)
		return
	}
	defer stream.Close()

	for {
		response, err := stream.Recv()
		if errors.Is(err, io.EOF) {
			fmt.Println("流式结束")
			return
		}

		if err != nil {
			fmt.Printf("流式错误:%v\n", err)
			return
		}

		fmt.Printf("流式响应:\n%s\n", response)
	}
}
音频转文字
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("转录错误:%v\n", err)
		return
	}
	fmt.Println(resp.Text)
}
音频字幕生成
package main

import (
	"context"
	"fmt"
	"os

	openai "github.com/sashabaranov/go-openai"
)

func main() {
	c := openai.NewClient(os.Getenv("OPENAI_KEY"))

	req := openai.AudioRequest{
		Model:    openai.Whisper1,
		FilePath: os.Args[1],
		Format:   openai.AudioResponseFormatSRT,
	}
	resp, err := c.CreateTranscription(context.Background(), req)
	if err != nil {
		fmt.Printf("转录错误:%v\n", err)
		return
	}
	f, err := os.Create(os.Args[1] + ".srt")
	if err != nil {
		fmt.Printf("无法打开文件:%v\n", err)
		return
	}
	defer f.Close()
	if _, err := f.WriteString(resp.Text); err != nil {
		fmt.Printf("写入文件时出错:%v\n", err)
		return
	}
}
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:         "一只鹦鹉在滑板上表演技巧,卡通风格,自然光,高细节",
		Size:           openai.CreateImageSize256x256,
		ResponseFormat: openai.CreateImageResponseFormatURL,
		N:              1,
	}

	respUrl, err := c.CreateImage(ctx, reqUrl)
	if err != nil {
		fmt.Printf("图像生成错误:%v\n", err)
		return
	}
	fmt.Println(respUrl.Data[0].URL)

	// 示例图像以 base64 格式
	reqBase64 := openai.ImageRequest{
		Prompt:         "一个人形鹦鹉穿着经典服装的肖像,高细节,逼真的光线,虚幻引擎效果",
		Size:           openai.CreateImageSize256x256,
		ResponseFormat: openai.CreateImageResponseFormatB64JSON,
		N:              1,
	}

	respBase64, err := c.CreateImage(ctx, reqBase64)
	if err != nil {
		fmt.Printf("图像生成错误:%v\n", err)
		return
	}

	imgBytes, err := base64.StdEncoding.DecodeString(respBase64.Data[0].B64JSON)
	if err != nil {
		fmt.Printf("Base64 解码错误:%v\n", err)
		return
	}

	r := bytes.NewReader(imgBytes)
	imgData, err := png.Decode(r)
	if err != nil {
		fmt.Printf("PNG 解码错误:%v\n", err)
		return
	}

文件, err := os.Create("example.png")
	if err != nil {
		fmt.Printf("创建文件错误::%v\n", err)
		return
	}
	defer file.Close()

	if err := png.Encode(file, imgData); err != nil {
		fmt.Printf("PNG编码错误::%v\n", err)
		return
	}

	fmt.Println("图像已保存为example.png")
}
GPT Image 1 图像生成
package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"os"

	openai "github.com/sashabaranov/go-openai"
)

func main() {
	c := openai.NewClient("your token")
	ctx := context.Background()

	req := openai.ImageRequest{
		Prompt:            "一只鹦鹉在滑板上表演特技。图片底部有一条醒目的横幅,上面写着‘SKATE MASTER’。卡通风格,自然光,高细节,1:1长宽比。",
		Background:        openai.CreateImageBackgroundOpaque,
		Model:             openai.CreateImageModelGptImage1,
		Size:              openai.CreateImageSize1024x1024,
		N:                 1,
		Quality:           openai.CreateImageQualityLow,
		OutputCompression: 100,
		OutputFormat:      openai.CreateImageOutputFormatJPEG,
		// Moderation: 		 openai.CreateImageModerationLow,
		// User: 					 "",
	}

	resp, err := c.CreateImage(ctx, req)
	if err != nil {
		fmt.Printf("图像生成错误::%v\n", err)
		return
	}

	fmt.Println("图像Base64:", resp.Data[0].B64JSON)

	// 解码Base64数据
	imgBytes, err := base64.StdEncoding.DecodeString(resp.Data[0].B64JSON)
	if err != nil {
		fmt.Printf("Base64解码错误::%v\n", err)
		return
	}

	// 将图像写入文件
	outputPath := "generated_image.jpg"
	err = os.WriteFile(outputPath, imgBytes, 0644)
	if err != nil {
		fmt.Printf("写入图像文件失败::%v\n", err)
		return
	}

	fmt.Printf("图像已保存为%s\n", outputPath)
}
配置代理
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)

参见:https://pkg.go.dev/github.com/sashabaranov/go-openai#ClientConfig

ChatGPT支持上下文
package main

import (
	"bufio"
	"context"
	"fmt"
	"os"
	"strings"

	"github.com/sashabaranov/go-openai"
)

func main() {
	client := openai.NewClient("your token")
	messages := make([]openai.ChatCompletionMessage, 0)
	reader := bufio.NewReader(os.Stdin)
	fmt.Println("对话")
	fmt.Println("---------------------")

	for {
		fmt.Print("-> ")
		text, _ := reader.ReadString('\n')
		// 将CRLF转换为LF
		text = strings.Replace(text, "\n", "", -1)
		messages = append(messages, openai.ChatCompletionMessage{
			Role:    openai.ChatMessageRoleUser,
			Content: text,
		})

		resp, err := client.CreateChatCompletion(
			context.Background(),
			openai.ChatCompletionRequest{
				Model:    openai.GPT3Dot5Turbo,
				Messages: messages,
			},
		)

		if err != nil {
			fmt.Printf("ChatCompletion错误::%v\n", err)
			continue
		}

		content := resp.Choices[0].Message.Content
		messages = append(messages, openai.ChatCompletionMessage{
			Role:    openai.ChatMessageRoleAssistant,
			Content: content,
		})
		fmt.Println(content)
	}
}
Azure OpenAI ChatGPT
package main

import (
	"context"
	"fmt"

	openai "github.com/sashabaranov/go-openai"
)

func main() {
	config := openai.DefaultAzureConfig("your Azure OpenAI Key", "https://your Azure OpenAI Endpoint")
	// 如果你使用的部署名称与模型名称不同,可以自定义AzureModelMapperFunc函数
	// config.AzureModelMapperFunc = func(model string) string {
	// 	azureModelMapping := map[string]string{
	// 		"gpt-3.5-turbo": "your gpt-3.5-turbo部署名称",
	// 	}
	// 	return azureModelMapping[model]
	// }

	client := openai.NewClientWithConfig(config)
	resp, err := client.CreateChatCompletion(
		context.Background(),
		openai.ChatCompletionRequest{
			Model: openai.GPT3Dot5Turbo,
			Messages: []openai.ChatCompletionMessage{
				{
					Role:    openai.ChatMessageRoleUser,
					Content: "Hello Azure OpenAI!",
				},
			},
		},
	)
	if err != nil {
		fmt.Printf("ChatCompletion错误::%v\n", err)
		return
	}

	fmt.Println(resp.Choices[0].Message.Content)
}
嵌入语义相似度
package main

import (
	"context"
	"log"
	openai "github.com/sashabaranov/go-openai"

)

func main() {
	client := openai.NewClient("your-token")

	// 为用户查询创建一个EmbeddingRequest
	queryReq := openai.EmbeddingRequest{
		Input: []string{"一只土拨鼠能刨多少土?"},
		Model: openai.AdaEmbeddingV2,
	}

	// 为用户查询创建嵌入向量
queryResponse, err := client.CreateEmbeddings(context.Background(), queryReq)
if err != nil {
	log.Fatal("创建查询嵌入向量时出错:", err)
}

	// 为目标文本创建一个EmbeddingRequest
targetReq := openai.EmbeddingRequest{
	 Input: []string{"如果土拨鼠真的会刨土,它能刨多少土呢?"},
	 Model: openai.AdaEmbeddingV2,
}

	// 为目标文本创建嵌入向量
targetResponse, err := client.CreateEmbeddings(context.Background(), targetReq)
if err != nil {
	log.Fatal("创建目标嵌入向量时出错:", err)
}

	// 现在我们已经有了用户查询和目标文本的嵌入向量,就可以计算它们之间的相似度了。
queryEmbedding := queryResponse.Data[0]
targetEmbedding := targetResponse.Data[0]

similarity, err := queryEmbedding.DotProduct(&targetEmbedding)
if err != nil {
	log.Fatal("计算点积时出错:", err)
}

log.Printf("查询和目标文本之间的相似度分数为%f", similarity)
}
Azure OpenAI嵌入
package main

import (
	"context"
	"fmt"

	openai "github.com/sashabaranov/go-openai"
)

func main() {

	config := openai.DefaultAzureConfig("your Azure OpenAI Key", "https://your Azure OpenAI Endpoint")
	config.APIVersion = "2023-05-15" // 可选地更新到最新API版本

	// 如果你使用的部署名称与模型名称不同,可以自定义AzureModelMapperFunc函数
	//config.AzureModelMapperFunc = func(model string) string {
	//    azureModelMapping := map[string]string{
	//        "gpt-3.5-turbo":"your gpt-3.5-turbo部署名称",
	//    }
	//    return azureModelMapping[model]
	//}

input := "需要向量化处理的文本"

client := openai.NewClientWithConfig(config)
resp, err := client.CreateEmbeddings(
	context.Background(),
	openai.EmbeddingRequest{
		Input: []string{input},
		Model: openai.AdaEmbeddingV2,
	},
)
if err != nil {
	fmt.Printf("CreateEmbeddings错误::%v\n", err)
	return
}

向量 := resp.Data[0].Embedding // 一个包含1536维浮点数的数组

fmt.Println(vectors[:10], "...", vectors[len(vectors)-10:])
}
用于函数调用的 JSON Schema

现在,聊天补全功能可以选择调用函数以获取更多信息(请参阅此处的开发者文档)。

为了描述可调用函数的类型,必须提供一个 JSON Schema。虽然有许多比本库所能提供的更为先进的 JSON Schema 库,但我们仍包含了一个简单的 jsonschema 包,供希望使用此功能而无需自行格式化 JSON Schema 负载的人士使用。

开发者文档中给出了如下 JSON Schema 定义作为示例:

{
  "name":"get_current_weather",
  "description":"获取给定地点的当前天气",
  "parameters":{
    "type":"object",
    "properties":{
        "location":{
          "type":"string",
          "description":"城市和州,例如旧金山,加州"
        },
        "unit":{
          "type":"string",
          "enum":[
              "celsius",
              "fahrenheit"
          ]
        }
    },
    "required":[
        "location"
    ]
  }
}

使用 jsonschema 包,可以通过结构体创建该 Schema,如下所示:

FunctionDefinition{
  Name: "get_current_weather",
  Parameters: jsonschema.Definition{
    Type: jsonschema.Object,
    Properties: map[string]jsonschema.Definition{
      "location": {
        Type: jsonschema.String,
        Description: "城市和州,例如旧金山,加州",
      },
      "unit": {
        Type: jsonschema.String,
        Enum: []string{"celsius", "fahrenheit"},
      },
    },
    Required: []string{"location"},
  },
}

FunctionDefinitionParameters 字段可以接受上述任一格式,甚至可以接受来自其他库的嵌套结构体(只要能够被序列化为 JSON 即可)。

错误处理

OpenAI 维护了清晰的文档,说明如何 处理 API 错误

示例:

e := &openai.APIError{}
if errors.As(err, &e) {
  switch e.HTTPStatusCode {
    case 401:
      // 认证或密钥无效(不要重试)
    case 429:
      // 速率限制或引擎过载(等待后重试)
    case 500:
      // OpenAI 服务器错误(重试)
    default:
      // 未处理的情况
  }
}
微调模型
package main

import (
	"context"
	"fmt"
	"github.com/sashabaranov/go-openai"
)

func main() {
	client := openai.NewClient("your token")
	ctx := context.Background()

	// 创建一个包含对话模型训练数据的 .jsonl 文件
	// {"prompt": "<提示文本>", "completion": "<理想生成文本>"}
	// {"prompt": "<提示文本>", "completion": "<理想生成文本>"}
	// {"prompt": "<提示文本>", "completion": "<理想生成文本>"}

	// 对话模型使用以下文件格式进行训练:
	// {"messages": [{"role": "system", "content": "Marv 是一个既基于事实又带讽刺意味的聊天机器人。"}, {"role": "user", "content": "法国的首都是哪里?"}, {"role": "assistant", "content": "巴黎,好像大家都知道似的。"}]}
	// {"messages": [{"role": "system", "content": "Marv 是一个既基于事实又带讽刺意味的聊天机器人。"}, {"role": "user", "content": "《罗密欧与朱丽叶》是谁写的?"}, {"role": "assistant", "content": "哦,就是那个叫威廉·莎士比亚的人呗。你听说过他吗?"}]}
	// {"messages": [{"role": "system", "content": "Marv 是一个既基于事实又带讽刺意味的聊天机器人。"}, {"role": "user", "content": "月球离地球有多远?"}, {"role": "assistant", "content": "大约 384,400 公里吧。多一点少一点也没啥关系,反正谁在乎呢。"}]}

	// 可以使用 OpenAI CLI 工具来验证数据。
	// 更多信息请参阅:https://platform.openai.com/docs/guides/fine-tuning

	file, err := client.CreateFile(ctx, openai.FileRequest{
		FilePath: "training_prepared.jsonl",
		Purpose:  "fine-tune",
	})
	if err != nil {
		fmt.Printf("上传 JSONL 文件时出错:%v\n", err)
		return
	}

	// 创建微调任务
	// 流式传输事件直到任务完成(这通常需要几分钟,但如果队列中有许多任务或您的数据集很大,则可能需要数小时)。
	// 使用下面的方法来了解模型的状态。
	fineTuningJob, err := client.CreateFineTuningJob(ctx, openai.FineTuningJobRequest{
		TrainingFile: file.ID,
		Model:        "davinci-002", // gpt-3.5-turbo-0613、babbage-002。
	})
	if err != nil {
		fmt.Printf("创建新的微调模型时出错:%v\n", err)
		return
	}

	fineTuningJob, err = client.RetrieveFineTuningJob(ctx, fineTuningJob.ID)
	if err != nil {
		fmt.Printf("获取微调模型时出错:%v\n", err)
		return
	}
	fmt.Println(fineTuningJob.FineTunedModel)

	// 一旦 fineTuningJob 的状态变为 `succeeded`,您就可以在 Completion Request 或 Chat Completion Request 中使用您的微调模型。

	// resp, err := client.CreateCompletion(ctx, openai.CompletionRequest{
	//	 Model:  fineTuningJob.FineTunedModel,
	//	 Prompt: "your prompt",
	// })
	// if err != nil {
	//	 fmt.Printf("创建完成请求时出错:%v\n", err)
	//	 return
	// }
	//
	// fmt.Println(resp.Choices[0].Text)
}
结构化输出
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 出错:%v", err)
	}
	resp, err := client.CreateChatCompletion(ctx, openai.ChatCompletionRequest{
		Model: openai.GPT4oMini,
		Messages: []openai.ChatCompletionMessage{
			{
				Role:    openai.ChatMessageRoleSystem,
				Content: "你是一位乐于助人的数学家教。请逐步引导用户解决问题。",
			},
			{
				Role:    openai.ChatMessageRoleUser,
				Content: "我该如何解方程 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 出错:%v", err)
	}
	err = schema.Unmarshal(resp.Choices[0].Message.Content, &result)
	if err != nil {
		log.Fatalf("Unmarshal schema 出错:%v", err)
	}
	fmt.Println(result)
}
更多内容请参阅 `examples/` 文件夹。

常见问题解答

为什么在指定温度字段为0并提出相同问题时,我们得不到相同的答案?

即使将温度字段设置为0,也不能保证每次都会得到完全一致的响应。这背后涉及多个因素。

  1. Go OpenAI 的行为:当您在 Go OpenAI 中将温度字段设置为0时,由于使用了 omitempty 标签,该字段会被从请求中移除。因此,OpenAI API 会采用默认值1。
  2. 输入/输出的 token 数量:如果输入和输出中的 token 数量较多,即便将温度设置为0,仍可能出现非确定性行为。尤其是在使用约32,000个 token 时,即使温度为0,非确定性行为的发生概率也会达到最高。

由于上述原因,即使是相同的问题,也可能返回不同的答案。

解决方法:

  1. 截至2023年11月,可以结合使用 新的 seed 参数system_fingerprint 响应字段,同时合理管理温度参数。
  2. 使用 math.SmallestNonzeroFloat32:将温度字段设置为 math.SmallestNonzeroFloat32 而不是0,可以模拟将温度设为0的效果。
  3. 限制 token 数量:通过限制输入和输出中的 token 数量,尤其是避免接近32,000 token 的大请求,可以降低非确定性行为的风险。

采取这些策略后,您可以期待更一致的结果。

相关问题: 请求结构体的 omitempty 选项在参数为0时会生成错误的请求。

Go OpenAI 是否提供 token 计数功能?

目前,Go OpenAI 并未提供 token 计数功能,未来也没有计划加入此功能。不过,如果有无需依赖其他库即可实现 token 计数的方法,或许可以将其合并到 Go OpenAI 中。否则,更适合将其单独实现在一个专用的库或仓库中。

关于 token 计数,您可以参考以下链接:

相关问题: 是否可以集成 GPT-3 Tokenizer 的实现?

参与贡献

请遵循 贡献指南,以确保您的贡献能够顺利且高效地完成。

感谢

在此,我们想向本项目的 贡献者 和赞助者致以最诚挚的谢意:

感谢每一位!是你们的帮助让我们取得了远超预期的成果。期待我们携手迈向更加辉煌的未来!

版本历史

v1.41.22025/09/12
v1.41.12025/08/12
v1.41.02025/08/11
v1.40.52025/07/11
v1.40.42025/07/08
v1.40.32025/06/25
v1.40.22025/06/16
v1.40.12025/05/29
v1.40.02025/05/13
v1.39.12025/05/03
v1.39.02025/04/29
v1.38.32025/04/27
v1.38.22025/04/17
v1.38.12025/03/20
v1.38.02025/02/25
v1.37.02025/02/06
v1.36.12024/12/27
v1.36.02024/11/30
v1.35.72024/11/20
v1.35.62024/11/08

常见问题

相似工具推荐

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

156k|★★☆☆☆|今天
开发框架Agent语言模型

gemini-cli

gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。

100.8k|★★☆☆☆|5天前
插件Agent图像

markitdown

MarkItDown 是一款由微软 AutoGen 团队打造的轻量级 Python 工具,专为将各类文件高效转换为 Markdown 格式而设计。它支持 PDF、Word、Excel、PPT、图片(含 OCR)、音频(含语音转录)、HTML 乃至 YouTube 链接等多种格式的解析,能够精准提取文档中的标题、列表、表格和链接等关键结构信息。 在人工智能应用日益普及的今天,大语言模型(LLM)虽擅长处理文本,却难以直接读取复杂的二进制办公文档。MarkItDown 恰好解决了这一痛点,它将非结构化或半结构化的文件转化为模型“原生理解”且 Token 效率极高的 Markdown 格式,成为连接本地文件与 AI 分析 pipeline 的理想桥梁。此外,它还提供了 MCP(模型上下文协议)服务器,可无缝集成到 Claude Desktop 等 LLM 应用中。 这款工具特别适合开发者、数据科学家及 AI 研究人员使用,尤其是那些需要构建文档检索增强生成(RAG)系统、进行批量文本分析或希望让 AI 助手直接“阅读”本地文件的用户。虽然生成的内容也具备一定可读性,但其核心优势在于为机器

93.4k|★★☆☆☆|1周前
插件开发框架

LLMs-from-scratch

LLMs-from-scratch 是一个基于 PyTorch 的开源教育项目,旨在引导用户从零开始一步步构建一个类似 ChatGPT 的大型语言模型(LLM)。它不仅是同名技术著作的官方代码库,更提供了一套完整的实践方案,涵盖模型开发、预训练及微调的全过程。 该项目主要解决了大模型领域“黑盒化”的学习痛点。许多开发者虽能调用现成模型,却难以深入理解其内部架构与训练机制。通过亲手编写每一行核心代码,用户能够透彻掌握 Transformer 架构、注意力机制等关键原理,从而真正理解大模型是如何“思考”的。此外,项目还包含了加载大型预训练权重进行微调的代码,帮助用户将理论知识延伸至实际应用。 LLMs-from-scratch 特别适合希望深入底层原理的 AI 开发者、研究人员以及计算机专业的学生。对于不满足于仅使用 API,而是渴望探究模型构建细节的技术人员而言,这是极佳的学习资源。其独特的技术亮点在于“循序渐进”的教学设计:将复杂的系统工程拆解为清晰的步骤,配合详细的图表与示例,让构建一个虽小但功能完备的大模型变得触手可及。无论你是想夯实理论基础,还是为未来研发更大规模的模型做准备

90.1k|★★★☆☆|1周前
语言模型图像Agent

NextChat

NextChat 是一款轻量且极速的 AI 助手,旨在为用户提供流畅、跨平台的大模型交互体验。它完美解决了用户在多设备间切换时难以保持对话连续性,以及面对众多 AI 模型不知如何统一管理的痛点。无论是日常办公、学习辅助还是创意激发,NextChat 都能让用户随时随地通过网页、iOS、Android、Windows、MacOS 或 Linux 端无缝接入智能服务。 这款工具非常适合普通用户、学生、职场人士以及需要私有化部署的企业团队使用。对于开发者而言,它也提供了便捷的自托管方案,支持一键部署到 Vercel 或 Zeabur 等平台。 NextChat 的核心亮点在于其广泛的模型兼容性,原生支持 Claude、DeepSeek、GPT-4 及 Gemini Pro 等主流大模型,让用户在一个界面即可自由切换不同 AI 能力。此外,它还率先支持 MCP(Model Context Protocol)协议,增强了上下文处理能力。针对企业用户,NextChat 提供专业版解决方案,具备品牌定制、细粒度权限控制、内部知识库整合及安全审计等功能,满足公司对数据隐私和个性化管理的高标准要求。

87.6k|★★☆☆☆|1周前
开发框架语言模型

ML-For-Beginners

ML-For-Beginners 是由微软推出的一套系统化机器学习入门课程,旨在帮助零基础用户轻松掌握经典机器学习知识。这套课程将学习路径规划为 12 周,包含 26 节精炼课程和 52 道配套测验,内容涵盖从基础概念到实际应用的完整流程,有效解决了初学者面对庞大知识体系时无从下手、缺乏结构化指导的痛点。 无论是希望转型的开发者、需要补充算法背景的研究人员,还是对人工智能充满好奇的普通爱好者,都能从中受益。课程不仅提供了清晰的理论讲解,还强调动手实践,让用户在循序渐进中建立扎实的技能基础。其独特的亮点在于强大的多语言支持,通过自动化机制提供了包括简体中文在内的 50 多种语言版本,极大地降低了全球不同背景用户的学习门槛。此外,项目采用开源协作模式,社区活跃且内容持续更新,确保学习者能获取前沿且准确的技术资讯。如果你正寻找一条清晰、友好且专业的机器学习入门之路,ML-For-Beginners 将是理想的起点。

85.1k|★★☆☆☆|4天前
图像数据工具视频