|
|
@@ -118,22 +118,32 @@ def _build_evidence_pack(
|
|
|
return _reject(item_reason)
|
|
|
|
|
|
matched_post_ids = _merge_post_ids(itemset.get("matched_post_ids") for itemset in itemsets)
|
|
|
- source_post_id = _choose_source_post_id(evidence_refs, demand_item, matched_post_ids)
|
|
|
- if not source_post_id:
|
|
|
+ requested_source_post_id = _choose_source_post_id(evidence_refs, demand_item, matched_post_ids)
|
|
|
+ if not requested_source_post_id:
|
|
|
return _reject("source_post_id cannot be resolved from DB-validated matched_post_ids")
|
|
|
- if source_post_id not in set(matched_post_ids):
|
|
|
+ if requested_source_post_id not in set(matched_post_ids):
|
|
|
return _reject(
|
|
|
- f"source_post_id {source_post_id} is not in matched_post_ids for itemset_ids={itemset_ids}"
|
|
|
+ f"source_post_id {requested_source_post_id} is not in matched_post_ids for itemset_ids={itemset_ids}"
|
|
|
)
|
|
|
|
|
|
element_bindings = query_element_bindings_for_items(
|
|
|
execution_id=int(execution_id),
|
|
|
itemset_items=itemset_items,
|
|
|
- post_ids=[source_post_id],
|
|
|
+ post_ids=[requested_source_post_id],
|
|
|
)
|
|
|
binding_reason = _validate_element_bindings(itemset_items, element_bindings)
|
|
|
if binding_reason:
|
|
|
- return _reject(binding_reason)
|
|
|
+ resolved_source_post_id, element_bindings, binding_reason = _resolve_source_post_with_bindings(
|
|
|
+ execution_id=int(execution_id),
|
|
|
+ itemset_items=itemset_items,
|
|
|
+ matched_post_ids=matched_post_ids,
|
|
|
+ preferred_post_id=requested_source_post_id,
|
|
|
+ )
|
|
|
+ if binding_reason:
|
|
|
+ return _reject(binding_reason)
|
|
|
+ source_post_id = resolved_source_post_id
|
|
|
+ else:
|
|
|
+ source_post_id = requested_source_post_id
|
|
|
|
|
|
seed_terms = _resolve_seed_terms(evidence_refs, itemset_items, element_bindings)
|
|
|
seed_reason = _validate_seed_terms(seed_terms, itemset_items, element_bindings)
|
|
|
@@ -419,6 +429,47 @@ def _choose_source_post_id(
|
|
|
return matched_post_ids[0] if matched_post_ids else ""
|
|
|
|
|
|
|
|
|
+def _resolve_source_post_with_bindings(
|
|
|
+ execution_id: int,
|
|
|
+ itemset_items: list[dict[str, Any]],
|
|
|
+ matched_post_ids: list[str],
|
|
|
+ preferred_post_id: str,
|
|
|
+) -> tuple[str, list[dict[str, Any]], str | None]:
|
|
|
+ broad_bindings = query_element_bindings_for_items(
|
|
|
+ execution_id=int(execution_id),
|
|
|
+ itemset_items=itemset_items,
|
|
|
+ post_ids=matched_post_ids,
|
|
|
+ limit_per_item=max(len(matched_post_ids), 200),
|
|
|
+ )
|
|
|
+ by_item_id = {
|
|
|
+ int(binding["itemset_item_id"]): set(_normalize_list(binding.get("matched_post_ids")))
|
|
|
+ for binding in broad_bindings
|
|
|
+ if binding.get("itemset_item_id") is not None
|
|
|
+ }
|
|
|
+ candidate_posts: set[str] | None = set(matched_post_ids)
|
|
|
+ for item in itemset_items:
|
|
|
+ item_id = int(item["itemset_item_id"])
|
|
|
+ item_posts = {str(post_id) for post_id in by_item_id.get(item_id, set())}
|
|
|
+ if not item_posts:
|
|
|
+ return "", broad_bindings, f"itemset_item_id {item_id} has no exact PG topic element binding"
|
|
|
+ candidate_posts = candidate_posts & item_posts if candidate_posts is not None else item_posts
|
|
|
+
|
|
|
+ ordered_candidates = [post_id for post_id in matched_post_ids if post_id in (candidate_posts or set())]
|
|
|
+ if not ordered_candidates:
|
|
|
+ return "", broad_bindings, "no source_post_id can close all PG topic element bindings"
|
|
|
+
|
|
|
+ source_post_id = preferred_post_id if preferred_post_id in ordered_candidates else ordered_candidates[0]
|
|
|
+ exact_bindings = query_element_bindings_for_items(
|
|
|
+ execution_id=int(execution_id),
|
|
|
+ itemset_items=itemset_items,
|
|
|
+ post_ids=[source_post_id],
|
|
|
+ )
|
|
|
+ binding_reason = _validate_element_bindings(itemset_items, exact_bindings)
|
|
|
+ if binding_reason:
|
|
|
+ return "", exact_bindings, binding_reason
|
|
|
+ return source_post_id, exact_bindings, None
|
|
|
+
|
|
|
+
|
|
|
def _validate_element_bindings(
|
|
|
itemset_items: list[dict[str, Any]],
|
|
|
element_bindings: list[dict[str, Any]],
|