mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 23:41:12 +08:00
### What problem does this PR solve? Fix #14340 ## Problem Description When using an **Agentic Agent** (not Workflow) with one or more Retrieval tools (e.g., Dataset Retrieval + Memory Retrieval), the agent silently returns an empty response (`agent_response: ""`) after hanging for several minutes. The server logs show: ``` AttributeError: 'ChatCompletionMessageToolCall' object has no attribute 'index' ``` This error propagates as a `GENERIC_ERROR`, causing the canvas to return an empty response. The subsequent Memory save task then receives the empty `agent_response` and logs: ``` Document for referred_document_id XXXX not found ``` ## Reproduction Steps 1. Set `DOC_ENGINE=infinity` (or `elasticsearch` — the engine itself is not the root cause). 2. Create a blank **Agentic Agent** (not a Workflow). 3. Add **two Retrieval tools** to the Agent node: - `Retrieval_DS` → Dataset (Knowledge Base) - `Retrieval_Mem` → Memory component 4. Add a **Message** node with **Save to Memory** enabled. 5. Launch the agent and send any message (e.g., "hola"). 6. The agent hangs and returns an empty response. ## Root Cause Analysis The crash occurs in `_append_history` and `_append_history_batch` inside `rag/llm/chat_model.py`. These methods directly access `.index` on tool call objects: ```python # _append_history_batch { "index": tc.index, # <-- crashes here ... } ``` However, **non-streaming** LLM responses (`stream=False`) return `ChatCompletionMessageToolCall` objects, which **do not have an `index` field** according to the OpenAI API specification. The `index` field only exists on `ChoiceDeltaToolCall` objects returned in **streaming** responses (`stream=True`). When the agentic agent triggers an internal `full_question` call (used to compress multi-turn conversation history), the request is incorrectly routed through `async_chat_with_tools` because `is_tools=True` is set at the `LLMBundle` level. If the LLM decides to emit `tool_calls` during this auxiliary request, the code enters the non-streaming tool loop and crashes when trying to append history. ## Fix Replaced all direct `.index` accesses with `getattr(..., "index", None)` for safe, backward-compatible access: | Method | File | Line | Change | |--------|------|------|--------| | `_append_history` | `rag/llm/chat_model.py` | ~L304 | `tool_call.index` → `getattr(tool_call, "index", None)` | | `_append_history_batch` | `rag/llm/chat_model.py` | ~L332 | `tc.index` → `getattr(tc, "index", None)` | | `_append_history` | `rag/llm/chat_model.py` | ~L1467 | `tool_call.index` → `getattr(tool_call, "index", None)` | | `_append_history_batch` | `rag/llm/chat_model.py` | ~L1496 | `tc.index` → `getattr(tc, "index", None)` | ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Signed-off-by: noob <yixiao121314@outlook.com>