
Clinical term mapping to standard medical terminologies: a clinical text phrase runs through entity extraction, embedding, and resolution to reach standard codes across RxNorm, ICD-10-CM, and other terminologies, powered by 90+ vocabularies across John Snow Labs’ JSL Models Hub and Terminology Server.
Clinical term mapping to standard medical terminologies (what NLP pipelines call entity resolution) turns a phrase pulled from clinical text, such as “metformin 500 mg” or “laparoscopic cholecystectomy,” into the exact code a downstream system needs: an RxNorm RXCUI, a CPT procedure code, an ICD-10-CM diagnosis code.
John Snow Labs solves this two ways.
Terminology Server is a dedicated lookup, search, and cross-vocabulary mapping service pre-loaded with 90+ vocabularies, including the Unified Medical Language System (UMLS), ICD, SNOMED CT, RxNorm, and LOINC, for looking up and cross-mapping codes you already have.
SentenceEntityResolver models and their companion mapper models handle the other half: turning a free-text span your NLP pipeline just extracted into that same kind of code in the first place.
John Snow Labs publishes 150+ SentenceEntityResolver models, 110+ companion mapper models, and 100+ ready-to-use resolution pipelines on the JSL Models Hub, spanning the medical coding systems clinical NLP pipelines rely on most.
Why extracting an entity isn’t enough
If your pipeline runs named entity recognition on clinical text, you’re only halfway to something usable. Feed a model “patient reports chest pain, rule out MI” and it correctly tags “chest pain” as a Symptom and “MI” as a Disease. That’s real, hard-won accuracy. But nothing downstream consumes a string. Claims systems speak ICD-10-CM. Pharmacy systems speak RxNorm. Registries speak SNOMED CT or one of dozens of other vocabularies, each on its own independent release cycle. A pipeline that stops at “I found a Symptom” has done half the job.
Clinical term mapping to standard medical terminologies is the second half: mapping that extracted span to the code a specific vocabulary actually uses. It looks like a lookup problem until you look at the data. The same clinical concept shows up in a dozen surface forms (“heart attack,” “MI,” “acute myocardial infarction”), some terms are genuinely ambiguous depending on specialty (“ASD” meaning autism spectrum disorder in a psychiatric note and atrial septal defect in a cardiology one), and the target vocabularies keep changing on their own schedules. Your resolution layer has to handle all of that, not just the clean cases.
John Snow Labs builds the production stack that healthcare and life sciences organizations use for this: Healthcare NLP and Medical LLM, with the resolver and mapper models described below published on the JSL Models Hub, and Terminology Server covering the lookup and cross-mapping side.
The models available out of the box
Most resolvers ship with a companion mapper. The resolver handles the fuzzy problem: free text into a code. The mapper handles the deterministic one: a known code into a related code or attribute, such as an ICD-10-CM code into its Centers for Medicare & Medicaid Services (CMS)-HCC risk category, an NDC package code into its HCPCS billing equivalent, or a gene symbol into its HGNC ID. Splitting the two matters because they fail differently, and conflating them produces a component that’s slow at the easy problem and unreliable at the hard one.
Across the JSL Models Hub, that adds up to 150+ resolver models and 110+ mapper models, covering terminologies from RxNorm, ICD-10-CM, ICD-10-PCS, and SNOMED CT to smaller, more specialized ones: HGNC gene symbols, ATC drug classifications, HCPCS, ICD-O tumor codes, MeSH, NCIt, HPO, ICD-11, and more. On top of the individual models, 100+ ready-to-use resolution pipelines bundle the full NER-to-code flow for a given terminology into a single downloadable artifact, so a team doesn’t have to assemble the pipeline stages by hand to get a working resolver running.
How we build training data for each resolver
A resolver is only as good as the dictionary behind it: every known way of writing a concept, mapped to the code it means. That dictionary is built from a combination of public and proprietary data, curated rather than merged wholesale.
Four principles hold across every terminology we support:
- Coverage is guaranteed, not assumed. Every code in the target vocabulary keeps at least one training example, checked at the code level after training, not just assumed from the source file.
- Deduplication order is chosen on purpose. When multiple ways of writing the same concept collide, the cleanest surface form is what the model actually trains on.
- Sources are merged deliberately, not by convenience. Public and proprietary data are combined with each source validated on its own terms, not stitched together as-is.
- Genuine ambiguity is preserved, not resolved away. A term with two valid meanings, “ASD” for autism spectrum disorder versus atrial septal defect, stays mapped to both, so the trained model can surface both candidates instead of confidently picking one and burying the other.
Every dataset is validated against the current, active version of its source vocabulary before training starts. The RxNorm accuracy figures later in this piece come from that same discipline.
Three ways to embed a chunk before resolution
A SentenceEntityResolverModel doesn’t classify into a fixed label set. It encodes the input with BertSentenceEmbeddings, then returns the closest matches from an index of every known synonym, ranked by distance. That’s also why a new terminology release doesn’t require retraining a classifier: it means re-embedding the updated dictionary.
The resolver architecture stays fixed across all three variants below; only the embedding stage feeding into it changes. The chunk can be embedded alone, blended with its surrounding sentence, or merged with the other entities around it, like a drug’s dose and form:

Same resolver, three ways to embed the chunk: all three pipelines share the same preprocessing through NerConverter, then diverge at the embedding stage — plain BertSentenceEmbeddings, BertSentenceChunkEmbeddings for sentence context, or EntityChunkEmbeddings for related entities like dose and form — before the same SentenceEntityResolverModel.
The next two sections cover the two enhanced variants in detail.
Giving a chunk its sentence’s context
A resolver working from the chunk text alone can’t use anything the sentence around it says. Take “She complains of pain in right leg.” The extracted chunk is just “pain,” and embedded alone it resolves to ICD-10-CM R07.2, “precordial pain,” a generic match with no location.
BertSentenceChunkEmbeddings fixes this by producing a weighted blend of the chunk’s own embedding and its surrounding sentence’s embedding, controlled by a single parameter, setChunkWeight (default 0.5, equal weight to each). Feed that blended embedding into the same SentenceEntityResolverModel used everywhere else in the pipeline, and the same chunk now resolves to M79.661, “pain in right lower leg,” correctly pulling the location from the sentence the chunk itself never mentioned.

Same chunk, sentence context changes the resolved code: “pain” alone resolves to R07.2, precordial pain, but with BertSentenceChunkEmbeddings blending in the sentence, the same chunk resolves to M79.661, pain in right lower leg.
It’s a drop-in replacement in your pipeline, used across several resolvers, including ICD-10-CM and CPT, wherever context-dependent disambiguation is worth the extra embedding stage.
Merging a drug with its dose and form
A plain NER pass on “metformin 500 mg tablet” returns three separate chunks: metformin (DRUG), 500 mg (STRENGTH), tablet (FORM). Resolved independently, “metformin” alone loses the dose and form information that often changes which RxNorm code is correct. EntityChunkEmbeddings merges them back together. Given a target entity type like DRUG and its related attributes (STRENGTH, ROUTE, FORM), it uses dependency parsing to combine syntactically related chunks into one weighted, embedded unit, then feeds that into the same SentenceEntityResolverModel architecture used everywhere else in the pipeline.
The effect shows up directly in the code returned. “Metformin 500 mg tablet” resolves to RxCUI 860974, metformin hydrochloride 500 MG, instead of a bare ingredient match. “2.5 mg coumadin” resolves to RxCUI 855313, warfarin sodium 2.5 MG [Coumadin], correctly tying a brand name to its generic ingredient and dose in one step, the same kind of brand-to-generic distinction that tripped up general-purpose LLMs in the benchmark below.

Merging a drug with its dose and form: EntityChunkEmbeddings combines the DRUG, STRENGTH, and FORM chunks into one embedded unit before resolution. “metformin” + “500 mg” + “tablet” resolves to RxCUI 860974, metformin hydrochloride 500 MG; “coumadin” + “2.5 mg” resolves to RxCUI 855313, warfarin sodium 2.5 MG [Coumadin].
How we validate accuracy before publishing a model
When a coding system publishes a new release, the affected resolvers get retrained and republished, not left to drift. Every model is checked against its own training vocabulary, against the previous published version where one exists on the Hub, and against the current, active release of its source vocabulary, so a resolver never hands back a code that’s since been retired or superseded. For several terminologies, that check runs the complete pipeline end to end, real free text through NER, embedding, and resolution, not just isolated terms in a light pipeline, since a model that resolves a clean term correctly can still fail once it’s feeding on your own messier, real-world input.
How the resolver compares to general-purpose LLMs
That internal discipline is one thing. To see how a purpose-built resolver compares to general-purpose language models on this task, we ran a closed-book benchmark across four coding systems: SNOMED CT, RxNorm, ICD-10-CM, and ICD-O. 110 items per system, 100 headline terms plus 10 checking whether a model knows about codes added or retired in the current release, scored against Claude Opus 5, Claude Sonnet 5, Claude Fable 5, GPT-5.6, and Gemini 3.6 Flash, each answering cold with no tools or database access.

John Snow Labs wins all four coding systems: top-1 accuracy mapping clinical text to the exact code across ICD-10-CM, RxNorm, ICD-O, and SNOMED CT, compared against Claude Opus 5, Sonnet 5, Fable 5, GPT-5.6, and Gemini 3.6 Flash.
Our resolvers won on all four systems: 76.4% on SNOMED CT, 91.8% on RxNorm, 95.5% on ICD-10-CM, and 96.4% on ICD-O, each ahead of every LLM tested. The margin tracks how memorable a coding system’s own codes are: SNOMED CT concept IDs and RxNorm RXCUIs are long numeric strings no one can reason their way to, so the gap runs as high as 25 points over the best LLM there; ICD-10-CM and ICD-O codes are shorter and partly mnemonic, so every model closes in.
General-purpose LLMs shared common failure patterns across the benchmark. They confused concept types, returning a related but wrong kind of code. Their training data has a fixed cutoff, so they missed newly added codes and occasionally mistook a superseded code for a current one. And on multiple systems, a model returned a code that doesn’t exist at all, a fabrication rather than a near miss. Our resolvers never do this: even on the misses, the code returned is a real, semantically related concept, not an invented one.
Take “Coumadin.” One model in our test returned RXCUI 11289, warfarin, the bare ingredient, instead of 202421, the brand-specific code the item actually asked for, a confusion between concept types that showed up across every system in the benchmark.

Same drug name, two different concept types: asked to resolve “Coumadin,” one general-purpose LLM returned RXCUI 11289 (warfarin, the bare ingredient) instead of 202421 (Coumadin, the brand name asked for). Our resolver returned the correct code.
“Mechanical cardiac valve prosthesis in situ” is a concept added to SNOMED CT’s current release. Every LLM in our test missed it. Our resolver, retrained on the same release, returned the correct code, 591071000124109.

One model’s training predates this code: asked to resolve “mechanical cardiac valve prosthesis in situ,” a concept added to SNOMED CT’s current release, 0 of 5 general-purpose LLMs returned the correct code. Our resolver, retrained on the same release, returned 591071000124109.
Asked to code “unspecified fracture of shaft of left fibula, initial encounter for closed fracture,” one model returned S82.403A, a code that doesn’t exist in ICD-10-CM at all. The real code is S82.402A.

A code that doesn’t exist in ICD-10-CM: one general-purpose LLM returned S82.403A, an invalid code, instead of S82.402A, the real ICD-10-CM code for the fracture described. Our resolver returned the correct code.
Terminology Server: searching, cross-mapping, and value sets without training a model
Terminology Server is John Snow Labs’ dedicated lookup, search, and cross-vocabulary mapping service, pre-loaded with 90+ vocabularies from RxNorm and SNOMED CT to UMLS itself. It takes text the same way a resolver does, but it doesn’t stop there: give it a SNOMED CT concept ID and it returns the ICD-10 equivalent; give it a cohort definition and it returns every code that qualifies, not just one.
Where a resolver model matches free text to the nearest code by embedding distance, Terminology Server does the deterministic, schema-based version of that same search, plus lookups and cross-mapping for codes you already have.

Terminology Server’s search UI: a query for “hypertension,” filtered to LOINC, returning matched concept names, source documents, hierarchical concept codes, and domains across the selected code systems.
- Smart text-to-code search — spell-check and abbreviation-tolerant, so a misspelled or shorthand query still finds the right code.
- Context resolution search — ranks results by relevance to what you’re actually looking for, not just string match.
- Boolean search — AND/OR logic for precise, compound queries.
- Advanced filtering — by domain, OMOP standard concept status, validity, and confidence score.
- Concept maps — official cross-vocabulary crosswalks, such as SNOMED CT to ICD-10.
- Schema-based document coding — extracts and codes entities from a full document against a defined schema, with deterministic output.
- Value sets — build and version your own from a CSV, or start from prebuilt public sets like CMS’s chronic-conditions list.
- Model Context Protocol (MCP) server integration — exposes the same search and mapping modules as tools an agentic AI workflow can call directly.
- Full API access — everything available in the UI is available programmatically.
Terminology Server deploys on-premises, on your own infrastructure, or through the AWS and Azure marketplaces on your own virtual VPN.
Try the models and Terminology Server yourself

