Skip to content

Python SDK

Embed llm-context-search directly in your agents, RAG pipelines or tools.


Basic usage

import asyncio
import httpx
from llm_context_search import ContextSearchEngine
from llm_context_search.providers import SearXNGProvider

async def main():
    async with httpx.AsyncClient() as client:
        engine = ContextSearchEngine(
            provider=SearXNGProvider(
                base_url="http://localhost:8888",
                http_client=client,
            )
        )

        bundle = await engine.build_context(
            "Python asyncio best practices",
            language="en",
            max_results=10,
            max_sources=5,
            max_passages=12,
            budget_tokens=4000,
        )

        print(bundle.context_text)
        print(f"~{bundle.token_estimate} tokens in {bundle.stats.elapsed_ms} ms")

asyncio.run(main())

Engine methods

engine.build_context(query, ...)ContextBundle

Full pipeline: search → fetch → extract → rank → pack.

bundle = await engine.build_context(
    "query",
    language="en",        # default: "en"
    max_results=10,       # default from config
    max_sources=5,        # default from config
    max_passages=12,      # default from config
    budget_tokens=4000,   # default from config
)

bundle.context_text      # str - Markdown passages ready for LLM
bundle.token_estimate    # int - approximate token count
bundle.sources           # list[SourceDocument]
bundle.passages          # list[Passage] - all ranked passages
bundle.selected_passages # list[Passage] - passages included in context
bundle.stats             # RetrievalStats

engine.collect_sources(query, ...)SourceCollection

Search, fetch and extract - without chunking or ranking.

collection = await engine.collect_sources("query", max_sources=5)

collection.sources   # list[SourceDocument]
collection.stats     # RetrievalStats

for source in collection.sources:
    print(source.url, source.fetch_status, source.extracted_chars)

engine.search(query, ...)list[SearchResult]

Search only - no page fetching.

results = await engine.search("query", language="en", max_results=10)

for r in results:
    print(r.rank, r.title, r.url, r.snippet)

Context manager

The engine owns an internal httpx.AsyncClient unless you pass one. Use it as an async context manager to ensure cleanup:

async with ContextSearchEngine(provider=provider) as engine:
    bundle = await engine.build_context("query")

Configuration

Pass a ContextSearchConfig to tune every aspect of the pipeline:

from llm_context_search import ContextSearchEngine, ContextSearchConfig
from llm_context_search.providers import SearXNGProvider

config = ContextSearchConfig(
    max_results=15,
    max_sources=8,
    max_passages=20,
    budget_tokens=8000,
    fetch_timeout_seconds=15.0,
    chunk_target_chars=1000,
    search_cache_ttl_seconds=600,
)

engine = ContextSearchEngine(provider=provider, config=config)

See the Configuration reference for all options.


Replacing pipeline components

Every stage is a Protocol. Pass your own implementations to override defaults:

from llm_context_search.providers.base import SearchProvider
from llm_context_search.rank.base import PassageRanker
from llm_context_search.models import SearchResult, Passage, SourceDocument

class MyProvider:
    name = "my-api"

    async def search(
        self, query: str, *, language: str = "en", max_results: int = 10
    ) -> list[SearchResult]:
        # call your own search API
        ...

class MyRanker:
    def rank(
        self, query: str, passages: list[Passage], sources: dict[str, SourceDocument]
    ) -> list[Passage]:
        # BM25, embeddings, reranker, etc.
        ...

engine = ContextSearchEngine(
    provider=MyProvider(),
    ranker=MyRanker(),
)

Available protocols:

Protocol Default implementation Role
SearchProvider SearXNGProvider Fetches search results
PageFetcherProtocol PageFetcher Downloads HTML pages
ContentExtractor TrafilaturaExtractor Extracts main text
PassageChunker ParagraphChunker Splits text into passages
PassageRanker LexicalRanker Ranks passages by relevance
SourceScorer SourceQualityScorer Scores source quality
ContextPacker MarkdownPacker Packs passages to token budget

Data models

from llm_context_search.models import (
    SearchResult,      # title, url, snippet, rank
    SourceDocument,    # url, fetch_status, extraction_status, extracted_text, quality_score
    Passage,           # text, source_url, lexical_score, final_score
    ContextBundle,     # context_text, token_estimate, sources, passages, stats
    SourceCollection,  # sources, stats
    RetrievalStats,    # counts + elapsed_ms
)