mirror of
https://github.com/vxcontrol/langchaingo.git
synced 2026-07-19 21:54:17 -04:00
agents: Add more robust response handling to executor.go (#1316)
* agents: fix handling of observation suffix in tool inputs Add test coverage to ensure the executor properly trims nObservation: suffix from tool inputs before passing them to tools. This prevents tools from receiving malformed input that includes the observation marker. - Add TestExecutorTrimsObservationSuffix to verify trimming behavior - Add test case in MRKL output parser for action inputs with observation suffix - Add tools field to testAgent to support tool testing --------- Co-authored-by: Travis Cline <travis.cline@gmail.com>
This commit is contained in:
+1
-1
@@ -134,7 +134,7 @@ func (e *Executor) doAction(
|
||||
}), nil
|
||||
}
|
||||
|
||||
observation, err := tool.Call(ctx, action.ToolInput)
|
||||
observation, err := tool.Call(ctx, strings.TrimSuffix(action.ToolInput, "\nObservation:"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+58
-1
@@ -23,6 +23,7 @@ type testAgent struct {
|
||||
err error
|
||||
inputKeys []string
|
||||
outputKeys []string
|
||||
tools []tools.Tool
|
||||
|
||||
recordedIntermediateSteps []schema.AgentStep
|
||||
recordedInputs map[string]string
|
||||
@@ -50,7 +51,7 @@ func (a testAgent) GetOutputKeys() []string {
|
||||
}
|
||||
|
||||
func (a *testAgent) GetTools() []tools.Tool {
|
||||
return nil
|
||||
return a.tools
|
||||
}
|
||||
|
||||
func TestExecutorWithErrorHandler(t *testing.T) {
|
||||
@@ -171,3 +172,59 @@ func TestExecutorWithOpenAIFunctionAgent(t *testing.T) {
|
||||
require.True(t, strings.Contains(result, "2012") || strings.Contains(result, "March"),
|
||||
"correct answer 2012 or March not in response")
|
||||
}
|
||||
|
||||
// mockTool implements the tools.Tool interface for testing
|
||||
type mockTool struct {
|
||||
name string
|
||||
description string
|
||||
receivedInputPtr *string
|
||||
}
|
||||
|
||||
func (m *mockTool) Name() string {
|
||||
return m.name
|
||||
}
|
||||
|
||||
func (m *mockTool) Description() string {
|
||||
return m.description
|
||||
}
|
||||
|
||||
func (m *mockTool) Call(_ context.Context, input string) (string, error) {
|
||||
*m.receivedInputPtr = input
|
||||
return "mock result", nil
|
||||
}
|
||||
|
||||
func TestExecutorTrimsObservationSuffix(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
|
||||
// Create a mock tool that records what input it receives
|
||||
var receivedInput string
|
||||
mockToolInst := &mockTool{
|
||||
name: "mock_tool",
|
||||
description: "A mock tool for testing",
|
||||
receivedInputPtr: &receivedInput,
|
||||
}
|
||||
|
||||
// Create a test agent that returns an action with trailing "\nObservation:"
|
||||
testAgent := &testAgent{
|
||||
actions: []schema.AgentAction{
|
||||
{
|
||||
Tool: "mock_tool",
|
||||
ToolInput: "test input\nObservation:",
|
||||
Log: "Action: mock_tool\nAction Input: test input\nObservation:",
|
||||
},
|
||||
},
|
||||
inputKeys: []string{"input"},
|
||||
outputKeys: []string{"output"},
|
||||
tools: []tools.Tool{mockToolInst},
|
||||
}
|
||||
|
||||
executor := agents.NewExecutor(testAgent, agents.WithMaxIterations(1))
|
||||
|
||||
_, err := chains.Call(ctx, executor, map[string]any{"input": "test question"})
|
||||
// We expect ErrNotFinished since our test agent doesn't provide a finish action
|
||||
require.ErrorIs(t, err, agents.ErrNotFinished)
|
||||
|
||||
// Verify that the tool received the input with "\nObservation:" trimmed off
|
||||
require.Equal(t, "test input", receivedInput, "Tool should receive input with \\nObservation: suffix trimmed")
|
||||
}
|
||||
|
||||
@@ -36,6 +36,16 @@ func TestMRKLOutputParser(t *testing.T) {
|
||||
expectedFinish: nil,
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
input: "Action: calculator\nAction Input: 5 + 3\nObservation:",
|
||||
expectedActions: []schema.AgentAction{{
|
||||
Tool: "calculator",
|
||||
ToolInput: "5 + 3\nObservation:",
|
||||
Log: "Action: calculator\nAction Input: 5 + 3\nObservation:",
|
||||
}},
|
||||
expectedFinish: nil,
|
||||
expectedErr: nil,
|
||||
},
|
||||
}
|
||||
|
||||
a := OneShotZeroAgent{}
|
||||
|
||||
Reference in New Issue
Block a user