starfriend commited on
Commit
efb00d7
·
verified ·
1 Parent(s): 09da502

Upload public_routes.py

Browse files
backend/media_analysis/public_routes.py CHANGED
@@ -62,9 +62,18 @@ def media_analyze_public():
62
  paper = {"paper_id": str(idx), "metadata_row_index": idx,
63
  "paper_title": str(row.get("Title") or row.get("title") or "")[:400],
64
  "doi": str(row.get("DOI") or row.get("doi") or "")[:200]}
65
- # Match only explicit Figure N or Table N; media is never chosen arbitrarily.
66
- if not re.search(r"\b(?:figure|fig\.?|table)\s*\d+\b", question, re.I):
 
 
 
 
 
 
67
  return jsonify({"error": "Specify Figure N or Table N"}), 400
 
 
 
68
  # Fixed provider and model on server, not client. Hard bound to avoid runaway bills.
69
  provider = os.getenv("WATERSCOPE_PUBLIC_MEDIA_PROVIDER", "deepseek").strip().lower()
70
  if provider not in ("azure", "deepseek"):
@@ -90,15 +99,23 @@ def media_analyze_public():
90
  except ValueError: pass
91
  return jsonify({"error": "Media analysis is busy; please retry shortly"}), 429
92
  try:
93
- model_question = question.strip() + (
94
- "\n\nAnswer presentation: Use readable names (e.g., Table 1 or Figure 2). "
95
- "Do not mention internal paper indexes, source labels like table_01, or "
96
- "backend identifiers. Answer only what the question asks."
97
- )
98
- result = analyze_media_question(model_question, [paper], enabled=True,
99
  provider=provider, model=model, max_output_tokens=4096 if export_csv else 1600,
100
  evidence_mode="combined", export_csv=export_csv,
101
  analysis_mode="extract_all" if export_csv else "interpret")
 
 
 
 
 
 
 
 
 
 
102
  # Do not send large duplicate tabular records: CSV already carries the data.
103
  result.pop("structured_data", None)
104
  if "answer" in result:
 
62
  paper = {"paper_id": str(idx), "metadata_row_index": idx,
63
  "paper_title": str(row.get("Title") or row.get("title") or "")[:400],
64
  "doi": str(row.get("DOI") or row.get("doi") or "")[:200]}
65
+ # The resolver scans the entire question for numbered media labels. This
66
+ # public single-media endpoint must receive exactly ONE unique media label;
67
+ # instructional examples must never accidentally become requested sources.
68
+ refs = {
69
+ ("table" if m.group(1).lower() == "table" else "figure", int(m.group(2)))
70
+ for m in re.finditer(r"\b(fig(?:ure)?\.?|table)\s*0*(\d+)\b", question, re.I)
71
+ }
72
+ if not refs:
73
  return jsonify({"error": "Specify Figure N or Table N"}), 400
74
+ if len(refs) != 1:
75
+ return jsonify({"error": "Please analyze one numbered figure or table at a time"}), 400
76
+ requested_kind, requested_number = next(iter(refs))
77
  # Fixed provider and model on server, not client. Hard bound to avoid runaway bills.
78
  provider = os.getenv("WATERSCOPE_PUBLIC_MEDIA_PROVIDER", "deepseek").strip().lower()
79
  if provider not in ("azure", "deepseek"):
 
99
  except ValueError: pass
100
  return jsonify({"error": "Media analysis is busy; please retry shortly"}), 429
101
  try:
102
+ # IMPORTANT: pass the user's media reference unchanged to the resolver.
103
+ # Appending example labels such as "Table 1 or Figure 2" makes the
104
+ # image selector load both sources, even for a single-table request.
105
+ result = analyze_media_question(question.strip(), [paper], enabled=True,
 
 
106
  provider=provider, model=model, max_output_tokens=4096 if export_csv else 1600,
107
  evidence_mode="combined", export_csv=export_csv,
108
  analysis_mode="extract_all" if export_csv else "interpret")
109
+ # Fail closed if an upstream change ever introduces unrelated media.
110
+ sources = result.get("sources") or result.get("source_identifiers") or []
111
+ if len(sources) != 1:
112
+ return jsonify({"error": "Media source mismatch: expected exactly one source"}), 502
113
+ src_label = str(sources[0].get("label") or "")
114
+ src_match = re.search(r"\b(fig(?:ure)?|table)[\s_.-]*0*(\d+)\b", src_label, re.I)
115
+ if (not src_match or
116
+ ("table" if src_match.group(1).lower() == "table" else "figure") != requested_kind or
117
+ int(src_match.group(2)) != requested_number):
118
+ return jsonify({"error": "Media source mismatch: requested and returned labels differ"}), 502
119
  # Do not send large duplicate tabular records: CSV already carries the data.
120
  result.pop("structured_data", None)
121
  if "answer" in result: