Skip to main content
Version: 0.11

Python: Embeddings & Search

A complete walkthrough of embeddings, vector search, and hybrid search in Python. For the concepts behind each step — model dimensions, the bring-your-own-vector model, hybrid scoring — see the guide pages on Embedding Models, Vector Search, and Hybrid & Lexical Search.

All KV-store calls take/return JSON strings.

Embed text

import atelico, json
engine = atelico.Engine()

MODEL = "in-memory::sentence-transformers/all-MiniLM-L6-v2"

resp = json.loads(engine.embed(json.dumps({
"model": MODEL,
"input": ["The guard saw a thief enter the keep at midnight."],
})))
vector = resp["data"][0]["embedding"] # 384-dim list[float]

# Or a direct cosine similarity between two strings:
sim = engine.embed_similarity(MODEL, "a knight's blade", "a warrior's sword")

Create a store, insert, query

embed_dim must match the model — 384 for MiniLM/bge-small, 768 for bge-base.

# 1. Create (persisted under db_path)
engine.kvstore_create(json.dumps({
"store_id": "npc-memory",
"db_path": "./data/npc-memory",
"embed_dim": 384,
}))

# 2. Insert — key_embedding is the vector you produced above
engine.kvstore_insert("npc-memory", json.dumps([{
"id": "mem-001",
"key_text": "The guard saw a thief enter the keep at midnight.",
"key_embedding": vector,
"facets": {"npc_id": "guard-01", "location": "keep"},
"priority": 0.8,
}]))

# 3. Query — embed the question, then search
q = json.loads(engine.embed(json.dumps({"model": MODEL, "input": ["who broke in?"]})))
results = json.loads(engine.kvstore_query("npc-memory", json.dumps({
"query_embedding": q["data"][0]["embedding"],
"query_text": "who broke in?",
"facet_filters": {"npc_id": "guard-01"},
"limit": 5,
})))
for r in results:
print(r["key_text"], r["similarity"], r["combined_score"])

print("entries:", engine.kvstore_count("npc-memory", ""))

Add a BM25 full-text index once, then blend keyword and vector scores:

engine.kvstore_create_fts_index("npc-memory", "key_text")

response = json.loads(engine.kvstore_hybrid_query("npc-memory", json.dumps({
"embeddings": q["data"][0]["embedding"],
"text": "thief keep",
"fts_column": "key_text",
"limit": 5,
"vector_weight": 0.6,
"lexical_weight": 0.4,
})))
for row, trace in zip(response["results"], response["scores"]):
print(row["key_text"], trace["merged_score"])

See Hybrid & Lexical Search for the scoring details and the lexical-only (kvstore_lexical_query) variant.