You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

197 lines
5.1 KiB
Go

/*
* Copyright 2025 CloudWeGo Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"context"
"fmt"
"github.com/cloudwego/eino/adk"
"github.com/cloudwego/eino/adk/prebuilt/supervisor"
"github.com/cloudwego/eino/components/tool"
"github.com/cloudwego/eino/compose"
"github.com/cloudwego/eino-examples/adk/common/model"
"github.com/cloudwego/eino-examples/flow/agent/multiagent/plan_execute/tools"
)
func buildSearchAgent(ctx context.Context) (adk.Agent, error) {
m := model.NewChatModel()
type searchReq struct {
Query string `json:"query"`
}
type searchResp struct {
Result string `json:"result"`
}
search := func(ctx context.Context, req *searchReq) (*searchResp, error) {
return &searchResp{
Result: "In 2024, the US GDP was $29.18 trillion and New York State's GDP was $2.297 trillion",
}, nil
}
searchTool, err := tools.SafeInferTool("search", "search the internet for info", search)
if err != nil {
return nil, err
}
return adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Name: "research_agent",
Description: "the agent responsible to search the internet for info",
Instruction: `
You are a research agent.
INSTRUCTIONS:
- Assist ONLY with research-related tasks, DO NOT do any math
- DO NOT estimate any numbers.
- After you're done with your tasks, respond to the supervisor directly
- Respond ONLY with the results of your work, do NOT include ANY other text.`,
Model: m,
ToolsConfig: adk.ToolsConfig{
ToolsNodeConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{searchTool},
UnknownToolsHandler: func(ctx context.Context, name, input string) (string, error) {
return fmt.Sprintf("unknown tool: %s", name), nil
},
},
},
})
}
func buildMathAgent(ctx context.Context) (adk.Agent, error) {
m := model.NewChatModel()
type addReq struct {
A float64 `json:"a"`
B float64 `json:"b"`
}
type addResp struct {
Result float64
}
add := func(ctx context.Context, req *addReq) (*addResp, error) {
return &addResp{
Result: req.A + req.B,
}, nil
}
addTool, err := tools.SafeInferTool("add", "add two numbers", add)
if err != nil {
return nil, err
}
type multiplyReq struct {
A float64 `json:"a"`
B float64 `json:"b"`
}
type multiplyResp struct {
Result float64
}
multiply := func(ctx context.Context, req *multiplyReq) (*multiplyResp, error) {
return &multiplyResp{
Result: req.A * req.B,
}, nil
}
multiplyTool, err := tools.SafeInferTool("multiply", "multiply two numbers", multiply)
if err != nil {
return nil, err
}
type divideReq struct {
A float64 `json:"a"`
B float64 `json:"b"`
}
type divideResp struct {
Result float64
}
divide := func(ctx context.Context, req *divideReq) (*divideResp, error) {
return &divideResp{
Result: req.A / req.B,
}, nil
}
divideTool, err := tools.SafeInferTool("divide", "divide two numbers", divide)
if err != nil {
return nil, err
}
return adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Name: "math_agent",
Description: "the agent responsible to do math",
Instruction: `
You are a math agent.
INSTRUCTIONS:
- Assist ONLY with math-related tasks
- After you're done with your tasks, respond to the supervisor directly
- Respond ONLY with the results of your work, do NOT include ANY other text.`,
Model: m,
ToolsConfig: adk.ToolsConfig{
ToolsNodeConfig: compose.ToolsNodeConfig{
Tools: []tool.BaseTool{addTool, multiplyTool, divideTool},
UnknownToolsHandler: func(ctx context.Context, name, input string) (string, error) {
return fmt.Sprintf("unknown tool: %s", name), nil
},
},
},
})
}
func buildSupervisor(ctx context.Context) (adk.Agent, error) {
m := model.NewChatModel()
sv, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{
Name: "supervisor",
Description: "the agent responsible to supervise tasks",
Instruction: `
You are a supervisor managing two agents:
- a research agent. Assign research-related tasks to this agent
- a math agent. Assign math-related tasks to this agent
Assign work to one agent at a time, do not call agents in parallel.
Do not do any work yourself.`,
Model: m,
Exit: &adk.ExitTool{},
})
if err != nil {
return nil, err
}
searchAgent, err := buildSearchAgent(ctx)
if err != nil {
return nil, err
}
mathAgent, err := buildMathAgent(ctx)
if err != nil {
return nil, err
}
return supervisor.New(ctx, &supervisor.Config{
Supervisor: sv,
SubAgents: []adk.Agent{searchAgent, mathAgent},
})
}