Spaces:
Running on Zero
Running on Zero
| from __future__ import annotations | |
| import re | |
| from pozify.contracts import ( | |
| CoachSummary, | |
| ExerciseClassification, | |
| IssueMarkers, | |
| RepAnalysis, | |
| Reps, | |
| Variation, | |
| Verification, | |
| ) | |
| from pozify.knowledge_cards import known_issue_labels | |
| DIAGNOSIS_PATTERNS = ( | |
| "diagnos", | |
| "injury", | |
| "tendonitis", | |
| "tear", | |
| "impingement", | |
| "pathology", | |
| "medical assessment", | |
| ) | |
| INJURY_PREVENTION_PATTERNS = ( | |
| "prevent injury", | |
| "injury prevention", | |
| "avoid injury", | |
| ) | |
| NEGATIVE_VARIATION_CONTEXT = ( | |
| "is an issue", | |
| "is a fault", | |
| "is a problem", | |
| "fault", | |
| "problem", | |
| "error", | |
| "wrong", | |
| "incorrect", | |
| "should be fixed", | |
| ) | |
| SAFE_VARIATION_CONTEXT = ( | |
| "not-issue context", | |
| "not an issue", | |
| "rather than a fault", | |
| "context rather than a fault", | |
| ) | |
| def _contains_negative_variation_language(lines: list[str], labels: list[str]) -> bool: | |
| for line in lines: | |
| lowered = line.lower() | |
| if not any(label in lowered for label in labels): | |
| continue | |
| if any(token in lowered for token in SAFE_VARIATION_CONTEXT): | |
| continue | |
| if any(token in lowered for token in NEGATIVE_VARIATION_CONTEXT): | |
| return True | |
| return False | |
| def _summary_sections(summary: CoachSummary) -> list[str]: | |
| return [ | |
| summary.summary, | |
| *summary.what_you_did, | |
| *summary.what_looked_good, | |
| *summary.what_changed_across_reps, | |
| *summary.valid_variation_vs_issue, | |
| *summary.top_fixes, | |
| *summary.next_session_plan, | |
| *summary.confidence_notes, | |
| ] | |
| def _normalized_text(summary: CoachSummary) -> str: | |
| return " ".join(_summary_sections(summary)).lower() | |
| def _mentioned_labels(summary: CoachSummary) -> set[str]: | |
| text = " ".join(_summary_sections(summary)) | |
| labels = set(re.findall(r"`([a-z0-9_]+)`", text)) | |
| lowered = text.lower() | |
| for label in known_issue_labels(): | |
| if label in lowered: | |
| labels.add(label) | |
| return labels | |
| def _confidence_notes_required( | |
| classification: ExerciseClassification, | |
| analysis: RepAnalysis, | |
| variation: Variation, | |
| reps: Reps, | |
| issues: IssueMarkers, | |
| ) -> bool: | |
| if classification.confidence < 0.7: | |
| return True | |
| if variation.variation_confidence < 0.7: | |
| return True | |
| if float(analysis.aggregate_metrics.get("pose_valid_ratio", 1.0)) < 0.85: | |
| return True | |
| if len(reps.reps) == 0: | |
| return True | |
| if len(issues.issues) == 0: | |
| return True | |
| return False | |
| def run( | |
| summary: CoachSummary, | |
| issues: IssueMarkers, | |
| variation: Variation, | |
| *, | |
| classification: ExerciseClassification, | |
| analysis: RepAnalysis, | |
| reps: Reps, | |
| ) -> Verification: | |
| allowed_issues = {issue.issue for issue in issues.issues} | |
| mentioned_labels = _mentioned_labels(summary) | |
| mentioned_issues = mentioned_labels & known_issue_labels() | |
| no_issue_outside_json = mentioned_issues <= allowed_issues | |
| variation_lines = summary.valid_variation_vs_issue + summary.top_fixes | |
| variation_text = " ".join(variation_lines).lower() | |
| variation_not_overcorrected = True | |
| variation_labels = [variation.detected_variation, *variation.not_issues] | |
| if _contains_negative_variation_language(variation_lines, variation_labels): | |
| variation_not_overcorrected = False | |
| if variation.detected_variation and variation.detected_variation not in variation_text: | |
| variation_not_overcorrected = False | |
| normalized = _normalized_text(summary) | |
| no_diagnosis = all(pattern not in normalized for pattern in DIAGNOSIS_PATTERNS) | |
| no_injury_prevention_claim = all( | |
| pattern not in normalized for pattern in INJURY_PREVENTION_PATTERNS | |
| ) | |
| confidence_present = ( | |
| not _confidence_notes_required(classification, analysis, variation, reps, issues) | |
| ) or bool(summary.confidence_notes) | |
| checks = { | |
| "no_issue_outside_json": no_issue_outside_json, | |
| "variation_not_overcorrected": variation_not_overcorrected, | |
| "no_diagnosis": no_diagnosis, | |
| "no_injury_prevention_claim": no_injury_prevention_claim, | |
| "confidence_notes_present_when_required": confidence_present, | |
| } | |
| notes: list[str] = [] | |
| if not no_issue_outside_json: | |
| extra = sorted(mentioned_issues - allowed_issues) | |
| notes.append(f"Summary mentioned issue labels not present in JSON: {', '.join(extra)}.") | |
| if not variation_not_overcorrected: | |
| notes.append("Summary did not keep valid variation context separate from issue correction.") | |
| if not no_diagnosis: | |
| notes.append("Summary used diagnosis-style language.") | |
| if not no_injury_prevention_claim: | |
| notes.append("Summary made an injury-prevention claim.") | |
| if not confidence_present: | |
| notes.append("Summary is missing required confidence notes.") | |
| return Verification( | |
| passed=all(checks.values()), | |
| checks=checks, | |
| notes=notes, | |
| ) | |