Spaces:
Sleeping
Sleeping
| """ | |
| Reference pipeline orchestrator. | |
| Wire into your LLM runner. Supports packs built from free-form scenarios. | |
| """ | |
| from pathlib import Path | |
| from typing import Tuple, Dict, Any | |
| import json | |
| from ..validators import schema_validator, unit_validator, math_validator, policy_validator | |
| from ..graders.rule_grader import grade | |
| from .io_utils import load_json | |
| # ------------------------- | |
| # REPLACE with your actual LLM runner | |
| def call_model(system_prompt: str, user_prompt: str, temperature: float = 0.2, top_p: float = 0.9) -> str: | |
| raise NotImplementedError("call_model must be implemented in your environment.") | |
| # ------------------------- | |
| def build_user_prompt(template_text: str, context: str, data_inputs: str, constraints: str) -> str: | |
| return ( | |
| template_text | |
| .replace("{CONTEXT}", context) | |
| .replace("{DATA_INPUTS}", data_inputs) | |
| .replace("{CONSTRAINTS}", constraints) | |
| ) | |
| def run_clarityops(pack_dir: str) -> Tuple[Dict[str, Any], Any]: | |
| pack = Path(pack_dir) | |
| root = pack.parents[1] | |
| system_prompt = (root / "prompts" / "system_two_phase.txt").read_text(encoding="utf-8") | |
| user_template = (root / "prompts" / "user_template.txt").read_text(encoding="utf-8") | |
| inputs = load_json(pack / "inputs.json") | |
| constraints = load_json(pack / "constraints.json") | |
| schema_cfg = load_json(pack / "schema.json") | |
| # Optional — only required if you want grading | |
| rubric_path = pack / "rubric.json" | |
| expected_path = pack / "expected.json" | |
| rubric = load_json(rubric_path) if rubric_path.exists() else {"set_equals": [], "must_contain": [], "numeric_equals": []} | |
| expected = load_json(expected_path) if expected_path.exists() else {"note": "No expected gold provided."} | |
| # Build Phase 1 user prompt | |
| context_block = inputs.get("context", "No context provided.") | |
| data_block = json.dumps(inputs.get("data_inputs", {}), ensure_ascii=False, indent=2) | |
| constraints_block = json.dumps(constraints, ensure_ascii=False, indent=2) | |
| # ---- Phase 1: Clarification Questions | |
| user_prompt_phase1 = build_user_prompt(user_template, context_block, data_block, constraints_block) | |
| user_prompt_phase1 += "\n\n[INSTRUCTION TO MODEL] Produce **Phase 1** only. Do not produce Phase 2 yet." | |
| clarif_raw = call_model(system_prompt, user_prompt_phase1) | |
| # ---- Collect answers | |
| clarif_answers_path = pack / "clarifications.json" | |
| if clarif_answers_path.exists(): | |
| clarif_answers = load_json(clarif_answers_path) | |
| # If the file is still the placeholder, raise to force operator to fill it | |
| if clarif_answers.get("_note"): | |
| raise RuntimeError(f"Clarification answers required. Edit and remove _note in: {clarif_answers_path}") | |
| else: | |
| raise RuntimeError(f"Clarification answers file missing: {clarif_answers_path}") | |
| # Merge clarifications into inputs for Phase 2 | |
| merged_inputs = inputs.copy() | |
| merged_inputs["clarifications"] = clarif_answers | |
| # ---- Phase 2: Structured Analysis | |
| user_prompt_phase2 = build_user_prompt( | |
| user_template, | |
| context_block, | |
| json.dumps(merged_inputs, ensure_ascii=False, indent=2), | |
| constraints_block | |
| ) | |
| user_prompt_phase2 += "\n\n[INSTRUCTION TO MODEL] Produce **Phase 2** only (final structured analysis), using clarified inputs." | |
| final_raw = call_model(system_prompt, user_prompt_phase2) | |
| # Parse final output JSON | |
| try: | |
| output = json.loads(final_raw) | |
| except Exception as e: | |
| raise ValueError(f"Failed to parse model output as JSON. Raw:\n{final_raw}") from e | |
| # Validators (hard guardrails) | |
| schema_validator.assert_valid(output, str(root / "schemas" / "analysis_output.schema.json")) | |
| unit_validator.assert_valid(output, str(root / "core" / "policy_global.json")) | |
| math_validator.assert_valid(output) | |
| policy_validator.assert_valid(output, str(pack / "constraints.json")) | |
| # Optional grading | |
| grader_result = grade(output, str(rubric_path)) if rubric_path.exists() else {"score": 0, "max_score": 0, "notes": ["No rubric."]} | |
| output["_grader"] = grader_result | |
| output["_clarifications_summary"] = clarif_raw | |
| return output, clarif_raw | |