dify icon indicating copy to clipboard operation
dify copied to clipboard

fix(llm/nodes.py): Ensure that the output returns without any exceptions

Open auxpd opened this issue 11 months ago • 1 comments

Summary

Using a workflow for tool encapsulation, when core/workflow/nodes/llm/node.py LLMNode._run is called before the result_text is initialized, it causes the last output dict to reference an uninitialized variable

I directly appended the correct output to the result of the LLM output to ensure that there were no exceptions in the preceding process.

[!Tip] Close issue syntax: Fixes #<issue number> or Resolves #<issue number>, see documentation for more details. Fixes #14876

Screenshots

Before After
... ...

Checklist

[!IMPORTANT]
Please review the checklist below before submitting your pull request.

  • [ ] This change requires a documentation update, included: Dify Document
  • [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • [x] I've updated the documentation accordingly.
  • [x] I ran dev/reformat(backend) and cd web && npx lint-staged(frontend) to appease the lint gods

auxpd avatar Mar 04 '25 08:03 auxpd

I have a question, why the source code pulls the outside of the exception catch? I'm not sure if I'm missing any designs

auxpd avatar Mar 04 '25 08:03 auxpd

Can this change fix #14876? It seems that unless the issue occurs at

outputs = {"text": result_text, "usage": jsonable_encoder(usage), "finish_reason": finish_reason}

there should be no difference between the two.

laipz8200 avatar Mar 05 '25 05:03 laipz8200

This is the previous error stack message:
2025-03-01 18:56:13.046 ERROR [ThreadPoolExecutor-10_5] [graph_engine.py:815] - Node 信息提取 run failed Traceback (most recent call last): File "/app/api/core/workflow/graph_engine/graph_engine.py", line 626, in _run_node for item in generator: ^^^^^^^^^ File "/app/api/core/workflow/nodes/base/node.py", line 84, in run yield from result File "/app/api/core/workflow/nodes/llm/node.py", line 212, in _run outputs = {"text": result_text, "usage": jsonable_encoder(usage), "finish_reason": finish_reason} ^^^^^^^^^^^ UnboundLocalError: cannot access local variable 'result_text' where it is not associated with a value 2025-03-01 18:56:13.047 ERROR [ThreadPoolExecutor-10_5] [graph_engine.py:576] - Unknown Error when generating in parallel Traceback (most recent call last): File "/app/api/core/workflow/graph_engine/graph_engine.py", line 553, in _run_parallel_node for item in generator: ^^^^^^^^^ File "/app/api/core/workflow/graph_engine/graph_engine.py", line 312, in _run raise e File "/app/api/core/workflow/graph_engine/graph_engine.py", line 283, in _run for item in generator: ^^^^^^^^^ File "/app/api/core/workflow/graph_engine/graph_engine.py", line 816, in _run_node raise e File "/app/api/core/workflow/graph_engine/graph_engine.py", line 626, in _run_node for item in generator: ^^^^^^^^^ File "/app/api/core/workflow/nodes/base/node.py", line 84, in run yield from result File "/app/api/core/workflow/nodes/llm/node.py", line 212, in _run outputs = {"text": result_text, "usage": jsonable_encoder(usage), "finish_reason": finish_reason} ^^^^^^^^^^^ UnboundLocalError: cannot access local variable 'result_text' where it is not associated with a value

auxpd avatar Mar 05 '25 06:03 auxpd

If "outputs" dict is expected to be returned with a normal response, would it be more appropriate to put it in the try struct?

auxpd avatar Mar 05 '25 06:03 auxpd

The root issue is that a return statement is missing in the except block, but your method can also resolve the problem.

laipz8200 avatar Mar 05 '25 06:03 laipz8200