react

package
v0.26.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 13, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

ReAct Strategy

ReAct (Reasoning and Acting) is a strategy for gollem that implements the framework described in the paper "ReAct: Synergizing Reasoning and Acting in Language Models".

Overview

The ReAct strategy alternates between three phases to solve complex problems:

  1. Thought: The LLM reasons about the current situation and decides what to do next
  2. Action: The LLM takes an action (calls a tool or provides a final response)
  3. Observation: The results of the action are observed and fed back into the next thought cycle

This cycle continues until the LLM has gathered sufficient information to provide a final answer.

Features

  • Explicit TAO Cycle: Clearly structured Thought-Action-Observation phases
  • Loop Detection: Prevents infinite loops by detecting repeated actions
  • Error Handling: Gracefully handles tool execution errors with retry logic
  • Safety Limits: Maximum iteration count to prevent runaway execution
  • Trace Export: Complete execution history can be exported for debugging and analysis
  • Customizable Prompts: All prompts can be customized to fit your use case

Basic Usage

package main

import (
    "context"
    "fmt"

    "github.com/gollem-dev/gollem"
    "github.com/gollem-dev/gollem/llm/openai"
    "github.com/gollem-dev/gollem/strategy/react"
)

func main() {
    ctx := context.Background()

    // Create LLM client
    llmClient, err := openai.New(ctx, "your-api-key")
    if err != nil {
        panic(err)
    }

    // Create ReAct strategy
    strategy := react.New(llmClient,
        react.WithMaxIterations(20),
        react.WithMaxRepeatedActions(3),
    )

    // Create agent with ReAct strategy
    agent := gollem.New(llmClient, gollem.WithStrategy(strategy))

    // Execute
    response, err := agent.Execute(ctx, gollem.Text("What is the weather in Tokyo?"))
    if err != nil {
        panic(err)
    }

    fmt.Println(response)

    // Export trace for analysis
    trace := strategy.ExportTrace()
    fmt.Printf("Total iterations: %d\n", trace.Summary.TotalIterations)
    fmt.Printf("Tool calls: %d\n", trace.Summary.ToolCallsCount)
}

Configuration Options

WithMaxIterations

Sets the maximum number of iterations before forcibly terminating. Default is 20.

strategy := react.New(llmClient,
    react.WithMaxIterations(10),
)
WithMaxRepeatedActions

Sets how many times the same action can be repeated before detecting a loop. Default is 3.

strategy := react.New(llmClient,
    react.WithMaxRepeatedActions(5),
)
WithThoughtPrompt

Customizes the prompt used to encourage reasoning.

strategy := react.New(llmClient,
    react.WithThoughtPrompt("Think carefully about the next step:"),
)
WithObservationPrompt

Customizes the prompt template for observations. Should contain two %s placeholders for tool name and result.

strategy := react.New(llmClient,
    react.WithObservationPrompt("Tool %s returned: %s\nWhat should we do next?"),
)
WithFewShotExamples

Enables few-shot learning with provided examples (planned for future release).

examples := []react.FewShotExample{
    {
        Question: "What is 2+2?",
        Thought: "I need to calculate 2+2",
        Action: "calculator(2+2)",
        Observation: "4",
        Answer: "The answer is 4",
    },
}

strategy := react.New(llmClient,
    react.WithFewShotExamples(examples),
)

Trace Export

The ReAct strategy records the complete execution trace, which can be exported for debugging and analysis.

// Export trace
trace := strategy.ExportTrace()

// Access summary
fmt.Printf("Total iterations: %d\n", trace.Summary.TotalIterations)
fmt.Printf("Success rate: %.2f\n", trace.Summary.SuccessRate)
fmt.Printf("Duration: %s\n", trace.Summary.Duration)

// Access individual entries
for _, entry := range trace.Entries {
    if entry.Thought != nil {
        fmt.Printf("Thought: %s\n", entry.Thought.Content)
    }
    if entry.Action != nil {
        fmt.Printf("Action: %s\n", entry.Action.Type)
        if entry.Action.Type == react.ActionTypeToolCall {
            for _, call := range entry.Action.ToolCalls {
                fmt.Printf("  - Tool Call: %s with args %v\n", call.Name, call.Arguments)
            }
        } else if entry.Action.Type == react.ActionTypeRespond {
            fmt.Printf("  - Response: %s\n", entry.Action.Response)
        }
    }
    if entry.Observation != nil {
        fmt.Printf("Observation: success=%v\n", entry.Observation.Success)
        if !entry.Observation.Success {
            fmt.Printf("  - Error: %s\n", entry.Observation.Error)
        }
    }
}

