Build field suggestions from vision candidate fields
This commit is contained in:
parent
b06e260dad
commit
d542bcfdf8
|
|
@ -696,6 +696,76 @@ def build_vision_candidate_fields(classification: dict[str, Any]) -> list[dict[s
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
|
||||||
|
def build_vision_field_suggestions(
|
||||||
|
candidate_fields: list[dict[str, Any]],
|
||||||
|
existing_fields: dict[str, Any] | None = None,
|
||||||
|
) -> list[dict[str, Any]]:
|
||||||
|
"""
|
||||||
|
Convert vision candidate fields into simple add/update/ignore suggestions.
|
||||||
|
|
||||||
|
This intentionally stays conservative:
|
||||||
|
- high confidence merchant/time/item_count/money candidates are surfaced
|
||||||
|
- symbol/noise is ignored
|
||||||
|
- existing field comparison can be expanded later
|
||||||
|
"""
|
||||||
|
existing_fields = existing_fields or {}
|
||||||
|
suggestions: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
type_to_existing_key = {
|
||||||
|
"merchant_or_header": "merchant_raw",
|
||||||
|
"transaction_time": "transaction_time",
|
||||||
|
"item_count": "item_count",
|
||||||
|
"money_amounts": "amount_candidates",
|
||||||
|
}
|
||||||
|
|
||||||
|
for field in candidate_fields or []:
|
||||||
|
candidate_type = field.get("candidate_type")
|
||||||
|
if candidate_type == "symbol_or_noise":
|
||||||
|
continue
|
||||||
|
|
||||||
|
confidence = float(field.get("confidence") or 0)
|
||||||
|
ocr_confidence = field.get("ocr_confidence")
|
||||||
|
value = field.get("value")
|
||||||
|
|
||||||
|
if not value:
|
||||||
|
continue
|
||||||
|
|
||||||
|
min_conf = 0.40
|
||||||
|
if candidate_type in {"merchant_or_header", "transaction_time"}:
|
||||||
|
min_conf = 0.60
|
||||||
|
elif candidate_type == "money_amounts":
|
||||||
|
min_conf = 0.50
|
||||||
|
|
||||||
|
if confidence < min_conf:
|
||||||
|
continue
|
||||||
|
|
||||||
|
existing_key = type_to_existing_key.get(candidate_type, candidate_type)
|
||||||
|
existing_value = existing_fields.get(existing_key)
|
||||||
|
|
||||||
|
action = "add"
|
||||||
|
if existing_value:
|
||||||
|
action = "review_update" if str(existing_value).strip() != str(value).strip() else "already_present"
|
||||||
|
|
||||||
|
suggestions.append(
|
||||||
|
{
|
||||||
|
"suggestion_type": candidate_type,
|
||||||
|
"target_field": existing_key,
|
||||||
|
"action": action,
|
||||||
|
"value": value,
|
||||||
|
"existing_value": existing_value,
|
||||||
|
"confidence": confidence,
|
||||||
|
"ocr_confidence": ocr_confidence,
|
||||||
|
"source": "vision_candidate_fields",
|
||||||
|
"source_region_index": field.get("source_region_index"),
|
||||||
|
"source_bbox": field.get("source_bbox"),
|
||||||
|
"source_crop_path": field.get("source_crop_path"),
|
||||||
|
"raw_text": field.get("raw_text"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return suggestions
|
||||||
|
|
||||||
def build_vision_assisted_layout(source_layout: dict[str, Any] | None, vision_result: dict[str, Any]) -> dict[str, Any]:
|
def build_vision_assisted_layout(source_layout: dict[str, Any] | None, vision_result: dict[str, Any]) -> dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Convert vision analysis into normal layout_json.
|
Convert vision analysis into normal layout_json.
|
||||||
|
|
@ -716,6 +786,7 @@ def build_vision_assisted_layout(source_layout: dict[str, Any] | None, vision_re
|
||||||
region_score,
|
region_score,
|
||||||
)
|
)
|
||||||
candidate_fields = build_vision_candidate_fields(region_classification)
|
candidate_fields = build_vision_candidate_fields(region_classification)
|
||||||
|
field_suggestions = build_vision_field_suggestions(candidate_fields)
|
||||||
|
|
||||||
layout["vision_assisted"] = True
|
layout["vision_assisted"] = True
|
||||||
layout["vision_assisted_status"] = normalized_vision.get("status", "unknown")
|
layout["vision_assisted_status"] = normalized_vision.get("status", "unknown")
|
||||||
|
|
@ -725,6 +796,7 @@ def build_vision_assisted_layout(source_layout: dict[str, Any] | None, vision_re
|
||||||
layout["vision_region_score"] = region_score
|
layout["vision_region_score"] = region_score
|
||||||
layout["vision_region_classification"] = region_classification
|
layout["vision_region_classification"] = region_classification
|
||||||
layout["vision_candidate_fields"] = candidate_fields
|
layout["vision_candidate_fields"] = candidate_fields
|
||||||
|
layout["vision_field_suggestions"] = field_suggestions
|
||||||
layout["layout_sync_source"] = "vision_assisted"
|
layout["layout_sync_source"] = "vision_assisted"
|
||||||
layout["layout_needs_review"] = True
|
layout["layout_needs_review"] = True
|
||||||
return layout
|
return layout
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue