Skip to content

Using the SQLite Store

SQLiteVectorStore persists documents and vectors in a local SQLite database file. It uses exact cosine similarity, which is appropriate for local small-to-medium indexes.

Create an index

from pyaistack import RAG
from pyaistack.chunking import TextChunker
from pyaistack.loaders import DirectoryLoader
from pyaistack.vectorstores import SQLiteVectorStore

documents = DirectoryLoader("/path/to/knowledge/", file_type="text").load()

rag = RAG(
    vector_store=SQLiteVectorStore("knowledge.db"),
    chunker=TextChunker(),
)
rag.add_documents(documents)

Reuse an index ask()

Create a new RAG instance with the same database path and embedding model. Do not add the documents again.

from pyaistack import RAG
from pyaistack.vectorstores import SQLiteVectorStore

rag = RAG(
    embedding_model="embeddinggemma",
    llm_model="gemma3:4b",
    vector_store=SQLiteVectorStore("knowledge.db"),
)

answer = rag.ask("What information is available?")
print(answer.text)

Use search() when you need the matching chunks, their metadata, and similarity scores without calling the LLM. This is useful for inspecting retrieval results or building a custom response flow.

results = rag.search("What information is available?", top_k=3)

for result in results:
    print(result.score)
    print(result.document.metadata)
    print(result.document.text)

Use ask() when you want PyAIStack to retrieve the chunks and generate a grounded natural-language answer. Use search() when you only need retrieval.

Aspect rag.search() rag.ask()
Purpose Retrieves relevant chunks only Retrieves chunks and generates an LLM answer
Calls embedding model Yes Yes
Calls chat/LLM model No Yes
Return value tuple[SearchResult, ...] RAGAnswer
Includes score Yes, per result Available in answer.sources
Includes metadata Yes, per result Available in answer.sources
Has .text answer No Yes, via answer.text
Best for Debugging retrieval, custom UI, source inspection Normal user-facing question answering
Example results = rag.search("budget planning") answer = rag.ask("How should I plan a budget?")

Filter by metadata

Pass metadata_filter to either search() or ask() to limit retrieval to documents with matching metadata. Every supplied key/value must match. A scalar filter matches a scalar value exactly or one value in stored list metadata; a list filter requires every requested value to be present. Filtering happens before cosine scoring.

finance_results = rag.search(
    "How should a monthly budget be reviewed?",
    metadata_filter={"category": "finance"},
)

answer = rag.ask(
    "How should a monthly budget be reviewed?",
    metadata_filter={"category": "finance", "audience": "general"},
)
print(answer.text)

Add metadata while indexing

Metadata filters can only match fields stored during indexing. Add them with LoadedDocument(metadata={"category": "finance"}) or rag.add(..., metadatas=[...]).

No metadata indexed

if no Metadata available or indexed then result will not found even if it is present.

The store binds itself to the first embedding model and vector dimension. To use a different embedding model, clear and rebuild the index:

rag.clear()

For hundreds of thousands of chunks or more, use a dedicated indexed vector database in a future PyAIStack adapter.