From e6dc410d7dfb05bd12b928df9184d86b617fe60c Mon Sep 17 00:00:00 2001 From: Chaim Date: Sun, 7 Jun 2026 19:58:48 +0000 Subject: [PATCH] feat(digests): use Sonnet for digest metadata extraction (X12) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit חילוץ-המטא-דאטה של יומון (תג-מושג, כותרת-הלכה, מראה-מקום, תגיות מסיכום עמוד-אחד) הוא משימה פשוטה בנפח גבוה — Sonnet הוא נקודת-האיזון מהירות/עלות, בניגוד לחילוץ-הלכות שמצמיד Opus. - config.DIGEST_EXTRACT_MODEL (env-tunable, ברירת-מחדל claude-sonnet-4-6). - digest_metadata_extractor.extract(model=None) → ברירת-מחדל מה-config; קודם לא צוין model → רץ על ברירת-המחדל של ה-CLI (Opus 4.8). אומת: extract על יומון 5163 עם Sonnet החזיר תג-מושג/כותרת/מראה-מקום/תחום/ תגיות תקינים (~36s). claude_session נשאר local-only. Co-Authored-By: Claude Opus 4.8 (1M context) --- mcp-server/src/legal_mcp/config.py | 4 ++++ .../src/legal_mcp/services/digest_metadata_extractor.py | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/mcp-server/src/legal_mcp/config.py b/mcp-server/src/legal_mcp/config.py index 7a96859..fd907ac 100644 --- a/mcp-server/src/legal_mcp/config.py +++ b/mcp-server/src/legal_mcp/config.py @@ -54,6 +54,10 @@ REDIS_URL = os.environ.get("REDIS_URL", "redis://127.0.0.1:6380/0") # pinned. HALACHA_EXTRACT_MODEL = os.environ.get("HALACHA_EXTRACT_MODEL", "claude-opus-4-8") HALACHA_EXTRACT_EFFORT = os.environ.get("HALACHA_EXTRACT_EFFORT", "xhigh") +# Digest (X12) metadata extraction is a simpler, high-volume task (concept tag, +# headline, underlying citation, tags from a one-page summary) — Sonnet is the +# speed/cost sweet-spot here, unlike halacha extraction which pins Opus. Tune via env. +DIGEST_EXTRACT_MODEL = os.environ.get("DIGEST_EXTRACT_MODEL", "claude-sonnet-4-6") # Effort for BULK queue-drain extraction (process_pending over many precedents). # xhigh is the quality sweet-spot for a single precedent but very slow at scale # (a 64-chunk case ≈ 20 min). Bulk drains use a lighter effort to cut wall-clock; diff --git a/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py b/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py index 45ef0fd..6745439 100644 --- a/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py +++ b/mcp-server/src/legal_mcp/services/digest_metadata_extractor.py @@ -19,6 +19,7 @@ from __future__ import annotations import logging from datetime import date as date_type +from legal_mcp import config from legal_mcp.config import parse_llm_json from legal_mcp.services import claude_session @@ -79,13 +80,17 @@ def _norm_date(result: dict, key: str) -> date_type | None: return None -async def extract(raw_text: str) -> dict: +async def extract(raw_text: str, model: str | None = None) -> dict: """Extract digest metadata from raw text. Returns a dict (never raises). Keys: yomon_number, digest_date (date|None), concept_tag, headline_holding, summary, underlying_citation, underlying_court, underlying_date (date|None), underlying_judge, practice_area, appeal_subtype, subject_tags (list[str]). Missing/invalid fields are omitted so the caller's merge keeps user values. + + Model: defaults to ``config.DIGEST_EXTRACT_MODEL`` (Sonnet — this is a + high-volume, simple extraction; no need for Opus). Override per-call via + ``model``. """ text = (raw_text or "").strip() if not text: @@ -95,6 +100,7 @@ async def extract(raw_text: str) -> dict: try: result = await claude_session.query_json( user_msg, system=DIGEST_EXTRACTION_PROMPT, + model=(model or config.DIGEST_EXTRACT_MODEL or None), ) except Exception as e: # surfaced as warning, not swallowed silently (§6) logger.warning("digest_metadata_extractor: query failed: %s", e) -- 2.49.1