The JSL live demo: selecting the sbiobertresolve_rxnorm model to resolve DRUG entities from sample clinical text, with matched RxNorm codes highlighted inline.
You can browse the models on the JSL Models Hub, work through the entity resolution notebooks in the Spark NLP Healthcare certification training series on GitHub, or try the live demo directly, no local install required. For Terminology Server, schedule a demo or browse the documentation to see the search, concept maps, and value sets described above in action.
FAQ
What is clinical term mapping to standard medical terminologies? It’s the process of mapping a span of clinical text, a diagnosis, drug name, procedure, or lab test mentioned in a note, to the exact code a standardized medical vocabulary uses for it, such as an ICD-10-CM code, an RxNorm RXCUI, or a SNOMED CT concept ID. NLP pipelines call this step entity resolution.
How is entity resolution different from named entity recognition (NER)? NER finds and labels a span of text as a category, such as Symptom or Drug. Entity resolution takes that span and matches it to a specific code in a specific coding system. They’re sequential steps in the same pipeline, not the same task.
How does this compare to using a general-purpose LLM like Claude or GPT? In a closed-book benchmark across SNOMED CT, RxNorm, ICD-10-CM, and ICD-O, our resolvers scored higher than every LLM tested, Claude Opus 5, Sonnet 5, Fable 5, GPT-5.6, and Gemini 3.6 Flash, with the largest gaps on SNOMED CT and RxNorm, where codes are long numeric strings no model can reason its way to.
Which medical coding systems does John Snow Labs support? Pretrained SentenceEntityResolver models are live on the JSL Models Hub for RxNorm, SNOMED CT, ICD-10-CM, ICD-10-PCS, ICD-O, MeSH, NCIt, HCPCS, CPT, MedDRA, UMLS, ATC, HGNC, NDC, HPO, ICD-11, LOINC, and more.
What is SentenceChunkEmbeddings and when should I use it? BertSentenceChunkEmbeddings blends an extracted chunk’s own embedding with its surrounding sentence’s embedding, so the same surface form can resolve differently depending on context. Reach for it when the same chunk text can mean different things in your notes, a lab value modified by “elevated” versus “normal,” for example.
What is EntityChunkEmbeddings and when should I use it? EntityChunkEmbeddings merges a target entity, like a drug, with its related attributes, such as strength, route, and form, into one embedded chunk before resolution. Reach for it when a code in your data depends on more than the entity name alone, a dosage or form that changes which RxNorm code is correct, for example.
How are new resolver models validated before release? Each release is checked against its own training vocabulary, against the previous published version where one exists on the Hub, and against the current, active source vocabulary, so a published model never hands back a retired or superseded code.
What’s the difference between the resolver models and Terminology Server? SentenceEntityResolver models turn a free-text span into a code by embedding distance, the resolver’s own best guess at the nearest match. Terminology Server does deterministic, schema-based lookup and cross-mapping for codes and terminologies you already have, plus its own text search.
References and Further Reading (Selected Technical Resources)
The technical blog posts below cover related implementation details:
- High Accuracy Resolution of Medical Entities to Standard Codes Using Novel Sentence Embeddings
- State-of-the-Art RxNorm Code Mapping with NLP: Comparative Analysis Between the Tools by John Snow Labs, Amazon, and GPT-4
- Mapping Medical Terms to MedDRA Ontology Using Healthcare NLP
- Comparing Spark NLP for Healthcare and ChatGPT in Extracting ICD10-CM Codes from Clinical Notes
- Understanding the Context of Clinical Terms in Spark NLP
- Medical Terminologies in Generative AI Lab: From Entity to Standard Code
Readers seeking deeper methodological detail are encouraged to consult the peer-reviewed papers published by the John Snow Labs research team.





