// Export as JSON
jsonData, err := strategy.ExportTraceJSON()
if err != nil {
    panic(err)
}
fmt.Println(string(jsonData))

Safety Features

Loop Detection

The strategy detects when the same action is repeated multiple times and automatically terminates to prevent infinite loops.

strategy := react.New(llmClient,
    react.WithMaxRepeatedActions(3), // Stop after 3 repeated actions
)
Maximum Iterations

A hard limit on the number of iterations prevents runaway execution.

strategy := react.New(llmClient,
    react.WithMaxIterations(20), // Stop after 20 iterations
)
Error Handling

Tool execution errors are gracefully handled:

  • Errors are recorded in the observation
  • The LLM is informed of the error and can retry or try a different approach
  • After 3 consecutive errors, execution is terminated

Best Practices

  1. Set appropriate iteration limits: Too low and complex tasks may not complete; too high and you risk excessive API costs.

  2. Customize prompts for your domain: The default prompts are general-purpose. Customizing them can improve performance for specific use cases.

  3. Monitor the trace: Use ExportTrace() to understand how the LLM is reasoning and identify areas for improvement.

  4. Provide clear tool descriptions: The ReAct strategy works best when tools have clear, concise descriptions that explain what they do.

  5. Handle errors gracefully: Design your tools to return meaningful error messages that the LLM can understand and act upon.

Troubleshooting

The agent keeps repeating the same action

Reduce WithMaxRepeatedActions to detect loops earlier, or improve your tool descriptions so the LLM understands when a tool has already been tried.

The agent runs out of iterations before completing

Increase WithMaxIterations, or break down your problem into smaller sub-problems.

Tool errors are not being handled well

Ensure your tools return descriptive error messages. The LLM needs to understand what went wrong to try a different approach.

References

Documentation

Overview

Package react implements the ReAct (Reasoning and Acting) strategy for gollem.

ReAct is a framework that combines reasoning and acting in language models. It alternates between thought (reasoning), action (tool use), and observation (results) to solve complex problems step by step.

Basic usage:

strategy := react.New(llmClient,
    react.WithMaxIterations(20),
    react.WithMaxRepeatedActions(3),
)

agent := gollem.New(llmClient, gollem.WithStrategy(strategy))
response, err := agent.Execute(ctx, gollem.Text("What is the weather in Tokyo?"))

Index

Constants

View Source
const (
	// DefaultSystemPrompt is the default system prompt for ReAct strategy
	DefaultSystemPrompt = `` /* 981-byte string literal not displayed */

	// DefaultThoughtPrompt is the default prompt to encourage reasoning
	DefaultThoughtPrompt = `Thought:`

	// DefaultObservationPromptTemplate is the template for observation prompts
	// Use with fmt.Sprintf(DefaultObservationPromptTemplate, toolName, result)
	DefaultObservationPromptTemplate = `Observation: %s returned:
%s

Thought:`
)

Default prompt templates based on ReAct paper

View Source
const (
	// DefaultMaxIterations is the default maximum number of iterations
	DefaultMaxIterations = 20
	// DefaultMaxRepeatedActions is the default maximum number of repeated actions
	DefaultMaxRepeatedActions = 3
	// MaxConsecutiveErrors is the maximum number of consecutive errors before giving up
	MaxConsecutiveErrors = 3
)

Variables

This section is empty.

Functions

This section is empty.

Types

type ActionData

type ActionData struct {
	Type      ActionType             `json:"type"`
	ToolCalls []*gollem.FunctionCall `json:"tool_calls,omitempty"`
	Response  string                 `json:"response,omitempty"`
}

ActionData represents the action taken by the LLM

type ActionEvent

type ActionEvent struct {
	Iteration  int      `json:"iteration"`
	ActionType string   `json:"action_type"`
	ToolNames  []string `json:"tool_names,omitempty"`
}

ActionEvent is recorded when an action is taken.

type ActionType

type ActionType string

ActionType represents the type of action taken

const (
	// ActionTypeToolCall indicates the action is calling one or more tools
	ActionTypeToolCall ActionType = "tool_call"
	// ActionTypeRespond indicates the action is responding to the user
	ActionTypeRespond ActionType = "respond"
)

type FewShotExample

type FewShotExample struct {
	Question    string `json:"question"`
	Thought     string `json:"thought"`
	Action      string `json:"action"`
	Observation string `json:"observation"`
	Answer      string `json:"answer"`
}

FewShotExample represents a single few-shot learning example

type ObservationData

type ObservationData struct {
	ToolResults []ToolResult `json:"tool_results"`
	Success     bool         `json:"success"`
	Error       string       `json:"error,omitempty"`
}

ObservationData represents the results observed from actions

type ObservationEvent

type ObservationEvent struct {
	Iteration int  `json:"iteration"`
	Success   bool `json:"success"`
}

ObservationEvent is recorded when tool results are observed.

type Option

type Option func(*Strategy)

Option is a function that configures the Strategy

func WithFewShotExamples

func WithFewShotExamples(examples []FewShotExample) Option

WithFewShotExamples enables few-shot learning with provided examples

func WithMaxIterations

func WithMaxIterations(max int) Option

WithMaxIterations sets the maximum number of iterations Default is 20 if not specified

func WithMaxRepeatedActions

func WithMaxRepeatedActions(max int) Option

WithMaxRepeatedActions sets the maximum number of times the same action can be repeated This helps detect infinite loops. Default is 3 if not specified

func WithObservationPrompt

func WithObservationPrompt(prompt string) Option

WithObservationPrompt sets a custom observation prompt template The template should contain two %s placeholders for tool name and result Example: "Tool %s result: %s\nNext thought:"

func WithSystemPrompt

func WithSystemPrompt(prompt string) Option

WithSystemPrompt sets a custom system prompt If not set, DefaultSystemPrompt will be used

func WithThoughtPrompt

func WithThoughtPrompt(prompt string) Option

WithThoughtPrompt sets a custom thought prompt If not set, DefaultThoughtPrompt will be used

type Strategy

type Strategy struct {
	// contains filtered or unexported fields
}

Strategy implements the ReAct (Reasoning and Acting) pattern

func New

func New(client gollem.LLMClient, options ...Option) *Strategy

New creates a new ReAct strategy instance

func (*Strategy) ExportTrace

func (s *Strategy) ExportTrace() *TraceExport

ExportTrace exports the complete trace data

func (*Strategy) ExportTraceJSON

func (s *Strategy) ExportTraceJSON() ([]byte, error)

ExportTraceJSON exports the trace data as JSON

func (*Strategy) Handle

Handle implements the ReAct loop logic

func (*Strategy) Init

func (s *Strategy) Init(ctx context.Context, inputs []gollem.Input) error

Init initializes the strategy with initial inputs

func (*Strategy) Tools

func (s *Strategy) Tools(ctx context.Context) ([]gollem.Tool, error)

Tools returns the tools provided by this strategy (none for ReAct)

type TAOEntry

type TAOEntry struct {
	Iteration   int              `json:"iteration"`
	Thought     *ThoughtData     `json:"thought,omitempty"`
	Action      *ActionData      `json:"action,omitempty"`
	Observation *ObservationData `json:"observation,omitempty"`
	Timestamp   time.Time        `json:"timestamp"`
}

TAOEntry represents a single Thought-Action-Observation cycle entry

type ThoughtData

type ThoughtData struct {
	Content   string `json:"content"`   // The thought content generated by LLM
	Reasoning string `json:"reasoning"` // The reasoning process
}

ThoughtData represents the reasoning process of the LLM

type ThoughtEvent

type ThoughtEvent struct {
	Iteration int    `json:"iteration"`
	Content   string `json:"content"`
}

ThoughtEvent is recorded when the LLM generates a thought.

type ToolResult

type ToolResult struct {
	ToolName string `json:"tool_name"`
	Success  bool   `json:"success"`
	Output   string `json:"output"`
	Error    string `json:"error,omitempty"`
}

ToolResult represents the result of a single tool execution

type TraceExport

type TraceExport struct {
	Entries  []TAOEntry    `json:"entries"`
	Summary  TraceSummary  `json:"summary"`
	Metadata TraceMetadata `json:"metadata"`
}

TraceExport represents the exportable trace data

type TraceMetadata

type TraceMetadata struct {
	Strategy       string    `json:"strategy"`
	StartTime      time.Time `json:"start_time"`
	EndTime        time.Time `json:"end_time"`
	CompletionType string    `json:"completion_type"` // "success", "max_iterations", "loop_detected", "error"
}

TraceMetadata contains metadata about the trace execution

type TraceSummary

type TraceSummary struct {
	TotalIterations int           `json:"total_iterations"`
	ToolCallsCount  int           `json:"tool_calls_count"`
	SuccessRate     float64       `json:"success_rate"`
	Duration        time.Duration `json:"duration"`
}

TraceSummary contains summary statistics of the trace

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL