Skip to main content

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:

  • options of search_with_options, query_options of generative_answer and indexing_options of upload_and_index_files are read with json.loads(), so they are sent as JSON strings;
  • indexing_options of add_and_index_texts and options/search_options of the chat endpoints are read as objects, so they are sent as JSON objects;
  • uploaded files use the field name files[] and input texts texts[];
  • 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)

Source distribution for sse-lib 0.1.0
File Size Uploaded Provenance
sse_lib-0.1.0.tar.gz 55.0 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for sse-lib 0.1.0
File Interpreter ABI Platform
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page