This is an automated email from the ASF dual-hosted git repository.
alexstocks pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-go-samples.git
The following commit(s) were added to refs/heads/main by this push:
new e3c7c421 feat: upgrade CoT Agent to ReAct Agent (#913)
e3c7c421 is described below
commit e3c7c4210537f22d6051480b021abc392b470d5d
Author: CAICAII <[email protected]>
AuthorDate: Sat Sep 20 17:12:25 2025 +0800
feat: upgrade CoT Agent to ReAct Agent (#913)
---
book-flight-ai-agent/go-server/agents/cot_agent.go | 90 +++++++++++----------
book-flight-ai-agent/go-server/cmd/server.go | 10 +--
.../go-server/conf/bookflight_prompt.yml | 10 +--
book-flight-ai-agent/go-server/react-agent | Bin 0 -> 81942016 bytes
4 files changed, 56 insertions(+), 54 deletions(-)
diff --git a/book-flight-ai-agent/go-server/agents/cot_agent.go
b/book-flight-ai-agent/go-server/agents/cot_agent.go
index 08c25ad0..abec7639 100644
--- a/book-flight-ai-agent/go-server/agents/cot_agent.go
+++ b/book-flight-ai-agent/go-server/agents/cot_agent.go
@@ -34,32 +34,32 @@ import (
"github.com/apache/dubbo-go-samples/book-flight-ai-agent/go-server/tools"
)
-type CotAgentRunner struct {
+type ReactAgentRunner struct {
llm model.LLM
tools tools.Tools
maxThoughtSteps int32
- cotPrompts conf.CfgPrompts
+ reactPrompts conf.CfgPrompts
memoryAgent []map[string]any
memoryMsg []map[string]any
}
-func NewCotAgentRunner(
+func NewReactAgentRunner(
llm model.LLM,
tools tools.Tools,
maxSteps int32,
- cotPrompts conf.CfgPrompts,
-) CotAgentRunner {
- return CotAgentRunner{
+ reactPrompts conf.CfgPrompts,
+) ReactAgentRunner {
+ return ReactAgentRunner{
llm: llm,
tools: tools,
maxThoughtSteps: maxSteps,
- cotPrompts: cotPrompts,
+ reactPrompts: reactPrompts,
memoryAgent: []map[string]any{},
memoryMsg: []map[string]any{},
}
}
-func (cot *CotAgentRunner) Run(
+func (react *ReactAgentRunner) Run(
ctx context.Context,
input string,
callopt model.Option,
@@ -69,28 +69,32 @@ func (cot *CotAgentRunner) Run(
opts := model.NewOptions(callopt)
// Init Memory
- cot.memoryAgent = []map[string]any{}
- cot.memoryMsg = cot.updateMessage(cot.memoryMsg, input, "")
+ react.memoryAgent = []map[string]any{}
+ react.memoryMsg = react.updateMessage(react.memoryMsg, input, "")
var task string
- if len(cot.memoryMsg) > 0 {
- task = cot.summaryIntent(timeNow, callopt)
+ if len(react.memoryMsg) > 0 {
+ task = react.summaryIntent(timeNow, callopt)
} else {
task = input
}
- // Runner
+ // ReAct Loop: Reasoning -> Acting -> Observation
var response string
var action actions.Action
var idxThoughtStep int32
var taskState TaskState
- for idxThoughtStep < cot.maxThoughtSteps {
- action, response = cot.thinkStep(task, timeNow, callopt, opts)
+ for idxThoughtStep < react.maxThoughtSteps {
+ // Reasoning: Think about what to do next
+ action, response = react.reasoningStep(task, timeNow, callopt,
opts)
taskState = InitTaskState(action.Method)
- observation := cot.execAction(action, opts)
- cot.memoryAgent = cot.updateMemory(cot.memoryAgent, response,
observation)
+ // Acting: Execute the action
+ observation := react.execAction(action, opts)
+
+ // Observation: Update memory with the result
+ react.memoryAgent = react.updateMemory(react.memoryAgent,
response, observation)
if InterruptTask(taskState) {
break
@@ -101,21 +105,21 @@ func (cot *CotAgentRunner) Run(
var err error
reply := "Sorry, failed to complete your task."
- if idxThoughtStep < cot.maxThoughtSteps {
- reply, err = cot.finalStep(task, input, timeNow, taskState,
callopt, callrst)
+ if idxThoughtStep < react.maxThoughtSteps {
+ reply, err = react.finalStep(task, input, timeNow, taskState,
callopt, callrst)
- cot.memoryMsg = cot.updateMessage(cot.memoryMsg, task, reply)
+ react.memoryMsg = react.updateMessage(react.memoryMsg, task,
reply)
if taskState == TaskCompleted || taskState == TaskUnrelated {
- cot.memoryMsg = []map[string]any{}
+ react.memoryMsg = []map[string]any{}
}
}
return reply, err
}
-func (cot *CotAgentRunner) GetInputCtx(input string) string {
+func (react *ReactAgentRunner) GetInputCtx(input string) string {
var respBuilder strings.Builder // Use strings.Builder
- for _, msg := range cot.memoryAgent {
+ for _, msg := range react.memoryAgent {
if val, ok := msg["user"]; ok {
respBuilder.WriteString(fmt.Sprintf("\n%v", val))
}
@@ -125,41 +129,41 @@ func (cot *CotAgentRunner) GetInputCtx(input string)
string {
return strings.TrimSpace(respBuilder.String())
}
-func (cot *CotAgentRunner) summaryIntent(timeNow string, callopt model.Option)
string {
+func (react *ReactAgentRunner) summaryIntent(timeNow string, callopt
model.Option) string {
prompt := prompts.CreatePrompt(
- cot.cotPrompts.IntentPrompt,
+ react.reactPrompts.IntentPrompt,
map[string]any{
- "memory": cot.memoryMsg,
+ "memory": react.memoryMsg,
"time": timeNow,
},
)
- response, _ := cot.llm.Call(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
+ response, _ := react.llm.Call(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
return model.RemoveThink(response)
}
-func (cot *CotAgentRunner) thinkStep(
+func (react *ReactAgentRunner) reasoningStep(
task string,
now string,
callopt model.Option,
opts model.Options,
) (actions.Action, string) {
prompt := prompts.CreatePrompt(
- cot.cotPrompts.ReactPrompt,
+ react.reactPrompts.ReactPrompt,
map[string]any{
"task": task,
- "memory": cot.memoryAgent,
+ "memory": react.memoryAgent,
"time": now,
- "tools": cot.tools.ToolsDescription(),
+ "tools": react.tools.ToolsDescription(),
"format_instructions":
conf.GetConfigPrompts().FormatInstructions,
},
)
- response, _ := cot.llm.Invoke(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
+ response, _ := react.llm.Invoke(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
opts.CallOpt("\n")
response = model.RemoveThink(response)
return actions.NewAction(response), response
}
-func (cot *CotAgentRunner) finalStep(
+func (react *ReactAgentRunner) finalStep(
task string,
input string,
date string,
@@ -168,31 +172,31 @@ func (cot *CotAgentRunner) finalStep(
callrst model.CallFunc,
) (string, error) {
config := map[string]any{"task": task}
- promptTemplate := cot.cotPrompts.FinalPrompt
+ promptTemplate := react.reactPrompts.FinalPrompt
switch taskState {
case TaskUnrelated:
- promptTemplate = cot.cotPrompts.UnrelatedPrompt
+ promptTemplate = react.reactPrompts.UnrelatedPrompt
config["task"] = input
case TaskInputRequired:
- promptTemplate = cot.cotPrompts.InputPrompt
- config["memory"] = cot.memoryAgent
+ promptTemplate = react.reactPrompts.InputPrompt
+ config["memory"] = react.memoryAgent
default:
- config["memory"] = cot.memoryAgent
+ config["memory"] = react.memoryAgent
config["time"] = date
}
prompt := prompts.CreatePrompt(promptTemplate, config)
- reply, err := cot.llm.Call(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
+ reply, err := react.llm.Call(context.Background(), prompt, callopt,
ollama.WithTemperature(0.0))
reply = model.RemoveThink(reply)
callrst(reply)
return reply, err
}
-func (cot *CotAgentRunner) execAction(action actions.Action, opts
model.Options) string {
+func (react *ReactAgentRunner) execAction(action actions.Action, opts
model.Options) string {
var err error
var observation string = fmt.Sprintf("Can't find tool: %v.",
action.Method)
- tool := cot.tools.QueryTool(action.Method)
+ tool := react.tools.QueryTool(action.Method)
if tool != nil {
strArgs, _ := json.Marshal(action.Params)
observation, err = tool.Call(context.Background(),
string(strArgs))
@@ -204,13 +208,13 @@ func (cot *CotAgentRunner) execAction(action
actions.Action, opts model.Options)
return observation
}
-func (cot *CotAgentRunner) updateMemory(memory []map[string]any, response
string, observation string) []map[string]any {
+func (react *ReactAgentRunner) updateMemory(memory []map[string]any, response
string, observation string) []map[string]any {
return append(memory,
map[string]any{"input": response, "output": "\nResult:\n" +
observation},
)
}
-func (cot *CotAgentRunner) updateMessage(memory []map[string]any, msgUser
string, msgAgent string) []map[string]any {
+func (react *ReactAgentRunner) updateMessage(memory []map[string]any, msgUser
string, msgAgent string) []map[string]any {
if msgUser != "" {
memory = append(memory, map[string]any{"Human": msgUser})
}
diff --git a/book-flight-ai-agent/go-server/cmd/server.go
b/book-flight-ai-agent/go-server/cmd/server.go
index 7cca7dd2..6182dcfd 100644
--- a/book-flight-ai-agent/go-server/cmd/server.go
+++ b/book-flight-ai-agent/go-server/cmd/server.go
@@ -65,14 +65,14 @@ func getTools() tools.Tools {
}
type ChatServer struct {
- llm *ollama.LLMOllama
- cot agents.CotAgentRunner
+ llm *ollama.LLMOllama
+ react agents.ReactAgentRunner
}
func NewChatServer() (*ChatServer, error) {
llm := ollama.NewLLMOllama(cfgEnv.Model, cfgEnv.Url)
- cot := agents.NewCotAgentRunner(llm, getTools(), 10,
conf.GetConfigPrompts())
- return &ChatServer{llm: llm, cot: cot}, nil
+ react := agents.NewReactAgentRunner(llm, getTools(), 10,
conf.GetConfigPrompts())
+ return &ChatServer{llm: llm, react: react}, nil
}
func (s *ChatServer) Chat(ctx context.Context, req *chat.ChatRequest, stream
chat.ChatService_ChatServer) (err error) {
@@ -105,7 +105,7 @@ func (s *ChatServer) Chat(ctx context.Context, req
*chat.ChatRequest, stream cha
}
input := req.Messages[len(req.Messages)-1].Content
- _, err = s.cot.Run(ctx, input, ollama.WithStreamingFunc(respFunc),
rstFunc)
+ _, err = s.react.Run(ctx, input, ollama.WithStreamingFunc(respFunc),
rstFunc)
if err != nil {
log.Printf("Run failed: %v", err)
}
diff --git a/book-flight-ai-agent/go-server/conf/bookflight_prompt.yml
b/book-flight-ai-agent/go-server/conf/bookflight_prompt.yml
index 89a84cff..8d54714a 100644
--- a/book-flight-ai-agent/go-server/conf/bookflight_prompt.yml
+++ b/book-flight-ai-agent/go-server/conf/bookflight_prompt.yml
@@ -2,7 +2,7 @@ reactPrompt: "
当前的任务执行记录:
{memory}
-你是强大的AI飞机票助手,可以使用工具与指令查询并购买飞机票。
+你是强大的AI飞机票助手,使用ReAct模式来完成任务。
你可以使用以下工具或指令,它们又称为动作或actions:
{tools}
@@ -14,13 +14,11 @@ reactPrompt: "
1. 若问题与查询/购买机票无关时,直接调用 TaskUnrelated 指令;
2. 查询/购买机票的必要信息:出发地、目的地、出发时间;除此之外自行推断。
-按照以下格式输出:
+请按照以下ReAct格式输出:
-任务:你收到的需要执行的任务
-思考: 观察你的任务和执行记录,并思考你下一步应该采取的行动
-根据以下格式说明,输出你选择执行的动作/工具:
+**Thought(思考)**: 分析当前情况,回顾之前的行动结果,决定下一步应该做什么
+**Action(行动)**: 根据以下格式说明,输出你选择执行的动作/工具:
{format_instructions}
-。
"
intentPrompt: "
diff --git a/book-flight-ai-agent/go-server/react-agent
b/book-flight-ai-agent/go-server/react-agent
new file mode 100644
index 00000000..a800d5c9
Binary files /dev/null and b/book-flight-ai-agent/go-server/react-agent differ