Spaces:
Sleeping
Sleeping
| """ | |
| Output projection using configurable field selection. | |
| Responsibilities: | |
| - Load output_config.json and interpret projection rules. | |
| - Shape merged canonical records into the final JSON schema. | |
| - Include or exclude provenance and confidence based on config. | |
| - Serialize the result for writing to disk. | |
| Separates "what we know" (internal model) from "what we emit" (output contract). | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import asdict | |
| from typing import Any | |
| from .utils import read_json_file | |
| def load_output_config(path: str) -> dict[str, Any]: | |
| """ | |
| Load and validate the output projection configuration. | |
| Args: | |
| path: Filesystem path to output_config.json. | |
| Returns: | |
| Parsed configuration dict. | |
| """ | |
| return read_json_file(path) | |
| def project_candidate( | |
| candidate: dict[str, Any], | |
| config: dict[str, Any], | |
| ) -> dict[str, Any]: | |
| """ | |
| Project a merged candidate onto the configured output shape. | |
| This function does not mutate the input candidate. | |
| Args: | |
| candidate: Fully merged internal candidate record. | |
| config: Output projection configuration. | |
| Returns: | |
| Final candidate dict ready for JSON serialization. | |
| """ | |
| projected: dict[str, Any] = {} | |
| include_confidence = config.get("include_confidence", True) | |
| include_provenance = config.get("include_provenance", True) | |
| fields = config.get("fields", []) | |
| rename_map = config.get("rename", {}) | |
| on_missing = config.get("on_missing", {}) | |
| default_missing_action = on_missing.get("default", "omit") | |
| proj_confidence: dict[str, float] = {} | |
| proj_provenance: dict[str, Any] = {} | |
| for field in fields: | |
| output_key = rename_map.get(field, field) | |
| val = candidate.get(field) | |
| # Check if missing or empty | |
| is_missing = val is None or val == "" or val == [] or val == {} | |
| if is_missing: | |
| action = on_missing.get(field, default_missing_action) | |
| if action == "null": | |
| projected[output_key] = None | |
| elif action == "empty_object": | |
| projected[output_key] = {} | |
| elif action == "omit": | |
| continue | |
| else: | |
| projected[output_key] = val | |
| # Handle confidence key and value if requested | |
| if include_confidence and "confidence" in candidate: | |
| conf_val = candidate["confidence"].get(field) | |
| if conf_val is not None: | |
| proj_confidence[output_key] = conf_val | |
| # Handle provenance key and value if requested | |
| if include_provenance and "provenance" in candidate: | |
| prov_val = candidate["provenance"].get(field) | |
| if prov_val is not None: | |
| if hasattr(prov_val, "__dataclass_fields__"): | |
| proj_provenance[output_key] = asdict(prov_val) | |
| else: | |
| proj_provenance[output_key] = prov_val | |
| if include_confidence: | |
| projected["confidence"] = proj_confidence | |
| if include_provenance: | |
| projected["provenance"] = proj_provenance | |
| return projected | |
| def project_candidates( | |
| candidate_list: list[dict[str, Any]], | |
| config: dict[str, Any], | |
| ) -> list[dict[str, Any]]: | |
| """ | |
| Project a list of merged candidates onto the configured output shape. | |
| Args: | |
| candidate_list: List of fully merged candidate records. | |
| config: Output projection configuration. | |
| Returns: | |
| List of projected candidate dicts. | |
| """ | |
| return [project_candidate(c, config) for c in candidate_list] | |