langgenius / dify

Dify is an open-source LLM app development platform. Dify's intuitive interface combines AI workflow, RAG pipeline, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production.
https://dify.ai
Other
46.79k stars 6.61k forks source link

How to add more iterations in iteration? #8889

Open zzkzzk1984 opened 2 hours ago

zzkzzk1984 commented 2 hours ago

Self Checks

1. Is this request related to a challenge you're experiencing? Tell me about your story.

How to add more iterations in iteration

2. Additional context or comments

No response

3. Can you help us with this feature?

dosubot[bot] commented 2 hours ago

I found a similar open issue that was closed recently. The solution provided involves adjusting the max_iteration property in the tempPayload object. This can be done using a slider or an input field within the AgentSetting component. Here is the relevant code snippet:

const maxIterationsMin = 1
const maxIterationsMax = 5

...

<ItemPanel
  className='mb-4'
  icon={
    <Unblur className='w-4 h-4 text-[#FB6514]' />
  }
  name={t('appDebug.agent.setting.maximumIterations.name')}
  description={t('appDebug.agent.setting.maximumIterations.description')}
>
  <div className='flex items-center'>
    <Slider
      className='mr-3 w-[156px]'
      min={maxIterationsMin}
      max={maxIterationsMax}
      value={tempPayload.max_iteration}
      onChange={(value) => {
        setTempPayload({
          ...tempPayload,
          max_iteration: value,
        })
      }}
    />

    <input
      type="number"
      min={maxIterationsMin}
      max={maxIterationsMax} step={1}
      className="block w-11 h-7 leading-7 rounded-lg border-0 pl-1 px-1.5 bg-gray-100 text-gray-900  placeholder:text-gray-400 focus:ring-1 focus:ring-inset focus:ring-primary-600"
      value={tempPayload.max_iteration}
      onChange={(e) => {
        let value = parseInt(e.target.value, 10)
        if (value < maxIterationsMin)
          value = maxIterationsMin

        if (value > maxIterationsMax)
          value = maxIterationsMax
        setTempPayload({
          ...tempPayload,
          max_iteration: value,
        })
      }} />
  </div>
</ItemPanel>

This code allows you to set the number of iterations within the range defined by maxIterationsMin and maxIterationsMax [1].

Additionally, to add more iterations in the IterationNode class, you need to modify the _run method to handle additional iterations. Here is the relevant part of the code that handles the iterations:

try:
    for _ in range(len(iterator_list_value)):
        # run workflow
        rst = graph_engine.run()
        for event in rst:
            if isinstance(event, (BaseNodeEvent | BaseParallelBranchEvent)) and not event.in_iteration_id:
                event.in_iteration_id = self.node_id
            if (
                isinstance(event, BaseNodeEvent)
                and event.node_type == NodeType.ITERATION_START
                and not isinstance(event, NodeRunStreamChunkEvent)
            ):
                continue

            if isinstance(event, NodeRunSucceededEvent):
                if event.route_node_state.node_run_result:
                    metadata = event.route_node_state.node_run_result.metadata
                    if not metadata:
                        metadata = {}

                    if NodeRunMetadataKey.ITERATION_ID not in metadata:
                        metadata[NodeRunMetadataKey.ITERATION_ID] = self.node_id
                        metadata[NodeRunMetadataKey.ITERATION_INDEX] = variable_pool.get_any(
                            [self.node_id, "index"]
                        )
                        event.route_node_state.node_run_result.metadata = metadata

                yield event
            elif isinstance(event, BaseGraphEvent):
                if isinstance(event, GraphRunFailedEvent):
                    # iteration run failed
                    yield IterationRunFailedEvent(
                        iteration_id=self.id,
                        iteration_node_id=self.node_id,
                        iteration_node_type=self.node_type,
                        iteration_node_data=self.node_data,
                        start_at=start_at,
                        inputs=inputs,
                        outputs={"output": jsonable_encoder(outputs)},
                        steps=len(iterator_list_value),
                        metadata={"total_tokens": graph_engine.graph_runtime_state.total_tokens},
                        error=event.error,
                    )
                    yield RunCompletedEvent(
                        run_result=NodeRunResult(
                            status=WorkflowNodeExecutionStatus.FAILED,
                            error=event.error,
                        )
                    )
                    return
            else:
                event = cast(InNodeEvent, event)
                yield event

        # append to iteration output variable list
        current_iteration_output = variable_pool.get_any(self.node_data.output_selector)
        outputs.append(current_iteration_output)

        # remove all nodes outputs from variable pool
        for node_id in iteration_graph.node_ids:
            variable_pool.remove_node(node_id)

        # move to next iteration
        current_index = variable_pool.get([self.node_id, "index"])
        if current_index is None:
            raise ValueError(f"iteration {self.node_id} current index not found")

        next_index = int(current_index.to_object()) + 1
        variable_pool.add([self.node_id, "index"], next_index)

        if next_index < len(iterator_list_value):
            variable_pool.add([self.node_id, "item"], iterator_list_value[next_index])

        yield IterationRunNextEvent(
            iteration_id=self.id,
            iteration_node_id=self.node_id,
            iteration_node_type=self.node_type,
            iteration_node_data=self.node_data,
            index=next_index,
            pre_iteration_output=jsonable_encoder(current_iteration_output)
            if current_iteration_output
            else None,
        )

To add more iterations, you can modify the loop condition or the iterator_list_value to include more items. For example, if you want to double the number of iterations, you can concatenate the list with itself:

iterator_list_value = iterator_list_value + iterator_list_value

Or, you can change the loop condition to iterate more times:

for _ in range(2 * len(iterator_list_value)):
    # run workflow
    # ...

Make sure to adjust the logic accordingly to handle the additional iterations properly [2][3].

To continue talking to Dosu, mention @dosu.