Reviewable ICD-10 suggestions from text and documents, powered by decision models.
Project concept artwork — the SDK is a Python library, not a graphical application.
Formerly ICDJev. The repository is now icdlens; the package, Python imports and CLI remain icdjev for compatibility. Text and document lookup support Jev and Clef backends as described below.
ICDLens is a Python SDK for WHO ICD-10 catalogue lookup and reviewable AI-assisted coding suggestions. Instead of asking a model to generate code strings freely, it evaluates catalogue candidates using typed decision questions and exposes model-support scores for human review. Initialize once, call get_icd(text), and receive typed results. A local-only CLI is included.
- Local catalogue: inspect codes, labels, hierarchy, inclusions, exclusions and modifier-derived codes without network access.
- Optional AI lookup: traverse the catalogue and verify exact-code support using TypeSafe/Jev or Cloudflare Clef.
- Review reports: inspect evaluated candidates, scores, cutoff decisions and depth truncation; export JSON-ready dictionaries.
| Backend | Intended use | SDK status |
|---|---|---|
| TypeSafe Jev | Text-based candidate evaluation and exact-code verification | Available |
| Cloudflare Clef | Text and image-based decisions | Available |
| Cloudflare Clef-flash | Lower-latency text and image-based decisions | Available |
These models evaluate predefined questions rather than generate free-form answers. Their scores indicate model support, not validated clinical confidence. Jev is the default text backend. Choose backend="clef" or backend="clef-flash" for Cloudflare Workers AI. Document lookup automatically uses Clef when called on a Jev instance.
- Accept multiple images and PDFs, with optional DOC/DOCX-to-PDF conversion.
- Provide independently usable document preparation helpers: PDF pages to base64 PNG, configurable longest-edge rendering (default: 2,048 pixels), and aspect-ratio preservation.
- Enable lossless PNG optimization by default, with an opt-out; keep resizing separate from encoding compression. Output is lossless PNG; disabling optimization does not disable PNG compression.
- Prepare document inputs for Clef with file/page provenance and explicit request-limit handling. Each image group returns an independent review; results are not merged into a whole-record decision.
Install the documents extra for PDF/image preparation. DOC/DOCX conversion requires LibreOffice or a caller-provided converter. The SDK remains focused on ICD coding assistance, not general-purpose document extraction.
Experimental coding assistance, not a clinical diagnosis or automated billing system. Human review is required. This is WHO ICD-10, not ICD-10-CM.
Python 3.10 or newer:
# Catalogue only — no runtime dependencies:
pip install 'icdjev @ git+https://github.com/Advaidv121/icdlens.git'
# Include the optional hosted AI SDK:
pip install 'icdjev[jev] @ git+https://github.com/Advaidv121/icdlens.git'
# Clef needs no TypeSafe SDK; add local PDF/image preparation:
pip install 'icdjev[documents] @ git+https://github.com/Advaidv121/icdlens.git'The package is not yet published to PyPI. From a local clone, use pip install . or pip install '.[jev]' instead. Pin a Git commit in production for reproducibility.
Download an official WHO ICD-10 English ClaML file and unzip it:
curl --fail --location --output icd102019en.xml.zip \
https://icdcdn.who.int/icd10/claml/icd102019en.xml.zip
unzip icd102019en.xml.zipWHO download index · ClaML information
Edition metadata is read from the file. WHO classification data is not bundled or automatically downloaded. Review WHO's terms before using or redistributing it; the MIT code license does not cover WHO data.
Provide your TypeSafe/Jev credential through TYPESAFE_API_KEY in your runtime environment or secret store. Never commit a real key.
from icdjev import ICDLookup
with ICDLookup(catalogue_path='icd102019en.xml') as icd:
matches = icd.get_icd(
'Pneumonia, unspecified organism and type, is documented after assessment.'
)
for match in matches:
print(match.code, match.label, match.probability)The SDK sends the note and candidate context to TypeSafe. Use synthetic text for development. Real patient submissions require organizational approval and appropriate vendor privacy/security agreements.
Initialize once and reuse for multiple notes. If you do not use with, call icd.close() when finished. You may pass jev_key= explicitly with a value obtained from your secret store.
with ICDLookup(catalogue_path='icd102019en.xml') as icd:
review = icd.get_icd(
'Pneumonia is documented after assessment.', include_candidates=3
)
payload = review.to_dict()
for candidate in review.candidates:
print(candidate.code, candidate.support_score, candidate.status)By default, get_icd() returns list[ICDCode]. A positive include_candidates=N returns ICDReviewResult with accepted matches and up to N highest-scoring evaluated assignable candidates. Candidate limits do not limit accepted matches in normal mode.
threshold=0.6overrides the acceptance cutoff for one call; the instance default is0.8.best_score=Trueverifies and returns the top evaluated codes even below the cutoff (N matches, or one if N is zero). Weak results are flagged withbelow_thresholdandthreshold_bypassed. Hierarchy exploration stays threshold-gated: this is not an exhaustive search.- Scores represent model support, not validated clinical confidence. No primary/secondary encounter roles are assigned.
Set CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_AUTH_TOKEN securely in your process environment. A .env file is not loaded automatically. Never commit credentials.
from icdjev import ICDLookup, pdf_to_base64_png, prepare_documents
# Local preparation only; no API call:
pages = pdf_to_base64_png("synthetic_note.pdf", target_longest_edge=2048)
prepared = prepare_documents(["synthetic_note.pdf", "synthetic_scan.png"], compress=True)
with ICDLookup(catalogue_path="icd102019en.xml", backend="clef") as icd:
matches = icd.get_icd("Essential hypertension is documented.")
report = icd.get_icd_from_documents(
["synthetic_note.pdf", "synthetic_scan.png"],
compress=True, # False skips optional lossless encoding optimization.
)
for batch in report.batches:
print(batch.sources)
for match in batch.review.matches:
print(match.code, match.label, match.probability)
payload = report.to_dict()Use backend="clef-flash" for the faster variant. The same attached image group accompanies every traversal and verification call. More than four images, or more than eight MiB combined, are split into separate groups. Each group's scores and source pages stay separate: no cross-batch reconciliation or averaging is performed. Review all groups, especially when later pages contradict earlier ones.
Document reports expose per-request model/usage, total request count, and source-file/page metadata without embedding image payloads. Paths and results can still be sensitive. Hosted inference sends evidence to the selected provider; obtain approval and appropriate vendor agreements before submitting patient information.
No hosted SDK or API key needed:
from icdjev import Catalogue
catalogue = Catalogue.load('icd102019en.xml')
print(catalogue.get('E11.9').full_label)
print(catalogue.validate('E11.9'))icdjev --file icd102019en.xml info
icdjev --file icd102019en.xml show E11.9
icdjev --file icd102019en.xml search 'diabetes'Runnable examples · Architecture
- All suggestions require human review; review reports expose
needs_review=True. - Model instructions reject negated, suspected, historical and family conditions, but this is not a deterministic medical guarantee.
- Catalogue exclusions and pairing rules are available for inspection; AI lookup does not enforce exclusion adjudication, dagger/asterisk pairing, or encounter sequencing. Review those rules yourself.
- Block-level external-cause modifiers are not expanded; catalogue warnings report this limitation.
- No validated clinical accuracy benchmark is claimed. Offline tests use synthetic fixtures and fake judges to verify software behavior, not medical performance.
- The library does not automatically persist keys, notes or results. Saved reports can contain sensitive information.
git clone https://github.com/Advaidv121/icdlens.git
cd icdlens
uv sync --locked --extra jev --extra documents --extra dev
uv run --no-sync pytest
uv run --no-sync ruff check src tests examples
uv run --no-sync ruff format --check src tests examples
uv buildCI runs offline tests, lint, formatting, builds and a core-only wheel import check on Python 3.10–3.13. Hosted inference is optional, requires your own credential and may incur API charges:
uv run --extra jev python examples/simple_lookup.py \
--file /path/to/icd102019en.xml 'Pneumonia is documented after assessment.'Contributing · Security · Changelog
Code is licensed under MIT. WHO data and third-party services have separate terms. This project is not affiliated with or endorsed by WHO, TypeSafe or Cloudflare.
