llm

package
v1.9.0 Latest Latest
Warning

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

Go to latest
Published: Jul 1, 2026 License: Apache-2.0 Imports: 37 Imported by: 0

README

llm — Eino LLM 高级封装库

基于 Eino 框架的生产级 LLM 工具调用与 Agent 封装库。本 README 旨在为 AI 编程助手提供完整的上下文索引。

ℹ️ 路径选择

  • 新项目请使用 NewADKAgent(go-kit 主推,基于 eino adk.ChatModelAgent);复杂任务用 NewDeepAgent
  • NewAgent(基于 react.Agent)为 go-kit legacy,仅维护向后兼容、不再演进。
  • 「legacy」是 go-kit 自身取向(顺应 eino 把核心能力投入 ADK), eino 已废弃 react。
  • 切换成本:仅改函数名,AgentConfig 完全兼容。
  • 能力对照见 CAPABILITY_DIFF.md,演进决策见 ROADMAP.md

🌟 核心特性

  • 多协议统一路由:一键切换 OpenAI / Claude / DeepSeek / Gemini / Ollama / Moonshot(Kimi) 等模型协议。
  • React Agent 增强:内置工具调用循环、自动重试、死循环检测。
  • StructTool:基于 Go 结构体标签(tag)自动生成 JSON Schema,支持嵌套结构、枚举值。
  • 可观测性:开箱即用的 Langfuse 和自定义 LogClient 集成。
  • 运行时动态控制:支持请求级别的模型替换、工具替换、参数调整。
  • 流式完整支持:从推理到工具调用再到最终回答的全链路流式。

🚀 快速开始

1. 初始化模型配置
cfg := llm.ModelConfig{
    Protocol: llm.OPENAI, // 或 llm.CLAUDE, llm.OLLAMA ...
    BaseURL:  "https://api.openai.com/v1", // 可选
    APIKey:   "sk-xxx",
    Model:    "gpt-4o",
}
2. 定义工具 (推荐 StructTool)

使用 struct 定义目标结构,自动生成 Schema:

type WeatherResult struct {
    City        string `json:"city" desc:"城市" required:"true"`
    Condition   string `json:"condition" desc:"天气情况" required:"true"`
    Temperature string `json:"temperature" desc:"温度" required:"true"`
}

weatherTool := llm.NewStructTool[WeatherResult]("extract_weather", "提取天气结果")
3. 创建 Agent 并运行
// 主推 NewADKAgent(基于 eino adk.ChatModelAgent)。配置与 legacy NewAgent 完全兼容。
agent, _ := llm.NewADKAgent(ctx, llm.AgentConfig{
    Model: llm.AgentModelConfig{Config: cfg},
    Tools: llm.ToolsConfig{Invokable: []llm.InvokableTool{weatherTool}},
    Prompt: llm.PromptConfig{
        System: "从用户请求中提取天气结果,输出必须是合法 JSON。",
    },
    Execution: llm.ExecutionConfig{
        Mode:              llm.Extraction,
        DirectReturnTools: map[string]struct{}{"extract_weather": {}},
    },
})

msg, _ := agent.Generate(ctx, []*schema.Message{
    schema.UserMessage("北京天气晴,25摄氏度。请提取结构化结果。"),
})
fmt.Println(msg.Content)

🛠 高级功能

0. 思考模式 (Thinking)

部分模型支持"思考"模式(如 Claude Extended Thinking、DeepSeek R1、Qwen3 思考模式)。通过 ModelConfig.Thinking 统一控制:

cfg := llm.ModelConfig{
    Protocol: llm.CLAUDE,
    Model:    "claude-sonnet-4-20250514",
    APIKey:   "sk-xxx",
    Thinking: &llm.ThinkingConfig{
        Enable:       true,
        BudgetTokens: 10000, // 仅 Claude 支持
    },
}

供应商映射

供应商 映射方式
Claude Config.Thinking{Enable, BudgetTokens}
OpenAI / Kimi ExtraFields["thinking"] = {"type": "enabled"}
Qwen Config.EnableThinking
DeepSeek Config.ThinkingConfig{Type: "enabled"}
Gemini Config.ThinkingConfig{IncludeThoughts, ThinkingBudget}
Ollama Config.Thinking{Value: true}
Ark Config.Thinking{Type: "enabled"}

语义约定

  • Thinking == nil(默认):不传参数,使用模型自身默认行为
  • Thinking.Enable = true:显式开启思考
  • Thinking.Enable = false:显式关闭(用于关闭默认开启思考的模型,如 DeepSeek R1)

Extraction 模式自动关闭

当使用 Extraction 模式(强制 tool call)时,思考模式会自动关闭。因为 Qwen/DeepSeek 等模型的思考模式与 tool_choice: required 不兼容,同时使用会导致 API 报错。

1. 额外参数透传 (ExtraFields)

通过 ModelConfig.ExtraFields 可以透传任意参数到请求 JSON 的第一层:

cfg := llm.ModelConfig{
    Protocol:    llm.OPENAI,
    Model:       "gpt-4o",
    APIKey:      "sk-xxx",
    ExtraFields: map[string]any{
        "custom_param": "value",
    },
}

支持透传的供应商:Claude(AdditionalRequestFields)、OpenAI/Kimi(ExtraFields)、Qwen(继承 OpenAI)。DeepSeek 暂不支持 config 级透传。

优先级:用户 ExtraFields 优先于 ThinkingConfig 自动生成的字段,可用于覆盖默认映射。

2. 执行模式与配置约束

推荐优先使用 Execution.Mode 描述 Agent 行为:

  • Conversation:纯对话,不启用工具
  • Assistant:工具可用,由模型自行决定是否调用
  • Extraction:先完成工具任务,再决定是否总结

配置约束:

  • ModeToolChoice 同时传入时,以 Mode 为准;ToolChoice 仅保留兼容路径
  • Conversation 不允许同时配置工具、MaxRetriesDirectReturnTools
  • Assistant 不允许配置 MaxRetries
  • DirectReturnTools 中的工具名必须真实存在,否则 NewAgent 会直接返回错误
3. 可观测性 (Observability)

llm 现在有两条互补的观测链路:

  • Callbacks / NewLogHandler:保留现有组件级日志语义,适合看底层 ChatModel / Tool 组件有没有被调用
  • StructuredLogs:新增的 Agent 语义日志,适合排查“为什么没调工具 / 为什么重试 / 为什么 direct return”

两者可以同时开启:

// 初始化 Langfuse
lfHandler, flush, _ := llm.NewLangfuseHandler(&llm.LangfuseConfig{...})
defer flush()

// 初始化日志客户端(示例:go-kit/kit)
logger := kit.New(kit.Options{Format: kit.FormatJSON})
logHandler := llm.NewLogHandler(logger)

// 注入 Agent
agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    // ...
    Observability: llm.ObservabilityConfig{
        Callbacks: []callbacks.Handler{lfHandler, logHandler},
        StructuredLogs: &llm.StructuredLogConfig{
            Client:           logger,
            LogToolArguments: true,
            LogToolResults:   true,
            MaxFieldLength:   256,
        },
    },
})

说明:

  • NewLogHandler 的输出语义没有改,仍然只输出 Component Start / Component End / Component Error
  • NewLogHandlerStructuredLogs 现在都依赖 LogClient 接口,而不是 *slog.Logger
  • LogClient 只要求实现 Info(ctx, msg, fields...)Error(ctx, msg, fields...)
  • StructuredLogs 会输出 agent.start / model.decision / tool.start / tool.success / tool.error / agent.end
  • 当前没有为 RuntimeSpec 做缓存;构造成本不在热路径,不值得为此引入额外状态
  • 当前不承诺公开 ParentMessageID 一类字段;上游 schema.Message 没有稳定的顶层 message id
  • 结构化日志和 callback 日志都会继承调用时的 ctx;如果你的 LogClient 会从 ctx 提取 trace_id/request_id,这些字段会自然出现在日志里
  • 每次 Generate / Stream 都会生成一个 invocation_id,用于区分并发链路

常用字段:

  • invocation_id:单次 Generate / Stream 的链路标识
  • agent.startexecution_modetool_countdirect_return_enabledmessage_count
  • model.decisionconfigured_tool_choicetool_call_counttool_namesfinish_reasonreasoning_tokens
  • tool.starttool_nametool_call_idattemptarguments
  • tool.successtool_nameattemptlatency_msresultdirect_return
  • tool.errortool_nameattemptlatency_msretryableterminalerror
  • agent.endstatuslatency_msdirect_return

Assistant 场景日志示例:

{"level":"INFO","msg":"agent.start","event":"agent.start","invocation_id":"inv-001","execution_mode":"assistant","tool_count":1,"direct_return_enabled":false,"message_count":1}
{"level":"INFO","msg":"model.decision","event":"model.decision","invocation_id":"inv-001","execution_mode":"assistant","configured_tool_choice":"allowed","tool_call_count":1,"tool_names":["lookup_user"],"finish_reason":"tool_calls"}
{"level":"INFO","msg":"tool.start","event":"tool.start","invocation_id":"inv-001","tool_name":"lookup_user","tool_call_id":"tc1","attempt":1,"arguments":"{\"name\":\"Alice\"}"}
{"level":"INFO","msg":"tool.success","event":"tool.success","invocation_id":"inv-001","tool_name":"lookup_user","tool_call_id":"tc1","attempt":1,"latency_ms":12,"result":"{\"name\":\"Alice\"}"}
{"level":"INFO","msg":"agent.end","event":"agent.end","invocation_id":"inv-001","execution_mode":"assistant","tool_count":1,"direct_return_enabled":false,"latency_ms":38,"status":"success"}

Extraction 重试 + direct return 日志示例:

{"level":"INFO","msg":"agent.start","event":"agent.start","invocation_id":"inv-002","execution_mode":"extraction","tool_count":1,"direct_return_enabled":true,"message_count":1}
{"level":"INFO","msg":"model.decision","event":"model.decision","invocation_id":"inv-002","execution_mode":"extraction","configured_tool_choice":"forced","tool_call_count":1,"tool_names":["extract_resume"]}
{"level":"INFO","msg":"tool.start","event":"tool.start","invocation_id":"inv-002","tool_name":"extract_resume","tool_call_id":"tc1","attempt":1,"arguments":"{\"query\":\"bad\"}"}
{"level":"ERROR","msg":"tool.error","event":"tool.error","invocation_id":"inv-002","tool_name":"extract_resume","tool_call_id":"tc1","attempt":1,"latency_ms":4,"retryable":true,"terminal":false,"error":"missing required field"}
{"level":"INFO","msg":"model.decision","event":"model.decision","invocation_id":"inv-002","execution_mode":"extraction","configured_tool_choice":"forced","tool_call_count":1,"tool_names":["extract_resume"]}
{"level":"INFO","msg":"tool.start","event":"tool.start","invocation_id":"inv-002","tool_name":"extract_resume","tool_call_id":"tc2","attempt":2,"arguments":"{\"query\":\"good\"}"}
{"level":"INFO","msg":"tool.success","event":"tool.success","invocation_id":"inv-002","tool_name":"extract_resume","tool_call_id":"tc2","attempt":2,"latency_ms":6,"result":"{\"name\":\"Alice\"}","direct_return":true}
{"level":"INFO","msg":"agent.end","event":"agent.end","invocation_id":"inv-002","execution_mode":"extraction","tool_count":1,"direct_return_enabled":true,"latency_ms":29,"status":"success","direct_return":true}

排障顺序建议:

  1. 先看 agent.start,确认 execution_modetool_countdirect_return_enabled 是否符合预期
  2. 再看 model.decision,判断模型是否真的产出了 tool_calls
  3. 如果有 tool.start 但没有 tool.success,继续看 tool.errorretryable / terminal
  4. 如果工具成功但结果不像最终回答,检查 direct_return 是否命中,或者是否仍回到了模型总结
4. Extraction 模式与失败修复
agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    // ...
    Execution: llm.ExecutionConfig{
        Mode:       llm.Extraction, // 强制模型先完成工具任务
        MaxRetries: 3,              // 工具报错后反馈给模型修正再试
    },
})

MaxRetries 只在 Extraction 模式下有效;如果放到 ConversationAssistantNewAgent 会直接报错。

5. 工具结果直接返回 (Direct Return)

某些场景下(如搜索),工具执行后不需要模型再通过 LLM 总结,直接返回工具结果可节省 Token:

agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    // ...
    Execution: llm.ExecutionConfig{
        Mode: llm.Assistant,
        DirectReturnTools: map[string]struct{}{
            "search_tool": {}, // 执行完 search_tool 后立即结束对话并返回结果
        },
    },
})

DirectReturnTools 只能填写已经注册到 Tools.StandardTools.Invokable 或 MCP 中的工具名。

6. 运行时动态控制 (Runtime Options)

GenerateStream 时动态修改行为,不影响 Agent 实例。

import "github.com/cloudwego/eino/flow/agent"

// 场景 A: 临时更换模型 (例如降级到 3.5)
agent.Generate(ctx, input, agent.WithChatModel(gpt35Model))

// 场景 B: 调整温度
agent.Generate(ctx, input, agent.WithChatModelOptions(model.WithTemperature(0.1)))

// 场景 C: 获取中间状态 (Result Event Stream)
logOpt, future := agent.WithMessageFuture()
go func() {
    defer future.Close()
    stream, _ := future.GetMessageStreams()
    for { msg, _ := stream.Recv(); fmt.Println("中间状态:", msg) }
}()
agent.Generate(ctx, input, logOpt)

ADK 路径(NewADKAgent / NewDeepAgent)的运行时参数:使用 go-kit 选项, 仅支持参数调整(运行时换模型请新建 Agent 实例):

agent.Generate(ctx, input, llm.WithTemperature(0.1), llm.WithMaxTokens(512), llm.WithTopP(0.9))
// 高级:透传任意 eino model.Option
agent.Generate(ctx, input, llm.WithModelOptions(model.WithStop([]string{"\n"})))
7. 多模态输入 (Multimodal)

为支持图片/音频的模型(GPT-4o / Claude 3+ / Gemini 等)构造多模态用户消息。 URL 支持 HTTP(S) 链接或 data: URI:

URL 仅允许 http / https / data(base64 data URI)协议,其它(如 file://) 返回 llm.ErrUnsupportedContentURLScheme(防本地文件读取 / SSRF 纵深防御):

// 单图 + 文本
msg, err := llm.UserImageMessage("https://example.com/cat.png", "这是什么动物?")
if err != nil { /* 处理非法 URL 协议 */ }
// 多图 + 文本(顺序保留)
msg, _ = llm.UserImageMessages([]string{urlA, urlB}, "对比这两张图")
// 音频 + 文本
msg, _ = llm.UserAudioMessage("https://example.com/a.wav", "转写这段音频")

resp, _ := agent.Generate(ctx, []*schema.Message{msg})
8. 工具层防御 (Tool Defense)

应对模型幻觉工具名、坏参数 JSON、工具执行报错,避免 Agent 流程中断。 四项均为可选,未配置时行为不变;react 与 ADK 两路均生效:

errToText := true
tools := llm.ToolsConfig{
    Invokable: []llm.InvokableTool{myTool},
    // 工具名别名:模型输出别名 → 路由到规范工具名
    Aliases: map[string][]string{"search": {"find", "query_tool"}},
    // 模型调用未注册工具时的兜底(返回文本让模型纠错)
    UnknownHandler: func(ctx context.Context, name, input string) (string, error) {
        return "unknown tool: " + name + ",请改用已注册的工具", nil
    },
    // 执行前修复参数 JSON
    ArgumentsFixer: func(ctx context.Context, name, args string) (string, error) {
        return sanitizeJSON(args), nil
    },
    // 工具报错转文本回传模型(默认关闭,生产推荐开启)
    ErrorToText: &errToText,
}
9. 模型调用自动重试 (Model Retry)

当模型 API 返回限速(429)、服务不可用(502/503)等暂态错误时,自动重试,无需业务层处理。

NewADKAgent 路径生效;NewAgent(legacy)不受影响。

agent, _ := llm.NewADKAgent(ctx, llm.AgentConfig{
    Model: llm.AgentModelConfig{Config: cfg},
    Resilience: llm.ResilienceConfig{
        ModelRetry: llm.ModelRetryConfig{
            MaxRetries: 3, // 最多重试 3 次(不含首次调用)
        },
    },
})

内置重试规则(默认 IsRetryAble):

触发重试 不触发
429 / rate limit / too many requests context.Canceled / context.DeadlineExceeded
502 Bad Gateway 400 / 401 / 403 / 404(客户端错误)
503 Service Unavailable 其他未知错误

退避策略由 eino 内置实现:首次 100ms,指数增长,上限 10s,含随机抖动。

自定义重试规则

ModelRetry: llm.ModelRetryConfig{
    MaxRetries: 3,
    IsRetryAble: func(err error) bool {
        return strings.Contains(err.Error(), "upstream connect error")
    },
},

📦 架构说明

llm 包是对 CloudWeGo Eino 框架的 Opinionated 封装:

  • Model: 实现了 eino/components/model 接口。
  • Agent: 封装了 eino/flow/agent/react
  • Tool: 提供了 StructTooleino/components/tool 的适配器。

如需更复杂的编排(如多 Agent 协作),可使用 agent.ExportGraph() 导出底层 Graph 节点,嵌入到 Eino 的 Graph 中。

Documentation

Overview

Package llm 提供大模型 Agent 的统一封装。

路径选择:

  • 新代码请使用 NewADKAgent(基于 eino adk.ChatModelAgent,go-kit 主推路径)。
  • NewDeepAgent 用于复杂任务(内置规划/子Agent委派/文件系统/Shell 的预置应用)。
  • NewAgent(基于 eino react.Agent)为 go-kit legacy 路径,仅维护向后兼容、 不再演进;新能力只在 ADK 路径实现。

说明:「legacy」是 go-kit 自身的产品取向(顺应 eino 把核心能力投入 ADK 的方向), 并不代表 eino 已废弃 react —— 截至 eino v0.9.8,flow/agent/react 仍在维护。 切换成本:仅改函数名,AgentConfig 配置完全兼容。

三个工厂共享配置层(AgentConfig)和模型工厂(NewModel):

  • NewADKAgent: 基于 eino adk.ChatModelAgent(v0.9 ADK 路径,主推)
  • NewDeepAgent: 基于 eino adk.DeepAgent(内置规划/子Agent委派/文件系统/Shell)
  • NewAgent: 基于 eino react.Agent(legacy,向后兼容)

核心能力:

  • 多供应商模型路由(OpenAI/Claude/DeepSeek/Gemini/Ark/Ollama/Qwen 等)
  • 三种执行模式:Conversation(纯对话)、Assistant(工具可选)、 Extraction(强制工具调用 + 失败修复重试)
  • 并发控制(ConcurrencyConfig.MaxConcurrency,Agent 调用级信号量, 多实例互不影响)
  • 模型调用自动重试(ResilienceConfig.ModelRetry,429/502/503 等暂态错误, 仅 ADK 路径,内置退避;可自定义 IsRetryAble 规则)
  • 思考模式统一配置(ThinkingConfig,Extraction 模式自动关闭)
  • 多模态输入(UserImageMessage/UserImageMessages/UserAudioMessage, http/https/data URL 协议白名单)
  • MCP 工具集成
  • 工具防御层(ToolsConfig 的 Aliases / UnknownHandler / ArgumentsFixer / ErrorToText)
  • 可观测性(Langfuse callback、结构化日志)

Extraction 模式下强制工具调用时会自动关闭思考模式, 因为部分模型在 tool_choice=forced 下对 reasoning 输出支持不稳定, 且 Extraction 场景只需确定性参数提取,无需额外推理。

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMissingModel 模型名缺失(ModelConfig.Model 为空)。
	ErrMissingModel = errors.New("llm: model is required")

	// ErrMissingBaseURL 兼容协议(OPENAI_COMPAT / CLAUDE_COMPAT)缺少 BaseURL。
	ErrMissingBaseURL = errors.New("llm: base url is required for compat protocol")

	// ErrMissingAPIKey 调用所需 Provider 时缺少 API Key。
	ErrMissingAPIKey = errors.New("llm: api key is required")

	// ErrUnsupportedProtocol 不支持的 ModelProtocol。
	ErrUnsupportedProtocol = errors.New("llm: unsupported model protocol")

	// ErrInvalidConfig AgentConfig 配置无效或冲突(执行模式与其它字段冲突等)。
	ErrInvalidConfig = errors.New("llm: invalid agent config")

	// ErrExtractionRetriesExhausted Extraction 模式重试耗尽,
	// 模型未能产出符合工具 JSON Schema 的参数。
	ErrExtractionRetriesExhausted = errors.New("llm: extraction retries exhausted")

	// ErrUnknownMCPProtocol 未知的 MCP 协议(仅支持 "stdio" / "sse")。
	ErrUnknownMCPProtocol = errors.New("llm: unknown mcp protocol")

	// ErrUnsupportedContentURLScheme 多模态内容 URL 使用了不允许的协议。
	// 仅允许 http / https / data,拒绝 file:// 等以防本地文件读取 / SSRF。
	ErrUnsupportedContentURLScheme = errors.New("llm: unsupported content url scheme")
)

包级 sentinel error 定义。

调用方可通过 errors.Is(err, llm.ErrXxx) 精确判断错误类型, 而非依赖脆弱的字符串匹配。所有错误均以 fmt.Errorf("...: %w", ErrXxx) 形式包装,保留具体上下文(如 protocol 值)的同时支持 errors.Is。

Functions

func CombineTools added in v1.1.0

func CombineTools(args ...interface{}) []tool.BaseTool

CombineTools 合并单个工具或工具列表。 支持 tool.BaseTool 和 []tool.BaseTool 类型。 对于不支持的类型,会打印警告并忽略。

func ErrorToTextEnabled added in v1.9.0

func ErrorToTextEnabled() *bool

ErrorToTextEnabled 返回一个指向 true 的 *bool,便于内联配置 ToolsConfig.ErrorToText:

Tools: llm.ToolsConfig{ErrorToText: llm.ErrorToTextEnabled()}

func NewLangfuseHandler added in v1.1.0

func NewLangfuseHandler(cfg *LangfuseConfig) (callbacks.Handler, func(), error)

NewLangfuseHandler 创建一个 Langfuse 回调处理器。 返回的 flush 函数应该在程序退出前调用,确保所有 Trace 上报完成。

func NewLogHandler added in v1.1.0

func NewLogHandler(client LogClient) callbacks.Handler

NewLogHandler 创建一个基于 LogClient 的日志回调处理器。 它会记录组件的输入、输出和 Token 消耗(如果有),并沿用调用时的 ctx。

func NewMCPTools added in v1.1.0

func NewMCPTools(ctx context.Context, cfg MCPConfig) ([]tool.BaseTool, func() error, error)

NewMCPTools 创建 MCP Client 并加载工具。 返回工具列表和清理函数。清理函数用于关闭 Client。 注意:Client 的底层运行依赖于内部创建的 Context,该 Context 会在调用 cleanup 时取消。 传入的 ctx 仅用于初始化过程(握手超时控制)。

func NewModel added in v1.1.0

NewModel 根据 Protocol 创建对应的 eino-ext ToolCallingChatModel。

func UserAudioMessage added in v1.9.0

func UserAudioMessage(audioURL, text string) (*schema.Message, error)

UserAudioMessage 构造一条「音频 + 文本」用户消息(如 Gemini / GPT-4o-audio)。

func UserImageMessage added in v1.9.0

func UserImageMessage(imageURL, text string) (*schema.Message, error)

UserImageMessage 构造一条「图片 + 文本」用户消息。text 为空时仅含图片。

func UserImageMessages added in v1.9.0

func UserImageMessages(imageURLs []string, text string) (*schema.Message, error)

UserImageMessages 构造一条「多图 + 文本」用户消息,图片顺序保留。

Types

type ADKAgent added in v1.9.0

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

ADKAgent 基于 eino adk.ChatModelAgent 的 Agent 实现(v0.9 ADK 后端)。

与现有 Agent(react-based)并存:

  • NewAgent → react.Agent(v0.8 路径,保留向后兼容)
  • NewADKAgent → adk.ChatModelAgent(v0.9 路径,享受 ADK 新能力)

两者共享 AgentConfig / compileRuntimeSpec / NewModel / extractionState, 只在执行引擎层分叉。

func NewADKAgent added in v1.9.0

func NewADKAgent(ctx context.Context, cfg AgentConfig) (*ADKAgent, error)

NewADKAgent 创建基于 adk.ChatModelAgent 的 Agent。

配置复用 AgentConfig,执行引擎为 ADK(v0.9)。行为语义与 NewAgent 一致:

  • Conversation: 纯对话
  • Assistant: 工具可选
  • Extraction: 强制工具调用 + 失败修复重试(通过 ChatModelAgentMiddleware 实现)

并发控制通过 Concurrency.MaxConcurrency 配置,与 Agent 相同。

func NewDeepAgent added in v1.9.0

func NewDeepAgent(ctx context.Context, cfg DeepAgentConfig) (*ADKAgent, error)

NewDeepAgent 创建基于 adk.DeepAgent 的复杂任务 Agent。

DeepAgent 内置任务规划(write_todos)、子 Agent 委派(task)、 文件系统操作和 Shell 执行,适合"分析 CSV 并生成图表"这类 需要规划 + 多步 + 文件操作的复杂任务。

返回 *ADKAgent,与 NewADKAgent 返回类型一致,复用 Generate/Stream/Close/Agent API。 并发控制通过 Concurrency.MaxConcurrency 配置。

与 NewADKAgent(ChatModelAgent)的区别:

  • NewADKAgent:通用工具调用 Agent,你给什么工具用什么
  • NewDeepAgent:内置规划/子Agent委派/文件系统/Shell 的全家桶

func (*ADKAgent) Agent added in v1.9.0

func (a *ADKAgent) Agent() adk.Agent

Agent 返回底层 adk.Agent,用于将此 Agent 作为子 Agent 传给 NewDeepAgent 等需要 adk.Agent 的场景。

func (*ADKAgent) Close added in v1.9.0

func (a *ADKAgent) Close() error

Close 释放 Agent 持有的资源(如 MCP 工具连接)。

func (*ADKAgent) Generate added in v1.9.0

func (a *ADKAgent) Generate(ctx context.Context, messages []*schema.Message, opts ...GenerateOption) (msg *schema.Message, err error)

Generate 非流式调用 Agent。 内部消费 ADK 事件流,取最终 assistant 消息。

func (*ADKAgent) Stream added in v1.9.0

func (a *ADKAgent) Stream(ctx context.Context, messages []*schema.Message, opts ...GenerateOption) (*schema.StreamReader[*schema.Message], error)

Stream 流式调用 Agent。 返回最终模型输出的流式 StreamReader;并发名额在流消费结束时释放。

type Agent added in v1.1.0

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

Agent 封装 Eino ReactAgent,提供简化的高层 API。

func NewAgent added in v1.1.0

func NewAgent(ctx context.Context, cfg AgentConfig) (*Agent, error)

NewAgent 创建一个 Agent。 Mode 是推荐配置入口;如果 Mode 和 ToolChoice 同时设置,以 Mode 为准。

配置约束:

  • Conversation 不允许同时配置工具、MaxRetries 或 DirectReturnTools
  • Assistant 不允许配置 MaxRetries
  • DirectReturnTools 只能引用已注册的工具名

使用示例:

// 场景 1: 纯对话
agent, _ := llm.NewAgent(ctx, llm.AgentConfig{Model: llm.AgentModelConfig{Config: cfg}})
msg, _ := agent.Generate(ctx, messages)

// 场景 2: 强制调工具 → 结果回模型 → 模型决策
agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    Model: llm.AgentModelConfig{Config: cfg},
    Tools: llm.ToolsConfig{Invokable: []llm.InvokableTool{myTool}},
    Execution: llm.ExecutionConfig{Mode: llm.Extraction},
})

// 场景 3: 强制调工具 → 直接拿结果
agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    Model: llm.AgentModelConfig{Config: cfg},
    Tools: llm.ToolsConfig{Invokable: []llm.InvokableTool{myTool}},
    Execution: llm.ExecutionConfig{
        Mode:              llm.Extraction,
        DirectReturnTools: map[string]struct{}{"my_tool": {}},
    },
})

func (*Agent) Close added in v1.4.1

func (a *Agent) Close() error

func (*Agent) ExportGraph added in v1.1.0

func (a *Agent) ExportGraph() (compose.AnyGraph, []compose.GraphAddNodeOpt)

ExportGraph 导出底层 Graph,用于嵌入更大的编排图。

func (*Agent) Generate added in v1.1.0

func (a *Agent) Generate(ctx context.Context, messages []*schema.Message, opts ...agent.AgentOption) (msg *schema.Message, err error)

Generate 非流式调用 Agent。 模型会自动处理工具调用循环,直到返回最终答案。

func (*Agent) Stream added in v1.1.0

func (a *Agent) Stream(ctx context.Context, messages []*schema.Message, opts ...agent.AgentOption) (*schema.StreamReader[*schema.Message], error)

Stream 流式调用 Agent。 完整支持流式 tool call:模型推理 → 工具调用 → 再推理,全程流式。

type AgentConfig added in v1.1.0

type AgentConfig struct {
	Model         AgentModelConfig
	Prompt        PromptConfig
	Tools         ToolsConfig
	Execution     ExecutionConfig
	Streaming     StreamingConfig
	Observability ObservabilityConfig
	Concurrency   ConcurrencyConfig
	Resilience    ResilienceConfig

	// Middlewares 是用户自定义的 ADK ChatModelAgentMiddleware,仅 NewADKAgent
	// 路径生效(NewAgent legacy 路径忽略)。可用于接入 Eino 生态的内置
	// Middleware(如 ModelRetry / ModelFailover)或任意自定义钩子。
	//
	// 执行顺序:用户 Middleware 先于包内 Middleware(extraction / observability)
	// 注册,因此用户钩子可观察/拦截到包内行为。
	Middlewares []adk.ChatModelAgentMiddleware
}

type AgentModelConfig added in v1.4.1

type AgentModelConfig struct {
	Config   ModelConfig
	Instance model.ToolCallingChatModel
}

type ConcurrencyConfig added in v1.9.0

type ConcurrencyConfig struct {
	// MaxConcurrency 限制同一 Agent 实例上 Generate/Stream 的并发数。
	// 0 表示不限制(默认)。到达上限后新的调用会阻塞等待已有调用释放名额,
	// 等待中的调用可被 context 取消打断。
	MaxConcurrency int
}

ConcurrencyConfig 控制单个 Agent 实例的最大并发调用数。

type DeepAgentConfig added in v1.9.0

type DeepAgentConfig struct {
	// Model 是底层模型配置。
	Model AgentModelConfig

	// Name 和 Description 标识 Agent,用作子 Agent 时必填。
	Name        string
	Description string

	// Instruction 是 system prompt。为空时使用 DeepAgent 内置默认 prompt
	//(含通用助手行为、安全策略、编码风格、工具使用指南)。
	Instruction string

	// SubAgents 是可被 DeepAgent 委派任务的子 Agent。
	// 通过 ADKAgent.Agent() 获取底层 adk.Agent 传入。
	SubAgents []adk.Agent

	// Tools 是额外工具(除 DeepAgent 内置工具外)。
	Tools ToolsConfig

	// MaxIteration 限制最大推理迭代次数。
	MaxIteration int

	// Backend 设置后启用文件系统工具(read_file/write_file/edit_file/glob/grep)。
	// 可用 filesystem.NewInMemoryBackend() 创建内存实现。
	Backend filesystem.Backend

	// Shell 设置后启用 Shell 执行工具(非流式)。与 StreamingShell 互斥。
	Shell filesystem.Shell

	// StreamingShell 设置后启用流式 Shell 执行。与 Shell 互斥。
	StreamingShell filesystem.StreamingShell

	// WithoutWriteTodos 禁用内置 write_todos 规划工具。
	WithoutWriteTodos bool

	// WithoutGeneralSubAgent 禁用默认通用子 Agent。
	WithoutGeneralSubAgent bool

	// Concurrency 控制并发调用数(与 ADKAgent 相同语义)。
	Concurrency ConcurrencyConfig
}

DeepAgentConfig 是 NewDeepAgent 的配置。

DeepAgent 基于 eino adk.DeepAgent,内置任务规划(write_todos)、 子 Agent 委派(task)、文件系统工具和 Shell 执行, 适合需要多步规划 + 文件操作的复杂任务。

type ExecutionConfig added in v1.4.1

type ExecutionConfig struct {
	// Mode 是推荐配置入口,用于声明 Agent 的高层执行模式。
	Mode ExecutionMode
	// Deprecated: ToolChoice 仅保留给 legacy-only 兼容路径;新代码应优先使用 Mode。
	ToolChoice *schema.ToolChoice
	// MaxRetries 仅用于 Extraction;Conversation 和 Assistant 会拒绝该配置。
	MaxRetries int
	MaxStep    int
	// DirectReturnTools 仅允许引用已注册的工具名;Conversation 会拒绝该配置。
	DirectReturnTools map[string]struct{}
}

type ExecutionMode added in v1.4.1

type ExecutionMode string
const (
	// Conversation 表示纯对话,不启用工具。
	Conversation ExecutionMode = "conversation"
	// Assistant 表示工具可用,由模型自行决定是否调用。
	Assistant ExecutionMode = "assistant"
	// Extraction 表示先完成工具任务,再决定是否继续总结。
	Extraction ExecutionMode = "extraction"
)

type GenerateOption added in v1.9.0

type GenerateOption func(*generateConfig)

GenerateOption 是 ADKAgent.Generate / Stream 的运行时选项。

仅支持「运行时参数调整」(Temperature / MaxTokens / TopP 等),不支持 运行时整体替换模型——后者与 ADKAgent「构造时预建 runner」的设计冲突, 如需换模型请新建一个 Agent 实例(见 ROADMAP DR / O-004)。

func WithMaxTokens

func WithMaxTokens(n int) GenerateOption

WithMaxTokens 单次请求覆盖最大生成 token 数。

func WithModelOptions added in v1.9.0

func WithModelOptions(opts ...model.Option) GenerateOption

WithModelOptions 透传任意 eino model.Option(高级用法)。

func WithTemperature

func WithTemperature(t float32) GenerateOption

WithTemperature 单次请求覆盖采样温度。

func WithTopP

func WithTopP(p float32) GenerateOption

WithTopP 单次请求覆盖 top-p。

type InvokableTool added in v1.1.0

type InvokableTool interface {
	Info() *schema.ToolInfo
	Invoke(ctx context.Context, args string) (string, error)
}

InvokableTool 代表一个可执行工具(定义 + 执行能力)。 这是一个简化接口,可通过 ToolAdapter 适配到 Eino 标准 tool.InvokableTool。

type LangfuseConfig added in v1.1.0

type LangfuseConfig struct {
	Host      string
	PublicKey string
	SecretKey string
}

LangfuseConfig 是 Langfuse 的配置。

type LogClient added in v1.4.1

type LogClient interface {
	Info(ctx context.Context, msg string, fields ...any)
	Error(ctx context.Context, msg string, fields ...any)
}

type MCPConfig added in v1.1.0

type MCPConfig struct {
	Name    string // 此客户端的标识符
	Version string // 客户端版本,默认为 1.0.0

	Protocol MCPProtocol

	// Stdio 特定配置
	Command string
	Args    []string
	Env     []string

	// SSE 特定配置
	BaseURL string

	// 可选:过滤要包含的工具
	// 若为空,则加载所有工具
	ToolWhitelist []string
}

MCPConfig 定义单个 MCP 服务器连接的配置。

type MCPProtocol added in v1.1.0

type MCPProtocol string

MCPProtocol 定义 MCP 的传输协议。

const (
	MCPProtocolStdio MCPProtocol = "stdio"
	MCPProtocolSSE   MCPProtocol = "sse"
)

type MessageModifier added in v1.1.0

type MessageModifier = react.MessageModifier

MessageModifier 在每轮调用模型前修改消息列表。 常用于注入 system prompt 或上下文压缩。

type ModelConfig added in v1.1.0

type ModelConfig struct {
	Protocol ModelProtocol
	BaseURL  string
	APIKey   string
	Model    string
	Timeout  time.Duration

	MaxTokens   *int
	Temperature *float32
	TopP        *float32
	Stop        []string

	Thinking    *ThinkingConfig
	ExtraFields map[string]any
}

type ModelProtocol added in v1.1.0

type ModelProtocol string

ModelProtocol 定义模型厂商协议。

const (
	OPENAI        ModelProtocol = "OPENAI"
	OPENAI_COMPAT ModelProtocol = "OPENAI_COMPAT"
	CLAUDE        ModelProtocol = "CLAUDE"
	CLAUDE_COMPAT ModelProtocol = "CLAUDE_COMPAT"
	ARK           ModelProtocol = "ARK"
	ARKBOT        ModelProtocol = "ARKBOT"
	DEEPSEEK      ModelProtocol = "DEEPSEEK"
	GEMINI        ModelProtocol = "GEMINI"
	OLLAMA        ModelProtocol = "OLLAMA"
	QIANFAN       ModelProtocol = "QIANFAN"
	QWEN          ModelProtocol = "QWEN"
	KIMI          ModelProtocol = "KIMI"
)

type ModelRetryConfig added in v1.9.0

type ModelRetryConfig struct {
	// MaxRetries 最大重试次数(不含首次调用)。0 表示不重试。
	MaxRetries int
	// IsRetryAble 判断错误是否值得重试。
	// nil 时使用内置规则:429 / 502 / 503 / rate limit / too many requests;
	// 不重试 context 取消/超时及 4xx 客户端错误。
	IsRetryAble func(error) bool
}

ModelRetryConfig 控制 ADKAgent 模型调用的自动重试。 仅 NewADKAgent 路径生效;NewAgent(react)不受影响。

type ObservabilityConfig added in v1.4.1

type ObservabilityConfig struct {
	Callbacks      []callbacks.Handler
	StructuredLogs *StructuredLogConfig
}

type PromptConfig added in v1.4.1

type PromptConfig struct {
	System          string
	PrepareMessages MessageModifier
	RewriteHistory  MessageModifier
}

type ResilienceConfig added in v1.9.0

type ResilienceConfig struct {
	ModelRetry ModelRetryConfig
}

ResilienceConfig 控制 ADKAgent 的容错行为。

type RuntimeExecutionSpec added in v1.4.1

type RuntimeExecutionSpec struct {
	Mode              ExecutionMode
	DisableTools      bool
	ToolChoice        schema.ToolChoice
	RepairMaxAttempts int
	MaxStep           int
	DirectReturnTools map[string]struct{}
}

type RuntimeSpec added in v1.4.1

type RuntimeSpec struct {
	Model         AgentModelConfig
	Prompt        PromptConfig
	Tools         ToolsConfig
	Execution     RuntimeExecutionSpec
	Streaming     StreamingConfig
	Observability ObservabilityConfig
	Concurrency   ConcurrencyConfig
}

type StreamingConfig added in v1.4.1

type StreamingConfig struct {
	ToolCallChecker func(ctx context.Context, sr *schema.StreamReader[*schema.Message]) (bool, error)
}

type StructTool added in v1.1.0

type StructTool[T any] struct {
	// contains filtered or unexported fields
}

StructTool 是一个泛型工具,用于让模型生成指定结构体。

它利用 Tool Call 的 JSON Schema 约束模型输出格式:

  • 模型按 Schema 生成 JSON 参数
  • Invoke 内部做 json.Unmarshal 校验 + required 字段存在性检查
  • 成功 → 返回合法 JSON
  • 失败 → 返回 error,触发自动重试

配合 Extraction 模式和 DirectReturnTools 使用,实现「结构化输出提取」:

type JD struct {
    Title        string   `json:"title"`
    Requirements []string `json:"requirements"`
}

tool := llm.NewStructTool[JD]("generate_jd", "生成职位描述")

agent, _ := llm.NewAgent(ctx, llm.AgentConfig{
    Model: llm.AgentModelConfig{Config: cfg},
    Tools: llm.ToolsConfig{Invokable: []llm.InvokableTool{tool}},
    Execution: llm.ExecutionConfig{
        Mode:              llm.Extraction,
        DirectReturnTools: map[string]struct{}{"generate_jd": {}},
    },
    Prompt: llm.PromptConfig{
        System: "根据用户需求生成职位描述。",
    },
})

msg, _ := agent.Generate(ctx, messages)
var jd JD
json.Unmarshal([]byte(msg.Content), &jd)

func NewStructTool added in v1.1.0

func NewStructTool[T any](name, desc string) *StructTool[T]

NewStructTool 创建一个结构化输出提取工具。 自动从 T 的 json tag 生成 ToolInfo 的参数定义。

func (*StructTool[T]) Info added in v1.1.0

func (s *StructTool[T]) Info() *schema.ToolInfo

func (*StructTool[T]) Invoke added in v1.1.0

func (s *StructTool[T]) Invoke(_ context.Context, args string) (string, error)

type StructuredLogConfig added in v1.4.1

type StructuredLogConfig struct {
	// Client 负责输出 llm 的结构化日志;建议直接传入支持 ctx 的日志客户端。
	Client           LogClient
	LogToolArguments bool
	LogToolResults   bool
	MaxFieldLength   int
}

type ThinkingConfig added in v1.7.0

type ThinkingConfig struct {
	Enable       bool
	BudgetTokens int
}

type ToolAdapter added in v1.1.0

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

ToolAdapter 将 llm.InvokableTool 适配为 Eino tool.InvokableTool。 用于桥接简化接口与 Eino 标准接口。

func NewToolAdapter added in v1.1.0

func NewToolAdapter(t InvokableTool) *ToolAdapter

NewToolAdapter 创建一个工具适配器。

func (*ToolAdapter) Info added in v1.1.0

func (*ToolAdapter) InvokableRun added in v1.1.0

func (a *ToolAdapter) InvokableRun(ctx context.Context, argumentsInJSON string, _ ...tool.Option) (string, error)

type ToolsConfig added in v1.4.1

type ToolsConfig struct {
	Standard   []tool.BaseTool
	Invokable  []InvokableTool
	MCPServers []MCPConfig

	// Aliases 工具名别名:key=规范工具名,value=别名列表。
	// 当模型输出别名(如旧工具名)时,会被解析回规范工具名。
	Aliases map[string][]string

	// UnknownHandler 处理模型调用了未注册工具(幻觉工具名)的情况。
	// 返回的字符串作为 ToolResult 回传给模型,让 Agent 自行纠错;
	// 若为 nil,调用未知工具会返回错误(现有行为)。
	UnknownHandler func(ctx context.Context, name, input string) (string, error)

	// ArgumentsFixer 在工具执行前修复/改写参数 JSON(如去除 trailing comma)。
	// 若为 nil,参数原样透传。
	ArgumentsFixer func(ctx context.Context, name, arguments string) (string, error)

	// ErrorToText 为 true 时,工具执行错误(含 panic)被转为 ToolResult 文本回传给
	// 模型,而非中断 Agent 流程(生产推荐)。
	// 注意:为保持向后兼容,**默认(nil)为关闭**,行为与现状一致;需显式设置 true 开启。
	//
	// 安全提示:错误文本会原样发给模型(并可能出现在最终回复中),原始 error 若含
	// 内部细节(数据库字段、内网地址、堆栈等)存在泄露风险。如工具错误可能携带敏感
	// 信息,应在工具内部先脱敏,或不开启本选项而自行处理错误。
	ErrorToText *bool
}

Jump to

Keyboard shortcuts

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