ECG5000 Demo
The inertialai-chroma repository includes a fully working local demo that showcases multi-modal embeddings end-to-end using real biomedical sensor data. The demo ingests ECG recordings from the ECG5000 dataset into a Chroma collection and provides an interactive Streamlit web UI for querying and exploring the results.
This is the fastest way to see InertialAI's multi-modal embeddings produce meaningful, real-world results — without writing any application code yourself.
What It Demonstrates
Each ingested document pairs a human-readable ECG class description with 140 raw sensor readings from a single-lead ECG:
{
"text": "R-on-T premature ventricular contraction — early heartbeat on T-wave",
"time_series": [[-0.112, 0.043, 0.197, ...]], # 140 single-channel readings
}
The demo is specifically designed to surface capabilities that text-only or time-series-only embeddings could not replicate:
- Cross-modal retrieval — queries using lay medical language (
"cardiac emergency","heart attack warning signs") correctly surface the right ECG classes, even though those phrases do not appear in any stored document. - Signal-driven disambiguation — queries like
"ischemia"vs."myocardial injury"correctly rank ST depression above ST elevation and vice versa, a distinction that is invisible to a text-only model but is encoded in the signal morphology. - Semantic clustering — searching for
"abnormal ECG"consistently ranks Normal sinus rhythm at the bottom, demonstrating that the embeddings have internalized the clinical meaning of the signal shapes.
Prerequisites
| Requirement | Purpose |
|---|---|
| Docker + Compose v2 | Run the Chroma server and demo app |
make | Run the provided convenience targets |
curl + unzip | Download and extract the ECG5000 dataset |
| An InertialAI API key | Embed the ~200 ECG documents on first launch |
Quick Start
1. Clone the repository
git clone https://github.com/InertialAI/inertialai-chroma.git
cd inertialai-chroma
2. Download the dataset
make example-data-fetch
This downloads ECG5000.zip from the UCR Time Series Classification Archive and extracts the two ARFF source files into examples/sample-data/ecg5000/. The command is idempotent — running it again when the data is already present simply confirms that and exits.
3. Configure your API key
make example-init-env
# Open examples/.env and replace `your_api_key_here` with your real key
4. Start the services
make example-up
Docker Compose pulls the Chroma image, builds the demo app image, and starts both services. Open http://localhost:8501 in your browser.
On the first visit, the app detects that the Chroma collection is empty and automatically ingests the ECG5000 sample — approximately 200 documents across 5 classes — with a progress spinner. Ingestion requires a single API call and completes in under a minute on a typical connection.
The Dataset
ECG5000 is a subset of the UCR Time Series Classification Archive. It contains 5,000 ECG recordings (500 training, 4,500 test), each consisting of 140 timesteps of a single-lead ECG signal. The demo uses a stratified sample of 200 recordings — 40 per class.
| Class | Label | Signal description |
|---|---|---|
| 1 | Normal sinus rhythm | Regular, repeating PQRST complex — the reference baseline |
| 2 | R-on-T PVC | Premature ventricular contraction occurring on the T-wave of the previous beat |
| 3 | Paced beat | Artificially stimulated by a pacemaker — distinctive flat, square-wave morphology |
| 4 | ST depression | Depressed ST segment; associated with myocardial ischemia |
| 5 | ST elevation | Elevated ST segment; associated with acute myocardial injury |
These five classes make an ideal demo dataset because they span the full range of "normal vs. abnormal", include classes that are visually and semantically distinct (paced beat, PVC), and include classes that are superficially similar in text but meaningfully different in signal shape (ST depression vs. ST elevation).
Using the Streamlit UI
Search tab
Enter a free-text query. The app embeds it via InertialAI and queries Chroma for the nearest neighbours, returning a ranked results table with similarity scores and class labels, alongside ECG waveform charts for the top hits.
The queries below probe distinct capabilities of the multi-modal embedding model.
Normal vs. abnormal discrimination
| Query | What to expect |
|---|---|
healthy heart | Results dominated by class 1 (Normal sinus rhythm). Abnormal classes ranking highly would indicate weak signal encoding. |
abnormal ECG | The inverse — class 1 should rank at the bottom, abnormal classes at the top. |
Arrhythmia specificity
| Query | What to expect |
|---|---|
premature heartbeat | R-on-T PVCs (class 2) should rank first; other abnormal classes may follow, but normal rhythms should rank last. |
artificially paced rhythm | A clean test — paced beats (class 3) have a visually distinctive flat, square-wave morphology and a dedicated class label, so they should cluster tightly at the top. |
ST-segment differentiation
Classes 4 and 5 are superficially similar in text — both involve ST-segment abnormalities — but differ in clinical meaning and signal shape. This is where the time-series component of the embedding earns its place.
| Query | What to expect |
|---|---|
ischemia | ST depression (class 4) should rank above ST elevation (class 5). |
myocardial injury | The reverse — ST elevation (class 5) should lead. |
Cross-modal retrieval
The most compelling showcase: queries that use language not present in any stored document description. The model must rely entirely on the fused text + signal embedding to return correct results.
| Query | What to expect |
|---|---|
cardiac emergency | Abnormal classes should surface, with ST elevation and PVCs ranking highest. |
heart attack warning signs | Tests whether the model maps lay medical terminology to the correct ECG morphologies without any direct lexical match. |
elevated ST segment | Should surface class 5 (ST elevation) even though the exact phrase does not appear in any stored description. |
Browse tab
Paginated table of all ingested documents showing ID, class label, source file, text description, and time-series channel count. Useful for verifying ingest quality and exploring the dataset.
Sidebar
- Collection stats — total document count and per-class breakdown
- Re-ingest button — deletes and re-embeds all documents; useful if you want to re-run after a
make example-reset
Next Steps
- Multi-Modal Embeddings — understand the multi-modal input format in depth, with examples across industrial IoT, healthcare, financial, and sports analytics domains.
- Quickstart — build your own Chroma collection with
InertialAIEmbeddingFunctionfrom scratch. - Configuration Reference — explore dimensionality reduction, distance spaces, and other constructor options.