zhiyi commited on
Commit
29bb346
·
1 Parent(s): f943246

Fix hero contrast and validation repair errors

Browse files
Files changed (2) hide show
  1. app.py +8 -3
  2. tests/test_app.py +13 -1
app.py CHANGED
@@ -452,6 +452,11 @@ def extract_pdf(paper: dict[str, Any], max_chars: int = 14000) -> str:
452
  return "\n".join(pages)[:max_chars]
453
 
454
 
 
 
 
 
 
455
  def validate_stage_with_repairs(
456
  result: dict[str, Any],
457
  model_type: type[BaseModel],
@@ -469,7 +474,7 @@ def validate_stage_with_repairs(
469
  candidate = chat_json(
470
  f"Repair the {stage_name} JSON. Preserve valid content, fill missing fields, and return only the complete corrected object.",
471
  json.dumps({
472
- "validation_errors": exc.errors(include_url=False),
473
  "object_to_repair": candidate,
474
  "source_context": source_context,
475
  "schema": model_type.model_json_schema(),
@@ -703,7 +708,7 @@ def validate_report_with_repairs(report: dict[str, Any], context: dict[str, Any]
703
  "Repair an incomplete algorithm research report. Preserve its chosen research type, outline, layouts, and valid content. "
704
  "Fix only schema-invalid fields. Return the complete report as one JSON object and never invent source IDs.",
705
  json.dumps({
706
- "validation_errors": exc.errors(include_url=False),
707
  "report_to_repair": candidate,
708
  "evidence_cards": context.get("evidence_cards", []),
709
  "schema": ResearchReport.model_json_schema(),
@@ -1017,7 +1022,7 @@ def run_research_ui(
1017
 
1018
 
1019
  CSS = """
1020
- .gradio-container{max-width:none!important;padding-top:30px!important;background:linear-gradient(145deg,#f7f9fc,#eef3f8)!important}.app-hero{position:relative;z-index:0;margin:8px 4px 18px;padding:18px 22px;border:1px solid #dce5ef;border-radius:16px;background:linear-gradient(120deg,#0c1d2d,#153651);color:#fff;box-shadow:0 12px 35px #16334d1a}.app-hero h1{margin:0 0 5px;font-size:25px}.app-hero p{margin:0;color:#bcd0e3}.app-hero span{display:inline-block;margin-top:10px;padding:4px 8px;border:1px solid #ffffff2b;border-radius:999px;color:#82ead8;font-size:11px}
1021
  .preview-column{min-width:0}.input-column{max-width:430px;padding:14px!important;border:1px solid #dce5ef;border-radius:14px;background:#ffffffb8;box-shadow:0 10px 30px #1a38500d}
1022
  .preview-toolbar{align-items:center!important;justify-content:flex-end!important;gap:6px!important;min-height:38px}
1023
  .preview-title{margin-right:auto!important;min-width:180px}.download-chip{flex:0 0 auto!important;min-width:42px!important;max-width:52px!important;position:relative}
 
452
  return "\n".join(pages)[:max_chars]
453
 
454
 
455
+ def serializable_validation_errors(exc: ValidationError) -> list[dict[str, Any]]:
456
+ """Remove exception objects and raw inputs before sending validation feedback to the model."""
457
+ return exc.errors(include_url=False, include_context=False, include_input=False)
458
+
459
+
460
  def validate_stage_with_repairs(
461
  result: dict[str, Any],
462
  model_type: type[BaseModel],
 
474
  candidate = chat_json(
475
  f"Repair the {stage_name} JSON. Preserve valid content, fill missing fields, and return only the complete corrected object.",
476
  json.dumps({
477
+ "validation_errors": serializable_validation_errors(exc),
478
  "object_to_repair": candidate,
479
  "source_context": source_context,
480
  "schema": model_type.model_json_schema(),
 
708
  "Repair an incomplete algorithm research report. Preserve its chosen research type, outline, layouts, and valid content. "
709
  "Fix only schema-invalid fields. Return the complete report as one JSON object and never invent source IDs.",
710
  json.dumps({
711
+ "validation_errors": serializable_validation_errors(exc),
712
  "report_to_repair": candidate,
713
  "evidence_cards": context.get("evidence_cards", []),
714
  "schema": ResearchReport.model_json_schema(),
 
1022
 
1023
 
1024
  CSS = """
1025
+ .gradio-container{max-width:none!important;background:linear-gradient(145deg,#f7f9fc,#eef3f8)!important}.app-hero{margin:4px 4px 18px;padding:18px 22px;border:1px solid #dce5ef;border-radius:16px;background:linear-gradient(120deg,#0c1d2d,#153651);color:#fff;box-shadow:0 12px 35px #16334d1a}.app-hero h1{margin:0 0 5px;color:#fff!important;font-size:25px}.app-hero p{margin:0;color:#fff!important}.app-hero span{display:inline-block;margin-top:10px;padding:4px 8px;border:1px solid #ffffff2b;border-radius:999px;color:#82ead8;font-size:11px}
1026
  .preview-column{min-width:0}.input-column{max-width:430px;padding:14px!important;border:1px solid #dce5ef;border-radius:14px;background:#ffffffb8;box-shadow:0 10px 30px #1a38500d}
1027
  .preview-toolbar{align-items:center!important;justify-content:flex-end!important;gap:6px!important;min-height:38px}
1028
  .preview-title{margin-right:auto!important;min-width:180px}.download-chip{flex:0 0 auto!important;min-width:42px!important;max-width:52px!important;position:relative}
tests/test_app.py CHANGED
@@ -1,9 +1,10 @@
 
1
  import unittest
2
  from unittest.mock import patch
3
 
4
  from pydantic import ValidationError
5
 
6
- from app import ResearchReport, chat_json, deduplicate, infer_section_source_ids, normalize_comparison, normalize_process, parse_json_object, prepare_evidence_inputs, render_presentation, render_section_content, render_value, safe_slug, search_literature
7
 
8
 
9
  def base_report(section):
@@ -97,6 +98,17 @@ class AppTests(unittest.TestCase):
97
  with self.assertRaises(ValidationError):
98
  ResearchReport.model_validate(base_report(section))
99
 
 
 
 
 
 
 
 
 
 
 
 
100
  def test_comparison_requires_rows(self):
101
  section = {"title": "Compare", "purpose": "Compare engineering alternatives fairly.", "takeaway": "No choice is universally optimal here.", "layout": "comparison", "content": {"columns": ["speed", "quality"], "rows": []}, "source_ids": []}
102
  with self.assertRaises(ValidationError):
 
1
+ import json
2
  import unittest
3
  from unittest.mock import patch
4
 
5
  from pydantic import ValidationError
6
 
7
+ from app import ResearchReport, chat_json, deduplicate, infer_section_source_ids, normalize_comparison, normalize_process, parse_json_object, prepare_evidence_inputs, render_presentation, render_section_content, render_value, safe_slug, search_literature, serializable_validation_errors
8
 
9
 
10
  def base_report(section):
 
98
  with self.assertRaises(ValidationError):
99
  ResearchReport.model_validate(base_report(section))
100
 
101
+ def test_validation_feedback_is_json_serializable(self):
102
+ section = {"title": "Invalid", "purpose": "Trigger a custom validator error.", "takeaway": "The timeline is intentionally incomplete.", "layout": "timeline", "content": {"nodes": []}, "source_ids": []}
103
+ try:
104
+ ResearchReport.model_validate(base_report(section))
105
+ except ValidationError as exc:
106
+ errors = serializable_validation_errors(exc)
107
+ else:
108
+ self.fail("Expected report validation to fail")
109
+ json.dumps(errors)
110
+ self.assertNotIn("ctx", errors[0])
111
+
112
  def test_comparison_requires_rows(self):
113
  section = {"title": "Compare", "purpose": "Compare engineering alternatives fairly.", "takeaway": "No choice is universally optimal here.", "layout": "comparison", "content": {"columns": ["speed", "quality"], "rows": []}, "source_ids": []}
114
  with self.assertRaises(ValidationError):