Help us shape the future of Go! Take the 2026 Go Developer Survey

llm

package
v1.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 5, 2026 License: AGPL-3.0 Imports: 27 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Builtin = map[string]Provider{
	"deepseek": {
		Name:        "DeepSeek",
		ChatURL:     "https://api.deepseek.com/v1/chat/completions",
		PlatformURL: "https://platform.deepseek.com",
		HelpText:    "使用邮箱或手机号注册。完成实名认证后,进入「API Keys」创建密钥。预付费模式,最低充值 ¥1。",
		Temperature: floatPtr(0.7),
		Models: []ModelInfo{
			{
				ID:               "deepseek-v4-flash",
				Name:             "DeepSeek V4 Flash",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				ReasoningLevels:  []string{"high", "max"},
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-pro",
				Name:             "DeepSeek V4 Pro",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				ReasoningLevels:  []string{"high", "max"},
				SupportsVision:   false,
			},
		},
		BuildRequest: nil,
	},
	"opencode": {
		Name:         "OpenCode Zen",
		ChatURL:      "https://opencode.ai/zen/v1/chat/completions",
		PlatformURL:  "https://opencode.ai/auth",
		HelpText:     "OpenCode Zen 是 opencode.ai 的按量付费网关,提供 DeepSeek/GLM/Kimi/MiniMax 等精选模型及多个免费模型(均兼容 OpenAI chat/completions)。在 opencode.ai/auth 注册、添加账单信息后复制 API Key 填入。OpenCode 网关要求携带 x-opencode-session 会话头与自定义 User-Agent,Goink 已自动处理,无需额外配置。模型列表随时变动,可用下方「自动发现模型」拉取最新。",
		Temperature:  floatPtr(0.7),
		BuildHeaders: opencodeBuildHeaders,
		Models: []ModelInfo{
			{
				ID:               "glm-5.3",
				Name:             "GLM-5.3",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5.3-flash",
				Name:             "GLM-5.3 Flash",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5.2",
				Name:             "GLM-5.2",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5.1",
				Name:             "GLM-5.1",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "kimi-k3",
				Name:             "Kimi K3",
				ContextWindow:    1_048_576,
				MaxOutputTokens:  131_072,
				SupportsThinking: true,
				ReasoningLevels:  []string{"max"},
				SupportsVision:   true,
			},
			{
				ID:               "kimi-k2.7-code",
				Name:             "Kimi K2.7 Code",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "kimi-k2.6",
				Name:             "Kimi K2.6",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "deepseek-v4-pro",
				Name:             "DeepSeek V4 Pro",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-flash",
				Name:             "DeepSeek V4 Flash",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-flash-vision-exp",
				Name:             "DeepSeek V4 Flash Vision Exp",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "minimax-m3",
				Name:             "MiniMax M3",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "minimax-m2.7",
				Name:             "MiniMax M2.7",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "big-pickle",
				Name:             "Big Pickle",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: false,
				SupportsVision:   false,
			},
			{
				ID:               "mimo-v2.5-free",
				Name:             "MiMo-V2.5 Free",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "ling-3.0-flash-fin-free",
				Name:             "Ling 3.0 Flash Fin Free",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: false,
				SupportsVision:   false,
			},
			{
				ID:               "nemotron-3-ultra-free",
				Name:             "Nemotron 3 Ultra Free",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: false,
				SupportsVision:   false,
			},
			{
				ID:               "nemotron-3.5-lightning-free",
				Name:             "Nemotron 3.5 Lightning Free",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: false,
				SupportsVision:   false,
			},
		},
	},
	"opencode-go": {
		Name:         "OpenCode Go",
		ChatURL:      "https://opencode.ai/zen/go/v1/chat/completions",
		PlatformURL:  "https://opencode.ai/auth",
		HelpText:     "OpenCode Go 是 opencode.ai 的订阅制服务($10/月),覆盖 Kimi/GLM/DeepSeek/MiMo/Hy 等开源模型。在 opencode.ai/auth 注册并订阅 Go 后复制 API Key 填入。OpenCode Go 强制要求携带 x-opencode-session 会话头与自定义 User-Agent,Goink 已自动处理,无需额外配置。模型列表随订阅变动,可用下方「自动发现模型」拉取最新。",
		Temperature:  floatPtr(0.7),
		BuildHeaders: opencodeBuildHeaders,
		Models: []ModelInfo{
			{
				ID:               "kimi-k3",
				Name:             "Kimi K3",
				ContextWindow:    1_048_576,
				MaxOutputTokens:  131_072,
				SupportsThinking: true,
				ReasoningLevels:  []string{"max"},
				SupportsVision:   true,
			},
			{
				ID:               "glm-5.3",
				Name:             "GLM-5.3",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-pro",
				Name:             "DeepSeek V4 Pro",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-flash",
				Name:             "DeepSeek V4 Flash",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4.1-flash",
				Name:             "DeepSeek V4.1 Flash",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "deepseek-v4-flash-vision-exp",
				Name:             "DeepSeek V4 Flash Vision Exp",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  384_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "glm-5.3-flash",
				Name:             "GLM-5.3 Flash",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "kimi-k2.7-code",
				Name:             "Kimi K2.7 Code",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "glm-5.2",
				Name:             "GLM-5.2",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5.1",
				Name:             "GLM-5.1",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "kimi-k2.6",
				Name:             "Kimi K2.6",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "longcat-2.0",
				Name:             "LongCat-2.0",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "mimo-v2.5",
				Name:             "MiMo-V2.5",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "mimo-v2.5-pro",
				Name:             "MiMo-V2.5 Pro",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "hy4-preview",
				Name:             "Hy4 preview",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "hy3",
				Name:             "Hy3",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
		},
	},
	"doubao": {
		Name:        "Doubao",
		ChatURL:     "https://ark.cn-beijing.volces.com/api/v3/chat/completions",
		PlatformURL: "https://console.volcengine.com/ark/",
		HelpText:    "注册火山引擎并实名认证,进入火山方舟控制台。① 在「API 密钥管理」创建 API Key;② 在「开通管理」开通所需模型,每个模型有试用额度。",
		Temperature: floatPtr(0.1),
		Models: []ModelInfo{
			{
				ID:               "doubao-seed-2-1-pro-260628",
				Name:             "Seed 2.1 Pro",
				ContextWindow:    256_000,
				MaxOutputTokens:  256_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "doubao-seed-2-1-turbo-260628",
				Name:             "Seed 2.1 Turbo",
				ContextWindow:    256_000,
				MaxOutputTokens:  256_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "doubao-seed-2-0-lite-260428",
				Name:             "Seed 2.0 Lite",
				ContextWindow:    256_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "doubao-seed-2-0-code-preview-260215",
				Name:             "Seed 2.0 Code Preview",
				ContextWindow:    256_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "doubao-seed-character-260628",
				Name:             "Seed Character",
				ContextWindow:    128_000,
				MaxOutputTokens:  32_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
		},
	},
	"qwen": {
		Name:         "Qwen",
		ChatURL:      "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
		PlatformURL:  "https://platform.qianwenai.com",
		HelpText:     "注册后在「工作台 → API Key 管理」创建密钥。新用户有免费额度,API 地址统一使用 dashscope.aliyuncs.com,无需区分地域。如使用阿里云百炼平台,需自行将上方 Chat URL 替换为百炼地址。",
		Temperature:  floatPtr(0.7),
		BuildRequest: qwenBuildRequest,
		Models: []ModelInfo{
			{
				ID:               "qwen3.7-max",
				Name:             "Qwen3.7 Max",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  64_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "qwen3.7-plus",
				Name:             "Qwen3.7 Plus",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  64_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "qwen3.6-plus",
				Name:             "Qwen3.6 Plus",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  64_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "qwen3.6-flash",
				Name:             "Qwen3.6 Flash",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  64_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
		},
	},
	"zhipu": {
		Name:        "GLM",
		ChatURL:     "https://open.bigmodel.cn/api/paas/v4/chat/completions",
		PlatformURL: "https://open.bigmodel.cn",
		HelpText:    "手机号或微信注册。注册后点击「控制台」→「API Keys」→「新建」创建密钥。注册赠送体验额度。",
		Temperature: floatPtr(1.0),
		Models: []ModelInfo{
			{
				ID:               "glm-5.1",
				Name:             "GLM-5.1",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5",
				Name:             "GLM-5",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-5-turbo",
				Name:             "GLM-5-Turbo",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-4.7",
				Name:             "GLM-4.7",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-4.7-flashx",
				Name:             "GLM-4.7-FlashX",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "glm-4.7-flash",
				Name:             "GLM-4.7 Flash",
				ContextWindow:    200_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
		},
		BuildRequest: nil,
	},
	"minimax": {
		Name:         "MiniMax",
		ChatURL:      "https://api.minimaxi.com/v1/chat/completions",
		PlatformURL:  "https://platform.minimaxi.com",
		HelpText:     "手机号注册。赠送 ¥15 体验金。点击控制台 →「接口管理」→「创建 API Key」获取密钥。按量付费需在「余额」页面充值。",
		Temperature:  floatPtr(1.0),
		BuildRequest: minimaxBuildRequest,
		Models: []ModelInfo{
			{
				ID:               "MiniMax-M3",
				Name:             "MiniMax M3",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "MiniMax-M2.7",
				Name:             "MiniMax M2.7",
				ContextWindow:    204_800,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "MiniMax-M2.5",
				Name:             "MiniMax M2.5",
				ContextWindow:    204_800,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
		},
	},
	"mimo": {
		Name:         "MiMo",
		ChatURL:      "https://api.xiaomimimo.com/v1/chat/completions",
		PlatformURL:  "https://platform.xiaomimimo.com",
		HelpText:     "手机号注册。在控制台左侧「邀请有礼」输入邀请码领取 ¥10 体验金(有效期 40 天),然后在「API Keys」创建密钥。",
		Temperature:  floatPtr(1.0),
		BuildHeaders: mimoBuildHeaders,
		Models: []ModelInfo{
			{
				ID:               "mimo-v2.5-pro",
				Name:             "MiMo V2.5 Pro",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
			{
				ID:               "mimo-v2.5",
				Name:             "MiMo V2.5",
				ContextWindow:    1_000_000,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   false,
			},
		},
		BuildRequest: nil,
	},
	"moonshot": {
		Name:         "Kimi",
		ChatURL:      "https://api.moonshot.cn/v1/chat/completions",
		PlatformURL:  "https://platform.kimi.com",
		HelpText:     "手机号或微信登录。在控制台「API Key 管理」创建密钥。新用户赠送 ¥15 体验金,初始 RPM=3。累计充值 ¥50 升 Tier 1(RPM=200)。",
		BuildRequest: moonshotBuildRequest,
		Models: []ModelInfo{
			{
				ID:               "kimi-k2.7-code",
				Name:             "Kimi K2.7 Code",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "kimi-k2.6",
				Name:             "Kimi K2.6",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "kimi-k2.5",
				Name:             "Kimi K2.5",
				ContextWindow:    262_144,
				MaxOutputTokens:  128_000,
				SupportsThinking: true,
				SupportsVision:   true,
			},
			{
				ID:               "kimi-k3",
				Name:             "Kimi K3",
				ContextWindow:    1_048_576,
				MaxOutputTokens:  131_072,
				SupportsThinking: true,
				ReasoningLevels:  []string{"max"},
				SupportsVision:   true,
			},
		},
	},
}

Builtin 内置 provider 模板。APIKey 留空,运行时由用户配置注入。

Functions

func CountMessageTokens

func CountMessageTokens(msg map[string]any) (int, error)

CountMessageTokens 计算一条 OpenAI 格式消息的 token 数。 与 Python _count_msg_tokens 一致:只算 content + tool_calls + tool_call_id + reasoning_content。

func CountMessagesTokens

func CountMessagesTokens(messages []map[string]any) (total int, byRole map[string]int, err error)

CountMessagesTokens 计算消息列表的总 token 数,并按 role 分组计数。

func CountTokens

func CountTokens(text string) (int, error)

CountTokens 计算一段文本的 token 数。

func Merge

func Merge(builtin map[string]Provider, user *UserLLMConfig) map[string]Provider

Merge 合并内置模板和用户配置,返回组装完成的 Provider map。 内置模型全量加入(随代码版本),用户自定义模型去重追加。只产出用户配置过的 Provider。

func SaveUserConfig

func SaveUserConfig(path string, cfg *UserLLMConfig) error

SaveUserConfig 加密并写入用户 LLM 配置到文件。

Types

type APIError

type APIError struct {
	StatusCode int
	Message    string
	Retryable  bool
	RetryAfter time.Duration // 服务商指定的重试等待时间(来自 Retry-After header),0 表示无指定
	Kind       string        // 错误类型标记,用于 agent 层区分处理路径(如 "tool_args_invalid");空字符串=普通错误
}

APIError 表示 LLM API 的调用错误,包含可重试标记。

func (*APIError) Code

func (e *APIError) Code() apperr.Code

Code 实现 apperr.Coder 接口,将 StatusCode 映射为 apperr.Code 供 apperr.CodeFromError 提取。 映射逻辑从 apperr.codeFromLLMAPIError 搬来(v1.3.0 集中映射改接口模式), apperr 不再 import llm,依赖方向反转为 llm → apperr。

func (*APIError) Error

func (e *APIError) Error() string

type AvailableModel

type AvailableModel struct {
	Key              string // "deepseek/deepseek-v4-pro"
	ModelID          string // "deepseek-v4-pro"(独立字段,不依赖 Key 拆分)
	ProviderKey      string // "deepseek"(小写 key,与 ProviderView.Key 一致,供 ProviderIcon 匹配)
	ProviderName     string // "DeepSeek"
	ModelName        string // "DeepSeek V4 Pro"
	ContextWindow    int
	MaxOutputTokens  int
	SupportsThinking bool
	ReasoningLevels  []string
	SupportsVision   bool
}

AvailableModel 是前端下拉列表的模型选项。

func Models

func Models(providers map[string]Provider) []AvailableModel

Models 从 Provider map 中提取前端下拉列表。

type CallOptions

type CallOptions struct {
	Temperature     *float64 // 不传走 Provider 默认
	MaxTokens       *int     // 不传走 ModelInfo 默认
	ReasoningEffort *string  // 不传从 ModelInfo 取
	ThinkingEnabled *bool    // 不传从 ModelInfo 判断
	ToolChoice      any      // OpenAI tool_choice payload; nil = provider default
	SessionID       string   // 会话标识(如 Goink session_id),仅需要会话感知的服务商消费;空=无会话上下文(hook 内部兜底)
}

CallOptions LLM 调用的可选参数。nil 时全部使用 Provider/ModelInfo 默认值。

type CallToolOptions

type CallToolOptions struct {
	ReasoningEffort string               // 空则不设置
	MaxTokens       int                  // 0 表示走 ModelInfo 默认
	Attempts        int                  // 最大尝试次数,≤1 表示只试一次
	OnStatus        func(CallToolStatus) // 状态回调,可 nil
}

CallToolOptions 是 CallTool 的可选参数。

type CallToolStatus

type CallToolStatus string

CallToolStatus 描述一次 toolcall 调用过程中的状态,用于 OnStatus 回调推送。

const (
	CallToolThinking   CallToolStatus = "thinking"   // 模型推理中
	CallToolGenerating CallToolStatus = "generating" // 模型输出工具参数中
)

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client 是 LLM 流式调用的传输层。 持有多 provider,Run 时根据 providerName 选择合适的后端。

func NewClient

func NewClient(providers map[string]Provider, log *slog.Logger) *Client

NewClient 创建 LLM 客户端。providers 应为 Merge 产出的已组装配置。

func (*Client) CallTool

func (c *Client) CallTool(
	ctx context.Context,
	providerName, modelID string,
	messages []map[string]any,
	tools []map[string]any,
	toolName string,
	opts *CallToolOptions,
) (json.RawMessage, error)

CallTool 请求 LLM 调用指定工具并返回结构化 JSON。

部分供应商的 thinking mode 不兼容 tool_choice,因此只提供 tools, 由提示词约束模型调用目标工具。

tools 数组由调用方组装(通常只含 1 个工具);本函数负责流式接收、 重试、错误聚合。OnStatus 在 LLM 流事件时被调用,nil 时跳过。

返回值是 EventToolCallEnd 的 ArgumentsJSON(json.RawMessage), 调用方按目标类型 json.Unmarshal。

func (*Client) ChatStream

func (c *Client) ChatStream(
	ctx context.Context,
	providerName string,
	messages []map[string]any,
	tools []map[string]any,
	model string,
	opts *CallOptions,
) <-chan StreamEvent

ChatStream 发起流式对话,返回 SSE 事件 channel。

providerName 指明使用哪个 Provider,messages/tools 由调用方按 OpenAI Function Calling 格式组装。 Client 负责拼装完整 payload 并注入流式参数和钩子处理。

ctx 取消时底层 HTTP 连接被中止,channel 随之关闭。

func (*Client) GenerateText

func (c *Client) GenerateText(
	ctx context.Context,
	providerName string,
	messages []map[string]any,
	model string,
) (string, error)

GenerateText 发起非流式对话,返回模型生成的纯文本。 messages 由调用方自行组装,格式与 ChatStream 一致。

func (*Client) ProviderModel

func (c *Client) ProviderModel(providerName, modelID string) (*ModelInfo, bool)

ProviderModel 在指定 provider 中按 model ID 查找模型元信息。

func (*Client) Providers

func (c *Client) Providers() map[string]Provider

Providers 返回当前所有 provider 的只读引用。

func (*Client) Reload

func (c *Client) Reload(providers map[string]Provider)

Reload 热更新 providers 配置。不影响正在进行的 ChatStream(值拷贝)。

type LLMConfigView

type LLMConfigView struct {
	Providers []ProviderView `json:"providers"`
}

LLMConfigView 是 GetLLMConfig 返回的完整配置视图,合并内置模板和用户配置。

func BuildConfigView

func BuildConfigView(user *UserLLMConfig) *LLMConfigView

BuildConfigView 合并内置模板和用户配置,生成前端可用的完整视图。

func (*LLMConfigView) ToUserConfig

func (v *LLMConfigView) ToUserConfig() *UserLLMConfig

ToUserConfig 将前端视图转换回可持久化的 UserLLMConfig。 只保留有 APIKey 的 provider,无 key 的不写入(内置模板由 Merge 自动提供)。

保存用户填的 URL 原值,不再 normalizeURL:

  • 保存前前端已通过 TestConnection 验证 URL,并把探测到的正确 URL 回写到 pv.ChatURL
  • 二次 normalizeURL 会破坏已验证的 URL(测试和保存不一致)
  • 内置 provider 用户未改 URL 时留空,由 Merge 用 bp.ChatURL 兜底

type ModelInfo

type ModelInfo struct {
	ID               string   `json:"id"`                         // 模型标识,如 "deepseek-v4-pro"
	Name             string   `json:"name"`                       // 显示名称,如 "DeepSeek V4 Pro"
	ContextWindow    int      `json:"context_window"`             // 上下文窗口大小(token 数)
	MaxOutputTokens  int      `json:"max_output_tokens"`          // 最大输出 token 数
	SupportsThinking bool     `json:"supports_thinking"`          // 是否支持思考模式
	ReasoningLevels  []string `json:"reasoning_levels,omitempty"` // 多级推理等级,如 ["low","high","max"];nil=二值开关
	SupportsVision   bool     `json:"supports_vision"`            // 是否支持图片输入
}

ModelInfo 描述一个具体模型的元信息。

func DiscoverModels

func DiscoverModels(ctx context.Context, builtin map[string]Provider, providerName, chatURL, apiKey string) ([]ModelInfo, error)

DiscoverModels 调用 /models 端点自动发现可用模型列表。 从 chatURL 推导 modelsURL(去掉 /chat/completions,拼接 /models), 解析标准 OpenAI 格式及 Kimi 等扩展字段。返回的 ModelInfo 中未获取到的字段留零值。

type Provider

type Provider struct {
	Name         string                                                            `json:"name"`                  // 供应商名称,如 "DeepSeek"
	ChatURL      string                                                            `json:"chat_url"`              // 聊天补全端点
	APIKey       string                                                            `json:"api_key,omitempty"`     // API 密钥
	PlatformURL  string                                                            `json:"-"`                     // 注册平台 URL,仅内置模板使用
	HelpText     string                                                            `json:"-"`                     // 注册引导文字,仅内置模板使用
	Models       []ModelInfo                                                       `json:"models"`                // 可用模型列表
	Temperature  *float64                                                          `json:"temperature,omitempty"` // 默认创意度 0~2,nil 表示未设置,运行时取内置默认
	BuildRequest func(payload map[string]any) map[string]any                       `json:"-"`                     // 发送前改造请求体,nil 则原样发送
	BuildHeaders func(opts *CallOptions, base map[string]string) map[string]string `json:"-"`                     // 发送前改造请求头,nil 则使用默认 Bearer 鉴权;opts 可为 nil(无请求级上下文)
	ParseError   func(body []byte) error                                           `json:"-"`                     // 解析非标准错误响应体,nil 则使用默认 OpenAI 格式解析
}

Provider 定义一个大模型供应商的完整配置。 默认行为走 OpenAI 兼容格式,钩子函数用于处理供应商差异。 同时用作用户配置的 JSON 格式(Hooks 不参与序列化,反序列化后为 nil)。

type ProviderView

type ProviderView struct {
	Key           string      `json:"key"`            // provider 标识符,如 "deepseek"
	Name          string      `json:"name"`           // 显示名称
	ChatURL       string      `json:"chat_url"`       // API 端点
	APIKey        string      `json:"api_key"`        // 用户配置的 key,空表示未配置
	PlatformURL   string      `json:"platform_url"`   // 注册平台链接
	HelpText      string      `json:"help_text"`      // 注册引导文字
	Temperature   float64     `json:"temperature"`    // 默认创意度 0~2
	Source        string      `json:"source"`         // "builtin" | "custom"
	BuiltinModels []ModelInfo `json:"builtin_models"` // 内置模型,自定义 provider 为 nil
	CustomModels  []ModelInfo `json:"custom_models"`  // 用户添加的自定义模型
}

ProviderView 是单个 provider 的前端展示视图。

type SourceItem

type SourceItem struct {
	Title string `json:"title"`
	URL   string `json:"url"`
}

SourceItem 是单条搜索结果的元信息。

type StreamEvent

type StreamEvent struct {
	Type  StreamEventType
	Data  string         // EventThinking / EventContent 的文本数据
	Delta *ToolCallDelta // EventToolCallStart / EventToolCallArguments / EventToolCallEnd
	Usage map[string]any // EventUsage 时,原样透传 API 返回的 usage 对象
	Error error          // EventError 时的错误信息
}

StreamEvent 流式对话过程中产出的单个事件。 Data 承载 thinking/content 文本,Delta 承载工具调用信息,Usage 承载 token 统计。 错误事件通过 Error 字段传递。

type StreamEventType

type StreamEventType int

StreamEventType 流式事件的类型。

const (
	EventThinking          StreamEventType = iota // 模型推理/思考内容(DeepSeek reasoning_content)
	EventContent                                  // 普通文本内容
	EventToolCallStart                            // 工具调用开始(携带名称和 ID)
	EventToolCallArguments                        // 工具参数增量(arguments 累计字符串)
	EventToolCallEnd                              // 工具调用完成(arguments 已 parse 为 JSON)
	EventUsage                                    // 本次调用 token 用量
	EventError                                    // 错误(HTTP 错误或网络异常)
)

type TestConnectionInput

type TestConnectionInput struct {
	ProviderName string `json:"provider_name"`
	ChatURL      string `json:"chat_url"`
	APIKey       string `json:"api_key"`
	ModelID      string `json:"model_id"`
}

TestConnectionInput 是连通性测试的参数。

type TestConnectionResult added in v1.4.2

type TestConnectionResult struct {
	URL     string `json:"url"`
	Warning string `json:"warning"`
}

TestConnectionResult 是连通性测试的结果。 URL 是验证通过的实际端点(可能和入参不同,是 fallback 探测到的)。 Warning 是非致命提示(如 429 限流视为通过但提示用户当前被限速)。

func TestConnection

func TestConnection(ctx context.Context, builtin map[string]Provider, input TestConnectionInput) (TestConnectionResult, error)

TestConnection 发送最小化请求验证 provider 连通性。 多层 fallback:对候选 URL 逐个真测(真 key + model + stream + max_tokens=1), 找到第一个返回 200 + text/event-stream + 有效 SSE chunk(含 choices 字段)的候选, 返回该 URL。全部失败返回 error,附带最后一个候选的错误信息。

返回值:

  • (TestConnectionResult{URL:...}, nil):验证通过,URL 是实际可用的端点(可能和入参不同,是 fallback 探测到的)
  • (TestConnectionResult{URL:..., Warning:...}, nil):验证通过但有警告(如 429 限流视为通过)
  • (TestConnectionResult{}, error):所有候选均失败

设计目标:用户填啥都能 work。

调用方(前端)应将返回的 URL 回写到 provider.chat_url,确保保存的 URL 和测试时一致。 Warning 非空时也应展示给用户(不影响 ok 判定,但提示当前被限流等)。

type ToolCallDelta

type ToolCallDelta struct {
	ToolName      string          // EventToolCallStart 时填充
	ToolID        string          // EventToolCallStart 时填充
	ArgumentsText string          // EventToolCallArguments 时,累积后的完整 JSON 字符串
	ArgumentsJSON json.RawMessage // EventToolCallEnd 时,原始 JSON 字节,由调用方按需反序列化
}

ToolCallDelta 描述一次工具调用的增量信息。 工具调用通过 SSE 流分多次下发:先来 ID 和名称,再逐片来 arguments 字符串。 客户端内部维护按 index 的累积缓冲区,流结束后校验并发送原始 JSON。

type UserLLMConfig

type UserLLMConfig struct {
	Providers []Provider `json:"providers"`
}

UserLLMConfig 是用户 LLM 配置的持久化格式(加密 JSON)。 一个 provider 一个 key,内置模型随代码自动更新,自定义模型需完整填写信息。

func LoadUserConfig

func LoadUserConfig(path string) (*UserLLMConfig, error)

LoadUserConfig 从加密文件读取并解密用户 LLM 配置。 文件不存在时返回空的 UserLLMConfig 和 nil error。

type WebSearchResult

type WebSearchResult struct {
	Queries []string     `json:"queries"`
	Summary string       `json:"summary"`
	Sources []SourceItem `json:"sources"`
}

WebSearchResult 是一次 web 搜索的结果。

func SearchWeb

func SearchWeb(ctx context.Context, apiKey, model, query string) (*WebSearchResult, error)

SearchWeb 通过 DeepSeek Anthropic 端点执行一次带搜索的对话。 apiKey 是 DeepSeek 的 API key,model 如 "deepseek-v4-flash",query 是搜索词。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL