Eino-图编排

代码路径:

C:\Users\Administrator\go\pkg\mod\github.com\cloudwego\eino@v0.9.19\compose\graph.go

type graph struct {...}
graph{
    nodes: map[string]*graphNode{
        // 以下是一个个组件
        "Init":          { /* 初始化节点 */ },
        "ToolSearch":    { /* 新增Lambda节点:工具向量检索 */ },
        "ChatModel":     { /* AgenticModelNode */ },
        "CancelCheck":   { /* 中断检查 */ },
        "ToolNode":      { /* 依然挂载全部6个工具实现,不变 */ },
        "AfterToolCalls":{},
        "AfterToolCallsCancelCheck": {},
    },

    // 控制边发生变化:Init 不再直接进ChatModel,先走ToolSearch
    controlEdges: map[string][]string{
        compose.START:               {"Init"},
        "Init":                      {"ToolSearch"},   // 改动点:先去向量检索节点
        "ToolSearch":                {"ChatModel"},    // 检索完成,把召回的工具放入state,再进大模型
        "CancelCheck":               {"ToolNode"},
        "ToolNode":                  {"AfterToolCalls"},
        "AfterToolCalls":            {"AfterToolCallsCancelCheck"},
        "AfterToolCallsCancelCheck": {"ChatModel"},
    },

    branches: map[string][]*GraphBranch{
        "ChatModel": { /* 判断模型输出是否带ToolCall,逻辑不变 */ },
    },

    startNodes: []string{"Init"},
    endNodes:   []string{compose.END},

    stateGenerator: func(ctx context.Context) any {
        return &agenticState{
            Messages:             []*schema.AgenticMessage{},
            remainingIterations:  5,
            recalledTools:        []*schema.ToolInfo{}, // state新增字段:存放向量检索召回出来的工具描述
        }
    },
    compiled: true,
}

执行步骤如下:

Init:拿到用户消息 帮我查2025年贵州茅台的净利润,写入 state.Messages

ToolSearch:拿用户 query 向量检索,召回get_financial_report,存入 state.recalledTools

ChatModel:读取 state.recalledTools,仅把这 1 个工具描述拼进 system prompt,调用 LLM

LLM 输出 tool_call:get_financial_report(stock="600519",year="2025")

ChatModel 的分支检测:识别到存在 tool_call → 路由到 CancelCheck

CancelCheck:判断是否需要中断,无需中断,路由到 ToolNode

ToolNode:6 个工具实现里找到get_financial_report,执行,返回2025年贵州茅台净利润685亿

AfterToolCalls:把工具返回消息追加到 state.Messages

AfterToolCallsCancelCheck:检查是否中断,不需要,路由回到 ChatModel(循环)

ChatModel 再次调用大模型:把历史消息(用户 + 工具返回结果)丢给 LLM

LLM 这次直接输出纯文本答案,没有 tool_call

ChatModel 分支判断:无 tool_call → 路由到 END,流程结束

二、Eino 内置预制编排图

代码路径:

C:\Users\Administrator\go\pkg\mod\github.com\cloudwego\eino@v0.9.19\adk\react.go

func newAgenticReact(ctx context.Context, config *agenticReactConfig) (agenticReactGraph, error) {...}
// 1. 新建空图
g := compose.NewGraph[*agenticReactInput, *schema.AgenticMessage](...)

// 2. 注册各个节点(编排节点)
_ = g.AddLambdaNode(initNode_, ...)
_ = g.AddAgenticModelNode(chatModel_, wrappedModel, ...)
_ = g.AddLambdaNode(cancelCheckNode_, ...) // 框架内部编排加上CancelCheck
_ = g.AddAgenticToolsNode(toolNode_, toolsNode, ...)
_ = g.AddLambdaNode(afterToolCallsNode_, ...)

// 3. 增加边、分支(编排流转路线)
_ = g.AddEdge(compose.START, initNode_)
_ = g.AddEdge(initNode_, chatModel_)
// ... AddBranch 分支逻辑:ChatModel跑完判断是否有tool_call,选择下一跳

// 4. 返回组装好的图
return g, nil