callInternal method

  1. @override
Future<ChainValues> callInternal(
  1. ChainValues inputs
)
override

Call method to be implemented by subclasses (called by call). This is where the core logic of the chain should be implemented.

Implementation

@override
Future<ChainValues> callInternal(final ChainValues inputs) async {
  final List<AgentStep> intermediateSteps = [];

  // Construct a mapping of tool name to tool for easy lookup
  final nameToToolMap = {for (final tool in _internalTools) tool.name: tool};

  // Let's start tracking the number of iterations and time elapsed
  var iterations = 0;
  final stopwatch = Stopwatch()..start();

  ChainValues onAgentFinished(final AgentFinish result) {
    return {
      ...result.returnValues,
      if (returnIntermediateSteps)
        intermediateStepsOutputKey: intermediateSteps,
    };
  }

  // We now enter the agent loop (until it returns something).
  while (_shouldContinue(iterations, stopwatch.elapsed)) {
    final (result, nextSteps) = await takeNextStep(
      nameToToolMap,
      inputs,
      intermediateSteps,
    );

    if (result != null) {
      return onAgentFinished(result);
    }

    if (nextSteps != null) {
      intermediateSteps.addAll(nextSteps);

      if (nextSteps.length == 1) {
        final nextStep = nextSteps.first;
        final tool = nameToToolMap[nextStep.action.tool];

        if (tool != null && tool.returnDirect) {
          return onAgentFinished(
            AgentFinish(
              returnValues: {
                agent.returnValues.first: nextStep.observation,
              },
            ),
          );
        }
      }
    }

    iterations += 1;
  }

  final stopped = agent.returnStoppedResponse(
    earlyStoppingMethod,
    intermediateSteps,
  );
  return onAgentFinished(stopped);
}