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
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 ÷Resp{
|
|
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},
|
|
})
|
|
}
|