Advanced NER & Output Formatting¶
Post-processing matters as much as the base model. OpenMed codifies the heuristics from the public demos so you can go from noisy token output to high-quality, copy-pasteable spans in a few lines.
Advanced NER processor¶
openmed.processing.advanced_ner.AdvancedNERProcessor applies the same filtering stack used in the OpenMed Gradio app:
- Confidence filtering with a configurable threshold (
min_confidence). - Punctuation-only and short-span removal.
- Regex-based exclusions for common false positives.
- Optional edge stripping and gap-aware merging of adjacent entities.
- Smart BIO grouping fixes overlapping spans when
aggregation_strategy=None.
from openmed.processing.advanced_ner import create_advanced_processor
processor = create_advanced_processor(
min_confidence=0.65,
merge_adjacent=True,
max_merge_gap=8,
)
raw = pipeline(text) # HF token-classification output
entities = processor.process_pipeline_output(text, raw)
for span in entities:
print(span.label, span.text, span.score)
Use it when you need deterministic filtering outside of analyze_text or when you operate on raw tokens.
OutputFormatter & PredictionResult¶
openmed.processing.OutputFormatter normalizes predictions into dictionaries, JSON strings, HTML snippets, or CSV rows. The dataclasses in openmed/processing/outputs.py ensure the payload stays type-safe and ready for logging.
from openmed.processing import format_predictions
formatted = format_predictions(
raw_predictions,
original_text,
model_name="Disease Detection",
include_confidence=True,
confidence_threshold=0.6,
group_entities=True,
)
print(formatted.entities[0].to_dict())
print(formatted.to_dict())
HTML output¶
from openmed.processing.outputs import OutputFormatter
formatter = OutputFormatter(group_entities=True)
result = formatter.format_predictions(raw_predictions, text, model_name="Oncology")
html = formatter.to_html(result, tag_colors={"Cancer": "#f97316"})
The HTML helper wraps highlighted spans with semantic tags (data-entity="Cancer") so your dashboards can apply custom styles or tooltips.
CSV output¶
CSV export is handy when you need to feed BI tools or spreadsheets without additional ETL code.
Sentence spans & metadata¶
analyze_textattaches sentence spans (when pySBD is enabled) and forwardsmetadataobjects so each entity can carry extra context (e.g., the originating service, clinical section, or ontological hints).- The formatter ensures
confidence,start, andendoffsets are normalized to built-infloat/intso serializing to JSON never fails due to NumPy/PyTorch dtypes.
Guardrails¶
Pair the formatter with validation helpers from openmed.utils.validation:
from openmed.utils.validation import (
validate_confidence_threshold,
validate_output_format,
validate_batch_size,
)
These guardrails keep API endpoints resilient against out-of-range parameters and malformed payloads.
CLI JSON output contract¶
Every openmed subcommand accepts a uniform --json flag for scripting and agent use. When set, the command writes a single machine-readable document to stdout with stable top-level keys; without it, the command keeps its human-readable output.
Success envelope¶
{
"ok": true,
"command": "models list",
"data": { "count": 12, "models": [ /* command-specific payload */ ] }
}
ok— alwaystrueon success.command— the space-joined subcommand path.data— the command-specific payload with stable keys (documented per command in--help).
Error envelope¶
On failure the command writes the error envelope (to stdout in --json mode so an agent can parse a single stream) and exits non-zero:
{
"ok": false,
"command": "audit verify",
"error": { "code": "input_not_found", "message": "Input file not found: report.json" }
}
Without --json, the same failure prints the message to stderr. Either way the process exit code follows the table below.
Exit codes¶
| Code | Meaning |
|---|---|
0 | success |
1 | failure: runtime error (I/O, model load), or a gate/verification negative result — e.g. --strict / --fail-on-* violations, matching the repository's release-gate convention |
2 | usage / validation error (also argparse's own parse-error code) |
Scriptability: no openmed subcommand blocks on interactive input, so every command is safe to run non-interactively in a pipeline. This is enforced by tests/unit/cli/test_cli_json_output.py.
Tool schema registry & drift guard¶
The agent-facing tool schemas (used by the MCP server and the framework adapters) are defined once in openmed.mcp.tool_registry.TOOL_REGISTRY. A static bundle is published at openmed/interop/tools.json for offline consumers, generated from render_tool_registry_document().
tests/unit/interop/test_tool_schema_sync.py guards against drift: it asserts the registry, the MCP server's registered tools, every framework adapter's rendered definitions, and the committed tools.json bundle all agree on tool names and input/output schemas. Regenerate the bundle whenever the registry changes: