graph图编排
无大模型的图编排
go
package agent
import (
"context"
"fmt"
"github.com/cloudwego/eino/compose"
)
func Graph_agent() {
ctx := context.Background()
//未添加模型的graph流程 注册图 同时定义输入输出的类型 这里都为string类型
g := compose.NewGraph[string, string]()
lambda0 := compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
if input == "测试1" {
return "输入1", nil
} else if input == "测试2" {
return "输入2", nil
} else if input == "测试3" {
return "输入3", nil
}
return "", nil
})
lambda1 := compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
return "这里是节点1的输出", nil
})
lambda2 := compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
return "这里是节点2的输出", nil
})
lambda3 := compose.InvokableLambda(func(ctx context.Context, input string) (output string, err error) {
return "这里是节点3的输出", nil
})
// 加入节点
err := g.AddLambdaNode("lambda0", lambda0)
if err != nil {
panic(err)
}
err = g.AddLambdaNode("lambda1", lambda1)
if err != nil {
panic(err)
}
err = g.AddLambdaNode("lambda2", lambda2)
if err != nil {
panic(err)
}
err = g.AddLambdaNode("lambda3", lambda3)
if err != nil {
panic(err)
}
// 分支连接 增加边 用来标记节点与节点怎样连接的
err = g.AddEdge(compose.START, "lambda0")
if err != nil {
panic(err)
}
// 加入分支
err = g.AddBranch("lambda0", compose.NewGraphBranch(func(ctx context.Context, in string) (endNode string, err error) {
if in == "输入1" {
return "lambda1", nil
} else if in == "输入2" {
return "lambda2", nil
} else if in == "输入3" {
return "lambda3", nil
}
// 否则,返回 compose.END,表示流程结束
return compose.END, nil
}, map[string]bool{"lambda1": true, "lambda2": true, "lambda3": true, compose.END: true}))
if err != nil {
panic(err)
}
//增加边 lambda1这个节点直接连接end节点
err = g.AddEdge("lambda1", compose.END)
if err != nil {
panic(err)
}
err = g.AddEdge("lambda2", compose.END)
if err != nil {
panic(err)
}
err = g.AddEdge("lambda3", compose.END)
if err != nil {
panic(err)
}
// 编译
r, err := g.Compile(ctx)
if err != nil {
panic(err)
}
// 执行
answer, err := r.Invoke(ctx, "测试1")
if err != nil {
panic(err)
}
fmt.Println(answer)
}

来具体看下eino框架的各个api
- compose.NewGraph 新建图
注意这个图只定义了各个节点之间的流向,没有定义大模型,这个是eion框架设计的重要思想
- compose.InvokableLambda
把一个普通的 Go 函数适配成"可调用的图节点"。它接收形如 func(ctx context.Context, input T) (output U, err error) 的函数,返回一个实现了可调用接口的节点对象,供 AddLambdaNode 加入到 Graph 中并在运行时由编排调用 - g.AddLambdaNode
增加图节点 - g.AddEdge
增加图节点的边
即把当前的节点流向哪个节点 - g.AddBranch
增加图节点分支,即节点有多个分支输出的时候,可以使用AddBranch - g.Compile
图编排编译,定义好的"静态图"生成一个可执行的运行器 - r.Invoke
eino框架图编排实际运行函数
测试当前输出

这里是由于节点0定义了流向下一个节点的规则:输入1指向节点1,输入2指向节点2,输入3指向节点3
这里测试给定的输入为 answer, err := r.Invoke(ctx, "测试1")
因此节点流向了1,因此输出如上
增加包含大模型节点的图编排
go
package agent
import (
"context"
"fmt"
"github.com/cloudwego/eino-ext/components/model/ollama"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino/schema"
)
func NewGraphWithModel() {
ctx := context.Background()
//新建图
g := compose.NewGraph[map[string]string, *schema.Message]()
lambda := compose.InvokableLambda(func(ctx context.Context, input map[string]string) (output map[string]string, err error) {
if input["role"] == "gongke" {
return map[string]string{"role": "gongke", "content": input["content"]}, nil
}
if input["role"] == "wenke" {
return map[string]string{"role": "wenke", "content": input["content"]}, nil
}
return map[string]string{"role": "user", "content": input["content"]}, nil
})
GongkeLambda := compose.InvokableLambda(func(ctx context.Context, input map[string]string) (output []*schema.Message, err error) {
return []*schema.Message{
{
Role: schema.System,
Content: "你是一个专业的工科专业人士,回答问题很严肃认真,不会说废话",
},
{
Role: schema.User,
Content: input["content"],
},
}, nil
})
WenkeLambda := compose.InvokableLambda(func(ctx context.Context, input map[string]string) (output []*schema.Message, err error) {
return []*schema.Message{
{
Role: schema.System,
Content: "你是一位专业的文科人士,回答问题很温柔,拥有大量的文科知识",
},
{
Role: schema.User,
Content: input["content"],
},
}, nil
})
model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
BaseURL: "http://localhost:11434", // Ollama 服务地址
Model: "qwen3:0.6b", // 模型名称
})
if err != nil {
panic(err)
}
//注册节点
err = g.AddLambdaNode("lambda", lambda)
if err != nil {
panic(err)
}
err = g.AddLambdaNode("gongke", GongkeLambda)
if err != nil {
panic(err)
}
err = g.AddLambdaNode("wenke", WenkeLambda)
if err != nil {
panic(err)
}
err = g.AddChatModelNode("model", model)
if err != nil {
panic(err)
}
//链接节点 start->lambda
err = g.AddEdge(compose.START, "lambda")
if err != nil {
panic(err)
}
//加入分支分之直接把两个lambda节点和branch链接了 lambda-> gongke lambda->wenke
g.AddBranch("lambda", compose.NewGraphBranch(func(ctx context.Context, in map[string]string) (endNode string, err error) {
if in["role"] == "gongke" {
return "gongke", nil
}
if in["role"] == "wenke" {
return "wenke", nil
}
return "wenke", nil
}, map[string]bool{"wenke": true, "gongke": true}))
//把两个lambda节点和model节点进行连接 gongke->model
err = g.AddEdge("gongke", "model")
if err != nil {
panic(err)
}
// wenke->model
err = g.AddEdge("wenke", "model")
if err != nil {
panic(err)
}
//结束节点 model->END
err = g.AddEdge("model", compose.END)
if err != nil {
panic(err)
}
//编译
r, err := g.Compile(ctx)
if err != nil {
panic(err)
}
input := map[string]string{
"role": "wenke",
"content": "介绍下你自己",
}
//执行
answer, err := r.Invoke(ctx, input)
if err != nil {
panic(err)
}
fmt.Println(answer.Content)
}
输出
这里的函数逻辑和无大模型节点差不多,知识多了一段逻辑
g.AddChatModelNode
增加大模型节点
注意下注册大模型客户端
这里采用的本地化ollama部署 大模型使用的qwen3
go
model, err := ollama.NewChatModel(ctx, &ollama.ChatModelConfig{
BaseURL: "http://localhost:11434", // Ollama 服务地址
Model: "qwen3:0.6b", // 模型名称
})

这里通过区分role角色使得lambda节点流向不同的分支,在分支中拿到不同的提示词,从而输出给到下个大模型节点,从而输出不同的信息,如上输出给出的role=wenke
接下来把role修改下role=gongke
输出
可以看到用户的输出思考会根据用户给定的系统提示词作出思考输出
参考
b站eino开发框架教程