feat(0035e): manifest auto_group_threshold override + propagacion a Python
Manifest YAML puede declarar 'auto_group_threshold: <int>' a nivel top-level. enrichers.cpp lo parsea y lo guarda en EnricherSpec. jobs.cpp lo inyecta como campo opcional 'auto_group_threshold' en el JSON stdin del subprocess. Los enrichers Python que crean Groups (web_search, split_words, split_sentences, extract_iocs_text) leen el campo y, si viene > 0, lo usan en lugar de su DEFAULT_GROUP_THRESHOLD. Helper _coerce_threshold tolera int / str / None / 0 cayendo al default.
This commit is contained in:
@@ -48,6 +48,17 @@ DEFAULT_GROUP_THRESHOLD = 50
|
||||
GROUP_PREVIEW_K = 10
|
||||
|
||||
|
||||
def _coerce_threshold(raw, default: int) -> int:
|
||||
"""Acepta int / str numerico / None, devuelve >0 o el default (issue 0035e)."""
|
||||
if raw is None or raw == "":
|
||||
return default
|
||||
try:
|
||||
v = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return v if v > 0 else default
|
||||
|
||||
|
||||
def progress(p: float, stage: str = "") -> None:
|
||||
sys.stderr.write(f"PROGRESS:{p:.2f} {stage}\n")
|
||||
sys.stderr.flush()
|
||||
@@ -206,7 +217,9 @@ def main() -> int:
|
||||
try:
|
||||
has_group_col = has_group_id_column(conn)
|
||||
n_total = len(unique)
|
||||
threshold = DEFAULT_GROUP_THRESHOLD
|
||||
# Issue 0035e: respeta override del manifest si viene en ctx.
|
||||
threshold = _coerce_threshold(ctx.get("auto_group_threshold"),
|
||||
DEFAULT_GROUP_THRESHOLD)
|
||||
|
||||
if n_total >= threshold and has_group_col:
|
||||
# Group heterogeneo (provisional, ver docstring).
|
||||
|
||||
@@ -38,6 +38,17 @@ from datetime import datetime, timezone
|
||||
DEFAULT_GROUP_THRESHOLD = 50
|
||||
GROUP_PREVIEW_K = 10
|
||||
|
||||
|
||||
def _coerce_threshold(raw, default: int) -> int:
|
||||
"""Acepta int / str numerico / None, devuelve >0 o el default (issue 0035e)."""
|
||||
if raw is None or raw == "":
|
||||
return default
|
||||
try:
|
||||
v = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return v if v > 0 else default
|
||||
|
||||
# Split por delimitador de oracion (.!?) seguido de whitespace seguido de
|
||||
# inicial de oracion en mayusculas (incluye acentos espanoles). Robusto
|
||||
# para texto en espanol e ingles. Casos limite (abreviaturas como "Sr.",
|
||||
@@ -273,7 +284,9 @@ def main() -> int:
|
||||
try:
|
||||
has_group_col = has_group_id_column(conn)
|
||||
n_total = len(sentences)
|
||||
threshold = DEFAULT_GROUP_THRESHOLD
|
||||
# Issue 0035e: respeta override del manifest si viene en ctx.
|
||||
threshold = _coerce_threshold(ctx.get("auto_group_threshold"),
|
||||
DEFAULT_GROUP_THRESHOLD)
|
||||
|
||||
if n_total >= threshold and has_group_col:
|
||||
group_id = insert_group_entity(
|
||||
|
||||
@@ -39,6 +39,17 @@ from datetime import datetime, timezone
|
||||
DEFAULT_GROUP_THRESHOLD = 50
|
||||
GROUP_PREVIEW_K = 10
|
||||
|
||||
|
||||
def _coerce_threshold(raw, default: int) -> int:
|
||||
"""Acepta int / str numerico / None, devuelve >0 o el default (issue 0035e)."""
|
||||
if raw is None or raw == "":
|
||||
return default
|
||||
try:
|
||||
v = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return v if v > 0 else default
|
||||
|
||||
# Tokenizer: secuencias de letras (incluye acentos espanyoles + apostrofo
|
||||
# interno tipo "don't"). Mas robusto que split por espacios para texto
|
||||
# real con puntuacion adyacente. Numeros se ignoran — pensado para
|
||||
@@ -264,7 +275,9 @@ def main() -> int:
|
||||
try:
|
||||
has_group_col = has_group_id_column(conn)
|
||||
n_total = len(words)
|
||||
threshold = DEFAULT_GROUP_THRESHOLD
|
||||
# Issue 0035e: respeta override del manifest si viene en ctx.
|
||||
threshold = _coerce_threshold(ctx.get("auto_group_threshold"),
|
||||
DEFAULT_GROUP_THRESHOLD)
|
||||
|
||||
if n_total >= threshold and has_group_col:
|
||||
group_id = insert_group_entity(
|
||||
|
||||
@@ -50,6 +50,22 @@ DEFAULT_GROUP_THRESHOLD = 50
|
||||
GROUP_PREVIEW_K = 10
|
||||
|
||||
|
||||
def _coerce_threshold(raw, default: int) -> int:
|
||||
"""Acepta int / str numerico / None, devuelve >0 o el default.
|
||||
|
||||
Issue 0035e: el manifest puede declarar `auto_group_threshold: <int>`
|
||||
y jobs.cpp lo propaga al subprocess. Cualquier otro valor (None,
|
||||
"", 0, no parseable) cae al default global.
|
||||
"""
|
||||
if raw is None or raw == "":
|
||||
return default
|
||||
try:
|
||||
v = int(raw)
|
||||
except (TypeError, ValueError):
|
||||
return default
|
||||
return v if v > 0 else default
|
||||
|
||||
|
||||
def progress(p: float, stage: str = "") -> None:
|
||||
sys.stderr.write(f"PROGRESS:{p:.2f} {stage}\n")
|
||||
sys.stderr.flush()
|
||||
@@ -619,9 +635,11 @@ def main() -> int:
|
||||
try:
|
||||
has_group_col = has_group_id_column(conn)
|
||||
n_total = len(results)
|
||||
# Threshold: por ahora hardcoded; la lectura del manifest
|
||||
# vendra en 0035e (settings UI / overrides por enricher).
|
||||
threshold = DEFAULT_GROUP_THRESHOLD
|
||||
# Threshold: el manifest puede declarar `auto_group_threshold` y
|
||||
# jobs.cpp lo propaga via stdin (issue 0035e). Si no viene, se
|
||||
# usa el default interno del enricher.
|
||||
threshold = _coerce_threshold(ctx.get("auto_group_threshold"),
|
||||
DEFAULT_GROUP_THRESHOLD)
|
||||
|
||||
if n_total >= threshold and has_group_col:
|
||||
# Modo Twitter/Reddit: K sueltos + Group con N-K hijos.
|
||||
|
||||
Reference in New Issue
Block a user