Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Clinics on Rails (Brighton Ruby 2026)
Search
Alex Watt
June 25, 2026
42
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Clinics on Rails (Brighton RubyΒ 2026)
https://alexcwatt.com/act
https://www.youtube.com/watch?v=-PpU3xc7JJw
Alex Watt
June 25, 2026
Featured
See All Featured
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
2
340
GitHub's CSS Performance
jonrohan
1033
470k
Deep Space Network (abreviated)
tonyrice
0
410
Six Lessons from altMBA
skipperchong
29
4.6k
Building Better People: How to give real-time feedback that sticks.
wjessup
371
20k
Utilizing Notion as your number one productivity tool
mfonobong
4
640
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.7k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
330
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
570
Ethics towards AI in product and experience design
skipperchong
2
460
Transcript
π§β Clinics on Rails Alex Wattβ¨ @alexcwatt
None
None
None
None
None
π 2,200 families self-supporting
None
2025 Pittsburgh Team
None
Benefits of clinical data β’ Set volunteer expectations β’ Plan
for pharmacy β’ Understand community health over time
Requirements doc January 2024
None
Surveyed options Throughout 2024
BackpackEMR β Designed for mobile medical clinicsβ¨ β PII stored
outside of Ethiopia, could not host in country, limited reporting
Google Sheet β Free, ubiquitous, simpleβ¨ β Relational data, limited
data validation, more difficult integrations, permissions
OpenMRS & others β Powerful open source packageβ¨ β Seemed
non-trivial to deploy and customize
It had to be simple.
None
None
Built in a week (January 2025) Monday rails new Tuesday
Finished data models Wednesday Deployed with Hatchbox Thursday User policies & launch Friday Addressed feedback
None
Project Impact β’ Volunteers can help with medical data β’
Medical teams see their impact β’ Future teams are better prepared
1,583 patient encounters documented in 5 communities in Addis
Innovation Tokens acw.sh/boring
I spent only one token β on search.
Neoplasms Diseases of the blood or blood-forming organs Endocrine, nutritional,
or metabolic diseases etc.
None
Simple Hybrid Search + semantic fuzzy match
Simple Hybrid Search + semantic fuzzy match Query: fizzy sparkling
water soda frizzy hair Fizzyβs Diner
Simple Hybrid Search + informers gem (sentence-transformers) Jaro-Winkler
sentence-transformers/all-MiniLM-L6-v2 91 MB 1 vCPU and 1 GB RAM
Embedding computation MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2" EMBEDDER = Informers.pipeline("embedding", MODEL_NAME) def
embedding(text) embeddings_array = EMBEDDER.(text) Vector[*embeddings_array] end
Embedding computation MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2" EMBEDDER = Informers.pipeline("embedding", MODEL_NAME) def
embedding(text) embeddings_array = EMBEDDER.(text) Vector[*embeddings_array] end
Embeddings for diagnoses diagnoses_with_embeddings = Diagnosis.all.map do |diagnosis| text =
"#{diagnosis.name} (e.g., #{diagnosis.examples})" embedding = embedding(text) { diagnosis: diagnosis, embedding: embedding } end
Query embedding QUERY_PREFIX = "Represent this sentence for searching relevant
passages: " query_embedding = embedding(QUERY_PREFIX + query)
Search with embeddings and fuzzy text search LIMIT = 3
diagnoses_with_embeddings.filter_map do |d| semantic = cosine_similarity(query_embedding, d[:embedding]) fuzzy = fuzzy_score(query, d) semantic_relevant = semantic >= MIN_SEMANTIC_SCORE fuzzy_relevant = fuzzy >= MIN_FUZZY_SCORE next unless semantic_relevant || fuzzy_relevant [d[:diagnosis], [semantic, fuzzy].max] end.sort_by { |_, score| -score }.first(LIMIT).map(&:first)
Search with embeddings and fuzzy text search LIMIT = 3
diagnoses_with_embeddings.filter_map do |d| semantic = cosine_similarity(query_embedding, d[:embedding]) fuzzy = fuzzy_score(query, d) semantic_relevant = semantic >= MIN_SEMANTIC_SCORE fuzzy_relevant = fuzzy >= MIN_FUZZY_SCORE next unless semantic_relevant || fuzzy_relevant [d[:diagnosis], [semantic, fuzzy].max] end.sort_by { |_, score| -score }.first(LIMIT).map(&:first)
Search with embeddings and fuzzy text search LIMIT = 3
diagnoses_with_embeddings.filter_map do |d| semantic = cosine_similarity(query_embedding, d[:embedding]) fuzzy = fuzzy_score(query, d) semantic_relevant = semantic >= MIN_SEMANTIC_SCORE fuzzy_relevant = fuzzy >= MIN_FUZZY_SCORE next unless semantic_relevant || fuzzy_relevant [d[:diagnosis], [semantic, fuzzy].max] end.sort_by { |_, score| -score }.first(LIMIT).map(&:first)
None
None
What I hope you take away
#1: Your coffee ritual is (probably) weak β
#2: End-to-end ASAP π
#3: Simple software is great π¨π§
#4: Open-weight models are awesome β¨
#5: You can just do things πͺ
α αα°αααα acw.sh/act