A lightweight local document ingestion and retrieval package.
Project description
searchbox
searchbox is a lightweight Python package for local document ingestion and retrieval.
It does one thing:
- read local files or folders
- extract text from supported document types
- split long text into chunks
- store the chunks in SQLite
- retrieve the most relevant documents for a query
Install
Install from the current project directory:
pip install .
If you later publish it to PyPI under the same package name:
pip install searchbox
What It Supports
Supported file types:
.txt,.md,.rst.py,.toml,.yaml,.yml.csv,.tsv.json.html,.htm.pdf
Storage backend:
- SQLite database file on local disk
Retrieval behavior:
- documents are stored as chunks internally
- search is performed on chunks
- results are returned as document-level hits
- each result includes the best matching chunk text and matched chunk indexes
Quick Start
from searchbox import docsearch
engine = docsearch(db_path="docs.db", chunk_size=240, chunk_overlap=40)
engine.add_path("docs")
results = engine.search("how does indexing work", top_k=3)
for item in results:
print(item["id"], item["score"], item["metadata"]["matched_chunks"])
Main API
Create a search engine:
from searchbox import docsearch
engine = docsearch(
db_path="docs.db",
chunk_size=240,
chunk_overlap=40,
)
Available methods:
docsearch(db_path="searchbox.db", chunk_size=240, chunk_overlap=40)add_path(path, recursive=True, include_hidden=False, chunk_size=None, chunk_overlap=None)add_paths(paths, recursive=True, include_hidden=False, chunk_size=None, chunk_overlap=None)search(query, top_k=5)search_pretty(query, top_k=5, snippet_length=280)response(query, top_k=5)count()clear()supported_extensions()
Constructor Parameters
docsearch(...)
engine = docsearch(
db_path="searchbox.db",
chunk_size=240,
chunk_overlap=40,
)
Parameters:
db_path: SQLite database path; default issearchbox.dbchunk_size: number of words per chunk; default is240chunk_overlap: overlapping words between neighboring chunks; default is40
Notes:
chunk_sizemust be greater than0chunk_overlapmust be greater than or equal to0chunk_overlapmust be smaller thanchunk_size
Ingestion Methods
add_path(path, recursive=True, include_hidden=False, chunk_size=None, chunk_overlap=None)
Index one file or one directory.
If path is:
- a file: only that file is indexed
- a directory: files inside the directory are indexed
Returns:
- a list of inserted chunk ids
Parameters:
path: file path or directory pathrecursive: whenpathis a directory, whether to scan subdirectories; defaultTrueinclude_hidden: whether to include hidden files and hidden directories; defaultFalsechunk_size: optional per-call override of constructorchunk_sizechunk_overlap: optional per-call override of constructorchunk_overlap
Example:
engine.add_path("docs")
engine.add_path("README.md")
engine.add_path("docs", recursive=False)
add_paths(paths, recursive=True, include_hidden=False, chunk_size=None, chunk_overlap=None)
Index multiple files or directories in one call.
Parameters:
paths: a sequence of file or directory paths- all other parameters behave the same as
add_path(...)
Example:
engine.add_paths(
[
"docs",
"notes/project.md",
"data/reference",
]
)
Search Methods
search(query, top_k=5)
Search the indexed documents and return the most relevant document hits.
Parameters:
query: search texttop_k: maximum number of returned documents; default5
Returns:
- a list of result dictionaries sorted by descending relevance
response(query, top_k=5)
Alias of search(query, top_k=5).
Use whichever name you prefer.
search_pretty(query, top_k=5, snippet_length=280)
Search the indexed documents and return a more display-friendly result shape.
Parameters:
query: search texttop_k: maximum number of returned documents; default5snippet_length: max snippet length in characters; default280
Returns:
- a list of simplified dictionaries with
path,file_name,score,matched_chunk_count,matched_chunks,best_chunk_index, andsnippet
Examples
Index a single file
from searchbox import docsearch
engine = docsearch(db_path="single.db")
engine.add_path("guide.txt")
results = engine.search("installation guide", top_k=1)
print(results)
Index a directory
from searchbox import docsearch
engine = docsearch(db_path="docs.db")
engine.add_path("docs")
results = engine.search("local retrieval", top_k=3)
for item in results:
print(item["id"], item["title"], item["score"])
Index multiple locations
from searchbox import docsearch
engine = docsearch(db_path="multi.db")
engine.add_paths(["docs", "notes", "README.md"])
results = engine.search("api design", top_k=5)
for item in results:
print(item["metadata"]["source_path"])
Override chunk settings for one ingestion call
from searchbox import docsearch
engine = docsearch(db_path="docs.db", chunk_size=240, chunk_overlap=40)
engine.add_path(
"manuals",
chunk_size=120,
chunk_overlap=20,
)
Show supported file types
from searchbox import docsearch
engine = docsearch()
print(engine.supported_extensions())
Get display-friendly search output
from searchbox import docsearch
engine = docsearch(db_path="docs.db")
engine.add_path("papers")
results = engine.search_pretty("vllm", top_k=3)
for item in results:
print(item["path"])
print(item["score"])
print(item["matched_chunk_count"])
print(item["snippet"])
print("---")
Search Result Format
Each search result is a document-level hit.
Example:
[
{
"id": "guide.pdf",
"title": "guide.pdf",
"content": "best matching chunk text ...",
"score": 0.82,
"metadata": {
"source_path": "guide.pdf",
"source_name": "guide.pdf",
"chunk_count": 4,
"matched_chunks": [0, 1],
"best_chunk_index": 1,
},
}
]
Field meaning:
id: document identifier; currently the source file path string used by the result layertitle: display title derived from the file namecontent: the best matching chunk text for that documentscore: relevance scoremetadata["source_path"]: file path stored for the source documentmetadata["source_name"]: file name onlymetadata["chunk_count"]: total number of stored chunks for the filemetadata["matched_chunks"]: chunk indexes that matched the querymetadata["best_chunk_index"]: chunk index whose text is returned incontent
How Ingestion Works
When you call add_path(...) or add_paths(...):
searchboxreads each supported file- extracted text is normalized
- long text is split into overlapping word chunks
- every chunk is stored in the SQLite database
- later,
search(...)ranks chunks and merges them back into document-level results
This means:
- large files can still be searched effectively
- results are returned as documents, not raw chunks
contentin the result is the best matching chunk, not always the full original file
PDF Notes
PDF ingestion is supported.
Current behavior:
searchboxfirst tries the system commandpdftotext- if that fails, it uses a lightweight fallback extractor
Recommendation:
- if you care about PDF extraction quality, make sure
pdftotextis installed on the machine
Utility Methods
count()
Return the number of stored chunk rows in the SQLite database.
Example:
count = engine.count()
print(count)
clear()
Delete all stored chunk rows from the database.
Example:
engine.clear()
supported_extensions()
Return the currently supported file extensions.
Example:
print(engine.supported_extensions())
Behavior and Edge Cases
- unsupported file types are skipped
- empty or unreadable extracted content is skipped
- hidden files are skipped by default when scanning directories
- if a given path does not exist,
FileNotFoundErroris raised - if
queryis empty or blank,ValueErroris raised - if no document matches,
search(...)returns an empty list
Minimal End-to-End Example
from searchbox import docsearch
engine = docsearch(db_path="example.db")
engine.add_paths(
[
"docs",
"README.md",
"notes/plan.json",
]
)
results = engine.search("sqlite document retrieval", top_k=3)
for item in results:
print("path:", item["metadata"]["source_path"])
print("score:", item["score"])
print("best chunk:", item["content"])
print("matched chunks:", item["metadata"]["matched_chunks"])
print("---")
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file searchbox-0.2.0.tar.gz.
File metadata
- Download URL: searchbox-0.2.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0fe36450dc964324f8fba938537157f3197d365d29e165e0e68c11af3837ee8c
|
|
| MD5 |
4c67aecf9960cbf4b82a73bb185edd3e
|
|
| BLAKE2b-256 |
ac5a5342f3ffba65cd78c358c6b1a9f535ade2b070588169c8983d485beaf061
|
File details
Details for the file searchbox-0.2.0-py3-none-any.whl.
File metadata
- Download URL: searchbox-0.2.0-py3-none-any.whl
- Upload date:
- Size: 10.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e3935172f2cc6c33753c34ad91d8fa1d717f3c9959fd9dccc8ea5bf537d39016
|
|
| MD5 |
8fda527d10fe7c3eef893000684fd792
|
|
| BLAKE2b-256 |
dba5ec4db42e619091c6af2690f28da6de57f56e5bed8dc769c1b1813d8c56af
|