Просмотр исходного кода

Harden Hive gap evidence source resolution

SamLee 4 недель назад
Родитель
Сommit
ef9318c0f0
2 измененных файлов с 31 добавлено и 0 удалено
  1. 10 0
      examples/demand/demand_mysql.md
  2. 21 0
      examples/demand/evidence_pack_builder.py

+ 10 - 0
examples/demand/demand_mysql.md

@@ -63,6 +63,16 @@ $system$
 如果一条需求同时由多个证据支持,就在 `sources` 里放多条。不要再把“一个需求绑定几个 itemset”当成需求定义;itemset 只是可选证据来源之一。
 如果一条需求同时由多个证据支持,就在 `sources` 里放多条。不要再把“一个需求绑定几个 itemset”当成需求定义;itemset 只是可选证据来源之一。
 如果使用多个 itemset 作为证据,必须把每个 itemset 拆成独立的 `pattern_itemset` source,不要把并列 itemset 塞进同一个 source。
 如果使用多个 itemset 作为证据,必须把每个 itemset 拆成独立的 `pattern_itemset` source,不要把并列 itemset 塞进同一个 source。
 
 
+证据字段必须按 source 类型填写,字段名写错会被代码拒绝:
+
+- `pattern_itemset` 必须填写真实 `itemset_ids`,例如:
+  `{"source_kind":"pattern_itemset","source_tool":"get_itemset_detail","itemset_ids":[1590200],"element_names":["防诈反骗","影视传记","科普"],"element_type":"实质"}`。
+  不能只在 `reason` 里写“itemset 1590200”,也不能只写 `element_names`。
+- `high_weight_category` / `category_co_occurrence` 必须填写 `category_ids`、`category_names` 或 `category_paths`,例如:
+  `{"source_kind":"high_weight_category","source_tool":"get_weight_score_topn","category_names":["安全防护"],"element_type":"实质"}`。
+  分类名不要只放在 `element_names` 里。
+- `high_weight_element` / `element_co_occurrence` 才使用 `element_names`。
+
 ## 工作方式
 ## 工作方式
 
 
 1. 先看高权重元素和高权重分类:
 1. 先看高权重元素和高权重分类:

+ 21 - 0
examples/demand/evidence_pack_builder.py

@@ -276,6 +276,14 @@ def _resolve_pattern_itemset_source(
     )
     )
     if invalid_itemset_ids:
     if invalid_itemset_ids:
         return None, f"invalid itemset_ids: {invalid_itemset_ids}"
         return None, f"invalid itemset_ids: {invalid_itemset_ids}"
+    if not itemset_ids:
+        itemset_ids = _extract_itemset_ids_from_text(
+            source.get("reason"),
+            source.get("desc"),
+            source.get("description"),
+            _read_field(demand_item, "reason"),
+            _read_field(demand_item, "desc"),
+        )
     if not itemset_ids:
     if not itemset_ids:
         return None, "pattern_itemset source missing itemset_ids"
         return None, "pattern_itemset source missing itemset_ids"
 
 
@@ -391,6 +399,8 @@ def _resolve_elementish_source(
             groups.extend({"category_paths": [path]} for path in category_paths)
             groups.extend({"category_paths": [path]} for path in category_paths)
         elif category_names:
         elif category_names:
             groups.extend({"category_names": [name]} for name in category_names)
             groups.extend({"category_names": [name]} for name in category_names)
+        elif element_names:
+            groups.extend({"category_names": [name]} for name in element_names)
 
 
     if not groups:
     if not groups:
         groups.append(
         groups.append(
@@ -507,6 +517,17 @@ def _resolve_source_kind(
     return ""
     return ""
 
 
 
 
+def _extract_itemset_ids_from_text(*values: Any) -> list[int]:
+    ids: list[int] = []
+    for value in values:
+        if value is None:
+            continue
+        text = str(value)
+        for match in re.finditer(r"itemset\\s*[_#:::-]?\\s*(\\d{3,})", text, flags=re.IGNORECASE):
+            ids.append(int(match.group(1)))
+    return _unique_ints(ids)
+
+
 def _extract_evidence_refs(demand_item: Any) -> dict[str, Any]:
 def _extract_evidence_refs(demand_item: Any) -> dict[str, Any]:
     value = _read_field(demand_item, "evidence_refs", {})
     value = _read_field(demand_item, "evidence_refs", {})
     if isinstance(value, str):
     if isinstance(value, str):