Spaces:
Sleeping
Sleeping
| """ | |
| run.py | |
| ====== | |
| CLI entry point. Demonstrates the full pipeline and prints a QA summary. | |
| Usage: | |
| # Extraction + validation only (no API key needed): | |
| python run.py path/to/Master_Sheet.xlsx --no-llm | |
| # Full run with narratives (requires ANTHROPIC_API_KEY): | |
| python run.py path/to/Master_Sheet.xlsx --developer "Green Edge Consortium" | |
| The mini-grid capacities are an external input (developer-supplied, not in the | |
| survey data). Pass them with --solar-pv / --battery / --annual-consumption, or | |
| fill them in afterwards on the returned object before rendering. | |
| """ | |
| from __future__ import annotations | |
| import argparse | |
| from pue_report_agent import extract_master_sheet, validate, recompute | |
| from pue_report_agent.schema import EnergySystemSpec | |
| def main() -> None: | |
| ap = argparse.ArgumentParser(description="PUE report builder") | |
| ap.add_argument("master_sheet") | |
| ap.add_argument("--developer", default="the mini-grid developer") | |
| ap.add_argument("--no-llm", action="store_true", | |
| help="skip narrative generation (no API key required)") | |
| ap.add_argument("--solar-pv", default="") | |
| ap.add_argument("--battery", default="") | |
| ap.add_argument("--annual-consumption", default="") | |
| ap.add_argument("--date", default="", help="report date for the title page") | |
| ap.add_argument("--docx-out", default="", | |
| help="render a template-faithful .docx to this path") | |
| ap.add_argument("--json-out", default="", | |
| help="write the full PUEReportData JSON to this path") | |
| args = ap.parse_args() | |
| # 1. Deterministic extraction | |
| data = extract_master_sheet(args.master_sheet) | |
| # 2. Recompute every total from line items (never trust a sheet total) | |
| data = recompute(data) | |
| # 3. External developer-supplied capacity overrides (optional). Merge into | |
| # the already-extracted minigrid so we don't discard the distribution | |
| # metrics / inverter that extraction pulled from Key Findings. | |
| if args.solar_pv: | |
| data.minigrid.solar_pv = args.solar_pv | |
| if args.battery: | |
| data.minigrid.battery_storage = args.battery | |
| if args.annual_consumption: | |
| data.minigrid.annual_consumption = args.annual_consumption | |
| # 4. Validation / reconciliation | |
| data = validate(data) | |
| # 5. Narratives (optional). All narratives use Gemini. | |
| if not args.no_llm: | |
| from pue_report_agent import generate_narratives | |
| if generate_narratives is None: | |
| print("[warn] langchain not installed; skipping narratives.") | |
| else: | |
| data = generate_narratives(data) | |
| # 6. QA summary | |
| _print_summary(data) | |
| # 7. Render the template-faithful Word document | |
| if args.docx_out: | |
| from pue_report_agent.render import render | |
| render(data, args.docx_out, developer=args.developer, | |
| report_date=args.date) | |
| print(f"\nWrote {args.docx_out}") | |
| if args.json_out: | |
| with open(args.json_out, "w") as fh: | |
| fh.write(data.model_dump_json(indent=2)) | |
| print(f"Wrote {args.json_out}") | |
| def _print_summary(data) -> None: | |
| c = data.community | |
| print("=" * 64) | |
| print(f" {c.name} ({c.lga}, {c.state})") | |
| print("=" * 64) | |
| print(f" Interviewed: {data.interviews.total} " | |
| f"(farmers {data.interviews.farmers}, processors " | |
| f"{data.interviews.agroprocessors}, SME {data.interviews.sme}, " | |
| f"mobility {data.interviews.mobility})") | |
| print(f" Farmers: {data.farmers.male}M / {data.farmers.female}F, " | |
| f"{len(data.farmers.crops)} crops") | |
| print(f" Processors: {data.processors.male}M / {data.processors.female}F, " | |
| f"{len(data.processors.machinery)} machines on record") | |
| print(f" SME types: {len(data.sme.types)} Mobility: {data.mobility.total}") | |
| print(f" Pilot energy: {data.equipment_pilot.projection_total_kwh} kWh " | |
| f"ScaleUp: {data.equipment_scaleup.projection_total_kwh} kWh") | |
| print(f" Budget grand total: ₦{(data.budget.grand_total or 0):,.0f}") | |
| print(f" Financial models: {[m.model_name for m in data.financial_models]}") | |
| print() | |
| if data.warnings: | |
| print(f" ⚠ {len(data.warnings)} item(s) need review:") | |
| for w in data.warnings: | |
| print(f" • {w}") | |
| else: | |
| print(" ✓ no warnings") | |
| if __name__ == "__main__": | |
| main() | |