mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
fix(retrieval): keep manual metadata filter reusable inside Iteration (#14849)
## What problem does this PR solve? Closes #12582. When a Retrieval component sits inside an Iteration with a **manual** metadata filter that references the iteration variable (e.g. `{IterationItem:abc@item}`), every iteration reuses the value resolved on the **first** pass. Root cause: [`_resolve_manual_filter` in `agent/tools/retrieval.py`](https://github.com/infiniflow/ragflow/blob/main/agent/tools/retrieval.py#L144-L171) mutated `flt["value"]` in place. The `filters` list passed in is the live `self._param.meta_data_filter["manual"]` (see [`apply_meta_data_filter` in `common/metadata_utils.py:257-261`](https://github.com/infiniflow/ragflow/blob/main/common/metadata_utils.py#L257-L261)), so after the first iteration the param dict permanently held the resolved string instead of the original variable reference. ```text iter #1: flt["value"] = "{IterationItem:abc@item}" → resolved to "AI" after mutation: flt["value"] = "AI" ← written back into _param iter #2: flt["value"] = "AI" ← no {…} matches retrieval keeps filtering by "AI" forever ``` This PR returns a shallow copy with the resolved value instead, leaving the original filter (and its variable reference) intact for the next iteration. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## Test plan - [ ] Build an agent: `Agent (structured output → list of areas) → Iteration → Retrieval (manual filter: Area = {IterationItem/Item}) → Message`. Run with a multi-area query and confirm each iteration's Retrieval result matches its own item, not the first item. - [ ] Regression: Retrieval with a manual metadata filter outside an Iteration still resolves the variable correctly on each request. - [ ] Regression: Retrieval with no metadata filter and with `auto` / `semi_auto` filters behave unchanged.
This commit is contained in:
@@ -142,6 +142,11 @@ class Retrieval(ToolBase, ABC):
|
||||
return DocMetadataService.get_flatted_meta_by_kbs(kb_ids)
|
||||
|
||||
def _resolve_manual_filter(flt: dict) -> dict:
|
||||
# Return a new dict instead of mutating `flt` in place. The
|
||||
# caller passes filters straight out of self._param.meta_data_filter,
|
||||
# so mutating them would replace the variable reference with its
|
||||
# resolved value and every subsequent invocation (e.g. inside an
|
||||
# Iteration component) would reuse that stale value.
|
||||
pat = re.compile(self.variable_ref_patt)
|
||||
s = flt.get("value", "")
|
||||
out_parts = []
|
||||
@@ -167,8 +172,9 @@ class Retrieval(ToolBase, ABC):
|
||||
last = m.end()
|
||||
|
||||
out_parts.append(s[last:])
|
||||
flt["value"] = "".join(out_parts)
|
||||
return flt
|
||||
resolved = dict(flt)
|
||||
resolved["value"] = "".join(out_parts)
|
||||
return resolved
|
||||
|
||||
chat_mdl = None
|
||||
if self._param.meta_data_filter.get("method") in ["auto", "semi_auto"]:
|
||||
|
||||
Reference in New Issue
Block a user