Release notes for NLP API 2.37

Contents

Brief Summary

Release versions

  • NLP API version 2 Release 37.
  • Python SDK and client v7.1.0.
  • Java SDK and client v5.15.0 (deprecated).
  • NLP API specification v2.24.0: new processing features added entity-experiencer, entity-factuality, entity-contextual-validity, document-infer-structure
  • JSON result output schema v2.37.0 for emtellipro-json-2: added output for entity-experiencer, entity-factuality.
  • Depending on the installation parameters of the NLP API all the processing features are not enabled by default. A subset of the most useful processing features is enabled by default in most installed versions of the NLP API.

Highlights

  • New processing features: entity-experiencer, entity-factuality, entity-contextual-validity. These new features are not run by default as they are compute intensive.
  • New automated document category and subcategory detection.
  • New relation concept links for Experiencer relation.
  • New fast entity linking approach (when processing feature is ontology only; invoked without relation finding or confidence scores).
  • New document infer structure feature for documents missing table formatting and newlines.

New Features

Entity Contextual Validity

New processing feature entity-contextual-validity is an option provided to improve the precision for entity linking and negation finding. A larger context is used to validate entity linking. Since this check is more compute expensive it is not run by default but only when requested explicitly. It is meant to be run on more noisy sources of data and less useful for the more constrained language used in Radiology, Pathology reports. Clinical notes can sometimes include common uses of medical terms which can be ruled out using this feature.

Here are some examples how this works:

The patient was transferred from PIH Health this morning at
approximately 10:30 AM via non-emergent ambulance transport.

In the above input, the mention PIH could be erroneously linked to the SNOMED concept ID 48194001 which stands for Pregnancy-induced hypertension (disorder). However, in this case we can infer from the wider context that PIH Health is the name of an institution and therefore we can rule out the false positive entity link.

MRI imaging revealed a complete tear of the patient's VL tendon
sustained during an athletic injury three weeks prior.

In the above input, the mention VL could be erroneously linked to the SNOMED concept ID 395058002 which stands for Viral load (procedure). However, in this case we can identify this as incorrect and suppress that entity link.

There is no pleural abnormality. Similarly lacking evidence of
central adenopathy.

In the above input, the negation for adenopathy is linked to the negation in the previous sentence via the use of the term Similarly. By using a wider context we can determine that adenopathy should be negated rather than asserted.

There is no additional output in the NLP API JSON output when the processing feature of entity-contextual-validity is requested. It improves precision of the entity linking concept links and polarity attribute output specifically for the SNOMED and MEDCIN ontologies (MEDCIN output has to be explicitly enabled via a specific license for a particular installation of the NLP API).

Entity Experiencer Attribute

A new attribute called experiencer is generated for each entity mention when enabled using the processing feature entity-experiencer. For example, for the input:

the patient's mother said he had hepatitis during his vacation to
France last month.

The output JSON has the ‘experiencer’ attribute:

1{
2 "label": "E1",
3 "spans": [ .. ],
4 "section_name": "INTRO",
5 "attributes": {
6 "experiencer": "patient"
7 },
8 "concept_links": [
9 "Csnomed1"
10 ],
11 "locations": [ .. ],
12 "entity_type": { .. },
13 "text": [ "hepatitis" ]
14},

The output JSON from the NLP API now contains an experiencer attribute. The reason for the switch to an attribute is to provide simpler support for assumed entities like patient or family or provider.

The experiencer relation is still produced by the NLP API but in future releases the reason for producing assumed experiencer entities will no longer exist and this new experiencer attribute will be used instead. The experiencer attribute makes it much easier to limit searches to all the entities that are experienced by the patient.

Future versions of the NLP API will move to using the experiencer relation for only matched experiencers that have explicit matched spans of text. For example, in grandmother has alzheimers the experiencer relation links the mention grandmother to alzheimers and since it is a matched span grandmother is also assigned the SNOMED concept ID 113157001 for Grandmother (person). This allows for searches on precise person concept IDs. On the other hand, the experiencer attribute for the same sentence would be the string grandmother and the experiencer attribute makes it easier to limit searches to entities that are experienced by the patient and removes the need for any assumed experiencer entities.

The JSON schema for the experiencer attribute experiencer attribute is defined as a string datatype. The output will be the string "patient" to refer to the patient. When the experiencer is family the output is a string value like "mother", "father" or "mother and father". Healthcare provider experiencers are referred to as the string "provider" for activities in a healthcare setting.

Here are some examples:

mother and father have h/o cad.

Has the following experiencer attribute.

1{
2 "label": "E9",
3 "spans": [ .. ],
4 "section_name": "INTRO",
5 "attributes": {
6 "experiencer": "mother and father"
7 },
8 "concept_links": [ .. ],
9 "locations": [ .. ],
10 "entity_type": { .. },
11 "text": [ "cad" ]
12},

And for the following example:

The staff has verified that the instrument, sponge, and needle counts
were correct.

Has the following experiencer attribute for the healthcare activity of counting equipment.

1{
2 "label": "E11",
3 "spans": [ .. ],
4 "section_name": "INTRO",
5 "attributes": {
6 "experiencer": "provider"
7 },
8 "concept_links": [ .. ],
9 "locations": [ .. ],
10 "entity_type": { .. },
11 "text": [ "instrument, sponge, and needle counts" ]
12}

Entity Factuality Attribute

A new attribute called factuality is generated for each entity mention when enabled using the processing feature entity-factuality.

The main intention is to identify factual statements from broadly hypothetical statements or generic statements.

  • hypothetical: if the entity is hypothetical in any way.

    • part of an if statement.
    • a question for a radiologist or pathologist, e.g. “rule out appendicitis”.
    • scheduled or might occur in the future.
    • part of a differential diagnosis.
    • declared by the patient or family or friends, e.g. “patient’s mother said he had hepatitis last month”
    • part of a question being asked to the patient, e.g. ‘hopelessness’ in “Do you have feelings of hopelessness?” is part of a question.
    • part of PRN indications from medication prescriptions.
  • generic: entity is part of a general knowledge statement rather than applicable to the patient

    • guidance, counselling or educational statement.
    • expected ranges for a lab test or a guideline or legalese.
    • definition, a quote from a textbook or journal article.
    • part of a criteria list, or explanatory text rather than an actual patient finding.
  • factual: when none of the above is applicable, e.g. in “the patient has CAD”, “CAD” is ‘factual’.

For example, for input:

Please call your doctor if you have severe pain, persistent nausea,
vomiting, or any other concerns.

The ‘factuality’ attribute in this case for the entity severe pain would be ‘hypothetical’:

1{
2 "label": "E1",
3 "spans": [ .. ],
4 "section_name": "INTRO",
5 "attributes": {
6 "factuality": "hypothetical",
7 },
8 "concept_links": [ .. ],
9 "locations": [ .. ],
10 "entity_type": { .. },
11 "text": [ "severe pain" ]
12},

For the input:

Eating 5 servings of fresh food per day can help people lower their blood pressure.

The ‘factuality’ attribute in this case for the entity blood pressure would be ‘generic’:

1{
2 "label": "E9",
3 "spans": [ .. ],
4 "section_name": "INTRO",
5 "attributes": {
6 "factuality": "generic",
7 },
8 "concept_links": [ .. ],
9 "locations": [ .. ],
10 "entity_type": { .. },
11 "text": [ "blood pressure" ]
12}

In most cases where a patient’s disorders, symptoms, and other entities are mentioned the factuality attribute would be ‘factual’.

There is an overlap with other processing features: the factuality attribute overlaps with some other attributes:

  • uncertainty which comes from the entity-uncertainty processing feature overlaps with the hypothetical label in factuality.
  • question_status which comes from the entity-question-status processing feature overlaps with the hypothetical label in factuality.
  • guidance which comes from the entity-guidance processing feature overlaps with the generic label in factuality.

The aim of the factuality attribute is to provide a single easy search that can eliminate many individual cases of non-factual uses of an entity based on the context. It is much more general and more widely applicable, e.g. question_status is highly Radiology focused and limited to Indication sections in radiology reports.

Based on feedback, we may choose to deprecate the above processing features and output attributes if factuality, which is a more generalized attribute, ends up being more suitable for all the use cases compared to the attributes listed above.

In the NLP API v2.36 we introduced concept links associated with relations; specifically enabled for Qualifier relations and Anatomic Site relations.

