AnpherosAnpheros PlatformDevelopers

Anpheros Symptom Engine: methodology

How free-text symptoms in any language become WHO ICD-10 and ICD-11 concepts: the AI normalizer, presence and experiencer detection, the WHO-checked vocabulary, evaluation results, similar-case matching and limits.

The Anpheros Symptom Engine turns what a person writes about how they feel, in their own words and language, into international clinical concepts: a stable Anpheros identifier, a WHO ICD-10 code, a WHO ICD-11 code and a body system, together with whether the symptom is present, resolved, hypothetical or about someone else. It runs in production behind Anpheros Daily, publishes its results as HL7 FHIR R4 Observations on Anpheros Platform, and exposes the same terminology to any application through a REST and FHIR API. This page describes how it works, how it was checked, what it measures, and where its limits are.

At a glance

Concepts 86 (70 symptoms, 16 findings), identifiers SYM-0001…, never reused
Classifications WHO ICD-10 (Version 2019) and WHO ICD-11 MMS (2025-01), with the equivalence of each mapping
Body systems 13, taken from the ICD-11 chapter 21 blocks (nervous, digestive, respiratory, skin…)
Languages names in 20 languages; free text in the person's own language
Warning signs 32, for 14 concepts, quoted word for word from CDC and NIDDK
Normalizer evaluation 5 languages (Romanian, English, Spanish, German, French): primary code 97.5–100 %, presence and subject 92.5–98 %, negated symptoms reported as present 0 % in every language
Clinical review none yet: clinical_review: false on every response
Standards HL7 FHIR R4 (CodeSystem, ValueSet, ConceptMap, Observation), ICD-10, ICD-11, LOINC for lab results

1. The pipeline

A symptom goes through four steps. The person's text is never changed; every step adds data next to it.

  1. Capture. The raw entry is stored as written, with the moment it was noted, the phone's time zone, the language, and optionally intensity (1–10), onset and end. Nothing downstream rewrites it.
  2. Normalization (AI). A large language model (Google Gemini on Vertex AI) reads the text and returns, for each symptom it mentions: a primary ICD-10 code, optional secondary codes, a short label, and two attributes, assertion (present, absent, resolved, hypothetical, uncertain) and subject (the person, or someone else). The model may only choose codes from the Anpheros vocabulary; any other answer, an omitted entry or an invalid primary code counts as a failed attempt, never as "unknown symptom".
  3. Concept mapping (deterministic). The ICD-10 code is mapped to the Anpheros concept and, from it, to ICD-11 and the body system. This step uses fixed tables, not AI, so the same code always gives the same concept.
  4. Publication. Only symptoms that are present and about the person become FHIR Observations in the person's record, and only after normalization succeeds. If a later edit or re-normalization changes that, the Observation is withdrawn; the version history stays.

2. Presence, time and experiencer

Clinical text often mentions symptoms that the person does not have. Clinical natural-language processing calls this negation, temporality and experiencer detection (the NegEx and ConText family of methods). The engine handles the same three questions with the model's assertion and subject attributes:

Written Assertion / subject Published as the person's symptom?
"I've had a headache since Tuesday" present / self yes
"my head doesn't hurt any more" resolved / self no
"I might get a fever tomorrow" hypothetical / self no
"my mother has a cough" present / other no

A relative's complaint is never turned into family history automatically.

3. The vocabulary and how it was checked

The vocabulary covers ICD-10 chapter XVIII (R00–R94) and, where WHO classifies a symptom in another chapter, the WHO code: constipation K59.0, tinnitus H93.1, double vision H53.2, blurred vision H53.8, itching L29.9, joint pain M25.5, back pain M54, sleep problems G47.

4. Evaluation

The normalizer is evaluated on a fixed set of 100 synthetic cases written in Romanian (the language of most current users), each with the expected primary code, assertion and subject. 32 of the cases are deliberately not present: negated, resolved, hypothetical, uncertain or about another person. Results with the current prompt (version 3, 15 October 2026):

Metric Result Target
Primary code correct 100 % ≥ 85 %
Assertion and subject both correct 98 % —
Negated symptoms reported as present 0 % ≤ 3 %

The two errors were administrative entries ("an appointment with the cardiologist on Tuesday", "I want to lose 5 kg") classified as hypothetical instead of present; neither is a symptom. The test set has not been reviewed by a clinician, so the scores are indicative.

Other languages (16 October 2026). 40 of the cases, covering every category, were translated into English, Spanish, German and French, with the same expected answers; the informal cases were rewritten in each language's own informal style. The instructions to the model stayed the same.

Language Cases Primary code Presence and subject Negated reported as present
Romanian 100 100 % 98 % 0 %
English 40 100 % 97.5 % 0 %
Spanish 40 97.5 % 92.5 % 0 %
German 40 100 % 97.5 % 0 %
French 40 100 % 95 % 0 %

Most remaining errors are the same administrative entries ("cardiologist appointment on Tuesday", "check-up, all fine") or a choice between two non-present states ("no fever today" as resolved rather than absent); none of them publishes a symptom. The one coding difference was Spanish "escalofríos y malestar" (chills and malaise) coded as malaise (R53) with chills (R68) as a secondary code, rather than the reverse.

Names shown to people follow their language: the app displays the concept name in the user's language (lay name first) and the presence note ("resolved", "someone else") in the app's 20 languages.

In production (16 October 2026), after the vocabulary was checked against WHO, every stored symptom was re-normalized. On the records of real users: all symptoms normalized, 0 present symptoms left as "unclear", and 0 symptoms that are not present published as the person's own (independent audit of the published Observations).

5. Similar cases (in development)

The next component compares people by their symptoms and abnormal lab results, to suggest, only with explicit consent, people who report something very similar.

It does not suggest a diagnosis or a disease.

6. How applications use it

7. Limits

Related