mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-19 11:45:10 +08:00
Fix TypeError in meta_filter when using numeric metadata (#12286)
The filter_out function in metadata_utils.py was using a list of tuples to evaluate conditions. Python eagerly evaluates all tuple elements when constructing the list, causing "input in value" to be evaluated even when the operator is "=". When input and value are floats (after numeric conversion), this causes TypeError: "argument of type 'float' is not iterable". This change replaces the tuple list with if-elif chain, ensuring only the matching condition is evaluated. ### What problem does this PR solve? Fixes #12285 When using comparison operators like `=`, `>`, `<` with numeric metadata, the `filter_out` function throws `TypeError("argument of type 'float' is not iterable")`. This is because Python eagerly evaluates all tuple elements when constructing a list, causing `input in value` to be evaluated even when the operator is `=`. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [ ] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe):
This commit is contained in:
@ -13,6 +13,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
import ast
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, Dict
|
from typing import Any, Callable, Dict
|
||||||
|
|
||||||
@ -49,8 +50,8 @@ def meta_filter(metas: dict, filters: list[dict], logic: str = "and"):
|
|||||||
try:
|
try:
|
||||||
if isinstance(input, list):
|
if isinstance(input, list):
|
||||||
input = input[0]
|
input = input[0]
|
||||||
input = float(input)
|
input = ast.literal_eval(input)
|
||||||
value = float(value)
|
value = ast.literal_eval(value)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
if isinstance(input, str):
|
if isinstance(input, str):
|
||||||
@ -58,28 +59,41 @@ def meta_filter(metas: dict, filters: list[dict], logic: str = "and"):
|
|||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
value = value.lower()
|
value = value.lower()
|
||||||
|
|
||||||
for conds in [
|
matched = False
|
||||||
(operator == "contains", input in value if not isinstance(input, list) else all([i in value for i in input])),
|
try:
|
||||||
(operator == "not contains", input not in value if not isinstance(input, list) else all([i not in value for i in input])),
|
if operator == "contains":
|
||||||
(operator == "in", input in value if not isinstance(input, list) else all([i in value for i in input])),
|
matched = input in value if not isinstance(input, list) else all(i in value for i in input)
|
||||||
(operator == "not in", input not in value if not isinstance(input, list) else all([i not in value for i in input])),
|
elif operator == "not contains":
|
||||||
(operator == "start with", str(input).lower().startswith(str(value).lower()) if not isinstance(input, list) else "".join([str(i).lower() for i in input]).startswith(str(value).lower())),
|
matched = input not in value if not isinstance(input, list) else all(i not in value for i in input)
|
||||||
(operator == "end with", str(input).lower().endswith(str(value).lower()) if not isinstance(input, list) else "".join([str(i).lower() for i in input]).endswith(str(value).lower())),
|
elif operator == "in":
|
||||||
(operator == "empty", not input),
|
matched = input in value if not isinstance(input, list) else all(i in value for i in input)
|
||||||
(operator == "not empty", input),
|
elif operator == "not in":
|
||||||
(operator == "=", input == value),
|
matched = input not in value if not isinstance(input, list) else all(i not in value for i in input)
|
||||||
(operator == "≠", input != value),
|
elif operator == "start with":
|
||||||
(operator == ">", input > value),
|
matched = str(input).lower().startswith(str(value).lower()) if not isinstance(input, list) else "".join([str(i).lower() for i in input]).startswith(str(value).lower())
|
||||||
(operator == "<", input < value),
|
elif operator == "end with":
|
||||||
(operator == "≥", input >= value),
|
matched = str(input).lower().endswith(str(value).lower()) if not isinstance(input, list) else "".join([str(i).lower() for i in input]).endswith(str(value).lower())
|
||||||
(operator == "≤", input <= value),
|
elif operator == "empty":
|
||||||
]:
|
matched = not input
|
||||||
try:
|
elif operator == "not empty":
|
||||||
if all(conds):
|
matched = bool(input)
|
||||||
ids.extend(docids)
|
elif operator == "=":
|
||||||
break
|
matched = input == value
|
||||||
except Exception:
|
elif operator == "≠":
|
||||||
pass
|
matched = input != value
|
||||||
|
elif operator == ">":
|
||||||
|
matched = input > value
|
||||||
|
elif operator == "<":
|
||||||
|
matched = input < value
|
||||||
|
elif operator == "≥":
|
||||||
|
matched = input >= value
|
||||||
|
elif operator == "≤":
|
||||||
|
matched = input <= value
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if matched:
|
||||||
|
ids.extend(docids)
|
||||||
return ids
|
return ids
|
||||||
|
|
||||||
for k, v2docs in metas.items():
|
for k, v2docs in metas.items():
|
||||||
|
|||||||
Reference in New Issue
Block a user