sse_lib
Thin Python client for the Semantic Search Engine (SSE) REST API
(src/sse_api/ in this repository).
sse_lib is a client-side layer only: it maps Python calls onto the HTTP
endpoints of a running SSE backend and turns the JSON answers into small
dataclasses. It does not import Django, torch, pymilvus or any other
server dependency — the single runtime requirement is requests.
from sse_lib import SSEClient, SearchOptions, GenerativeOptions
client = SSEClient("http://localhost:8271", token="...")
client.create_collection(
"my_docs",
"My Documents",
"Test collection",
embedder="radlab/polish-bi-encoder-mean",
reranker="radlab/polish-cross-encoder",
index_type="HNSW",
chunking={"max_tokens_in_chunk": 128, "number_of_overlap_tokens": 0},
)
client.upload_files("my_docs", ["invoice.pdf", "regulations.zip"])
client.index_documents("my_docs", ["Some text to index."], category="Notes")
found = client.search("my_docs", "policy on data retention",
SearchOptions(max_results=20, rerank_results=True))
answer = client.generate_answer(
found.query_response_id,
GenerativeOptions(
generative_model="radlab/pLLama-3-8B-DPO-L",
percentage_rank_mass=40,
),
)
print(answer.answer)
Chunking belongs to the collection, not to a single call: declare it with
create_collection(..., chunking={...}) (or strict_chunking=True to forbid any
deviation) and the indexing calls above may leave both keys out — the server takes
the settings of the collection. client.embedders_info() returns
max_model_length of every embedder, the largest chunk its model can take in
(client.rerankers_info() the pair budget of the rerankers). Passing
max_tokens_in_chunk / number_of_overlap_tokens per call, or once per client
with SSEClient(..., default_indexing_options={...}), still works; a split which
cannot exist (overlap >= chunk) raises SSEValueError before the request goes
out. percentage_rank_mass of generate_answer is required by the backend and
has no library-wide default on purpose.
Installation
From a checkout:
pip install ./sse_lib # or: pip install -e ./sse_lib (development)
Once published to a registry, pip install sse-lib is all that is needed — the
package is standalone and versioned independently (sse_lib.__version__).
Python 3.9+, requests as the only runtime dependency.
Authentication
| Mode | How |
|---|---|
| Pre-existing token (default DRF token auth) | SSEClient(host, token="...") — sent as Authorization: Token <value> |
| Login with user and password | SSEClient(host, username="user", password="...") — POST login runs lazily, before the first request |
Keycloak / OAuth (backend started with ENV_USE_KC_AUTH=1) |
client.login_url() → redirect the user → client.login_with_code(code, state); later client.refresh_access_token() and client.logout() |
| Custom scheme | SSEClient(host, token="...", token_type="Bearer") |
Configuration
| Constructor argument | Environment variable | Default | Meaning |
|---|---|---|---|
api_host |
SSE_API_HOST |
– | http://localhost:8271; the scheme may be omitted (localhost → http, anything else → https) |
api_prefix |
SSE_API_PREFIX |
api |
Path between the host and the endpoints; set api/v1 for versioned deployments (main.api in django-config.json) |
token |
SSE_API_TOKEN |
– | Value of the Authorization header |
language |
SSE_API_LANGUAGE |
pl |
Sent as lang on every call (pl / en) |
timeout |
SSE_API_TIMEOUT |
60.0 |
Per-request timeout in seconds |
verify, session, headers, max_retries |
– | True, new session, {}, 2 |
TLS verification, shared requests.Session, extra headers, GET retries |
default_search_options, default_indexing_options |
– | – | Client-wide option defaults merged into every search / indexing call |
SSEClient is a context manager; leaving the block closes the HTTP session.
API coverage
| Client method | REST endpoint |
|---|---|
create_collection(...) |
POST new_collection |
list_collections(), get_collection(name), collection_exists(name) |
GET collections |
list_categories(collection) |
GET categories |
list_documents(collection, with_disabled=False), list_document_details(collection) |
GET documents |
upload_files(collection, files, ...) |
POST upload_and_index_files |
document_content(collection, document, from_page=None, max_pages=None, chunk_type=None) |
GET document_content |
index_documents(collection, documents, ...) |
POST add_and_index_texts |
indexing_status(collection=None, job_id=None) |
GET indexing_status |
delete_texts(collection, chunk_ids) |
POST delete_texts |
delete_documents(collection, documents=None, document_ids=None) |
POST delete_documents |
delete_collection(collection) |
POST delete_collection |
set_documents_use_in_search(collection, documents=None, document_ids=None, use_in_search=False), deactivate_documents(...), activate_documents(...) |
POST set_documents_use_in_search |
list_question_templates() |
GET question_templates |
list_filter_options() |
GET filter_options |
search(collection, query, options, ...) |
POST search_with_options |
generate_answer(query_response_id, options, ...) |
POST generative_answer |
rate_answer(answer_response_id, value, value_max, comment=None) |
POST rate_generative_answer |
list_search_history(collection=None, query_response_id=None), get_search_history(query_response_id), delete_search_history(query_ids=None, query_response_ids=None) |
GET search_history, GET get_search_history, POST delete_search_history |
list_generative_models(), list_embedders(), list_rerankers() |
GET generative_models, GET embedders, GET rerankers |
embedders_info(), rerankers_info() |
GET embedders, GET rerankers — models_info with vector_size, device and max_model_length |
new_chat(...), send_chat_message(...), save_chat(...), get_chat_by_hash(...), list_chats() |
POST new_chat, POST add_user_message, POST save_chat, GET get_chat_by_hash, GET chats |
login(), login_with_code(), refresh_access_token(), logout(), login_url() |
POST login, POST refresh_token, POST logout, POST login_url |
health(), is_healthy() |
GET healthz (public — no token, no login) |
request(method, endpoint, ...), get(...), post(...) |
any endpoint, including ones this release does not wrap |
Collections may be passed as a name, a Collection returned by
create_collection() / list_collections(), or any mapping with a name key.
A Collection also carries the settings of the collection: metadata_json,
chunking ({} when none was declared) and strict_chunking.
GET documents has two views. The default one lists the names of the
documents which take part in the search (list_documents()); with
with_disabled=True — and always in list_document_details() — the server
adds the deactivated documents together with their id and use_in_search
flag. Those identifiers are what document_ids[] of delete_documents and
set_documents_use_in_search expects.
send_chat_message(..., collection="my_docs") requires an explicit collection,
even if the chat was created with one: the current server resolves the collection
from each message request. Omitting it raises SSEValueError before sending.
Set api_prefix="" for deployments without an API path prefix; an explicitly
provided empty prefix overrides SSE_API_PREFIX.
Options objects
| Class | Used by | Notes |
|---|---|---|
SearchOptions |
search() |
Only the fields that are set are sent; extra merges unknown keys |
IndexingOptions |
upload_files(), index_documents() |
Serialises the five cleaning keys the server reads with options["..."]; the two chunk keys appear only when set, so the collection decides |
GenerativeOptions |
generate_answer(), send_chat_message() |
None fields are dropped; carries use_doc_names_in_response, the flag the generator reads from the same query_options |
ChatOptions |
new_chat(), send_chat_message() (chat_options=) |
The four pipeline switches (use_rag_supervisor, use_content_supervisor, use_intelligent_query_rewrite, query_instruction) merged into the single options object the chat endpoints read |
Single options may also be passed as keyword arguments — the two calls below are equivalent:
client.search("my_docs", "query", SearchOptions(max_results=20, hybrid_search=True))
client.search("my_docs", "query", max_results=20, hybrid_search=True)
Unknown keys in search and generation dictionaries are preserved in extra;
unknown indexing keys raise SSEValueError. Per-call dictionaries override only
the supplied client defaults, while IndexingOptions instances supply a complete
configuration (including their dataclass defaults). Keyword arguments win over
both.
Wire-format quirks handled by the client
The backend is not uniform, and these traps are the reason the wrapper exists:
optionsofsearch_with_options,query_optionsofgenerative_answerandindexing_optionsofupload_and_index_filesare read withjson.loads(), so they are sent as JSON strings;indexing_optionsofadd_and_index_textsandoptions/search_optionsof the chat endpoints are read as objects, so they are sent as JSON objects;- uploaded files use the field name
files[]and input textstexts[]; - endpoint paths have no trailing slash (that is how Django registers them);
- business errors come back as HTTP 200 with
{"status": false, "errors": [...]}.
Return values
Methods return dataclasses (sse_lib.models): Collection, SearchResponse
(with .hits of SearchHit), Answer, UploadResult, IndexingResult,
DocumentRef, Chat, ChatReply, ChatMessage, ChatHistory. Every one of them keeps the
untouched server payload in .raw, and
client.request("GET", "some_endpoint") returns the unwrapped body of any
endpoint for fields that are not modelled yet.
Errors
| Exception | Raised when |
|---|---|
SSEValueError |
An argument is rejected before the request is sent (empty query, unknown index type, ...) |
SSEConfigError |
Invalid configuration (missing host, non-positive timeout, login without credentials) |
SSEAPIError |
The API answered {"status": false, "errors": [...]} — inspect .error_names, .not_given_params |
SSEAuthenticationError |
HTTP 401/403 |
SSEHTTPError |
Any other non-2xx status |
SSETransportError |
No response at all (DNS, connection refused, timeout) |
All of them derive from SSEError, so a single except SSEError is enough for
a coarse handler. Idempotent GET calls are retried on connection errors and
on 429/502/503/504; POST is never replayed, because indexing twice is a real
side effect.
Development
cd sse_lib
PYTHONPATH=src python -m unittest discover -s tests -v # no installation needed
python -m pytest . # pytest, if available
black --check . && flake8 .
The tests never open a socket: tests/support.py replaces the HTTP session
with a recording double, which pins the exact payloads sent to the API.
Metadata
Release files for sse-lib 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| sse_lib-0.1.0.tar.gz | 55.0 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sse_lib-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 89.9 kB
Release files / sse_lib-0.1.0.tar.gz
| Download URL | sse_lib-0.1.0.tar.gz |
|---|---|
| Size | 55.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c31b9734cd4af90249311dde8ec5f3a070cf109a170a43e595b39b264c1c88d
|
|
BLAKE2b-256 checksum How to use checksums |
6f62d6aa540d0968944e802879e9a08a8520471e831bc569412e9f52460ac1b1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / sse_lib-0.1.0-py3-none-any.whl
| Download URL | sse_lib-0.1.0-py3-none-any.whl |
|---|---|
| Size | 34.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d112e507db8f7f4f59bfed5680ce923a2189258b6773b6e700e821b32ae42c4f
|
|
BLAKE2b-256 checksum How to use checksums |
3a0e2e6682d69be5300006d9e7347438a4a322b71d92eb7d1f11da2e218e337f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Security for sse-lib 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.