Files
langchaingo/agents/executor_test.go
T
2024-01-02 15:02:31 +08:00

141 lines
3.5 KiB
Go

package agents_test
import (
"context"
"os"
"strings"
"testing"
"github.com/stretchr/testify/require"
"github.com/tmc/langchaingo/agents"
"github.com/tmc/langchaingo/chains"
"github.com/tmc/langchaingo/llms/openai"
"github.com/tmc/langchaingo/prompts"
"github.com/tmc/langchaingo/schema"
"github.com/tmc/langchaingo/tools"
"github.com/tmc/langchaingo/tools/serpapi"
)
type testAgent struct {
actions []schema.AgentAction
finish *schema.AgentFinish
err error
inputKeys []string
outputKeys []string
recordedIntermediateSteps []schema.AgentStep
recordedInputs map[string]string
numPlanCalls int
}
func (a *testAgent) Plan(
_ context.Context,
intermediateSteps []schema.AgentStep,
inputs map[string]string,
) ([]schema.AgentAction, *schema.AgentFinish, error) {
a.recordedIntermediateSteps = intermediateSteps
a.recordedInputs = inputs
a.numPlanCalls++
return a.actions, a.finish, a.err
}
func (a testAgent) GetInputKeys() []string {
return a.inputKeys
}
func (a testAgent) GetOutputKeys() []string {
return a.outputKeys
}
func TestExecutorWithErrorHandler(t *testing.T) {
t.Parallel()
a := &testAgent{
err: agents.ErrUnableToParseOutput,
}
executor := agents.NewExecutor(
a,
nil,
agents.WithMaxIterations(3),
agents.WithParserErrorHandler(agents.NewParserErrorHandler(nil)),
)
_, err := chains.Call(context.Background(), executor, nil)
require.ErrorIs(t, err, agents.ErrNotFinished)
require.Equal(t, 3, a.numPlanCalls)
require.Equal(t, []schema.AgentStep{
{Observation: agents.ErrUnableToParseOutput.Error()},
{Observation: agents.ErrUnableToParseOutput.Error()},
}, a.recordedIntermediateSteps)
}
func TestExecutorWithMRKLAgent(t *testing.T) {
t.Parallel()
if openaiKey := os.Getenv("OPENAI_API_KEY"); openaiKey == "" {
t.Skip("OPENAI_API_KEY not set")
}
if serpapiKey := os.Getenv("SERPAPI_API_KEY"); serpapiKey == "" {
t.Skip("SERPAPI_API_KEY not set")
}
llm, err := openai.New()
require.NoError(t, err)
searchTool, err := serpapi.New()
require.NoError(t, err)
calculator := tools.Calculator{}
a, err := agents.Initialize(
llm,
[]tools.Tool{searchTool, calculator},
agents.ZeroShotReactDescription,
)
require.NoError(t, err)
result, err := chains.Run(context.Background(), a, "If a person lived three times as long as Jacklyn Zeman, how long would they live") //nolint:lll
require.NoError(t, err)
require.True(t, strings.Contains(result, "210"), "correct answer 210 not in response")
}
func TestExecutorWithOpenAIFunctionAgent(t *testing.T) {
t.Parallel()
if openaiKey := os.Getenv("OPENAI_API_KEY"); openaiKey == "" {
t.Skip("OPENAI_API_KEY not set")
}
if serpapiKey := os.Getenv("SERPAPI_API_KEY"); serpapiKey == "" {
t.Skip("SERPAPI_API_KEY not set")
}
llm, err := openai.NewChat()
require.NoError(t, err)
searchTool, err := serpapi.New()
require.NoError(t, err)
calculator := tools.Calculator{}
toolList := []tools.Tool{searchTool, calculator}
a := agents.NewOpenAIFunctionsAgent(llm,
toolList,
agents.NewOpenAIOption().WithSystemMessage("you are a helpful assistant"),
agents.NewOpenAIOption().WithExtraMessages([]prompts.MessageFormatter{
prompts.NewHumanMessagePromptTemplate("please be strict", nil),
}),
)
e := agents.NewExecutor(a, toolList)
require.NoError(t, err)
result, err := chains.Run(context.Background(), e, "what is HK singer Eason Chan's years old?") //nolint:lll
require.NoError(t, err)
require.True(t, strings.Contains(result, "47") || strings.Contains(result, "49"),
"correct answer 47 or 49 not in response")
}