Named Entity Recognition (NER)¶
The ner component family provides entity extraction, span detection, and character offset tracking.
Instead of prompting an LLM to output JSON spans, Daimon delegates span extraction to specialized models (such as GLiNER, BioLinkBERT, or token-classification networks), cutting latency and cost.
Configuration¶
Declare NER components under components: in your YAML config:
1. HTTP Microservice (ner/http)¶
Connects to any external or containerized microservice exposing an /extract endpoint (e.g., FastAPI, Triton Inference Server, or Hugging Face TEI):
components:
- name: clinical-ner
type: ner/http
metadata:
base_url: http://localhost:8000
api_key: optional-bearer-token
default_labels: "disease,symptom,procedure"
default_threshold: "0.60"
timeout_ms: "5000"
2. Local ONNX Runtime (ner/onnx)¶
Executes an exported ONNX model directly:
components:
- name: clinical-ner-onnx
type: ner/onnx
metadata:
model_path: /models/gliner-biomed-small.onnx
default_labels: "disease,symptom,procedure"
default_threshold: "0.60"
threads: "4"
Auto-Generated LLM Tool¶
When configured, Daimon injects an auto-generated tool into every LLM request:
- Tool Name:
{name}_extract - Parameters:
text(string, required): Unstructured text to extract spans from.labels(array of strings, optional): Custom labels overriding defaults.
When the LLM calls {name}_extract, the sidecar runs inference and returns the entity list back to the model within the agentic loop.
HTTP REST API¶
Call the endpoint directly via HTTP:
curl -s http://127.0.0.1:3500/v1/ner/clinical-ner/extract \
-H "Content-Type: application/json" \
-d '{
"text": "Patient has right knee effusion and mild asthma.",
"labels": ["disease", "symptom", "procedure"],
"threshold": 0.60
}'
Response:
{
"entities": [
{
"text": "right knee effusion",
"label": "symptom",
"start": 12,
"end": 31,
"confidence": 0.96
},
{
"text": "asthma",
"label": "disease",
"start": 46,
"end": 52,
"confidence": 0.94
}
]
}
SDK Usage¶
import daimon
client = daimon.Client()
entities = client.ner("clinical-ner").extract(
"Patient has right knee effusion and mild asthma.",
labels=["disease", "symptom", "procedure"],
threshold=0.60,
)
for entity in entities:
print(f"{entity.text} ({entity.label}) [{entity.start}:{entity.end}] score={entity.confidence:.2f}")
import { Client } from 'daimon-client';
const client = new Client();
const entities = await client.ner('clinical-ner').extract(
'Patient has right knee effusion and mild asthma.',
{
labels: ['disease', 'symptom', 'procedure'],
threshold: 0.60,
}
);
for (const entity of entities) {
console.log(`${entity.text} (${entity.label}) score=${entity.confidence}`);
}
import io.github.sonicboom15.daimon.Client;
import io.github.sonicboom15.daimon.Entity;
import java.util.List;
Client client = new Client();
List<Entity> entities = client.ner("clinical-ner").extract(
"Patient has right knee effusion and mild asthma.",
List.of("disease", "symptom", "procedure"),
0.60
);