Recipes
Copy-paste tasks that combine the browse and search layers. Each is self-contained;
swap in your own ids and queries. They assume curl, jq, and Python 3 with
sentence-transformers for the search examples.
BASE=https://lmmol.com
SEARCH=https://rtxz9xxyz7.execute-api.us-east-1.amazonaws.com/search
1. Look up one entity
curl -s $BASE/nodes/protein/P38398.json | jq '{id, name, synonyms}'
2. Everything connected to a disease
# Proteins and trials for hereditary breast carcinoma
curl -s $BASE/index/disease/MONDO_0016419.json \
| jq '{proteins: (.proteins|length), trials: (.trials|length)}'
3. Disease → proteins → read each one
BASE=https://lmmol.com
for id in $(curl -s $BASE/index/disease/MONDO_0016419.json | jq -r '.proteins[].id'); do
curl -s $BASE/nodes/protein/$id.json | jq -r '"\(.id)\t\(.name)"'
done
4. Clinical (ClinVar) associations for a gene
curl -s $BASE/index/clinvar/gene/BRCA1.json \
| jq -r '.diseases[] | "\(.significance)\t\(.id)\t\(.name)"'
5. Enumerate an entire type
# Walk every shard of the disease listing, printing id and name
BASE=https://lmmol.com
root=$(curl -s $BASE/index/list/disease/root.json)
shards=$(echo "$root" | jq -r '.shards | length') # or derive from count
for n in $(seq 0 $((shards - 1))); do
curl -s $BASE/index/list/disease/$n.json | jq -r '.[] | "\(.id)\t\(.name)"'
done
Be polite when crawling at scale: the files are CDN-cached, so cache locally and avoid re-fetching what you already have. Re-fetch
index.jsonto learn when counts have changed.
6. Semantic search, end to end (Python)
import requests
from sentence_transformers import SentenceTransformer
SEARCH = "https://rtxz9xxyz7.execute-api.us-east-1.amazonaws.com/search"
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
def search(text, indexes=("proteins", "trials"), top_k=10, filters=None):
qv = model.encode(text, normalize_embeddings=True).tolist()
body = {"queryVector": qv, "topK": top_k, "indexes": list(indexes)}
if filters:
body["filters"] = filters
r = requests.post(SEARCH, json=body, timeout=30)
r.raise_for_status()
return r.json()["results"] # sorted by distance, ascending
for hit in search("BRCA1 DNA repair and breast cancer risk"):
print(f'{hit["distance"]:.3f} {hit["type"]:8} {hit["id"]}')
7. Filtered search: recruiting Phase 3 trials
results = search(
"immunotherapy for advanced melanoma",
indexes=("trials",),
filters={"trials": {"phase": "Phase 3", "overall_status": "Recruiting"}},
)
8. Search to discover, browse to complete
The robust pattern: one search for entry points, then deterministic browsing to pull every connected fact without loss.
import requests
BASE = "https://lmmol.com"
# 1. Discover candidate proteins by concept
hits = search("tumor suppressor involved in homologous recombination",
indexes=("proteins",), top_k=5)
# 2. For each, browse its gene's clinical associations — exact, no ranking
for h in hits:
node = requests.get(f'{BASE}/nodes/protein/{h["id"]}.json').json()
for syn in node.get("synonyms", []):
cv = requests.get(f'{BASE}/index/clinvar/gene/{syn}.json')
if cv.ok:
for d in cv.json().get("diseases", []):
print(node["id"], syn, d["significance"], d["name"])
break
9. For an LLM agent: bootstrap from llms.txt
curl -s https://lmmol.com/llms.txt
Read it once, then navigate index.json → index/list/<type> → nodes/<type>/<id> →
backlink indexes with no further instructions. The walk is deterministic, so the agent
never has to guess whether a relevant record was left out of a similarity window — see
Browsing the Index.