Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion dingo/model/rule/rule_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2691,12 +2691,36 @@ class RuleDictConsistency(BaseRule):
}

_required_fields = [RequiredField.METADATA, RequiredField.CONTEXT]
dynamic_config = EvaluatorRuleArgs(parameters={"ignore_order": True})

@classmethod
def _normalize_value(cls, value, ignore_order: bool):
"""Normalize nested values for configurable order-aware comparison."""
if isinstance(value, dict):
return {
key: cls._normalize_value(value[key], ignore_order)
for key in sorted(value.keys(), key=lambda x: str(x))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using repr(x) as the sorting key is more robust than str(x) when dealing with mixed-type keys (e.g., it correctly distinguishes between the integer 1 and the string '1'). This also ensures consistency with the sorting logic used for lists and sets on lines 2708 and 2713.

Suggested change
for key in sorted(value.keys(), key=lambda x: str(x))
for key in sorted(value.keys(), key=lambda x: repr(x))

}

if isinstance(value, (list, tuple)):
normalized = [cls._normalize_value(item, ignore_order) for item in value]
if ignore_order:
return sorted(normalized, key=lambda x: repr(x))
return normalized

if isinstance(value, set):
normalized = [cls._normalize_value(item, ignore_order) for item in value]
return sorted(normalized, key=lambda x: repr(x))

return value

@classmethod
def eval(cls, input_data: Data) -> EvalDetail:
res = EvalDetail(metric=cls.__name__)
left_dict = getattr(input_data, "metadata", None)
right_dict = getattr(input_data, "context", None)
parameters = cls.dynamic_config.parameters or {}
ignore_order = parameters.get("ignore_order", True)

if not isinstance(left_dict, dict) or not isinstance(right_dict, dict):
res.status = True
Expand All @@ -2710,7 +2734,13 @@ def eval(cls, input_data: Data) -> EvalDetail:
diff_keys = []
all_keys = set(left_dict.keys()) | set(right_dict.keys())
for key in sorted(all_keys, key=lambda x: str(x)):
if key not in left_dict or key not in right_dict or left_dict[key] != right_dict[key]:
if key not in left_dict or key not in right_dict:
diff_keys.append(str(key))
continue

left_value = cls._normalize_value(left_dict[key], ignore_order)
right_value = cls._normalize_value(right_dict[key], ignore_order)
if left_value != right_value:
diff_keys.append(str(key))

if diff_keys:
Expand Down
7 changes: 0 additions & 7 deletions docs/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,6 @@ LLM 配置(支持额外字段,所有额外字段会直接透传给 LLM API
| key | str | null | No | API 密钥 |
| api_url | str | null | No | API URL |
| embedding_config | object | null | No | Embedding 模型独立配置(RAG 评估器使用) |
| temperature | number | 1 | No | 采样温度,0-2之间 |
| top_p | number | 1 | No | 核心采样概率 |
| max_tokens | number | 4000 | No | 最大生成token数 |
| presence_penalty | number | 0 | No | 存在惩罚,-2.0到2.0之间 |
| frequency_penalty | number | 0 | No | 频率惩罚,-2.0到2.0之间 |
| agent_config | object | null | No | Agent 专属配置(max_iterations、tools 等) |
| threshold | number | - | No | 评估通过阈值(各评估器自定义) |
| *其他字段* | any | - | No | 所有额外字段直接透传给 LLM API |

## 配置文件示例
Expand Down
17 changes: 4 additions & 13 deletions docs/technical/technical_all.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,19 +220,10 @@ dingo 在使用提示词进行评估任务的时候,必须同时使用场景
+ model
+ key
+ api_url
+ temperature(直接平铺在配置中)
+ top_p
+ max_tokens
+ presence_penalty
+ frequency_penalty
+ agent_config(Agent 评估器专用,包含 max_iterations、tools 等)

LLM 调参配置直接平铺在 `config` 对象中(不再嵌套在 `parameters` 字段下),会对模型推理产生影响,可以设置的值包括:
+ temperature
+ top_p
+ max_tokens
+ presence_penalty
+ frequency_penalty
+ embedding_config(RAG 评估器专用)
+ 其他字段(直接平铺在配置中并透传到 LLM API)

LLM 调参配置直接平铺在 `config` 对象中(不再嵌套在 `parameters` 字段下),除标准字段外,其它字段将直接透传到 LLM API。

更多参数细节可参考OpenAI API官方文档。

Expand Down
Loading