库使用指南

pkg/client 是一个独立的 Go 库——CLI 所做的一切,都是通过调用这个 package 完成的。你可以直接依赖它,完全不需要带上 CLI。

目录

go get github.com/SamyRai/go-z-ai
import "github.com/SamyRai/go-z-ai/pkg/client"

创建客户端

c, err := client.NewClient(client.Config{
    APIKey: os.Getenv("ZAI_API_KEY"),
})

或者,如果你只想要默认的环境变量配置、不要其他选项:

c, err := client.NewClientFromEnv() // reads ZAI_API_KEY, ZAI_API_BASE_URL

Config 字段:

Field Default Notes
APIKey 必填
BaseURL https://api.z.ai/api/paas/v4 用于覆盖 coding-plan 端点等
HTTPClient 内部配置的 *http.Client 如需自定义 TLS/代理行为,可传入自己的 transport
Timeout 30s 仅限制拨号/TLS/响应头等待时间——包含整个响应体的读取,因此绝不会截断正在进行的 SSE 流
MaxRetries 3 在 429/5xx/网络错误时重试。-1 表示完全禁用重试
RetryDelay 200ms 指数退避的基础延迟
ChinaAPIKey 回退到 APIKey 仅在你持有单独的 bigmodel.cn 专用凭据时才需要——见 账户与配额
Region RegionGlobal 选择 monitor/biz/agents/detection 的主机:RegionGlobal(api.z.ai)或 RegionChina(open.bigmodel.cn)。不会覆盖 BaseURL(聊天接口)或 Embeddings/Moderations 的主机。见 账户与配额

每个服务方法的第一个参数都是 context.Context,并一路传递到底层的 HTTP 调用——取消它即可中止请求或正在等待的重试退避。

服务

Client 为每个服务暴露一个方法,全部遵循同样的 c.<Service>().<Method>(ctx, ...) 形式:

Accessor Covers
c.Chat() Completions — CreateCreateAsyncCreateStreamCreateSimpleRunWithTools
c.Models() ListGetGetTextModelsGetVisionModelsGetFreeModelsRefreshCache
c.Images() GenerateGenerateAsync
c.Videos() Generate(始终异步)
c.Audio() TranscribeSpeech
c.Voice() CloneDeleteList——GLM-TTS 声音克隆
c.Layout() ParseHandwritingOCR
c.FileParser() CreateSyncResult——用于 RAG 的文档转文本
c.Files() UploadListDeleteContent
c.Batch() CreateRetrieveListCancel
c.Agents() InvokeAsyncResult
c.Anthropic() CreateCreateStream——Anthropic 协议 /v1/messages 接口
c.Embeddings() Create(路由到 open.bigmodel.cn
c.Moderations() Create(路由到 open.bigmodel.cn
c.Rerank() Create
c.Tools() WebSearchWebReaderTokenize
c.Usage()c.Quota()c.Detection()c.Account() GLM Coding Plan 用量/配额/账户监控
c.GetAsyncResult(ctx, id)c.WaitForResult(ctx, id, interval) 异步图像/视频/聊天任务的共享轮询

每一项请求校验(必填字段等)都在请求发送之前于客户端完成——对于缺少 model 这类问题,你会立刻拿到一个本地 error,而不是白白跑一次往返。

聊天补全

resp, err := c.Chat().Create(ctx, client.ChatRequest{
    Model: "glm-5.2",
    Messages: []client.Message{
        {Role: "system", Content: "You are a helpful assistant."},
        {Role: "user", Content: "Explain goroutines in one paragraph"},
    },
    Temperature: 0.7,
})
fmt.Println(resp.Choices[0].Message.Content)

流式

err := c.Chat().CreateStream(ctx, req, func(chunk client.StreamChunk) error {
    if len(chunk.Choices) > 0 {
        fmt.Print(chunk.Choices[0].Delta.Content)
    }
    return nil // a non-nil return aborts the stream
})

设置 req.StreamToolCall = true(GLM-4.6+)可以把工具调用的增量 跨多个事件流式地投放到 chunk.Choices[0].Delta.ToolCalls 里, 而不是在该轮结束时一次性整批返回。这在 UI 上展示"模型正在调用工具…"的进度时 很有用。尚未实测验证——见 路线图

异步

task, _ := c.Chat().CreateAsync(ctx, req)
result, err := c.WaitForResult(ctx, task.ID, 3*time.Second)

视觉(消息中的图像)

req.Messages[len(req.Messages)-1].Images = []string{
    "https://example.com/photo.jpg", // or a data: URI
}
req.Model = "glm-4.6v"

结构化输出

req.ResponseFormat = client.NewJSONSchemaFormat("my_schema", rawJSONSchema, true /* strict */)

函数调用

如果需要手动控制,自行检查 resp.Choices[0].Message.ToolCalls, 然后在再次调用 Create 之前追加 role: "tool" 消息。对于常见场景, RunWithTools 会替你驱动这个循环:

resp, err := c.Chat().RunWithTools(ctx, req, func(name, arguments string) (string, error) {
    switch name {
    case "get_weather":
        return `{"temp_c": 18}`, nil
    default:
        return "", fmt.Errorf("unknown tool %q", name)
    }
})

它会执行每一次工具调用,追加 assistant 和 tool 消息,并循环重复, 直到模型返回非工具类型的 finish reason 或超过 ToolMaxRounds(8)—— 可用 RunWithToolsLimit 设置不同的上限。工具执行器返回的错误会以工具结果 ("error: ...")的形式回传给模型,而不是返回给你的调用方,这样模型可以 自行恢复,整轮对话也不会因此失败。

工具类型

一个 Tool 携带三种 payload 之一,由其 Type 决定:

Constructor Type Payload
NewFunctionTool(name, desc, params) ToolTypeFunction"function" FunctionDef——模型按名称调用的可执行体
NewRetrievalTool(knowledgeID, prompt) ToolTypeRetrieval"retrieval" Retrieval——用于为回答提供依据的知识库
NewWebSearchTool(queries...) ToolTypeWebSearch"web_search" WebSearch——一个 search_query 列表

retrievalweb_search 在 docs.z.ai 上有文档,但此处尚未实测 验证——只有 function 已对照真实 API 确认。web_search 的 payload 形态({"search_query":[...]})遵循官方 Python SDK 示例;见 路线图

validateChatRequest 在客户端强制执行三条文档化的规则,这样你会拿到 清晰的本地错误,而不是服务器返回的晦涩错误:

值得检查的响应字段

除了 resp.Choices[0].Message.Content 之外:

工具 schema 兼容性

GLM 的聊天端点对工具 parameters 使用严格的 JSON-Schema 解析器: 包含 anyOfoneOfallOf,或 $ref/$defs 引用的 schema 会让 它返回 HTTP 500,而不是一个可用的错误。这些构造恰恰就是带类型的语言 所生成的——一个可为 null 的字段会变成 anyOf: [{…}, {"type":"null"}],一个被复用的 struct 会变成 $ref

默认情况下,客户端会在每次聊天请求之前把工具 schema 改写成 GLM 接受的 扁平子集(可为 null 的联合类型坍缩为底层类型、allOf 合并、$ref 内联展开),并尽量保留类型/描述信息。对于已经在受支持子集内的 schema 这是 no-op,并且永远不会改动你的 req.Tools

Anthropic 兼容的 Messages API

Z.AI 还在 /api/anthropic 暴露了一个 Anthropic 协议接口——也就是 GLM Coding Plan 把 Claude Code 指向的同一个端点。c.Anthropic() 是其 POST /v1/messages 的类型化客户端,与 OpenAI 风格接口的 c.Chat() 并列。它用你的 z.ai key 以 Bearer token 形式鉴权(不是 Anthropic 的 x-api-key),并自动发送 anthropic-version 头。

resp, err := c.Anthropic().Create(ctx, client.AnthropicMessageRequest{
    Model:     "glm-4.6",
    MaxTokens: 1024, // required by the Messages API
    System:    "You are concise.",
    Messages: []client.AnthropicMessage{
        client.AnthropicTextMessage("user", "Explain goroutines in one line"),
    },
})
fmt.Println(resp.Text()) // concatenated text blocks

流式传输会交付 Anthropic 原生的 SSE 事件(message_startcontent_block_delta、……),包含事件名和 JSON payload,你按事件类型 分别 unmarshal:

err := c.Anthropic().CreateStream(ctx, req, func(ev client.AnthropicStreamEvent) error {
    if ev.Type == "content_block_delta" {
        // ev.Data is {"delta":{"type":"text_delta","text":"…"}, …}
    }
    return nil
})

通过 AnthropicTool.InputSchema 声明的工具会得到与聊天工具相同的 GLM schema 规范化(见上文)。Config.DisableToolSchemaCompat 可关闭它。

深度思考(GLM 模型是推理模型)按请求开启,并用 resp.Thinking() 读回:

req.Thinking = &client.AnthropicThinking{Type: "enabled", BudgetTokens: 2048}
resp, _ := c.Anthropic().Create(ctx, req)
fmt.Println(resp.Thinking()) // thinking blocks, or reasoning_content if the
                             // endpoint surfaces reasoning that way instead
fmt.Println(resp.Text())     // the answer, without the reasoning mixed in

成功路径上的响应形态是按 Anthropic 文档化的 Messages API 建模的,此处 尚未实测验证——见 路线图

错误处理

完整的 APIError 参考、错误码,以及默认的重试行为,请见 错误处理

多账户凭据管理

多账户凭据存储以及 GLM Coding Plan 的凭据/配置写入器位于 internal/accountsinternal/coding。它们对本模块是内部的——不属于 可导入的公开 API——因此可以不受 semver 约束地演进。pkg/client 是唯一 受支持的公开 package;accountscoding CLI 命令是驱动这些功能的 稳定入口。(这些 package 之前位于 pkg/ 下且可导入;迁移说明见 CHANGELOG。)

用本客户端测试你自己的代码

每个服务方法都是无接口的具体类型上的普通函数,因此常规的 Go 做法是把 Config.BaseURL 指向你控制的 httptest.Server。如果你想回放真实录制 的 Z.AI 流量而不是手写 stub,可以参考本仓库自身的测试是如何用 go-vcr 做的——pkg/client/*_test.gopkg/client/testdata/cassettes/——并阅读 贡献指南 § 实测验证约定 了解背后原因。

架构说明

关于服务在内部是如何组织的(doRequest 门面、重试/退避设计、为何有些服务 针对不同的 base URL 鉴权),请见 架构