feat: integrate Ontology pre-LLM filter into Pass 0b submit

Obligations classified before API call:
- evidence → skipped (saves API cost)
- composite → skipped (not atomic)
- framework_container → skipped (decompose separately)
- atomic → sent to LLM

Filter stats returned in submit response.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-04-26 09:13:32 +02:00
parent b3fbbbacfe
commit 7e3b1108e2

View File

@@ -3640,6 +3640,33 @@ class DecompositionPass:
if not prepared:
return {"status": "empty", "total_candidates": 0}
# Pre-LLM filter: skip evidence, containers, framework references
from services.control_ontology import classify_obligation
atomic_prepared = []
filtered_stats = {"evidence": 0, "composite": 0, "framework_container": 0, "atomic": 0}
for obl in prepared:
classification = classify_obligation(
obl["obligation_text"], obl.get("action", "")
)
routing = classification["routing"]
filtered_stats[routing] = filtered_stats.get(routing, 0) + 1
if routing == "atomic":
atomic_prepared.append(obl)
else:
logger.info("Pre-LLM filter: %s skipped (%s): %s",
obl["candidate_id"], routing, obl["obligation_text"][:80])
logger.info("Pre-LLM filter: %d%d atomic (skipped: %d evidence, %d composite, %d framework)",
len(prepared), len(atomic_prepared),
filtered_stats.get("evidence", 0),
filtered_stats.get("composite", 0),
filtered_stats.get("framework_container", 0))
prepared = atomic_prepared
if not prepared:
return {"status": "empty", "total_candidates": 0,
"filtered": filtered_stats}
requests = []
for i in range(0, len(prepared), batch_size):
batch = prepared[i : i + batch_size]
@@ -3686,6 +3713,7 @@ class DecompositionPass:
"total_candidates": len(prepared),
"total_requests": len(requests),
"batch_size": batch_size,
"pre_filter": filtered_stats,
}
async def process_batch_results(