use zeroentropy_community::{Client, MetadataValue};
use std::collections::HashMap;
use std::time::Duration;
use tokio::time::sleep;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::from_env()?;
let collection = "medical_transcriptions";
println!("\n=== ZeroEntropy EHR Search Demo ===\n");
println!("Creating collection '{}'...", collection);
match client.collections().add(collection).await {
Ok(_) => println!("✓ Collection created"),
Err(zeroentropy_community::Error::Conflict(_)) => {
println!("✓ Collection already exists")
}
Err(e) => return Err(e.into()),
}
let doc_list = client.documents().get_info_list(collection, Some(1), None).await?;
if doc_list.documents.is_empty() {
println!("\n=== Indexing Medical Transcriptions ===");
let temp_dir = std::env::temp_dir();
let csv_path = temp_dir.join("mtsamples.csv");
println!("Reading CSV from {}...", csv_path.display());
let csv_content = std::fs::read_to_string(&csv_path)?;
let mut rdr = csv::Reader::from_reader(csv_content.as_bytes());
let mut count = 0;
let max_docs = 100;
println!("Indexing first {} transcriptions...", max_docs);
for (idx, result) in rdr.records().enumerate() {
if count >= max_docs {
break;
}
let record = result?;
let description = record.get(0).unwrap_or("");
let specialty = record.get(1).unwrap_or("");
let _sample_name = record.get(2).unwrap_or("");
let transcription = record.get(3).unwrap_or("");
let keywords = record.get(4).unwrap_or("");
if transcription.is_empty() {
continue;
}
let mut metadata = HashMap::new();
metadata.insert(
"specialty".to_string(),
MetadataValue::String(specialty.to_string()),
);
metadata.insert(
"description".to_string(),
MetadataValue::String(description.to_string()),
);
if !keywords.is_empty() {
metadata.insert(
"keywords".to_string(),
MetadataValue::String(keywords.to_string()),
);
}
let doc_id = format!("record_{:04}", idx);
match client
.documents()
.add_text(collection, &doc_id, transcription, Some(metadata))
.await
{
Ok(_) => {
count += 1;
if count % 10 == 0 {
print!(".");
std::io::Write::flush(&mut std::io::stdout())?;
}
}
Err(zeroentropy_community::Error::Conflict(_)) => {
count += 1; }
Err(e) => eprintln!("\nWarning: Failed to index {}: {}", doc_id, e),
}
}
println!("\n✓ Indexed {} medical transcriptions", count);
println!("Waiting for indexing to complete...");
sleep(Duration::from_secs(5)).await;
} else {
println!("✓ Collection already contains documents");
}
let queries = vec![
(
"Patient with chest pain and shortness of breath",
"Finding cardiovascular symptoms across different documentation styles"
),
(
"History of diabetes and kidney problems",
"Finding related chronic conditions even with varied terminology"
),
(
"Postoperative complications and wound care",
"Surgical follow-up documentation"
),
(
"Mental health assessment and depression screening",
"Psychiatric and behavioral health notes"
),
(
"Imaging findings showing mass or lesion",
"Radiology and pathology reports"
),
];
println!("\n=== Clinical Query Examples ===\n");
for (query, description) in queries {
println!("Query: \"{}\"", query);
println!("Use case: {}", description);
let results = client
.queries()
.top_snippets(
collection,
query,
3, None, Some(true), Some(true), None, )
.await?;
if results.results.is_empty() {
println!(" No results found\n");
continue;
}
for (i, result) in results.results.iter().enumerate() {
let specialty = result
.metadata
.as_ref()
.and_then(|m| m.get("specialty"))
.and_then(|v| match v {
MetadataValue::String(s) => Some(s.as_str()),
_ => None,
})
.unwrap_or("Unknown");
println!("\n {}. [{}] Score: {:.4}", i + 1, specialty, result.score);
let snippet = if result.content.len() > 200 {
format!("{}...", &result.content[..200])
} else {
result.content.clone()
};
println!(" {}", snippet.replace('\n', " "));
}
println!("\n{}", "─".repeat(80));
}
println!("\n=== Specialty Filtering Example ===\n");
println!("Query: 'patient assessment' filtered to Cardiology specialty");
let mut filter = HashMap::new();
let mut specialty_filter = HashMap::new();
specialty_filter.insert(
"$eq".to_string(),
serde_json::Value::String("Cardiovascular / Pulmonary".to_string()),
);
filter.insert("specialty".to_string(), serde_json::Value::Object(
specialty_filter.into_iter().collect()
));
let results = client
.queries()
.top_snippets(
collection,
"patient assessment",
3,
Some(filter),
Some(true),
None,
None,
)
.await?;
println!("Found {} cardiology records:", results.results.len());
for (i, result) in results.results.iter().enumerate() {
println!(" {}. Score: {:.4}", i + 1, result.score);
let snippet = &result.content[..result.content.len().min(150)];
println!(" {}...", snippet.replace('\n', " "));
}
println!("\n=== Demo Complete ===");
println!("\nKey capabilities demonstrated:");
println!(" ✓ Semantic search - finds by meaning, not just keywords");
println!(" ✓ Cross-specialty search - works across all medical domains");
println!(" ✓ Metadata filtering - narrow searches by specialty, date, etc.");
println!(" ✓ Ranked results - most relevant findings first");
println!("\nPotential real-world applications:");
println!(" • Clinical decision support - find similar cases");
println!(" • Quality assurance - audit documentation patterns");
println!(" • Research cohort building - identify eligible patients");
println!(" • Prior authorization - find supporting documentation");
println!(" • Medical-legal review - locate relevant encounters");
Ok(())
}