# stemedb-ontology Domain Ontology Layer for Episteme - defines how subjects are structured based on predicate type and domain. Ensures conflicts collide correctly when different sources report on the same thing. ## Module Overview | Module | Purpose | |--------|---------| | `domain.rs` | Domain, EntityType, PredicateSchema, SourceTier builders | | `subject.rs` | SubjectBuilder for canonical subject construction | | `validator.rs` | Validates assertions against domain rules | | `client.rs` | HTTP client for StemeDB API | | `dto/` | Request/response DTOs for API communication | | `pharma/` | Pharmaceutical domain (reference implementation) | ## Quick Start ### CLI Usage (steme-pharma) ```bash # Build the CLI cargo build --release -p stemedb-ontology # Ingest FDA label data ./target/release/steme-pharma ingest semaglutide,tirzepatide # Ingest with mock conflicts for testing ./target/release/steme-pharma ingest semaglutide --with-conflicts # Query conflicts (Skeptic lens - default) ./target/release/steme-pharma query "Semaglutide:Type2Diabetes" hba1c_reduction_percent # Query with source hierarchy (Layered Consensus) ./target/release/steme-pharma query "Semaglutide:Type2Diabetes" weight_loss_percent --mode layered # Compare two drugs ./target/release/steme-pharma compare \ "Semaglutide:Type2Diabetes" \ "Tirzepatide:Type2Diabetes" \ --predicate hba1c_reduction_percent # Explore available predicates for a subject ./target/release/steme-pharma explore "Semaglutide:Type2Diabetes" # Validate a subject/predicate combination ./target/release/steme-pharma validate "Semaglutide:Type2Diabetes" hba1c_reduction_percent # JSON output (for scripting) ./target/release/steme-pharma --format json query "Semaglutide" nausea_rate ``` ### Programmatic Usage ```rust use stemedb_ontology::{pharma, SubjectBuilder, Validator}; use stemedb_ontology::client::StemeClient; use stemedb_ontology::pharma::extractors::{FdaLabelExtractor, MedicalExtractor, SourceInput}; use ed25519_dalek::SigningKey; use rand::rngs::OsRng; // Load the pharma domain definition let domain = pharma::definition(); // Build a subject using the ontology let schema = domain.get_schema("efficacy").unwrap(); let mut entities = std::collections::HashMap::new(); entities.insert("Drug".to_string(), "Semaglutide".to_string()); entities.insert("Indication".to_string(), "Type2Diabetes".to_string()); let subject = SubjectBuilder::build(schema, &entities, &domain).unwrap(); assert_eq!(subject, "Semaglutide:Type2Diabetes"); // Validate assertions let validator = Validator::new(&domain); let result = validator.validate("hba1c_reduction_percent", &subject, 0.95); assert!(result.is_ok()); // Extract and ingest claims let client = StemeClient::new("http://localhost:18180"); let extractor = FdaLabelExtractor::new(); let signing_key = SigningKey::generate(&mut OsRng); let agent_id = signing_key.verifying_key().to_bytes(); let hlc = uhlc::HLCBuilder::new().build(); let claims = extractor.extract(&SourceInput::DrugName("semaglutide".into())).await?; for claim in claims { let assertion = claim.to_assertion(&signing_key, agent_id, &hlc); let hash = client.assert(&assertion).await?; println!("Ingested: {}", hash); } // Query for conflicts let skeptic = client.skeptic("Semaglutide:Type2Diabetes", "hba1c_reduction_percent").await?; println!("Conflict score: {}", skeptic.conflict_score); ``` ## Architecture ``` ┌─────────────────────────────────────┐ │ Domain Definition │ │ (EntityTypes, Schemas, Hierarchy) │ └──────────────┬──────────────────────┘ │ ┌───────────────────────┼───────────────────────┐ │ │ │ v v v ┌─────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ SubjectBuilder │ │ Validator │ │ MedicalExtractor│ │ │ │ │ │ (trait) │ │ Build canonical │ │ Validate against │ │ Extract claims │ │ subject strings │ │ domain rules │ │ from sources │ └────────┬────────┘ └────────┬─────────┘ └────────┬─────────┘ │ │ │ └──────────────┬──────┴──────────────────────┘ │ v ┌───────────────────┐ │ StemeClient │ │ │ │ Submit assertions │ │ Query with lenses │ └─────────┬─────────┘ │ v ┌───────────────────┐ │ StemeDB API │ │ :18180/v1/* │ └───────────────────┘ ``` ## Subject Patterns Different predicate types use different subject structures to ensure proper collision: | Category | Pattern | Example | Use Case | |----------|---------|---------|----------| | Efficacy | `{Drug}:{Indication}` | `Semaglutide:Type2Diabetes` | Outcome measures for specific conditions | | Safety | `{Drug}` | `Semaglutide` | Adverse events (apply across indications) | | Mechanism | `{Drug}:{Target}` | `Semaglutide:GLP1R` | Pharmacology details | | Comparison | `{Drug}:{Comparator}:{Indication}` | `Semaglutide:Tirzepatide:Type2Diabetes` | Head-to-head trials | ## Source Hierarchy Claims are weighted by source authority: | Tier | Source Class | Weight | Examples | |------|--------------|--------|----------| | 0 | Regulatory | 1.0 | FDA Labels, EMA Reports | | 1 | Clinical | 0.9 | Phase III RCTs, Lancet, NEJM | | 2 | Observational | 0.7 | Real-World Evidence, FAERS | | 3 | Expert | 0.5 | Guidelines, ADA Standards | | 4 | Community | 0.3 | PatientsLikeMe, Moderated Forums | | 5 | Anecdotal | 0.1 | Reddit, Twitter, Blog Posts | ## Adding a New Domain See [Adding a Domain Guide](../../docs/guides/adding-a-domain.md) for step-by-step instructions on implementing new domains (e.g., cardiology, finance). ## Testing ```bash # Run all ontology tests cargo test -p stemedb-ontology # Run with output cargo test -p stemedb-ontology -- --nocapture # Consumer Health UAT cargo test -p stemedb-ontology --test consumer_health_uat ``` ## Related Documentation - [What is Episteme](../../what-is-episteme.md) - [Architecture](../../architecture.md) - [Vision](../../vision.md) - [Consumer Health Use Case](../../docs/app-concepts/consumer-health.md)