ddharmon v1 — Sub-cluster-anchored CDE Harmonization¶

Canonical end-to-end pipeline. Clusters cohort variables and NIH CDEs together using dual vectors (separate semantic + value-encoding embeddings), sub-clusters by value vectors, recommends a CDE per sub-cluster, and emits an LLM adopt / refine / novel recommendation per sub-cluster — routed to EITL (expert-in-the-loop) for human verification.

ingest (cohorts + CDE)
  → dual-vector embed (semantic + value)
    → semantic cluster (BERTopic)
      → value sub-cluster (HDBSCAN on value vectors, per topic)
        → CDE anchor per sub-cluster (medoid → best in-cluster CDE; GenCDE fallback)
          → adopt / refine / novel  (single classify-only LLM call)
            → EITL review queue

Lineage. v1 is a deliberately-scoped extension of the embedding-clustering-for-variable- harmonization line of work — Krishnamurthy 2025 (arXiv:2506.02160; CDE-side clustering) and Salimi 2025 (Sci Rep; PD-cohort clustering with HDBSCAN). We cluster cohort variables (source side), sub-cluster by value encoding, and anchor each sub-cluster to a CDE.

In v1: ingestion · dual-vector embedding · BERTopic · value sub-clustering · CDE anchoring · A/R/N classify → EITL. Out (publication-pending): the LLM coherence judge (j-signal), LLM concept-labeling, LLM spec authoring, granularity-loss (g-signal), deep recursive clustering, CDE CDM.

Runnable on a fresh clone. This notebook ships with two publicly-available example cohorts — All of Us (US precision-medicine surveys) and CLSA (Canadian Longitudinal Study on Aging) — plus the full NIH CDE catalog, all bundled under data/examples/. Run it end-to-end as shipped to see real cohorts flow through the pipeline, then swap in your own dictionaries by editing the loaders table in step 1.

The reusable logic lives in ddharmon.harmonization and ddharmon.clustering; this notebook is a thin orchestration over that API. (See notebooks/clustering/02_bertopic_clustering.ipynb for the research notebook with the full diagnostics, viz, and the cut LLM passes.)

In [ ]:
# Run this notebook from a clone of the ddharmon repo: its bundled example data lives in
# data/examples/, and every path below is relative to the repo root. This installs ddharmon
# and the extras the pipeline needs (embeddings → sentence-transformers, llm → anthropic Batch
# API, clustering, bertopic) directly from this repo — no external or dev references.
%pip install -q ".[embeddings,llm,clustering,bertopic]"
In [2]:
import json
import logging
from pathlib import Path

from ddharmon.ingestion import load_dictionary
from ddharmon.embedding import SentenceTransformerProvider, embed_dictionary
from ddharmon.harmonization import (
    harmonize_dictionaries,
    assemble_verdicts,
    write_prompts_jsonl,
    write_buckets,
    export_eitl_queue,
)
from ddharmon.llm import submit_and_wait  # Anthropic Batch API (needs ANTHROPIC_API_KEY)

try:
    from ddharmon.ingestion import preprocess_dictionary
except ImportError:
    preprocess_dictionary = None

logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("huggingface_hub").setLevel(logging.WARNING)
print("Imports OK")
Imports OK

1. Load cohorts + CDE catalog¶

The repo bundles two publicly-available example cohorts so this notebook runs end-to-end on a fresh clone. Swap them for your own dictionaries by editing the loaders table below:

  • AllOfUs — All of Us survey codebooks (REDCap-style; ~1.4k items, with response options). Public source: the All of Us Survey Data Codebooks.
  • CLSA — Canadian Longitudinal Study on Aging baseline dictionary (~5.5k variables, with value encodings). Public source: the CLSA data dictionaries.

CDEs are loaded as a cohort named NIH_CDE so they participate in clustering — each sub-cluster's anchor is the best CDE that lands in that sub-cluster. The bundled all_cdes_flat.tsv is the full NIH CDE repo (~22.7k CDEs, Krishnamurthy-scale, maximal anchor coverage). To regenerate it (or build a smaller subset) from the CDE repo JSON, run python scripts/flatten_cde_repo.py <input.json> <output.tsv>.

Bring your own cohorts. Each entry in loaders maps your dictionary's columns to load_dictionary's named kwargs (variable_name=, description=, value_encoding=, …). Drop your CSV/TSV in data/examples/ and add an entry — no other code changes needed.

In [3]:
DATA_DIR = Path("data/examples")  # bundled, publicly-available example dictionaries

# CDEs participate in clustering as a cohort. Ships with the full NIH CDE repo (~22.7k CDEs);
# rebuild or subset it with: python scripts/flatten_cde_repo.py <input.json> <output.tsv>
CDE_FILE = DATA_DIR / "all_cdes_flat.tsv"

# Two public example cohorts ship with the repo. Replace these with your own dictionaries —
# each loader just maps your columns onto load_dictionary's named kwargs.
loaders = {
    "NIH_CDE": (CDE_FILE, dict(
        variable_name="designation", field_id="tinyId",
        description="definition", question_text="question_text",
        data_type="datatype", value_encoding="permissible_values",
        category="classification", standard_code="concept_codes",
        embed_variable_name=True,
    )),
    "AllOfUs": (DATA_DIR / "all_of_us_surveys.csv", dict(
        variable_name="Item Concept", description="Field Label",
        category="Survey", data_type="Field Type",
        value_encoding="Choices, Calculations, OR Slider Labels",
        question_text="Field Label",
    )),
    "CLSA": (DATA_DIR / "clsa_baseline.csv", dict(
        variable_name="name", short_label="label:en", question_text="question:en",
        description="comment:en", category="table", data_type="valueType",
        units="unit", value_encoding="value_encoding",
    )),
    # Bring your own: copy the dict above, point it at data/examples/<your_file>.csv,
    # and map your column names to these kwargs.
}

cohorts = {}
for name, (path, kwargs) in loaders.items():
    if not path.exists():
        print(f"{name}: SKIPPED (not found: {path})")
        continue
    dd = load_dictionary(path, cohort_name=name, **kwargs)
    if preprocess_dictionary is not None:
        dd = preprocess_dictionary(dd)
    cohorts[name] = dd
    print(f"{name}: {dd.field_count} fields")

print(f"\nTotal: {sum(d.field_count for d in cohorts.values())} fields across {len(cohorts)} cohorts")
INFO: Column role mapping: {'designation': 'variable_name', 'tinyId': 'field_id', 'definition': 'description', 'datatype': 'data_type', 'classification': 'category', 'permissible_values': 'value_encoding', 'concept_codes': 'standard_code', 'question_text': 'question_text'}
INFO: Parsed 22743 fields from 22743 CSV rows
INFO: Hierarchy detection: 0 groups found, 0 synthetic parents created
INFO: load_dictionary(all_cdes_flat.tsv): 22269 fields in 1.76s
INFO: Unicode normalization: fixed 70 fields
INFO: Placeholder description replaced: "Complete the question for all hospitalized pulmonary embolism (PE)/deep vein thr" (11 fields)
INFO: Placeholder description replaced: "From CDC COVID-19 Community survey question bank (DRAFT)" (34 fields)
INFO: Placeholder description replaced: "NLM disclaimer: Consistent with Executive Order 14168, "gender" should not be us" (15 fields)
INFO: Placeholder description replaced: "No definition" (19 fields)
INFO: Placeholder description replaced: "Question is reversed scored" (17 fields)
INFO: Placeholder description replaced: "This term was developed in collaboration with the National Institute of Health's" (105 fields)
INFO: Substring dedup: suppressed 5551 variable names redundant with description
INFO: preprocess_dictionary(all_cdes_flat): 22269 fields preprocessed
INFO: Column role mapping: {'Item Concept': 'variable_name', 'Field Label': 'question_text', 'Field Type': 'data_type', 'Survey': 'category', 'Choices, Calculations, OR Slider Labels': 'value_encoding'}
NIH_CDE: 22265 fields
INFO: Parsed 1998 fields from 1998 CSV rows
INFO: Hierarchy detection: 0 groups found, 0 synthetic parents created
INFO: load_dictionary(all_of_us_surveys.csv): 1390 fields in 0.27s
INFO: Substring dedup: suppressed 9 variable names redundant with description
INFO: preprocess_dictionary(all_of_us_surveys): 1390 fields preprocessed
INFO: Column role mapping: {'name': 'variable_name', 'comment:en': 'description', 'label:en': 'short_label', 'valueType': 'data_type', 'unit': 'units', 'table': 'category', 'value_encoding': 'value_encoding', 'question:en': 'question_text'}
AllOfUs: 1390 fields
INFO: Parsed 6018 fields from 6018 CSV rows
INFO: Hierarchy detection: 0 groups found, 0 synthetic parents created
INFO: load_dictionary(clsa_baseline.csv): 5518 fields in 0.37s
INFO: Unicode normalization: fixed 27 fields
INFO: Placeholder description replaced: "1=lowest, 5 = highest" (16 fields)
INFO: Placeholder description replaced: "Added variable based on open text responses from other assistive devices used." (16 fields)
INFO: Placeholder description replaced: "Added variable based on open text responses from other caregiving provided." (12 fields)
INFO: Placeholder description replaced: "Associated with T score data" (10 fields)
INFO: Placeholder description replaced: "Associated with Z score data" (10 fields)
INFO: Placeholder description replaced: "Environment Canada, average of stations within 100 km" (26 fields)
INFO: Placeholder description replaced: "For a particular test frequency, if an error was recorded but no frequency value" (16 fields)
INFO: Placeholder description replaced: "Linked environmental data source - CANUE" (28 fields)
INFO: Placeholder description replaced: "Part of the Center for Epidemiologic Studies Short Depression Scale (CES-D 10). " (10 fields)
INFO: Placeholder description replaced: "Part of the Medical Outcomes Study (MOS) Social Support Survey. Sherbourne CD, S" (43 fields)
INFO: Placeholder description replaced: "Part of the Older Americans Resources and Services (OARS) Multidimensional Asses" (28 fields)
INFO: Placeholder description replaced: "Part of the Physical Activity Scale for the Elderly (PASE)© 1991 New England Res" (126 fields)
INFO: Placeholder description replaced: "Part of the SCREEN© instrument (Abbreviated version of SCREEN II©) developed by " (11 fields)
INFO: Placeholder description replaced: "Part of the Satisfaction with Life Scale (SWLS). Diener E, Emmons RA, Larsen RJ," (23 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (818 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (54 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (10 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (12 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (18 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (26 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (11 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (20 fields)
INFO: Placeholder description replaced: "Selected variable is part of a skip pattern. Please refer to the questionnaire f" (10 fields)
INFO: Placeholder description replaced: "The Parkinsonism Questionnaire was administered to Tracking Participants in the " (29 fields)
INFO: Placeholder description replaced: "The Personality Traits Questionnaire was administered only to participants in th" (30 fields)
INFO: Placeholder description replaced: "The Psychological Distress Questionnaire was administered only to participants i" (19 fields)
INFO: Placeholder description replaced: "This category was introduced in v2.6 of the MCQ questionnaire on June 2014. It w" (10 fields)
INFO: Placeholder description replaced: "This is a derived variable. It reflects the frequency of food item consumption b" (20 fields)
INFO: Placeholder description replaced: "This is a symmetry calculation variable. Refer to whole body DXA reanalysis data" (53 fields)
INFO: Placeholder description replaced: "This question was introduced in v2.6 of the MCQ questionnaire on June 2014. It w" (12 fields)
INFO: Placeholder description replaced: "average of NAPS stations within 50 km" (56 fields)
INFO: Placeholder description replaced: "average of NAPS stations within 50 km; using new NAPS adjustment for TEOM instru" (18 fields)
INFO: Placeholder description replaced: "kPa, Environment Canada, average of stations within 100 km" (14 fields)
INFO: Placeholder description replaced: "range 1- to +1" (38 fields)
INFO: Placeholder description replaced: "range 1- to +1. Greeness data unavailable for 2012. For the participants whose i" (76 fields)
INFO: Substring dedup: suppressed 1729 variable names redundant with description
INFO: preprocess_dictionary(clsa_baseline): 5518 fields preprocessed
CLSA: 5518 fields

Total: 29173 fields across 3 cohorts

2. Embed — dual vectors (semantic + value)¶

Each field gets two vectors: a semantic vector (question/description meaning) and a value vector (response-option / encoding structure). BERTopic clusters on the semantic vectors only; the value vectors drive sub-clustering in step 4. Embeddings are SQLite-cached, so re-runs only embed new/changed fields.

In [4]:
provider = SentenceTransformerProvider()
embedded = []
for name, dd in cohorts.items():
    ed = embed_dictionary(dd, provider=provider)
    embedded.append(ed)
    print(f"  {name}: {len(ed.embeddings)} semantic, {len(ed.value_embeddings)} value vectors")
print(f"\n{len(embedded)} dictionaries embedded.")

INFO: No device provided, using mps


INFO: Loading SentenceTransformer model from sentence-transformers/all-mpnet-base-v2.
/tmp/ddh_release_venv/lib/python3.12/site-packages/ddharmon/embedding/provider.py:77: FutureWarning: The `get_sentence_embedding_dimension` method has been renamed to `get_embedding_dimension`.
  self._dimension: int = self._model.get_sentence_embedding_dimension()  # type: ignore[assignment]
INFO: semantic embeddings: 0 cached, 22265 new
Embedding model loaded: all-mpnet-base-v2 (768d)
Batches:   0%|          | 0/348 [00:00<?, ?it/s]
Batches:   0%|          | 1/348 [00:04<26:12,  4.53s/it]
Batches:   1%|          | 2/348 [00:06<15:53,  2.76s/it]
Batches:   1%|          | 3/348 [00:07<12:15,  2.13s/it]
Batches:   1%|          | 4/348 [00:08<09:31,  1.66s/it]
Batches:   1%|▏         | 5/348 [00:09<08:08,  1.43s/it]
Batches:   2%|▏         | 6/348 [00:10<06:52,  1.20s/it]
Batches:   2%|▏         | 7/348 [00:11<06:19,  1.11s/it]
Batches:   2%|▏         | 8/348 [00:12<06:30,  1.15s/it]
Batches:   3%|▎         | 9/348 [00:13<05:55,  1.05s/it]
Batches:   3%|▎         | 10/348 [00:13<05:29,  1.02it/s]
Batches:   3%|▎         | 11/348 [00:14<05:20,  1.05it/s]
Batches:   3%|▎         | 12/348 [00:15<05:08,  1.09it/s]
Batches:   4%|▎         | 13/348 [00:16<04:47,  1.17it/s]
Batches:   4%|▍         | 14/348 [00:17<04:46,  1.17it/s]
Batches:   4%|▍         | 15/348 [00:18<04:38,  1.20it/s]
Batches:   5%|▍         | 16/348 [00:18<04:26,  1.24it/s]
Batches:   5%|▍         | 17/348 [00:19<04:13,  1.31it/s]
Batches:   5%|▌         | 18/348 [00:20<04:05,  1.35it/s]
Batches:   5%|▌         | 19/348 [00:21<04:17,  1.28it/s]
Batches:   6%|▌         | 20/348 [00:21<04:14,  1.29it/s]
Batches:   6%|▌         | 21/348 [00:22<04:17,  1.27it/s]
Batches:   6%|▋         | 22/348 [00:23<04:10,  1.30it/s]
Batches:   7%|▋         | 23/348 [00:24<04:05,  1.32it/s]
Batches:   7%|▋         | 24/348 [00:24<04:08,  1.30it/s]
Batches:   7%|▋         | 25/348 [00:25<04:02,  1.33it/s]
Batches:   7%|▋         | 26/348 [00:26<03:50,  1.40it/s]
Batches:   8%|▊         | 27/348 [00:26<03:51,  1.39it/s]
Batches:   8%|▊         | 28/348 [00:27<03:45,  1.42it/s]
Batches:   8%|▊         | 29/348 [00:28<03:32,  1.50it/s]
Batches:   9%|▊         | 30/348 [00:28<03:40,  1.44it/s]
Batches:   9%|▉         | 31/348 [00:29<03:27,  1.53it/s]
Batches:   9%|▉         | 32/348 [00:30<03:22,  1.56it/s]
Batches:   9%|▉         | 33/348 [00:30<03:17,  1.59it/s]
Batches:  10%|▉         | 34/348 [00:31<03:30,  1.49it/s]
Batches:  10%|█         | 35/348 [00:31<03:17,  1.58it/s]
Batches:  10%|█         | 36/348 [00:32<03:09,  1.64it/s]
Batches:  11%|█         | 37/348 [00:33<03:09,  1.64it/s]
Batches:  11%|█         | 38/348 [00:33<03:13,  1.60it/s]
Batches:  11%|█         | 39/348 [00:34<03:14,  1.58it/s]
Batches:  11%|█▏        | 40/348 [00:35<03:15,  1.58it/s]
Batches:  12%|█▏        | 41/348 [00:35<03:03,  1.67it/s]
Batches:  12%|█▏        | 42/348 [00:36<03:23,  1.51it/s]
Batches:  12%|█▏        | 43/348 [00:37<03:15,  1.56it/s]
Batches:  13%|█▎        | 44/348 [00:37<03:23,  1.50it/s]
Batches:  13%|█▎        | 45/348 [00:38<03:12,  1.57it/s]
Batches:  13%|█▎        | 46/348 [00:38<03:08,  1.60it/s]
Batches:  14%|█▎        | 47/348 [00:39<02:59,  1.67it/s]
Batches:  14%|█▍        | 48/348 [00:39<02:54,  1.72it/s]
Batches:  14%|█▍        | 49/348 [00:40<02:55,  1.70it/s]
Batches:  14%|█▍        | 50/348 [00:41<02:50,  1.74it/s]
Batches:  15%|█▍        | 51/348 [00:41<02:48,  1.76it/s]
Batches:  15%|█▍        | 52/348 [00:42<02:51,  1.73it/s]
Batches:  15%|█▌        | 53/348 [00:42<02:54,  1.69it/s]
Batches:  16%|█▌        | 54/348 [00:43<02:46,  1.76it/s]
Batches:  16%|█▌        | 55/348 [00:43<02:41,  1.81it/s]
Batches:  16%|█▌        | 56/348 [00:44<02:39,  1.83it/s]
Batches:  16%|█▋        | 57/348 [00:45<02:42,  1.79it/s]
Batches:  17%|█▋        | 58/348 [00:45<02:40,  1.81it/s]
Batches:  17%|█▋        | 59/348 [00:46<02:36,  1.85it/s]
Batches:  17%|█▋        | 60/348 [00:46<02:32,  1.89it/s]
Batches:  18%|█▊        | 61/348 [00:47<02:27,  1.95it/s]
Batches:  18%|█▊        | 62/348 [00:47<02:27,  1.93it/s]
Batches:  18%|█▊        | 63/348 [00:48<02:30,  1.90it/s]
Batches:  18%|█▊        | 64/348 [00:48<02:27,  1.92it/s]
Batches:  19%|█▊        | 65/348 [00:49<02:21,  2.00it/s]
Batches:  19%|█▉        | 66/348 [00:49<02:21,  1.99it/s]
Batches:  19%|█▉        | 67/348 [00:50<02:21,  1.99it/s]
Batches:  20%|█▉        | 68/348 [00:50<02:15,  2.07it/s]
Batches:  20%|█▉        | 69/348 [00:51<02:14,  2.08it/s]
Batches:  20%|██        | 70/348 [00:51<02:16,  2.03it/s]
Batches:  20%|██        | 71/348 [00:52<02:18,  2.00it/s]
Batches:  21%|██        | 72/348 [00:52<02:13,  2.07it/s]
Batches:  21%|██        | 73/348 [00:53<02:16,  2.01it/s]
Batches:  21%|██▏       | 74/348 [00:53<02:14,  2.04it/s]
Batches:  22%|██▏       | 75/348 [00:53<02:10,  2.09it/s]
Batches:  22%|██▏       | 76/348 [00:54<02:08,  2.12it/s]
Batches:  22%|██▏       | 77/348 [00:54<02:10,  2.08it/s]
Batches:  22%|██▏       | 78/348 [00:55<02:07,  2.12it/s]
Batches:  23%|██▎       | 79/348 [00:55<02:08,  2.10it/s]
Batches:  23%|██▎       | 80/348 [00:56<02:06,  2.12it/s]
Batches:  23%|██▎       | 81/348 [00:56<02:09,  2.07it/s]
Batches:  24%|██▎       | 82/348 [00:57<02:07,  2.08it/s]
Batches:  24%|██▍       | 83/348 [00:57<02:07,  2.08it/s]
Batches:  24%|██▍       | 84/348 [00:58<02:04,  2.12it/s]
Batches:  24%|██▍       | 85/348 [00:58<02:01,  2.16it/s]
Batches:  25%|██▍       | 86/348 [00:59<01:59,  2.20it/s]
Batches:  25%|██▌       | 87/348 [00:59<02:04,  2.10it/s]
Batches:  25%|██▌       | 88/348 [01:00<02:02,  2.12it/s]
Batches:  26%|██▌       | 89/348 [01:00<02:00,  2.15it/s]
Batches:  26%|██▌       | 90/348 [01:01<02:02,  2.11it/s]
Batches:  26%|██▌       | 91/348 [01:01<01:59,  2.16it/s]
Batches:  26%|██▋       | 92/348 [01:02<02:03,  2.08it/s]
Batches:  27%|██▋       | 93/348 [01:02<01:58,  2.15it/s]
Batches:  27%|██▋       | 94/348 [01:02<02:02,  2.07it/s]
Batches:  27%|██▋       | 95/348 [01:03<01:58,  2.13it/s]
Batches:  28%|██▊       | 96/348 [01:03<02:04,  2.03it/s]
Batches:  28%|██▊       | 97/348 [01:04<01:59,  2.10it/s]
Batches:  28%|██▊       | 98/348 [01:04<01:56,  2.15it/s]
Batches:  28%|██▊       | 99/348 [01:05<01:52,  2.21it/s]
Batches:  29%|██▊       | 100/348 [01:05<01:52,  2.21it/s]
Batches:  29%|██▉       | 101/348 [01:06<01:55,  2.14it/s]
Batches:  29%|██▉       | 102/348 [01:06<01:53,  2.17it/s]
Batches:  30%|██▉       | 103/348 [01:07<01:52,  2.17it/s]
Batches:  30%|██▉       | 104/348 [01:07<01:49,  2.23it/s]
Batches:  30%|███       | 105/348 [01:07<01:47,  2.26it/s]
Batches:  30%|███       | 106/348 [01:08<01:45,  2.30it/s]
Batches:  31%|███       | 107/348 [01:08<01:47,  2.24it/s]
Batches:  31%|███       | 108/348 [01:09<01:47,  2.24it/s]
Batches:  31%|███▏      | 109/348 [01:09<01:46,  2.25it/s]
Batches:  32%|███▏      | 110/348 [01:10<01:47,  2.22it/s]
Batches:  32%|███▏      | 111/348 [01:10<01:47,  2.21it/s]
Batches:  32%|███▏      | 112/348 [01:11<01:45,  2.24it/s]
Batches:  32%|███▏      | 113/348 [01:11<01:44,  2.24it/s]
Batches:  33%|███▎      | 114/348 [01:12<01:45,  2.23it/s]
Batches:  33%|███▎      | 115/348 [01:12<01:43,  2.26it/s]
Batches:  33%|███▎      | 116/348 [01:12<01:42,  2.26it/s]
Batches:  34%|███▎      | 117/348 [01:13<01:44,  2.22it/s]
Batches:  34%|███▍      | 118/348 [01:13<01:40,  2.28it/s]
Batches:  34%|███▍      | 119/348 [01:14<01:42,  2.23it/s]
Batches:  34%|███▍      | 120/348 [01:14<01:40,  2.26it/s]
Batches:  35%|███▍      | 121/348 [01:15<01:43,  2.20it/s]
Batches:  35%|███▌      | 122/348 [01:15<01:38,  2.28it/s]
Batches:  35%|███▌      | 123/348 [01:15<01:39,  2.27it/s]
Batches:  36%|███▌      | 124/348 [01:16<01:36,  2.31it/s]
Batches:  36%|███▌      | 125/348 [01:16<01:31,  2.43it/s]
Batches:  36%|███▌      | 126/348 [01:17<01:31,  2.44it/s]
Batches:  36%|███▋      | 127/348 [01:17<01:31,  2.41it/s]
Batches:  37%|███▋      | 128/348 [01:17<01:28,  2.48it/s]
Batches:  37%|███▋      | 129/348 [01:18<01:26,  2.53it/s]
Batches:  37%|███▋      | 130/348 [01:18<01:22,  2.63it/s]
Batches:  38%|███▊      | 131/348 [01:19<01:22,  2.62it/s]
Batches:  38%|███▊      | 132/348 [01:19<01:23,  2.58it/s]
Batches:  38%|███▊      | 133/348 [01:19<01:24,  2.55it/s]
Batches:  39%|███▊      | 134/348 [01:20<01:29,  2.39it/s]
Batches:  39%|███▉      | 135/348 [01:20<01:27,  2.44it/s]
Batches:  39%|███▉      | 136/348 [01:21<01:27,  2.42it/s]
Batches:  39%|███▉      | 137/348 [01:21<01:24,  2.50it/s]
Batches:  40%|███▉      | 138/348 [01:21<01:23,  2.51it/s]
Batches:  40%|███▉      | 139/348 [01:22<01:23,  2.51it/s]
Batches:  40%|████      | 140/348 [01:22<01:24,  2.46it/s]
Batches:  41%|████      | 141/348 [01:23<01:22,  2.50it/s]
Batches:  41%|████      | 142/348 [01:23<01:20,  2.56it/s]
Batches:  41%|████      | 143/348 [01:23<01:18,  2.62it/s]
Batches:  41%|████▏     | 144/348 [01:24<01:21,  2.52it/s]
Batches:  42%|████▏     | 145/348 [01:24<01:19,  2.54it/s]
Batches:  42%|████▏     | 146/348 [01:25<01:17,  2.60it/s]
Batches:  42%|████▏     | 147/348 [01:25<01:16,  2.64it/s]
Batches:  43%|████▎     | 148/348 [01:25<01:16,  2.62it/s]
Batches:  43%|████▎     | 149/348 [01:26<01:16,  2.60it/s]
Batches:  43%|████▎     | 150/348 [01:26<01:16,  2.59it/s]
Batches:  43%|████▎     | 151/348 [01:26<01:15,  2.62it/s]
Batches:  44%|████▎     | 152/348 [01:27<01:13,  2.68it/s]
Batches:  44%|████▍     | 153/348 [01:27<01:14,  2.61it/s]
Batches:  44%|████▍     | 154/348 [01:28<01:19,  2.43it/s]
Batches:  45%|████▍     | 155/348 [01:28<01:16,  2.52it/s]
Batches:  45%|████▍     | 156/348 [01:28<01:15,  2.53it/s]
Batches:  45%|████▌     | 157/348 [01:29<01:12,  2.62it/s]
Batches:  45%|████▌     | 158/348 [01:29<01:17,  2.44it/s]
Batches:  46%|████▌     | 159/348 [01:30<01:16,  2.46it/s]
Batches:  46%|████▌     | 160/348 [01:30<01:14,  2.53it/s]
Batches:  46%|████▋     | 161/348 [01:31<01:17,  2.40it/s]
Batches:  47%|████▋     | 162/348 [01:31<01:15,  2.47it/s]
Batches:  47%|████▋     | 163/348 [01:31<01:12,  2.55it/s]
Batches:  47%|████▋     | 164/348 [01:32<01:09,  2.66it/s]
Batches:  47%|████▋     | 165/348 [01:32<01:08,  2.68it/s]
Batches:  48%|████▊     | 166/348 [01:32<01:07,  2.70it/s]
Batches:  48%|████▊     | 167/348 [01:33<01:05,  2.78it/s]
Batches:  48%|████▊     | 168/348 [01:33<01:04,  2.79it/s]
Batches:  49%|████▊     | 169/348 [01:33<01:03,  2.81it/s]
Batches:  49%|████▉     | 170/348 [01:34<01:03,  2.81it/s]
Batches:  49%|████▉     | 171/348 [01:34<01:03,  2.80it/s]
Batches:  49%|████▉     | 172/348 [01:34<01:02,  2.84it/s]
Batches:  50%|████▉     | 173/348 [01:35<01:03,  2.75it/s]
Batches:  50%|█████     | 174/348 [01:35<01:00,  2.88it/s]
Batches:  50%|█████     | 175/348 [01:36<01:03,  2.74it/s]
Batches:  51%|█████     | 176/348 [01:36<01:04,  2.69it/s]
Batches:  51%|█████     | 177/348 [01:36<01:03,  2.70it/s]
Batches:  51%|█████     | 178/348 [01:37<01:02,  2.72it/s]
Batches:  51%|█████▏    | 179/348 [01:37<01:00,  2.81it/s]
Batches:  52%|█████▏    | 180/348 [01:37<00:58,  2.88it/s]
Batches:  52%|█████▏    | 181/348 [01:38<00:59,  2.82it/s]
Batches:  52%|█████▏    | 182/348 [01:38<01:02,  2.65it/s]
Batches:  53%|█████▎    | 183/348 [01:38<01:00,  2.72it/s]
Batches:  53%|█████▎    | 184/348 [01:39<00:57,  2.84it/s]
Batches:  53%|█████▎    | 185/348 [01:39<01:01,  2.63it/s]
Batches:  53%|█████▎    | 186/348 [01:40<00:59,  2.74it/s]
Batches:  54%|█████▎    | 187/348 [01:40<00:56,  2.85it/s]
Batches:  54%|█████▍    | 188/348 [01:40<00:55,  2.89it/s]
Batches:  54%|█████▍    | 189/348 [01:41<00:59,  2.69it/s]
Batches:  55%|█████▍    | 190/348 [01:41<00:55,  2.85it/s]
Batches:  55%|█████▍    | 191/348 [01:41<00:54,  2.91it/s]
Batches:  55%|█████▌    | 192/348 [01:42<00:53,  2.93it/s]
Batches:  55%|█████▌    | 193/348 [01:42<00:50,  3.06it/s]
Batches:  56%|█████▌    | 194/348 [01:42<00:52,  2.91it/s]
Batches:  56%|█████▌    | 195/348 [01:43<00:51,  2.97it/s]
Batches:  56%|█████▋    | 196/348 [01:43<00:50,  2.98it/s]
Batches:  57%|█████▋    | 197/348 [01:43<00:49,  3.08it/s]
Batches:  57%|█████▋    | 198/348 [01:44<00:47,  3.14it/s]
Batches:  57%|█████▋    | 199/348 [01:44<00:47,  3.11it/s]
Batches:  57%|█████▋    | 200/348 [01:44<00:49,  2.98it/s]
Batches:  58%|█████▊    | 201/348 [01:45<00:48,  3.04it/s]
Batches:  58%|█████▊    | 202/348 [01:45<00:52,  2.76it/s]
Batches:  58%|█████▊    | 203/348 [01:45<00:51,  2.83it/s]
Batches:  59%|█████▊    | 204/348 [01:46<00:51,  2.79it/s]
Batches:  59%|█████▉    | 205/348 [01:46<00:48,  2.94it/s]
Batches:  59%|█████▉    | 206/348 [01:46<00:46,  3.08it/s]
Batches:  59%|█████▉    | 207/348 [01:47<00:48,  2.92it/s]
Batches:  60%|█████▉    | 208/348 [01:47<00:46,  2.98it/s]
Batches:  60%|██████    | 209/348 [01:47<00:44,  3.13it/s]
Batches:  60%|██████    | 210/348 [01:48<00:48,  2.85it/s]
Batches:  61%|██████    | 211/348 [01:48<00:46,  2.96it/s]
Batches:  61%|██████    | 212/348 [01:48<00:44,  3.08it/s]
Batches:  61%|██████    | 213/348 [01:49<00:42,  3.19it/s]
Batches:  61%|██████▏   | 214/348 [01:49<00:41,  3.25it/s]
Batches:  62%|██████▏   | 215/348 [01:49<00:41,  3.24it/s]
Batches:  62%|██████▏   | 216/348 [01:50<00:41,  3.15it/s]
Batches:  62%|██████▏   | 217/348 [01:50<00:39,  3.33it/s]
Batches:  63%|██████▎   | 218/348 [01:50<00:38,  3.36it/s]
Batches:  63%|██████▎   | 219/348 [01:50<00:39,  3.28it/s]
Batches:  63%|██████▎   | 220/348 [01:51<00:39,  3.26it/s]
Batches:  64%|██████▎   | 221/348 [01:51<00:38,  3.26it/s]
Batches:  64%|██████▍   | 222/348 [01:51<00:39,  3.21it/s]
Batches:  64%|██████▍   | 223/348 [01:52<00:37,  3.35it/s]
Batches:  64%|██████▍   | 224/348 [01:52<00:36,  3.36it/s]
Batches:  65%|██████▍   | 225/348 [01:52<00:36,  3.38it/s]
Batches:  65%|██████▍   | 226/348 [01:52<00:35,  3.43it/s]
Batches:  65%|██████▌   | 227/348 [01:53<00:36,  3.31it/s]
Batches:  66%|██████▌   | 228/348 [01:53<00:37,  3.17it/s]
Batches:  66%|██████▌   | 229/348 [01:53<00:38,  3.06it/s]
Batches:  66%|██████▌   | 230/348 [01:54<00:38,  3.08it/s]
Batches:  66%|██████▋   | 231/348 [01:54<00:36,  3.23it/s]
Batches:  67%|██████▋   | 232/348 [01:54<00:36,  3.22it/s]
Batches:  67%|██████▋   | 233/348 [01:55<00:34,  3.30it/s]
Batches:  67%|██████▋   | 234/348 [01:55<00:33,  3.44it/s]
Batches:  68%|██████▊   | 235/348 [01:55<00:33,  3.33it/s]
Batches:  68%|██████▊   | 236/348 [01:56<00:33,  3.38it/s]
Batches:  68%|██████▊   | 237/348 [01:56<00:34,  3.20it/s]
Batches:  68%|██████▊   | 238/348 [01:56<00:34,  3.20it/s]
Batches:  69%|██████▊   | 239/348 [01:56<00:33,  3.30it/s]
Batches:  69%|██████▉   | 240/348 [01:57<00:30,  3.49it/s]
Batches:  69%|██████▉   | 241/348 [01:57<00:31,  3.43it/s]
Batches:  70%|██████▉   | 242/348 [01:57<00:29,  3.54it/s]
Batches:  70%|██████▉   | 243/348 [01:58<00:30,  3.49it/s]
Batches:  70%|███████   | 244/348 [01:58<00:29,  3.49it/s]
Batches:  70%|███████   | 245/348 [01:58<00:28,  3.59it/s]
Batches:  71%|███████   | 246/348 [01:58<00:28,  3.54it/s]
Batches:  71%|███████   | 247/348 [01:59<00:28,  3.60it/s]
Batches:  71%|███████▏  | 248/348 [01:59<00:26,  3.74it/s]
Batches:  72%|███████▏  | 249/348 [01:59<00:26,  3.70it/s]
Batches:  72%|███████▏  | 250/348 [01:59<00:25,  3.78it/s]
Batches:  72%|███████▏  | 251/348 [02:00<00:25,  3.74it/s]
Batches:  72%|███████▏  | 252/348 [02:00<00:25,  3.70it/s]
Batches:  73%|███████▎  | 253/348 [02:00<00:24,  3.89it/s]
Batches:  73%|███████▎  | 254/348 [02:00<00:23,  3.95it/s]
Batches:  73%|███████▎  | 255/348 [02:01<00:23,  3.96it/s]
Batches:  74%|███████▎  | 256/348 [02:01<00:22,  4.03it/s]
Batches:  74%|███████▍  | 257/348 [02:01<00:22,  4.03it/s]
Batches:  74%|███████▍  | 258/348 [02:01<00:21,  4.16it/s]
Batches:  74%|███████▍  | 259/348 [02:02<00:21,  4.18it/s]
Batches:  75%|███████▍  | 260/348 [02:02<00:21,  4.18it/s]
Batches:  75%|███████▌  | 261/348 [02:02<00:20,  4.24it/s]
Batches:  75%|███████▌  | 262/348 [02:02<00:20,  4.27it/s]
Batches:  76%|███████▌  | 263/348 [02:03<00:20,  4.08it/s]
Batches:  76%|███████▌  | 264/348 [02:03<00:20,  4.17it/s]
Batches:  76%|███████▌  | 265/348 [02:03<00:19,  4.26it/s]
Batches:  76%|███████▋  | 266/348 [02:03<00:19,  4.20it/s]
Batches:  77%|███████▋  | 267/348 [02:04<00:19,  4.17it/s]
Batches:  77%|███████▋  | 268/348 [02:04<00:19,  4.20it/s]
Batches:  77%|███████▋  | 269/348 [02:04<00:18,  4.38it/s]
Batches:  78%|███████▊  | 270/348 [02:04<00:17,  4.39it/s]
Batches:  78%|███████▊  | 271/348 [02:04<00:16,  4.56it/s]
Batches:  78%|███████▊  | 272/348 [02:05<00:16,  4.72it/s]
Batches:  78%|███████▊  | 273/348 [02:05<00:15,  4.79it/s]
Batches:  79%|███████▊  | 274/348 [02:05<00:15,  4.84it/s]
Batches:  79%|███████▉  | 275/348 [02:05<00:14,  4.87it/s]
Batches:  79%|███████▉  | 276/348 [02:06<00:15,  4.50it/s]
Batches:  80%|███████▉  | 277/348 [02:06<00:15,  4.61it/s]
Batches:  80%|███████▉  | 278/348 [02:06<00:15,  4.64it/s]
Batches:  80%|████████  | 279/348 [02:06<00:15,  4.55it/s]
Batches:  80%|████████  | 280/348 [02:06<00:14,  4.62it/s]
Batches:  81%|████████  | 281/348 [02:07<00:14,  4.71it/s]
Batches:  81%|████████  | 282/348 [02:07<00:13,  4.88it/s]
Batches:  81%|████████▏ | 283/348 [02:07<00:12,  5.11it/s]
Batches:  82%|████████▏ | 284/348 [02:07<00:12,  5.12it/s]
Batches:  82%|████████▏ | 285/348 [02:07<00:12,  5.19it/s]
Batches:  82%|████████▏ | 286/348 [02:08<00:12,  4.88it/s]
Batches:  82%|████████▏ | 287/348 [02:08<00:12,  5.00it/s]
Batches:  83%|████████▎ | 288/348 [02:08<00:11,  5.13it/s]
Batches:  83%|████████▎ | 289/348 [02:08<00:11,  5.16it/s]
Batches:  83%|████████▎ | 290/348 [02:08<00:10,  5.30it/s]
Batches:  84%|████████▎ | 291/348 [02:08<00:10,  5.25it/s]
Batches:  84%|████████▍ | 292/348 [02:09<00:10,  5.24it/s]
Batches:  84%|████████▍ | 293/348 [02:09<00:10,  5.15it/s]
Batches:  84%|████████▍ | 294/348 [02:09<00:10,  5.22it/s]
Batches:  85%|████████▍ | 295/348 [02:09<00:10,  5.09it/s]
Batches:  85%|████████▌ | 296/348 [02:09<00:09,  5.30it/s]
Batches:  85%|████████▌ | 297/348 [02:10<00:09,  5.46it/s]
Batches:  86%|████████▌ | 298/348 [02:10<00:09,  5.37it/s]
Batches:  86%|████████▌ | 299/348 [02:10<00:08,  5.48it/s]
Batches:  86%|████████▌ | 300/348 [02:10<00:08,  5.62it/s]
Batches:  86%|████████▋ | 301/348 [02:10<00:08,  5.80it/s]
Batches:  87%|████████▋ | 302/348 [02:10<00:07,  5.85it/s]
Batches:  87%|████████▋ | 303/348 [02:11<00:07,  5.72it/s]
Batches:  87%|████████▋ | 304/348 [02:11<00:08,  5.42it/s]
Batches:  88%|████████▊ | 305/348 [02:11<00:07,  5.72it/s]
Batches:  88%|████████▊ | 306/348 [02:11<00:07,  5.94it/s]
Batches:  88%|████████▊ | 307/348 [02:11<00:06,  6.22it/s]
Batches:  89%|████████▊ | 308/348 [02:11<00:06,  6.38it/s]
Batches:  89%|████████▉ | 309/348 [02:12<00:06,  6.16it/s]
Batches:  89%|████████▉ | 310/348 [02:12<00:05,  6.34it/s]
Batches:  89%|████████▉ | 311/348 [02:12<00:05,  6.40it/s]
Batches:  90%|████████▉ | 312/348 [02:12<00:05,  6.40it/s]
Batches:  90%|████████▉ | 313/348 [02:12<00:05,  6.49it/s]
Batches:  90%|█████████ | 314/348 [02:12<00:05,  6.79it/s]
Batches:  91%|█████████ | 315/348 [02:13<00:04,  6.93it/s]
Batches:  91%|█████████ | 316/348 [02:13<00:04,  7.01it/s]
Batches:  91%|█████████ | 317/348 [02:13<00:04,  7.12it/s]
Batches:  91%|█████████▏| 318/348 [02:13<00:04,  7.00it/s]
Batches:  92%|█████████▏| 319/348 [02:13<00:04,  6.87it/s]
Batches:  92%|█████████▏| 320/348 [02:13<00:04,  6.80it/s]
Batches:  92%|█████████▏| 321/348 [02:13<00:04,  6.65it/s]
Batches:  93%|█████████▎| 322/348 [02:14<00:03,  6.73it/s]
Batches:  93%|█████████▎| 323/348 [02:14<00:03,  6.95it/s]
Batches:  93%|█████████▎| 324/348 [02:14<00:03,  7.24it/s]
Batches:  93%|█████████▎| 325/348 [02:14<00:03,  7.23it/s]
Batches:  94%|█████████▎| 326/348 [02:14<00:02,  7.37it/s]
Batches:  94%|█████████▍| 327/348 [02:14<00:02,  7.56it/s]
Batches:  94%|█████████▍| 328/348 [02:14<00:02,  7.28it/s]
Batches:  95%|█████████▍| 329/348 [02:14<00:02,  7.18it/s]
Batches:  95%|█████████▍| 330/348 [02:15<00:02,  7.35it/s]
Batches:  95%|█████████▌| 331/348 [02:15<00:02,  7.53it/s]
Batches:  95%|█████████▌| 332/348 [02:15<00:02,  7.31it/s]
Batches:  96%|█████████▌| 333/348 [02:15<00:02,  7.34it/s]
Batches:  96%|█████████▌| 334/348 [02:15<00:01,  7.65it/s]
Batches:  96%|█████████▋| 335/348 [02:15<00:01,  7.85it/s]
Batches:  97%|█████████▋| 336/348 [02:15<00:01,  8.02it/s]
Batches:  97%|█████████▋| 337/348 [02:15<00:01,  8.31it/s]
Batches:  97%|█████████▋| 338/348 [02:16<00:01,  7.86it/s]
Batches:  97%|█████████▋| 339/348 [02:16<00:01,  8.01it/s]
Batches:  98%|█████████▊| 340/348 [02:16<00:00,  8.05it/s]
Batches:  98%|█████████▊| 341/348 [02:16<00:00,  8.11it/s]
Batches:  98%|█████████▊| 342/348 [02:16<00:00,  8.12it/s]
Batches:  99%|█████████▊| 343/348 [02:16<00:00,  6.91it/s]
Batches:  99%|█████████▉| 344/348 [02:16<00:00,  6.70it/s]
Batches:  99%|█████████▉| 345/348 [02:17<00:00,  6.40it/s]
Batches:  99%|█████████▉| 346/348 [02:17<00:00,  6.54it/s]
Batches: 100%|█████████▉| 347/348 [02:17<00:00,  6.71it/s]
Batches: 100%|██████████| 348/348 [02:17<00:00,  6.83it/s]
Batches: 100%|██████████| 348/348 [02:17<00:00,  2.53it/s]

INFO: value embeddings: 0 cached, 22265 new
Batches:   0%|          | 0/348 [00:00<?, ?it/s]
Batches:   0%|          | 1/348 [00:03<21:53,  3.79s/it]
Batches:   1%|          | 2/348 [00:07<20:14,  3.51s/it]
Batches:   1%|          | 3/348 [00:09<16:21,  2.85s/it]
Batches:   1%|          | 4/348 [00:11<15:12,  2.65s/it]
Batches:   1%|▏         | 5/348 [00:14<16:35,  2.90s/it]
Batches:   2%|▏         | 6/348 [00:16<14:55,  2.62s/it]
Batches:   2%|▏         | 7/348 [00:18<12:06,  2.13s/it]
Batches:   2%|▏         | 8/348 [00:19<10:32,  1.86s/it]
Batches:   3%|▎         | 9/348 [00:20<09:36,  1.70s/it]
Batches:   3%|▎         | 10/348 [00:21<08:38,  1.53s/it]
Batches:   3%|▎         | 11/348 [00:22<07:30,  1.34s/it]
Batches:   3%|▎         | 12/348 [00:23<06:31,  1.17s/it]
Batches:   4%|▎         | 13/348 [00:24<05:53,  1.06s/it]
Batches:   4%|▍         | 14/348 [00:25<05:41,  1.02s/it]
Batches:   4%|▍         | 15/348 [00:26<06:26,  1.16s/it]
Batches:   5%|▍         | 16/348 [00:27<05:34,  1.01s/it]
Batches:   5%|▍         | 17/348 [00:28<05:05,  1.08it/s]
Batches:   5%|▌         | 18/348 [00:28<04:19,  1.27it/s]
Batches:   5%|▌         | 19/348 [00:29<04:04,  1.34it/s]
Batches:   6%|▌         | 20/348 [00:29<03:46,  1.45it/s]
Batches:   6%|▌         | 21/348 [00:30<03:25,  1.59it/s]
Batches:   6%|▋         | 22/348 [00:30<03:18,  1.64it/s]
Batches:   7%|▋         | 23/348 [00:31<03:16,  1.66it/s]
Batches:   7%|▋         | 24/348 [00:31<02:52,  1.88it/s]
Batches:   7%|▋         | 25/348 [00:32<02:37,  2.05it/s]
Batches:   7%|▋         | 26/348 [00:33<03:10,  1.69it/s]
Batches:   8%|▊         | 27/348 [00:33<02:47,  1.92it/s]
Batches:   8%|▊         | 28/348 [00:33<02:25,  2.20it/s]
Batches:   8%|▊         | 29/348 [00:34<02:49,  1.89it/s]
Batches:   9%|▊         | 30/348 [00:35<03:00,  1.76it/s]
Batches:   9%|▉         | 31/348 [00:35<02:37,  2.01it/s]
Batches:   9%|▉         | 32/348 [00:36<02:54,  1.81it/s]
Batches:   9%|▉         | 33/348 [00:36<02:33,  2.05it/s]
Batches:  10%|▉         | 34/348 [00:37<02:49,  1.85it/s]
Batches:  10%|█         | 35/348 [00:37<02:23,  2.19it/s]
Batches:  10%|█         | 36/348 [00:37<02:08,  2.44it/s]
Batches:  11%|█         | 37/348 [00:38<02:17,  2.27it/s]
Batches:  11%|█         | 38/348 [00:38<01:49,  2.84it/s]
Batches:  11%|█         | 39/348 [00:38<01:37,  3.18it/s]
Batches:  11%|█▏        | 40/348 [00:38<01:33,  3.30it/s]
Batches:  12%|█▏        | 41/348 [00:38<01:20,  3.82it/s]
Batches:  12%|█▏        | 42/348 [00:39<01:41,  3.00it/s]
Batches:  12%|█▏        | 43/348 [00:39<01:58,  2.57it/s]
Batches:  13%|█▎        | 44/348 [00:40<02:13,  2.27it/s]
Batches:  13%|█▎        | 45/348 [00:40<01:52,  2.70it/s]
Batches:  13%|█▎        | 46/348 [00:41<02:01,  2.48it/s]
Batches:  14%|█▎        | 47/348 [00:41<02:08,  2.35it/s]
Batches:  14%|█▍        | 48/348 [00:41<01:52,  2.67it/s]
Batches:  14%|█▍        | 49/348 [00:42<01:59,  2.49it/s]
Batches:  14%|█▍        | 50/348 [00:42<01:45,  2.83it/s]
Batches:  15%|█▍        | 51/348 [00:42<01:38,  3.00it/s]
Batches:  15%|█▍        | 52/348 [00:43<01:29,  3.30it/s]
Batches:  15%|█▌        | 53/348 [00:43<01:21,  3.61it/s]
Batches:  16%|█▌        | 54/348 [00:43<01:20,  3.63it/s]
Batches:  16%|█▌        | 55/348 [00:43<01:14,  3.92it/s]
Batches:  16%|█▌        | 56/348 [00:44<01:17,  3.78it/s]
Batches:  16%|█▋        | 57/348 [00:44<01:29,  3.23it/s]
Batches:  17%|█▋        | 58/348 [00:44<01:32,  3.15it/s]
Batches:  17%|█▋        | 59/348 [00:45<01:24,  3.44it/s]
Batches:  17%|█▋        | 60/348 [00:45<01:35,  3.03it/s]
Batches:  18%|█▊        | 61/348 [00:45<01:22,  3.49it/s]
Batches:  18%|█▊        | 62/348 [00:45<01:13,  3.87it/s]
Batches:  18%|█▊        | 63/348 [00:46<01:18,  3.62it/s]
Batches:  18%|█▊        | 64/348 [00:46<01:10,  4.02it/s]
Batches:  19%|█▊        | 65/348 [00:46<01:06,  4.27it/s]
Batches:  19%|█▉        | 66/348 [00:46<01:04,  4.35it/s]
Batches:  19%|█▉        | 67/348 [00:47<01:00,  4.68it/s]
Batches:  20%|█▉        | 68/348 [00:47<00:59,  4.71it/s]
Batches:  20%|█▉        | 69/348 [00:47<01:00,  4.63it/s]
Batches:  20%|██        | 70/348 [00:47<01:00,  4.60it/s]
Batches:  20%|██        | 71/348 [00:48<01:12,  3.80it/s]
Batches:  21%|██        | 72/348 [00:48<01:18,  3.52it/s]
Batches:  21%|██        | 73/348 [00:48<01:13,  3.73it/s]
Batches:  21%|██▏       | 74/348 [00:48<01:11,  3.82it/s]
Batches:  22%|██▏       | 75/348 [00:49<01:07,  4.04it/s]
Batches:  22%|██▏       | 76/348 [00:49<01:02,  4.37it/s]
Batches:  22%|██▏       | 77/348 [00:49<01:02,  4.33it/s]
Batches:  22%|██▏       | 78/348 [00:49<01:00,  4.49it/s]
Batches:  23%|██▎       | 79/348 [00:49<00:53,  5.03it/s]
Batches:  23%|██▎       | 80/348 [00:49<00:48,  5.50it/s]
Batches:  23%|██▎       | 81/348 [00:50<00:46,  5.76it/s]
Batches:  24%|██▎       | 82/348 [00:50<00:43,  6.14it/s]
Batches:  24%|██▍       | 83/348 [00:50<00:40,  6.61it/s]
Batches:  24%|██▍       | 84/348 [00:50<00:37,  7.03it/s]
Batches:  24%|██▍       | 85/348 [00:50<00:35,  7.44it/s]
Batches:  25%|██▍       | 86/348 [00:50<00:36,  7.12it/s]
Batches:  25%|██▌       | 87/348 [00:50<00:38,  6.75it/s]
Batches:  25%|██▌       | 88/348 [00:51<00:36,  7.13it/s]
Batches:  26%|██▌       | 89/348 [00:51<00:35,  7.38it/s]
Batches:  26%|██▌       | 90/348 [00:51<00:36,  7.14it/s]
Batches:  26%|██▌       | 91/348 [00:51<00:40,  6.38it/s]
Batches:  26%|██▋       | 92/348 [00:51<00:39,  6.56it/s]
Batches:  27%|██▋       | 93/348 [00:51<00:40,  6.24it/s]
Batches:  27%|██▋       | 94/348 [00:52<00:40,  6.28it/s]
Batches:  27%|██▋       | 95/348 [00:52<00:40,  6.29it/s]
Batches:  28%|██▊       | 96/348 [00:52<00:44,  5.65it/s]
Batches:  28%|██▊       | 97/348 [00:52<00:43,  5.81it/s]
Batches:  28%|██▊       | 98/348 [00:52<00:39,  6.30it/s]
Batches:  28%|██▊       | 99/348 [00:52<00:35,  6.95it/s]
Batches:  29%|██▊       | 100/348 [00:52<00:34,  7.23it/s]
Batches:  29%|██▉       | 101/348 [00:53<00:42,  5.78it/s]
Batches:  29%|██▉       | 102/348 [00:53<00:39,  6.17it/s]
Batches:  30%|██▉       | 103/348 [00:53<00:38,  6.29it/s]
Batches:  30%|██▉       | 104/348 [00:53<00:36,  6.72it/s]
Batches:  30%|███       | 105/348 [00:53<00:39,  6.09it/s]
Batches:  30%|███       | 106/348 [00:54<00:43,  5.51it/s]
Batches:  31%|███       | 107/348 [00:54<00:42,  5.71it/s]
Batches:  31%|███       | 108/348 [00:54<00:47,  5.10it/s]
Batches:  31%|███▏      | 109/348 [00:54<00:43,  5.51it/s]
Batches:  32%|███▏      | 110/348 [00:54<00:40,  5.95it/s]
Batches:  32%|███▏      | 111/348 [00:54<00:37,  6.24it/s]
Batches:  32%|███▏      | 112/348 [00:55<00:37,  6.28it/s]
Batches:  32%|███▏      | 113/348 [00:55<00:39,  5.89it/s]
Batches:  33%|███▎      | 114/348 [00:55<00:44,  5.30it/s]
Batches:  33%|███▎      | 115/348 [00:55<00:43,  5.37it/s]
Batches:  33%|███▎      | 116/348 [00:55<00:43,  5.37it/s]
Batches:  34%|███▎      | 117/348 [00:55<00:40,  5.77it/s]
Batches:  34%|███▍      | 118/348 [00:56<00:42,  5.45it/s]
Batches:  34%|███▍      | 119/348 [00:56<00:38,  5.93it/s]
Batches:  34%|███▍      | 120/348 [00:56<00:36,  6.22it/s]
Batches:  35%|███▍      | 121/348 [00:56<00:33,  6.85it/s]
Batches:  35%|███▌      | 122/348 [00:56<00:33,  6.73it/s]
Batches:  35%|███▌      | 123/348 [00:56<00:32,  7.02it/s]
Batches:  36%|███▌      | 124/348 [00:56<00:29,  7.58it/s]
Batches:  36%|███▌      | 125/348 [00:57<00:27,  7.99it/s]
Batches:  36%|███▌      | 126/348 [00:57<00:27,  8.10it/s]
Batches:  37%|███▋      | 128/348 [00:57<00:23,  9.24it/s]
Batches:  37%|███▋      | 129/348 [00:57<00:24,  9.03it/s]
Batches:  38%|███▊      | 131/348 [00:57<00:22,  9.60it/s]
Batches:  38%|███▊      | 133/348 [00:57<00:22,  9.75it/s]
Batches:  39%|███▊      | 134/348 [00:58<00:26,  8.05it/s]
Batches:  39%|███▉      | 135/348 [00:58<00:25,  8.23it/s]
Batches:  39%|███▉      | 136/348 [00:58<00:31,  6.66it/s]
Batches:  39%|███▉      | 137/348 [00:58<00:31,  6.75it/s]
Batches:  40%|███▉      | 138/348 [00:58<00:29,  7.07it/s]
Batches:  40%|███▉      | 139/348 [00:58<00:28,  7.25it/s]
Batches:  40%|████      | 140/348 [00:58<00:30,  6.90it/s]
Batches:  41%|████      | 141/348 [00:59<00:31,  6.63it/s]
Batches:  41%|████      | 142/348 [00:59<00:29,  6.93it/s]
Batches:  41%|████      | 143/348 [00:59<00:32,  6.40it/s]
Batches:  41%|████▏     | 144/348 [00:59<00:32,  6.18it/s]
Batches:  42%|████▏     | 145/348 [00:59<00:33,  6.11it/s]
Batches:  42%|████▏     | 146/348 [00:59<00:34,  5.84it/s]
Batches:  42%|████▏     | 147/348 [01:00<00:33,  6.06it/s]
Batches:  43%|████▎     | 148/348 [01:00<00:31,  6.26it/s]
Batches:  43%|████▎     | 149/348 [01:00<00:30,  6.46it/s]
Batches:  43%|████▎     | 150/348 [01:00<00:29,  6.66it/s]
Batches:  43%|████▎     | 151/348 [01:00<00:27,  7.11it/s]
Batches:  44%|████▎     | 152/348 [01:00<00:30,  6.44it/s]
Batches:  44%|████▍     | 153/348 [01:01<00:31,  6.26it/s]
Batches:  44%|████▍     | 154/348 [01:01<00:29,  6.61it/s]
Batches:  45%|████▍     | 155/348 [01:01<00:26,  7.25it/s]
Batches:  45%|████▍     | 156/348 [01:01<00:26,  7.36it/s]
Batches:  45%|████▌     | 158/348 [01:01<00:23,  8.11it/s]
Batches:  46%|████▌     | 159/348 [01:01<00:23,  8.16it/s]
Batches:  46%|████▌     | 160/348 [01:01<00:22,  8.29it/s]
Batches:  46%|████▋     | 161/348 [01:01<00:22,  8.29it/s]
Batches:  47%|████▋     | 162/348 [01:02<00:22,  8.23it/s]
Batches:  47%|████▋     | 163/348 [01:02<00:21,  8.50it/s]
Batches:  47%|████▋     | 164/348 [01:02<00:21,  8.74it/s]
Batches:  47%|████▋     | 165/348 [01:02<00:20,  8.89it/s]
Batches:  48%|████▊     | 166/348 [01:02<00:20,  8.88it/s]
Batches:  48%|████▊     | 167/348 [01:02<00:20,  8.87it/s]
Batches:  49%|████▊     | 169/348 [01:02<00:19,  9.27it/s]
Batches:  49%|████▉     | 170/348 [01:02<00:19,  9.22it/s]
Batches:  49%|████▉     | 172/348 [01:03<00:18,  9.73it/s]
Batches:  50%|█████     | 174/348 [01:03<00:17,  9.93it/s]
Batches:  51%|█████     | 176/348 [01:03<00:16, 10.35it/s]
Batches:  51%|█████     | 178/348 [01:03<00:16, 10.32it/s]
Batches:  52%|█████▏    | 180/348 [01:03<00:15, 10.92it/s]
Batches:  52%|█████▏    | 182/348 [01:03<00:13, 12.34it/s]
Batches:  53%|█████▎    | 184/348 [01:04<00:13, 11.91it/s]
Batches:  53%|█████▎    | 186/348 [01:04<00:14, 11.26it/s]
Batches:  54%|█████▍    | 188/348 [01:04<00:14, 11.08it/s]
Batches:  55%|█████▍    | 190/348 [01:04<00:13, 12.07it/s]
Batches:  55%|█████▌    | 192/348 [01:04<00:11, 13.21it/s]
Batches:  56%|█████▌    | 194/348 [01:04<00:11, 13.61it/s]
Batches:  56%|█████▋    | 196/348 [01:05<00:10, 14.87it/s]
Batches:  57%|█████▋    | 198/348 [01:05<00:09, 15.67it/s]
Batches:  57%|█████▋    | 200/348 [01:05<00:09, 15.98it/s]
Batches:  58%|█████▊    | 202/348 [01:05<00:08, 16.58it/s]
Batches:  59%|█████▊    | 204/348 [01:05<00:08, 17.03it/s]
Batches:  59%|█████▉    | 206/348 [01:05<00:08, 16.89it/s]
Batches:  60%|█████▉    | 208/348 [01:05<00:07, 17.70it/s]
Batches:  61%|██████    | 211/348 [01:05<00:07, 18.18it/s]
Batches:  61%|██████▏   | 214/348 [01:06<00:07, 18.99it/s]
Batches:  62%|██████▏   | 217/348 [01:06<00:06, 19.32it/s]
Batches:  63%|██████▎   | 220/348 [01:06<00:06, 19.25it/s]
Batches:  64%|██████▍   | 222/348 [01:06<00:06, 19.29it/s]
Batches:  64%|██████▍   | 224/348 [01:06<00:06, 18.41it/s]
Batches:  65%|██████▌   | 227/348 [01:06<00:06, 18.55it/s]
Batches:  66%|██████▌   | 229/348 [01:06<00:06, 17.99it/s]
Batches:  68%|██████▊   | 235/348 [01:06<00:04, 26.89it/s]
Batches:  69%|██████▉   | 240/348 [01:07<00:03, 31.16it/s]
Batches:  70%|███████   | 245/348 [01:07<00:02, 34.74it/s]
Batches:  72%|███████▏  | 250/348 [01:07<00:02, 37.16it/s]
Batches:  73%|███████▎  | 255/348 [01:07<00:02, 38.65it/s]
Batches:  75%|███████▍  | 260/348 [01:07<00:02, 39.80it/s]
Batches:  76%|███████▌  | 265/348 [01:07<00:02, 40.54it/s]
Batches:  78%|███████▊  | 270/348 [01:07<00:01, 41.05it/s]
Batches:  79%|███████▉  | 275/348 [01:07<00:01, 41.32it/s]
Batches:  80%|████████  | 280/348 [01:08<00:01, 41.84it/s]
Batches:  82%|████████▏ | 285/348 [01:08<00:01, 42.57it/s]
Batches:  83%|████████▎ | 290/348 [01:08<00:01, 43.53it/s]
Batches:  85%|████████▍ | 295/348 [01:08<00:01, 43.81it/s]
Batches:  86%|████████▌ | 300/348 [01:08<00:01, 43.61it/s]
Batches:  88%|████████▊ | 305/348 [01:08<00:00, 43.34it/s]
Batches:  89%|████████▉ | 310/348 [01:08<00:00, 43.90it/s]
Batches:  91%|█████████ | 315/348 [01:08<00:00, 44.37it/s]
Batches:  92%|█████████▏| 320/348 [01:08<00:00, 43.91it/s]
Batches:  93%|█████████▎| 325/348 [01:09<00:00, 44.05it/s]
Batches:  95%|█████████▍| 330/348 [01:09<00:00, 41.99it/s]
Batches:  96%|█████████▋| 335/348 [01:09<00:00, 42.74it/s]
Batches:  98%|█████████▊| 340/348 [01:09<00:00, 42.83it/s]
Batches:  99%|█████████▉| 345/348 [01:09<00:00, 42.80it/s]
Batches: 100%|██████████| 348/348 [01:09<00:00,  5.00it/s]

WARNING: 5 fields have short embedding text (<20 chars) — may produce low-quality embeddings
INFO: Embedding 22265 fields: semantic (22265), value (22265 produced, 0 skipped)
INFO: embed_dictionary(all_cdes_flat): 22265 semantic, 22265 value embeddings in 208.14s
INFO: semantic embeddings: 0 cached, 1390 new
  NIH_CDE: 22265 semantic, 22265 value vectors
Batches:   0%|          | 0/22 [00:00<?, ?it/s]
Batches:   5%|▍         | 1/22 [00:03<01:19,  3.78s/it]
Batches:   9%|▉         | 2/22 [00:04<00:39,  1.98s/it]
Batches:  14%|█▎        | 3/22 [00:04<00:23,  1.26s/it]
Batches:  18%|█▊        | 4/22 [00:05<00:16,  1.09it/s]
Batches:  23%|██▎       | 5/22 [00:05<00:12,  1.37it/s]
Batches:  27%|██▋       | 6/22 [00:06<00:09,  1.67it/s]
Batches:  32%|███▏      | 7/22 [00:06<00:07,  1.99it/s]
Batches:  36%|███▋      | 8/22 [00:06<00:06,  2.33it/s]
Batches:  41%|████      | 9/22 [00:06<00:04,  2.64it/s]
Batches:  45%|████▌     | 10/22 [00:07<00:04,  2.84it/s]
Batches:  50%|█████     | 11/22 [00:07<00:03,  3.00it/s]
Batches:  55%|█████▍    | 12/22 [00:07<00:03,  3.15it/s]
Batches:  59%|█████▉    | 13/22 [00:08<00:02,  3.24it/s]
Batches:  64%|██████▎   | 14/22 [00:08<00:02,  3.11it/s]
Batches:  68%|██████▊   | 15/22 [00:08<00:02,  2.88it/s]
Batches:  73%|███████▎  | 16/22 [00:09<00:01,  3.11it/s]
Batches:  77%|███████▋  | 17/22 [00:09<00:01,  3.38it/s]
Batches:  82%|████████▏ | 18/22 [00:09<00:01,  3.70it/s]
Batches:  86%|████████▋ | 19/22 [00:09<00:00,  3.95it/s]
Batches:  91%|█████████ | 20/22 [00:09<00:00,  4.22it/s]
Batches:  95%|█████████▌| 21/22 [00:10<00:00,  4.52it/s]
Batches: 100%|██████████| 22/22 [00:10<00:00,  5.13it/s]
Batches: 100%|██████████| 22/22 [00:10<00:00,  2.15it/s]

INFO: value embeddings: 0 cached, 1390 new
Batches:   0%|          | 0/22 [00:00<?, ?it/s]
Batches:   5%|▍         | 1/22 [00:02<00:51,  2.46s/it]
Batches:   9%|▉         | 2/22 [00:03<00:28,  1.41s/it]
Batches:  14%|█▎        | 3/22 [00:03<00:17,  1.08it/s]
Batches:  18%|█▊        | 4/22 [00:03<00:11,  1.55it/s]
Batches:  23%|██▎       | 5/22 [00:03<00:08,  2.04it/s]
Batches:  27%|██▋       | 6/22 [00:04<00:06,  2.52it/s]
Batches:  32%|███▏      | 7/22 [00:04<00:04,  3.03it/s]
Batches:  36%|███▋      | 8/22 [00:04<00:03,  3.80it/s]
Batches:  41%|████      | 9/22 [00:04<00:03,  3.96it/s]
Batches:  45%|████▌     | 10/22 [00:04<00:02,  4.53it/s]
Batches:  50%|█████     | 11/22 [00:04<00:02,  5.08it/s]
Batches:  59%|█████▉    | 13/22 [00:05<00:01,  6.97it/s]
Batches:  73%|███████▎  | 16/22 [00:05<00:00, 10.78it/s]
Batches:  82%|████████▏ | 18/22 [00:05<00:00, 12.61it/s]
Batches: 100%|██████████| 22/22 [00:05<00:00, 17.93it/s]
Batches: 100%|██████████| 22/22 [00:05<00:00,  4.01it/s]
INFO: Embedding 1390 fields: semantic (1390), value (1390 produced, 0 skipped)
INFO: embed_dictionary(all_of_us_surveys): 1390 semantic, 1390 value embeddings in 15.82s
INFO: semantic embeddings: 0 cached, 5518 new
  AllOfUs: 1390 semantic, 1390 value vectors
Batches:   0%|          | 0/87 [00:00<?, ?it/s]
Batches:   1%|          | 1/87 [00:01<01:30,  1.05s/it]
Batches:   2%|▏         | 2/87 [00:01<01:03,  1.34it/s]
Batches:   3%|▎         | 3/87 [00:02<00:52,  1.61it/s]
Batches:   5%|▍         | 4/87 [00:02<00:46,  1.79it/s]
Batches:   6%|▌         | 5/87 [00:02<00:41,  1.97it/s]
Batches:   7%|▋         | 6/87 [00:03<00:38,  2.08it/s]
Batches:   8%|▊         | 7/87 [00:03<00:35,  2.26it/s]
Batches:   9%|▉         | 8/87 [00:04<00:33,  2.37it/s]
Batches:  10%|█         | 9/87 [00:04<00:31,  2.47it/s]
Batches:  11%|█▏        | 10/87 [00:04<00:30,  2.56it/s]
Batches:  13%|█▎        | 11/87 [00:05<00:28,  2.63it/s]
Batches:  14%|█▍        | 12/87 [00:05<00:27,  2.68it/s]
Batches:  15%|█▍        | 13/87 [00:05<00:26,  2.76it/s]
Batches:  16%|█▌        | 14/87 [00:06<00:25,  2.84it/s]
Batches:  17%|█▋        | 15/87 [00:06<00:24,  2.94it/s]
Batches:  18%|█▊        | 16/87 [00:06<00:23,  3.06it/s]
Batches:  20%|█▉        | 17/87 [00:07<00:26,  2.68it/s]
Batches:  21%|██        | 18/87 [00:07<00:23,  2.89it/s]
Batches:  22%|██▏       | 19/87 [00:07<00:22,  3.00it/s]
Batches:  23%|██▎       | 20/87 [00:08<00:22,  3.03it/s]
Batches:  24%|██▍       | 21/87 [00:08<00:22,  2.99it/s]
Batches:  25%|██▌       | 22/87 [00:08<00:20,  3.14it/s]
Batches:  26%|██▋       | 23/87 [00:09<00:19,  3.25it/s]
Batches:  28%|██▊       | 24/87 [00:09<00:19,  3.28it/s]
Batches:  29%|██▊       | 25/87 [00:09<00:18,  3.43it/s]
Batches:  30%|██▉       | 26/87 [00:09<00:17,  3.47it/s]
Batches:  31%|███       | 27/87 [00:10<00:17,  3.51it/s]
Batches:  32%|███▏      | 28/87 [00:10<00:16,  3.57it/s]
Batches:  33%|███▎      | 29/87 [00:10<00:16,  3.62it/s]
Batches:  34%|███▍      | 30/87 [00:11<00:15,  3.70it/s]
Batches:  36%|███▌      | 31/87 [00:11<00:15,  3.70it/s]
Batches:  37%|███▋      | 32/87 [00:11<00:15,  3.62it/s]
Batches:  38%|███▊      | 33/87 [00:11<00:14,  3.66it/s]
Batches:  39%|███▉      | 34/87 [00:12<00:14,  3.70it/s]
Batches:  40%|████      | 35/87 [00:12<00:13,  3.82it/s]
Batches:  41%|████▏     | 36/87 [00:12<00:13,  3.80it/s]
Batches:  43%|████▎     | 37/87 [00:12<00:12,  3.87it/s]
Batches:  44%|████▎     | 38/87 [00:13<00:13,  3.69it/s]
Batches:  45%|████▍     | 39/87 [00:13<00:12,  3.77it/s]
Batches:  46%|████▌     | 40/87 [00:13<00:12,  3.91it/s]
Batches:  47%|████▋     | 41/87 [00:14<00:13,  3.36it/s]
Batches:  48%|████▊     | 42/87 [00:14<00:15,  2.96it/s]
Batches:  49%|████▉     | 43/87 [00:14<00:13,  3.22it/s]
Batches:  51%|█████     | 44/87 [00:14<00:12,  3.45it/s]
Batches:  52%|█████▏    | 45/87 [00:15<00:11,  3.57it/s]
Batches:  53%|█████▎    | 46/87 [00:15<00:10,  3.78it/s]
Batches:  54%|█████▍    | 47/87 [00:15<00:10,  3.93it/s]
Batches:  55%|█████▌    | 48/87 [00:15<00:09,  4.04it/s]
Batches:  56%|█████▋    | 49/87 [00:16<00:09,  3.96it/s]
Batches:  57%|█████▋    | 50/87 [00:16<00:09,  4.02it/s]
Batches:  59%|█████▊    | 51/87 [00:16<00:08,  4.10it/s]
Batches:  60%|█████▉    | 52/87 [00:16<00:08,  4.08it/s]
Batches:  61%|██████    | 53/87 [00:17<00:08,  4.07it/s]
Batches:  62%|██████▏   | 54/87 [00:17<00:07,  4.13it/s]
Batches:  63%|██████▎   | 55/87 [00:17<00:07,  4.20it/s]
Batches:  64%|██████▍   | 56/87 [00:18<00:08,  3.48it/s]
Batches:  66%|██████▌   | 57/87 [00:18<00:08,  3.49it/s]
Batches:  67%|██████▋   | 58/87 [00:18<00:07,  3.82it/s]
Batches:  68%|██████▊   | 59/87 [00:18<00:06,  4.13it/s]
Batches:  69%|██████▉   | 60/87 [00:18<00:06,  4.35it/s]
Batches:  70%|███████   | 61/87 [00:19<00:05,  4.56it/s]
Batches:  71%|███████▏  | 62/87 [00:19<00:05,  4.44it/s]
Batches:  72%|███████▏  | 63/87 [00:19<00:05,  4.48it/s]
Batches:  74%|███████▎  | 64/87 [00:19<00:05,  4.32it/s]
Batches:  75%|███████▍  | 65/87 [00:20<00:05,  4.22it/s]
Batches:  76%|███████▌  | 66/87 [00:20<00:04,  4.47it/s]
Batches:  77%|███████▋  | 67/87 [00:20<00:04,  4.56it/s]
Batches:  78%|███████▊  | 68/87 [00:20<00:04,  4.50it/s]
Batches:  79%|███████▉  | 69/87 [00:20<00:04,  4.45it/s]
Batches:  80%|████████  | 70/87 [00:21<00:03,  4.46it/s]
Batches:  82%|████████▏ | 71/87 [00:21<00:03,  4.00it/s]
Batches:  83%|████████▎ | 72/87 [00:21<00:03,  4.11it/s]
Batches:  84%|████████▍ | 73/87 [00:21<00:03,  4.27it/s]
Batches:  85%|████████▌ | 74/87 [00:22<00:03,  3.78it/s]
Batches:  86%|████████▌ | 75/87 [00:22<00:03,  3.94it/s]
Batches:  87%|████████▋ | 76/87 [00:22<00:02,  3.99it/s]
Batches:  89%|████████▊ | 77/87 [00:22<00:02,  4.29it/s]
Batches:  90%|████████▉ | 78/87 [00:23<00:01,  4.63it/s]
Batches:  91%|█████████ | 79/87 [00:23<00:01,  4.97it/s]
Batches:  92%|█████████▏| 80/87 [00:23<00:01,  5.25it/s]
Batches:  93%|█████████▎| 81/87 [00:23<00:01,  5.63it/s]
Batches:  94%|█████████▍| 82/87 [00:23<00:00,  6.09it/s]
Batches:  95%|█████████▌| 83/87 [00:23<00:00,  6.55it/s]
Batches:  97%|█████████▋| 84/87 [00:23<00:00,  6.93it/s]
Batches:  98%|█████████▊| 85/87 [00:24<00:00,  6.90it/s]
Batches:  99%|█████████▉| 86/87 [00:24<00:00,  7.11it/s]
Batches: 100%|██████████| 87/87 [00:24<00:00,  3.58it/s]

INFO: value embeddings: 895 cached, 4623 new
Batches:   0%|          | 0/73 [00:00<?, ?it/s]
Batches:   1%|▏         | 1/73 [00:03<04:46,  3.98s/it]
Batches:   3%|▎         | 2/73 [00:06<03:43,  3.15s/it]
Batches:   4%|▍         | 3/73 [00:08<02:48,  2.40s/it]
Batches:   5%|▌         | 4/73 [00:08<01:57,  1.70s/it]
Batches:   7%|▋         | 5/73 [00:09<01:26,  1.27s/it]
Batches:   8%|▊         | 6/73 [00:09<01:05,  1.02it/s]
Batches:  10%|▉         | 7/73 [00:09<00:50,  1.32it/s]
Batches:  11%|█         | 8/73 [00:10<00:38,  1.68it/s]
Batches:  12%|█▏        | 9/73 [00:10<00:29,  2.14it/s]
Batches:  14%|█▎        | 10/73 [00:10<00:24,  2.59it/s]
Batches:  15%|█▌        | 11/73 [00:10<00:18,  3.28it/s]
Batches:  16%|█▋        | 12/73 [00:10<00:15,  3.98it/s]
Batches:  18%|█▊        | 13/73 [00:10<00:13,  4.59it/s]
Batches:  19%|█▉        | 14/73 [00:11<00:11,  5.25it/s]
Batches:  21%|██        | 15/73 [00:11<00:09,  5.92it/s]
Batches:  22%|██▏       | 16/73 [00:11<00:08,  6.56it/s]
Batches:  25%|██▍       | 18/73 [00:11<00:06,  8.54it/s]
Batches:  26%|██▌       | 19/73 [00:11<00:09,  5.86it/s]
Batches:  30%|███       | 22/73 [00:11<00:05,  9.49it/s]
Batches:  34%|███▍      | 25/73 [00:12<00:03, 13.06it/s]
Batches:  38%|███▊      | 28/73 [00:12<00:02, 15.86it/s]
Batches:  42%|████▏     | 31/73 [00:12<00:02, 17.79it/s]
Batches:  47%|████▋     | 34/73 [00:12<00:02, 19.22it/s]
Batches:  51%|█████     | 37/73 [00:12<00:01, 19.98it/s]
Batches:  55%|█████▍    | 40/73 [00:12<00:01, 20.13it/s]
Batches:  59%|█████▉    | 43/73 [00:12<00:01, 20.92it/s]
Batches:  63%|██████▎   | 46/73 [00:12<00:01, 21.13it/s]
Batches:  67%|██████▋   | 49/73 [00:13<00:01, 21.55it/s]
Batches:  71%|███████   | 52/73 [00:13<00:00, 21.79it/s]
Batches:  75%|███████▌  | 55/73 [00:13<00:00, 21.81it/s]
Batches:  79%|███████▉  | 58/73 [00:13<00:00, 18.13it/s]
Batches:  85%|████████▍ | 62/73 [00:13<00:00, 22.60it/s]
Batches:  90%|█████████ | 66/73 [00:13<00:00, 25.21it/s]
Batches:  97%|█████████▋| 71/73 [00:14<00:00, 25.66it/s]
Batches: 100%|██████████| 73/73 [00:14<00:00,  5.16it/s]

INFO: Embedding 5518 fields: semantic (5518), value (5518 produced, 0 skipped)
INFO: embed_dictionary(clsa_baseline): 5518 semantic, 5518 value embeddings in 38.70s
  CLSA: 5518 semantic, 5518 value vectors

3 dictionaries embedded.

3–6. Run the pipeline (cluster → sub-cluster → anchor → classify)¶

harmonize_dictionaries runs the whole chain. The single LLM call is the classify-only adopt/refine/novel pass; we submit it via the Anthropic Batch API (≈50% cheaper, resumable). Sub-clusters that can't be classified by an LLM are decided deterministically:

  • single_cohort — only one cohort present (no cross-cohort pooling) → skipped.
  • novel / unaligned — no candidate CDE in the sub-cluster (GenCDE needed) → forced verdict.
  • cde_only / noise — no cohort data / HDBSCAN noise → flagged, not harmonized.

Air-gapped? Call harmonize_dictionaries(embedded, classify=None) to get back result.prompt_records, export with write_prompts_jsonl, run scripts/process_prompts_batch.sh on a connected host, then assemble_verdicts(...).

In [5]:
WORK = Path("harmonization_artifacts")
WORK.mkdir(exist_ok=True)


def classify_via_batch(records):
    """Classify A/R/N prompts via the Anthropic Batch API. Returns {id: response}."""
    if not records:
        return {}
    prompts_path = WORK / "prompts_harmonize_arn.jsonl"
    responses_path = WORK / "responses_harmonize_arn.jsonl"
    write_prompts_jsonl(records, prompts_path)
    submit_and_wait(prompts_path, responses_path)  # needs ANTHROPIC_API_KEY
    responses = {}
    with open(responses_path) as f:
        for line in f:
            rec = json.loads(line)
            responses[rec["id"]] = rec["response"]
    return responses


result = harmonize_dictionaries(embedded, classify=classify_via_batch, min_cluster_size=15)
print(f"{len(result.verdicts)} sub-cluster verdicts ({len(result.prompt_records)} via LLM)")
INFO: topic_model_dictionaries: 29173 fields from 3 dicts
INFO: topic_model_dictionaries complete: 29173 fields, 516 topics, 7249 outliers in 549.49s
INFO: prepare_from_clusters: 516 clusters -> 10 LLM prompts, 1634 deterministic verdicts
INFO: Submitting 10 requests to Batch API (models=['claude-sonnet-4-6'])
INFO: Batch submitted: msgbatch_015SiAgS36VmYs3h57Rj3GqH (manifest: harmonization_artifacts/prompts_harmonize_arn.jsonl.batch_manifest.json)
Submitted batch msgbatch_015SiAgS36VmYs3h57Rj3GqH; polling every 60s until it ends...
  in_progress: succeeded=0 processing=10 errored=0
  in_progress: succeeded=0 processing=10 errored=0
  in_progress: succeeded=0 processing=10 errored=0
INFO: Batch msgbatch_015SiAgS36VmYs3h57Rj3GqH: status=ended, succeeded=10, processing=0, errored=0, expired=0, canceled=0
INFO: Wrote 10 responses to harmonization_artifacts/responses_harmonize_arn.jsonl (0 errors)
Done: 10 responses written to harmonization_artifacts/responses_harmonize_arn.jsonl
1644 sub-cluster verdicts (10 via LLM)

7. Outputs → buckets + EITL review queue¶

write_buckets writes one JSON per verdict bucket; export_eitl_queue writes a TSV review queue (refine/novel first) for the expert-in-the-loop app. Nothing is auto-applied — every recommendation is human-verified downstream.

In [6]:
counts = write_buckets(result, WORK / "buckets")
n_eitl = export_eitl_queue(result, WORK / "eitl_queue.tsv")
print("Buckets:", counts)
print(f"EITL queue: {n_eitl} sub-clusters -> {WORK / 'eitl_queue.tsv'}")
Buckets: {'cde_only': 1018, 'noise': 255, 'single_cohort': 355, 'novel': 11, 'adopt': 1, 'unaligned': 3, 'refine': 1}
EITL queue: 371 sub-clusters -> harmonization_artifacts/eitl_queue.tsv

Inspect verdicts¶

In [7]:
import pandas as pd

df = pd.DataFrame([
    {
        "sub_cluster": v.sub_cluster_id,
        "label": v.label,
        "verdict": v.verdict or "(skipped)",
        "mode": v.mode,
        "parent_cde_id": v.parent_cde_id,
        "anchor": v.anchor_designation,
        "confidence": v.confidence,
        "n_fields": v.n_fields,
        "cohorts": ";".join(v.cohorts),
        "decided_by": v.decided_by,
    }
    for v in result.verdicts
])
print(df["verdict"].value_counts())
df.sort_values(["verdict", "confidence"], ascending=[True, False]).head(30)
verdict
(skipped)    1628
novel          11
unaligned       3
adopt           1
refine          1
Name: count, dtype: int64
Out[7]:
sub_cluster label verdict mode parent_cde_id anchor confidence n_fields cohorts decided_by
0 0:0 (skipped) cde_only NaN NaN NaN 0 deterministic
1 0:1 (skipped) cde_only NaN NaN NaN 0 deterministic
2 0:-1 (skipped) noise NaN NaN NaN 0 deterministic
3 0:3 (skipped) cde_only NaN NaN NaN 0 deterministic
4 0:2 (skipped) cde_only NaN NaN NaN 0 deterministic
5 0:4 (skipped) cde_only NaN NaN NaN 0 deterministic
6 1:-1 (skipped) noise NaN NaN NaN 0 deterministic
7 1:1 (skipped) cde_only NaN NaN NaN 0 deterministic
8 1:2 (skipped) cde_only NaN NaN NaN 0 deterministic
9 1:0 (skipped) cde_only NaN NaN NaN 0 deterministic
10 2:0 (skipped) cde_only NaN NaN NaN 0 deterministic
11 2:1 (skipped) cde_only NaN NaN NaN 0 deterministic
12 2:2 (skipped) cde_only NaN NaN NaN 0 deterministic
13 2:-1 (skipped) noise NaN NaN NaN 0 deterministic
14 3:3 (skipped) cde_only NaN NaN NaN 0 deterministic
15 3:1 (skipped) cde_only NaN NaN NaN 0 deterministic
16 3:0 (skipped) cde_only NaN NaN NaN 0 deterministic
17 3:4 (skipped) cde_only NaN NaN NaN 0 deterministic
18 3:-1 (skipped) noise NaN NaN NaN 0 deterministic
19 3:2 (skipped) cde_only NaN NaN NaN 0 deterministic
20 4:-1 (skipped) noise NaN NaN NaN 0 deterministic
21 4:0 (skipped) cde_only NaN NaN NaN 0 deterministic
22 4:3 (skipped) cde_only NaN NaN NaN 0 deterministic
23 4:5 (skipped) cde_only NaN NaN NaN 0 deterministic
24 4:1 (skipped) cde_only NaN NaN NaN 0 deterministic
25 4:4 (skipped) cde_only NaN NaN NaN 0 deterministic
26 4:7 (skipped) cde_only NaN NaN NaN 0 deterministic
27 4:6 (skipped) cde_only NaN NaN NaN 0 deterministic
28 4:2 Last / Months / Com (skipped) single_cohort NaN NaN NaN 12 CLSA deterministic
29 5:0 (skipped) cde_only NaN NaN NaN 0 deterministic