starfriend commited on
Commit
488b8db
·
verified ·
1 Parent(s): 8ab6b53

Upload research_synthesis.py

Browse files
Files changed (1) hide show
  1. metadata_search/research_synthesis.py +62 -10
metadata_search/research_synthesis.py CHANGED
@@ -36,6 +36,7 @@ does NOT patch module globals, and therefore does not change production calls.
36
  from __future__ import annotations
37
 
38
  import math
 
39
  import os
40
  import time
41
  import types
@@ -283,7 +284,7 @@ def register_research_synthesis_route(research_bp):
283
  expected_token = os.getenv("WATERSCOPE_RESEARCH_TOKEN", "").strip()
284
  if expected_token:
285
  supplied = request.headers.get("X-Research-Token", "").strip()
286
- if supplied != expected_token:
287
  return jsonify({"ok": False, "error": "Unauthorized"}), 401
288
 
289
  body = request.get_json(force=True, silent=True) or {}
@@ -337,6 +338,29 @@ def register_research_synthesis_route(research_bp):
337
  application = _clean(body.get("application")) or "auto"
338
  model = _clean(body.get("model")) or None
339
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
  try:
341
  max_words_per_paper = int(
342
  body.get(
@@ -443,15 +467,40 @@ def register_research_synthesis_route(research_bp):
443
  )
444
 
445
  model_start = time.perf_counter()
446
- answer, strategy, diagnostics = (
447
- _research_generate_answer(
448
- question_to_model,
449
- full_context,
 
 
 
450
  application=application,
451
- model=model,
452
- max_new_tokens=max_new_tokens_requested,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  )
454
- )
455
  model_call_elapsed_s = (
456
  time.perf_counter() - model_start
457
  )
@@ -474,6 +523,9 @@ def register_research_synthesis_route(research_bp):
474
  answer_words > max_output_words
475
  ),
476
  "strategy": strategy,
 
 
 
477
  "application_requested": application,
478
  "application_used": application_used,
479
  "model_requested": model or "",
@@ -526,7 +578,7 @@ def register_research_synthesis_route(research_bp):
526
  "mcp" if chat_api.use_mcp() else "direct"
527
  ),
528
  "diagnostics": diagnostics,
529
- "llm_backend": chat_api.llm_backend_name(),
530
  "trace_status": {
531
  "captured_full_context": bool(
532
  full_context
@@ -555,7 +607,7 @@ def register_research_synthesis_route(research_bp):
555
  MAX_RESEARCH_PAPERS
556
  ),
557
  "token_override_scope": (
558
- "isolated_function_clone"
559
  ),
560
  },
561
  }
 
36
  from __future__ import annotations
37
 
38
  import math
39
+ import hmac
40
  import os
41
  import time
42
  import types
 
284
  expected_token = os.getenv("WATERSCOPE_RESEARCH_TOKEN", "").strip()
285
  if expected_token:
286
  supplied = request.headers.get("X-Research-Token", "").strip()
287
+ if not hmac.compare_digest(supplied, expected_token):
288
  return jsonify({"ok": False, "error": "Unauthorized"}), 401
289
 
290
  body = request.get_json(force=True, silent=True) or {}
 
338
  application = _clean(body.get("application")) or "auto"
339
  model = _clean(body.get("model")) or None
340
 
341
+ # Optional research-only provider selection. Existing HF requests
342
+ # remain the default and keep their original auto-routing behavior.
343
+ provider = (_clean(body.get("provider")) or "hf").lower()
344
+ if provider not in {"hf", "azure"}:
345
+ return jsonify({"ok": False, "error": "provider must be hf or azure"}), 400
346
+ if provider == "azure":
347
+ if os.getenv("ENABLE_EXTERNAL_LLM", "false").lower() not in {"1", "true", "yes"}:
348
+ return jsonify({"ok": False, "error": "External LLM is disabled"}), 403
349
+ # A research-only secret is mandatory for paid Azure calls.
350
+ research_token = os.getenv("WATERSCOPE_RESEARCH_TOKEN", "").strip()
351
+ supplied_token = request.headers.get("X-Research-Token", "").strip()
352
+ if not research_token or not hmac.compare_digest(supplied_token, research_token):
353
+ return jsonify({"ok": False, "error": "Unauthorized"}), 401
354
+ # The HF 'auto' application detection lives in the model Space;
355
+ # external calls require explicit matching application prompts.
356
+ from llm_services.agent_prompts import AGENT_APPLICATIONS
357
+ if application not in AGENT_APPLICATIONS:
358
+ return jsonify({
359
+ "ok": False,
360
+ "error": "For Azure, specify an application: "
361
+ + ", ".join(AGENT_APPLICATIONS),
362
+ }), 400
363
+
364
  try:
365
  max_words_per_paper = int(
366
  body.get(
 
467
  )
468
 
469
  model_start = time.perf_counter()
470
+ external_result = None
471
+ if provider == "azure":
472
+ from llm_services.llm_client import run_application
473
+ # The same complete context, question and application prompt
474
+ # are passed to both model paths. HF's prefix_context() is
475
+ # preserved in the external prompt as well.
476
+ external_result = run_application(
477
  application=application,
478
+ context=model_context,
479
+ question=question_to_model,
480
+ provider="azure",
481
+ model=None, # use AZURE_LLM_DEPLOYMENT, not HF selector
482
+ max_completion_tokens=max_new_tokens_requested,
483
+ )
484
+ answer = external_result["answer"]
485
+ strategy = f"waterscope:{application}"
486
+ diagnostics = {
487
+ "provider": "azure",
488
+ "model": external_result.get("model_returned"),
489
+ "finish_reason": external_result.get("finish_reason"),
490
+ "metering": external_result.get("metering"),
491
+ "prompt_version": external_result.get("prompt_version"),
492
+ "prompt_sha256": external_result.get("prompt_sha256"),
493
+ }
494
+ else:
495
+ answer, strategy, diagnostics = (
496
+ _research_generate_answer(
497
+ question_to_model,
498
+ full_context,
499
+ application=application,
500
+ model=model,
501
+ max_new_tokens=max_new_tokens_requested,
502
+ )
503
  )
 
504
  model_call_elapsed_s = (
505
  time.perf_counter() - model_start
506
  )
 
523
  answer_words > max_output_words
524
  ),
525
  "strategy": strategy,
526
+ "provider_used": provider,
527
+ "external_model": external_result.get("model_returned") if external_result else None,
528
+ "external_usage": external_result.get("metering") if external_result else None,
529
  "application_requested": application,
530
  "application_used": application_used,
531
  "model_requested": model or "",
 
578
  "mcp" if chat_api.use_mcp() else "direct"
579
  ),
580
  "diagnostics": diagnostics,
581
+ "llm_backend": "azure" if provider == "azure" else chat_api.llm_backend_name(),
582
  "trace_status": {
583
  "captured_full_context": bool(
584
  full_context
 
607
  MAX_RESEARCH_PAPERS
608
  ),
609
  "token_override_scope": (
610
+ "external_api" if provider == "azure" else "isolated_function_clone"
611
  ),
612
  },
613
  }