In this release, we extend relation concept links to Experiencer relations. As before the concept ID associated with the combined string from the two arguments in the relation is added to the list "concept_links".

For example, for the input:

Family history of cardiovascular disease.
1{
2 "label": "REX0",
3 "attributes": { .. },
4 "args": {
5 "experiencer": {
6 "ref": "E1",
7 "text": [ "Family history of" ]
8 },
9 "experienced": {
10 "ref": "E0",
11 "text": [ "cardiovascular disease" ]
12 }
13 },
14 "concept_links": [ "Csnomed2" ]
15}
16...
17{
18 "label": "Csnomed2",
19 "concept_id": "266894000",
20 "description": "Family history: Cardiovascular disease (situation)"
21}

For cases where a family member is the “experiencer” argument the concept link value for the Experiencer relation includes a “family history” concept associated with the “experienced” entity. For example, in the following input father is the experiencer of coronary artery disease.

father has had coronary artery disease.
1{
2 "label": "REX1",
3 "attributes": { .. },
4 "args": {
5 "experiencer": {
6 "ref": "E2",
7 "text": [ "father" ]
8 },
9 "experienced": {
10 "ref": "E3",
11 "text": [ "coronary artery disease" ]
12 }
13 },
14 "concept_links": [ "Csnomed5", ]
15}
16...
17{
18 "label": "Csnomed5",
19 "concept_id": "430091005",
20 "description": "Family history of coronary arteriosclerosis (situation)"
21}

Only links to SNOMED ontology are produced for Experiencer relations. However, all the ICD-10-CM concepts that are retrieved from the SNOMED concept ID are also added to the list of "concept_links".

Report Kind Detection

The report kind of a document is the combination of the document category and subcategory, for example the category Radiology with the subcategory CT.

In previous releases the report kind had to be supplied as part of the input, either in the mime multipart headers for the document or as fields on the document in the JSON input format. In this release both category and subcategory are optional in the NLP API specification. When they are not supplied, the NLP API detects the report kind automatically and the detected values are reported in the output.

The document attributes in the NLP API JSON output record how each value was obtained using a method field: manual when the value was set explicitly in the input, and automatic when it was detected by the NLP API. For a document submitted without a category or subcategory the output is:

1{
2 "id": "doc1",
3 "attributes": {
4 "category": {
5 "method": "automatic",
6 "value": "Radiology"
7 },
8 "subcategory": {
9 "method": "automatic",
10 "value": "CT"
11 }
12 },
13 "processing_status": { .. }
14}

Automatically detected values are drawn from the same lists of allowed categories and subcategories that are accepted in the input; see DocumentCategory and DocumentSubcategory in the API specification for the full list. A report kind that is supplied in the input is always used as given and is reported with a method of manual.

Automatic detection is not enabled in every installation of the NLP API. Where it is disabled, the report kind supplied in the input is used.

Document Infer Structure

New processing feature document-infer-structure rewrites the input text to restore structure such as tables and line breaks before the document is processed. It is intended for extremely poorly formatted inputs where newlines are no longer part of the document and any markings that indicated table structure have also been stripped out. Such documents lose the layout that NLP API relies on to find sections and to extract relations, in particular measurement relations in tabular data.

This feature applies to text input only and it is not run by default; it has to be requested explicitly. It is not intended for documents that already carry their original formatting.

For example, for an input where the line and column structure of a results table has been lost:

LABORATORY RESULTS Test Result Unit Sodium 138 mmol/L Potassium 4.1
mmol/L Creatinine 1.2 mg/dL

the feature infers the rows and columns of the table and writes it back into the document text in markdown format:

1LABORATORY RESULTS
2
3| Test | Result | Unit |
4| ---------- | ------ | ------ |
5| Sodium | 138 | mmol/L |
6| Potassium | 4.1 | mmol/L |
7| Creatinine | 1.2 | mg/dL |

Because the feature replaces the document text, the modified text is provided in the text field of the document in the NLP API JSON output:

1{
2 "id": "doc1",
3 "attributes": { .. },
4 "text": "LABORATORY RESULTS\n\n| Test | Result | Unit |\n ..",
5 "processing_status": { .. }
6}

The text change is not recoverable from the input, so the returned text is the text that all the spans and locations in the rest of the output refer to. Consumers that map output offsets back to their own copy of the document must use the returned text rather than the text that was submitted.

