Home / Blog / Guide

Installing and Using sim_LAR: A Practical Guide

sim_LAR is TekDatum's search library for Python — keyword search, semantic search, and hybrid search behind one simple API. Here's how to install it and start searching in minutes.

sim_LAR finds documents that are similar to a query — by keyword, by meaning, or by both at once — and returns a single ranked list no matter which signals you use. You supply the documents (and, for semantic search, embedding vectors from whatever model you already use); sim_LAR handles the indexing, scoring, and ranking.

This guide covers what you need to install and how to run semantic and hybrid search with a few lines of code.

01Installation

sim_LAR ships as two packages: simlar, the SDK with the public API, index classes, and framework integrations, and simlar-engine, which powers semantic vector search. Both are on public PyPI, and sim_LAR requires Python 3.11 or later.

pip install simlar
pip install simlar-engine

If you plan to use a specific framework integration, install the matching extra instead of the bare package:

pip install simlar[langchain]     # LangChain vector store
pip install simlar[haystack]      # Haystack integration
pip install simlar[llama_index]   # LlamaIndex integration

02Semantic Search

SimlarEngine finds documents that mean the same thing as your query, even if the wording is different. It runs on pre-computed embedding vectors, so you'll need simlar-engine installed and an embedding model of your choice. This example embeds 500 real questions from the BeIR/quora dataset with sentence-transformers' all-MiniLM-L6-v2 (a small, fast, 384-dimension model):

pip install datasets sentence-transformers
import numpy as np
from datasets import load_dataset
from sentence_transformers import SentenceTransformer
from simlar import SimlarEngine

ds     = load_dataset("BeIR/quora", "corpus", split="corpus[:500]")
corpus = ds["text"]
ids    = ds["_id"]

model   = SentenceTransformer("all-MiniLM-L6-v2")
vectors = model.encode(corpus, normalize_embeddings=True).astype(np.float32)  # (500, 384)
id_to_text = dict(zip(ids, corpus))

idx = SimlarEngine()
idx.add(ids=list(ids), vectors=vectors)
print(f"Indexed {idx.size} questions  |  embedding dim: {vectors.shape[1]}")

query_text = "What is the best programming language to learn first?"
query_vec  = model.encode([query_text], normalize_embeddings=True).astype(np.float32)  # (1, 384)

print(f"Query: '{query_text}'\n")
for r in idx.search(query_vec, k=5):
    print(f"  rank={r.rank}  score={r.score:.4f}  {id_to_text[r.id]}")

SimlarEngine also supports incremental updates — idx.update(ids=..., vectors=...) replaces an embedding in place, and idx.delete(ids=...) removes documents, both without rebuilding the index.

03Hybrid Search

For most real-world queries, you want both signals: exact-word precision and semantic depth. HelixIndex runs keyword and vector search in parallel and merges the two ranked lists into one, using a fusion strategy like ReciprocalRankFusion. Continuing with the same Quora corpus, ids, vectors, and model from the semantic search example above:

from simlar import HelixIndex, RelevanceIndex, SimlarEngine, ReciprocalRankFusion

index = HelixIndex(
    text_index= RelevanceIndex(),
    vector_index= SimlarEngine(),
    fusion=ReciprocalRankFusion(),
    top_k=5,
)
index.add(ids=list(ids), texts=list(corpus), vectors=vectors)
print(f"Index size: {index.size}")

query_text = "What is the best programming language to learn first?"
query_vec  = model.encode([query_text], normalize_embeddings=True).astype(np.float32)

# Pass query_text, query_vector, or both — HelixIndex fuses whatever signals it gets
print("Hybrid:")
for r in index.search(query_text=query_text, query_vector=query_vec, k=5):
    print(f"  rank={r.rank}  score={r.score:.4f}  {id_to_text[r.id][:80]}")

print("\nText only:")
for r in index.search(query_text=query_text, k=5):
    print(f"  rank={r.rank}  score={r.score:.4f}  {id_to_text[r.id][:80]}")

print("\nVector only:")
for r in index.search(query_vector=query_vec, k=5):
    print(f"  rank={r.rank}  score={r.score:.4f}  {id_to_text[r.id][:80]}")

If your corpus is too large to fit comfortably in memory, StreamingHybridIndex gives you the same hybrid approach but adds documents in batches, storing each batch as an independent shard that gets searched and merged at query time.

04Producing Embeddings

sim_LAR is model-agnostic: it accepts any (n, dim) float32 NumPy array, so you're not locked into all-MiniLM-L6-v2 from the examples above — swap in whichever embedding model or API already fits your stack (OpenAI, Cohere, a larger sentence-transformers model, your own fine-tuned model). The only requirement is that the same model produces both your corpus vectors and your query vectors, so they land in the same embedding space.

05Saving, Loading, and Extending

Every index type — keyword, semantic, or hybrid — shares the same save and load interface, and the loader detects the index type automatically. Continuing the hybrid example above:

import tempfile
from simlar import load_from_directory

with tempfile.TemporaryDirectory() as tmp:
    index.save(tmp)
    reloaded = load_from_directory(tmp)
    print(f"Reloaded index size: {reloaded.size}")

    # Confirm the reloaded index returns the same top result
    orig_top     = index.search(query_text=query_text, query_vector=query_vec, k=1)[0]
    reloaded_top = reloaded.search(query_text=query_text, query_vector=query_vec, k=1)[0]
    print(f"Top result matches original: {orig_top.id == reloaded_top.id}")

You can also register your own index implementation so it behaves like a built-in index, including full save/load support:

from simlar import VectorIndex, register

@register("my_index")
class MyIndex(VectorIndex):
    ...

06Choosing the Right Index

You have…You need…Use
Text onlyKeyword matchingRelevanceIndex
EmbeddingsSemantic similaritySimlarEngine
Text + embeddingsBoth signals, fits in memoryHelixIndex
Text + embeddings, massive scaleBoth signals, streamed in batchesStreamingHybridIndex

That's enough to go from pip install to a working search index — keyword, semantic, or hybrid. For architecture details and design rationale, see the Concepts guide; for the full public API surface, see the API Reference.

Building retrieval into your own product?

If you're evaluating sim_LAR for a production RAG pipeline or need help with framework integrations, we'd like to hear about your workload.

Talk to the TekDatum team