使用Go调用OpenAI兼容API模型

 更新时间:2026年05月17日 15:00:03   作者:传说之后  
本文介绍了使用Go语言调用兼容OpenAI API的模型(LMStudio/Ollama)的方法,主要涵盖了非流式对话、流式打字机效果、多轮上下文对话以及图片交互等内容,文章详细解释了如何准备环境,实现非流式对话的特点,需要的朋友可以参考下

摘要:用 Go 调用兼容 OpenAI API 的模型(LM Studio / Ollama),覆盖非流式对话、流式打字机效果、多轮上下文和图片交互。

一、环境准备

go get github.com/sashabaranov/go-openai

LM Studio / Ollama 提供与 OpenAI 兼容的 API 端点(默认 http://localhost:1234/v1)。

二、非流式对话

package main
import (
    "context"
    "fmt"
    openai "github.com/sashabaranov/go-openai"
)
func main() {
    config := openai.DefaultConfig("api")//填入ApiKey,得到一个"客户端默认配置"
    config.BaseURL = "http://localhost:1234/v1"//服务器地址
    client := openai.NewClientWithConfig(config)
    resp, err := client.CreateChatCompletion(
        context.Background(),
        openai.ChatCompletionRequest{
            Model: "local-model",  // 本地模型可任意命名
            Messages: []openai.ChatCompletionMessage{
                {Role: openai.ChatMessageRoleUser, Content: "你好,世界!"},
            },
        },
    )
    if err != nil {
        fmt.Printf("错误: %v\n", err)
        return
    }
    fmt.Println(resp.Choices[0].Message.Content)
}

特点:请求发出去后等待全部生成完才返回,适合短回复。

三、流式响应(打字机效果)

sequenceDiagram
    participant Go
    participant AI API

    Go->>AI API: CreateChatCompletionStream
    loop 逐字生成
        AI API-->>Go: Delta.Content = "你"
        AI API-->>Go: Delta.Content = "好"
        AI API-->>Go: Delta.Content = "!"
    end
    AI API-->>Go: io.EOF
func main() {
    client := openai.NewClientWithConfig(config)

    stream, err := client.CreateChatCompletionStream(
        context.Background(),
        openai.ChatCompletionRequest{
            Model: "local-model",
            Messages: []openai.ChatCompletionMessage{
                {Role: openai.ChatMessageRoleUser, Content: "写一首诗"},
            },
            Stream: true,  // 核心开关
        },
    )
    if err != nil {
        fmt.Printf("错误: %v\n", err)
        return
    }
    defer stream.Close()

    fmt.Print("AI: ")
    for {
        response, err := stream.Recv()
        if err != nil {
            break  // io.EOF 表示流结束
        }
        fmt.Print(response.Choices[0].Delta.Content)
    }
    fmt.Println()
}

四、多轮上下文对话

func main() {
    client := openai.NewClientWithConfig(config)
    messages := []openai.ChatCompletionMessage{}
    reader := bufio.NewReader(os.Stdin)

    fmt.Println("聊天开始(输入 quit 退出,new 新对话)")

    for {
        fmt.Print("\n你: ")
        input, _ := reader.ReadString('\n')
        input = strings.TrimSpace(input)

        if input == "quit" { break }
        if input == "new" {
            messages = []openai.ChatCompletionMessage{}
            fmt.Println("已开始新对话")
            continue
        }

        // 追加用户消息
        messages = append(messages, openai.ChatCompletionMessage{
            Role:    openai.ChatMessageRoleUser,
            Content: input,
        })

        // 发送完整历史
        stream, err := client.CreateChatCompletionStream(
            context.Background(),
            openai.ChatCompletionRequest{
                Model:    "local-model",
                Messages: messages,
                Stream:   true,
            },
        )
        if err != nil {
            fmt.Printf("错误: %v\n", err)
            continue
        }

        fmt.Print("AI: ")
        var full strings.Builder
        for {
            resp, err := stream.Recv()
            if err != nil { break }
            chunk := resp.Choices[0].Delta.Content
            fmt.Print(chunk)
            full.WriteString(chunk)
        }
        fmt.Println()
        stream.Close()

        // 追加 AI 回复到历史
        messages = append(messages, openai.ChatCompletionMessage{
            Role:    openai.ChatMessageRoleAssistant,
            Content: full.String(),
        })

        // 可选:清理过长历史
        // if len(messages) > 20 { messages = messages[len(messages)-20:] }
    }
}

核心要点

  • 每次请求把完整 messages 历史发给 API
  • AI 的回复也要加入历史
  • 注意 token 上限,旧消息要定期裁剪

五、图片交互

package main

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

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

// 编码本地图片为Base64字符串
func encodeImage(path string) (string, error) {
	data, err := os.ReadFile(path)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(data), nil
}

func main() {
	// 配置OpenAI兼容客户端(适配本地模型如Ollama、LocalAI等)
	config := openai.DefaultConfig("api")   //填入ApiKey
	config.BaseURL = "http://localhost:1234/v1" // 示例:Ollama的OpenAI兼容端点,请根据实际修改
	client := openai.NewClientWithConfig(config)

	// 图像描述(视觉模型)
	b64Img, err := encodeImage("path")//输入图片的路径
	if err != nil {
		fmt.Printf("读取/编码图片失败: %v\n", err)
		return
	}

	messages := []openai.ChatCompletionMessage{
		{
			Role: openai.ChatMessageRoleUser,
			MultiContent: []openai.ChatMessagePart{
				{Type: openai.ChatMessagePartTypeText, Text: "描述这张图片"},
				{Type: openai.ChatMessagePartTypeImageURL,
					ImageURL: &openai.ChatMessageImageURL{
						URL: "data:image/jpeg;base64," + b64Img, // Data URI scheme 的标准格式以及图片的Base64编码,如果格式不正确会导致无法被正确识别
					},
				},
			},
		},
	}
	/*// 常见格式
	  // JPEG 格式
	  url := "data:image/jpeg;base64," + jpegBase64

	  // PNG 格式
	  url := "data:image/png;base64," + pngBase64

	  // GIF 格式
	  url := "data:image/gif;base64," + gifBase64

	  // WebP 格式
	  url := "data:image/webp;base64," + webpBase64

	  // 通用方式(让模型自动检测)
	  url := "data:image/*;base64," + base64Data
	*/
	// 发起视觉流式请求
	stream, err := client.CreateChatCompletionStream(
		context.Background(),
		openai.ChatCompletionRequest{
			Model:    "qwen/qwen3.5-9b", // 替换为你实际部署的视觉模型名称,如 llava, bakllava
			Messages: messages,
			Stream:   true,
		},
	)
	if err != nil {
		fmt.Printf("创建流式请求失败: %v\n", err)
		return
	}
	defer stream.Close()

	fmt.Println("=== 图像描述结果 ===")
	for {
		response, err := stream.Recv()
		if err == io.EOF {
			fmt.Println("\n[流式响应结束]")
			break
		}
		if err != nil {
			fmt.Printf("\n流式接收错误: %v\n", err)
			break
		}
		// 打印增量内容
		fmt.Print(response.Choices[0].Delta.Content)
	}
}

六、总结

场景方法
简单问答CreateChatCompletion(非流式)
打字机效果CreateChatCompletionStreamStream: true
多轮对话维护 messages 切片,每次全量发送
图片分析MultiContent + base64 编码
上下文管理超过 token 限制时裁剪旧消息

Go 调用 AI 模型的核心就是三件事:构建 message 列表、选择流式/非流式、管理对话历史。go-openai 库让这一切变得简单。

以上就是使用Go调用OpenAI兼容API模型的详细内容,更多关于Go调用OpenAI兼容API的资料请关注脚本之家其它相关文章!

相关文章

  • golang gorm开发架构及写插件示例

    golang gorm开发架构及写插件示例

    这篇文章主要为大家介绍了golang gorm开发架构及写插件的详细示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2022-04-04
  • 解读golang中的const常量和iota

    解读golang中的const常量和iota

    这篇文章主要介绍了golang中的const常量和iota,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • golang 如何获取文件夹下面的文件列表

    golang 如何获取文件夹下面的文件列表

    这篇文章主要介绍了golang 获取文件夹下面的文件列表方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-05-05
  • Golang使用ttl机制保存内存数据方法详解

    Golang使用ttl机制保存内存数据方法详解

    ttl(time-to-live) 数据存活时间,我们这里指数据在内存中保存一段时间,超过期限则不能被读取到,与Redis的ttl机制类似。本文仅实现ttl部分,不考虑序列化和反序列化
    2023-03-03
  • k8s容器互联flannel vxlan通信原理

    k8s容器互联flannel vxlan通信原理

    这篇文章主要为大家介绍了k8s容器互联flannel vxlan通信原理详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Golang中的同步工具sync.Map示例详解

    Golang中的同步工具sync.Map示例详解

    sync.Map是Golang标准库提供的并发安全的Map类型,可以在多个goroutine并发读写Map的场景下不需要加锁,这篇文章主要介绍了Golang中的同步工具sync.Map详解,需要的朋友可以参考下
    2023-05-05
  • Go的os/exec执行超时导致程序死机的解决方案

    Go的os/exec执行超时导致程序死机的解决方案

    这篇文章主要介绍了Go的os/exec执行超时导致程序死机的几种解决方案,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-04-04
  • 在Golang中执行Shell命令的教程详解

    在Golang中执行Shell命令的教程详解

    在本教程中,我们将学习如何在 Golang 中执行shell命令(如 ls、mkdir 或 grep ),我们还将学习如何通过 stdin 和 stdout 传递 I/O 到正在运行的命令,以及管理长时间运行的命令,感兴趣的同学可以借鉴一下
    2023-05-05
  • Golang实现Md5校验的示例代码

    Golang实现Md5校验的示例代码

    本文主要介绍了Golang实现Md5校验的示例代码,要求接收方需要文件的md5值,和接收到的文件做比对,以免文件不完整,但引起bug,下面就一起来解决一下
    2024-08-08
  • 使用Go语言构建高效的二叉搜索树联系簿

    使用Go语言构建高效的二叉搜索树联系簿

    树是一种重要的数据结构,而二叉搜索树(BST)则是树的一种常见形式,在本文中,我们将学习如何构建一个高效的二叉搜索树联系簿,感兴趣的可以了解下
    2024-01-01

最新评论