Changes

Ontology updates

  • Update RxNorm ontology to 2025-10-06 edition.
  • Remove DrugBank as a source for RxNorm ontology.
  • Update UMLS ontologies (UMLS, NCI, LOINC, and HGNC) to 2025AB release.
  • Update Snomed, ICD10 and ICD10CM ontologies to 2025-09-01 release.
  • Update RadLex to 4.3 version.
  • Update Medcin ontology to November 2025 release.

MEDCIN updates

  • The processing feature entity-contextual-validity is enabled for MEDCIN ontology.
  • Updated Snomed-Medcin ontology with more descriptive FSNs by including specialty and Quippe Group ID.
  • Snomed-Medcin ontology filtered to remove non-clinical semantic types such as body structure, person, and geographic location.
  • Enable Snomed-Medcin mapping for entity matches that occur outside a labelled section (i.e., in the document introduction).
  • Medcin entity concept links are now also found by mapping from Snomed concepts, improving Medcin coverage.
  • Medcin concept IDs for relation arguments are now set to unknown when a mapping is not available.
  • Fix Medcin section labels that were incorrectly generated from duplicate concepts with prefixes.

Negation

  • Update negation finding for presents with: this phrase is now treated as asserting rather than negating an entity.
  • Add clear as a negation scope delimiter in comma-separated lists.
  • OP clear is treated as asserted when it appears in a list context.
  • Improved negation handling for entity names that contain the word negative (e.g., coag negative staph), reducing false positive negations.
  • Improved negation handling for absence of.
  • Improved negation handling for does report.

Section parsing

  • Improved section heading finder.

Bug fixes

  • Fix erroneous entity matches: unwanted concept types are now filtered out and shorter matches such as jaw are now correctly included.
  • Fix erroneous concept link from created to creatinine measurement concepts.
  • Fix bug where concept links skipped the filtering step when being applied to concatenated relation arguments.
  • Fix so that the input report kind is used when document type auto-detection is disabled.
  • Prevent any self-referential relations.
  • Snomed annotations that are determined to be incorrect via entity-contextual-validity are not mapped to ICD-10 or ICD-10-CM.
  • Remove spurious contraction matches in entity linking.

Model Updates

  • New fast entity linking approach (when processing feature is ontology only; invoked without relation finding or confidence scores).
  • Confidence scores now use the value from the disambiguation model when available.
  • New unified model for relation finding that replaces previous relation models for “anatomicsite-relations”, “experiencer-relations”, “followup-relations”, “measurement-relations”, “imagelink-relations”, “qualifier-relations”, and “temporality-relations”.
  • Added relation ontology info for ICD-10 and ICD-10-CM.
  • Auto-detected report kinds are marked as such in the output.
  • Quantization for the entity concept link confidence score model is now enabled by default, reducing memory requirements.

Measurement relation

  • New model for relation finding, significantly improving recall on measurements found in structured data such as tables.

Qualifier relation

  • No more qualifier-value to measurement-value relation arcs in qualifier relation output.
  • chronic is now only produced as part of the qualifier relation output rather than temporality relation.

Experiencer relation

  • Add relation concept links for matched experiencer relations (not assumed experiencers). This captures family history concepts such as family history of autism via a SNOMED concept link (e.g., Grandmother (person) 113157001) on the experiencer relation.
  • Improvements to experiencer subject pronoun suppression.
  • Remove link to associated finding concept in history of... relations.

Temporality relation

  • chronic is now only produced as part of the qualifier relation output rather than temporality relation.

Python Requirements

  • Minimum Python version required is v3.11.

Python SDK updates

The latest NLP API Python SDK at the time of release is version 7.1.0. Refer to the changelog for the Python SDK for a full explanation of the updates made since the last release. You will need to use at least version 5.7.0 of the Python SDK or later to send requests to the NLP API v2.37 but if you want to use the new features explained above you will need to use at least version 7.1.0.

New features in the Python SDK

To use existing NLP API databases with the new Python SDK you must do a data migration using the Python database client migrate subcommand:

$emtellipro-db-client migrate --database postgresql://username:password@hostname:port/example_db

Entity Mentions Comparison — v2.36 to v2.37

This comparison was done using 100K Discharge Summaries. Only the most frequent entity types are shown in this comparison.

