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

Reply via email to