Entities by entity type — change in current version v2.37

Entity typeCommonCommon %Distinct SNOMED concepts change %Concept-linked entities change %Polarity flips %
procedure3,966,46295.3%+3.3%+196.8%0.0782%
finding2,568,76794.0%+4.6%+37.0%1.1725%
disorder2,032,71896.2%+1.8%+14.1%0.1860%
person2,008,86998.6%+0.5%+99.6%0.0586%
observable entity1,034,22695.9%-0.1%+78.7%0.1901%
morphologic abnormality386,97594.7%+1.0%+11.1%0.2300%
physical object295,59495.2%+6.5%+30.7%0.1562%
regime/therapy240,28797.8%+2.8%+43.7%0.0651%
situation67,67466.5%+588.7%+3318.3%0.5090%
  • Common: Number of entities common to both builds: same position, same type, same concept.
  • Common %: Percentage of this type’s previous-build entities that are common to both builds.
  • Distinct SNOMED concepts change %: Change in the current version’s number of SNOMED codes: (current - previous) / previous.
  • Concept-linked entities change %: Change in the current version’s number of concept-linked entities: (current - previous) / previous.
  • Polarity flips %: Percentage of this type’s previous-build entities whose polarity changed, for example asserted to negated.
  • Reading: A plus means the current version is higher, a minus lower.

Entity span analysis by entity type

Entity typeChanged conceptRetypedOnly prevOnly currentLonger prevLonger current
procedure84,053122,3248,8879,5393,79632,474
finding55,86961,5729,47548,86914,19963,389
disorder28,27120,7021,2385,7478,10624,484
person3,55215,52110,1572,0871642,318
observable entity9,10331,9358,78913,8017972,715
morphologic abnormality75020,9531,4734984671,091
physical object5,7738,5003985,43856232
regime/therapy5363,781483921,585584
situation18411,29905,25062170,748
  • Changed concept: Entities with the same type but a different SNOMED code, either with exact match or change in span boundary.
  • Retyped: Entities given a different entity type, either with exact match or change in span boundary.
  • Only prev: Entities in the previous build with no overlapping entity in the current build.
  • Only current: Entities in the current build with no overlapping entity in the previous build.
  • Longer prev: Entities where both builds agree on type and concept and the previous build covers more characters.
  • Longer current: Entities where both builds agree on type and concept and the current build covers more characters.

Entity span length analysis

Entity typeEntities prevEntities currentAvg len prevp50 prevp95 prevAvg len currentp50 currentp95 current
procedure4,162,8804,215,6799.18.023.09.28.023.0
finding2,731,3872,880,50011.110.023.011.510.024.0
disorder2,113,7992,122,28013.712.029.013.712.029.0
person2,038,3832,024,3746.43.029.06.33.027.0
observable entity1,078,9561,082,8849.38.021.09.38.021.0
morphologic abnormality408,705404,5509.58.018.09.68.019.0
physical object310,577311,2047.97.017.08.07.017.0
regime/therapy245,622248,5069.79.021.09.79.021.0
situation101,769175,18214.914.027.016.215.027.0
  • Entities prev / current: Number of entities of this type in each build.
  • Avg len: Mean entity length in characters. Where the words sit apart, the gap between them is not counted.
  • p50: Median entity length.
  • p95: 95th percentile entity length: 1 in 20 entities is longer than this.

Benchmarking

  • Processed 1744 CCDs.
  • Total size: 34 MB; Average size: 67.35 KB.
  • 32x CPU: Intel(R) Xeon(R) Silver 4310 CPU @ 2.10 - 3.30 GHz w/18 MB Cache; 189G RAM
  • 1x GPU: Nvidia L4 w/24GB of RAM
  • Processing features: entity-polarity,entity-measurement-unit,medication-relations,measurement-relations,rxnorm-ontology,text,entity-uncertainty,snomed-ontology,snomedicd10cm-ontology,experiencer-relations,temporality-relations,anatomicsite-relations,qualifier-relations,entity-concept-link-confidence
  • Processed 1744 reports in 35:32.77s for an average per report processing time of 1.222921s per report
  • Output JSON file size: 269MB.
  • Saved 1744 documents to database in 56.89s (.032619s / document)
  • NLP API database size using Python database client output to sqlite: 446MB