Skip to main content

Knowhere Python SDK

PyPI version

Official Python SDK for the Knowhere document parsing API.

Installation

pip install knowhere-python-sdk

Or with uv:

uv add knowhere-python-sdk

Usage

import knowhere

client = knowhere.Knowhere(api_key="sk_...")

result = client.parse(
    url="https://example.com/report.pdf",
)

print(result.statistics.total_chunks)
print(result.full_markdown[:200])

for chunk in result.text_chunks:
    print(chunk.content[:80])

for page in result.page_chunks:
    print(page.content_source)       # "summary"
    print(page.content[:120])        # page-level summary
    print(page.metadata.page_nums)   # [4, 5, 6]

Retrieval and document lifecycle

New documents are published into a retrieval namespace. The server returns a stable document_id on job create when it has a planned id, and on the completed job_result after publication.

job = client.jobs.create(
    source_type="url",
    source_url="https://example.com/manual.pdf",
    namespace="support-center",
    document_metadata={"title": "Support manual"},
)

document_id = job.document_id
job_result = client.jobs.wait(job.job_id)
document_id = document_id or job_result.document_id

if document_id is None:
    raise RuntimeError("Expected document_id after successful publication.")

After the job is done and published, query the canonical document content:

response = client.retrieval.query(
    namespace="support-center",
    query="How do I reset Bluetooth pairing?",
    chunk_types=["page"],
    top_k=5,
    channels=["path", "term"],
    filter_mode="keep",
    signal_paths=["Bluetooth", "Pairing"],
)

print(response.router_used)
print(response.answer_text)
print(response.evidence_text)
print(response.stop_reason)
print(response.failure_reason)

for reference in response.referenced_chunks:
    print(reference.chunk_id, reference.chunk_type, reference.content_source)
    print(reference.metadata, reference.asset_url)

for result in response.results:
    print(result.chunk_id, result.chunk_type, result.content_source)
    print(result.content)
    print(result.score)
    print(result.source.source_file_name, result.source.section_path)

Use document_id to update or archive a document:

update_job = client.jobs.create(
    source_type="url",
    source_url="https://example.com/manual-v2.pdf",
    document_id=document_id,
)

document = client.documents.get(document_id)
print(document.status)

chunks = client.documents.list_chunks(
    document_id,
    page=1,
    page_size=50,
    chunk_type="page",
    include_asset_urls=True,
)
print(chunks.pagination.total)
if chunks.chunks:
    chunk = client.documents.get_chunk(
        document_id,
        chunks.chunks[0].id,
        include_asset_urls=True,
    )
    print(chunk.chunk.content)
    print(chunk.chunk.metadata.get("page_nums"))  # Page citations.
    print(chunk.chunk.asset_url)  # Requested 7-day URL when available.
    page_assets = chunk.chunk.metadata.get("pageAssets") or []
    print(page_assets)

source = client.documents.get_page_citation_source(document_id)
print(source.url)

client.documents.archive(document_id)

You can also list documents in a namespace:

documents = client.documents.list(
    namespace="support-center",
    page=1,
    page_size=50,
)
for document in documents.documents:
    print(document.document_id, document.status)
print(documents.pagination.total_pages)

Retrieval supports exclusions when clients want follow-up results that avoid previously used documents or sections:

response = client.retrieval.query(
    namespace="support-center",
    query="battery charging",
    exclude_document_ids=["doc_old"],
    exclude_sections=[
        {"document_id": "doc_123", "section_path": "Appendix / Legal"}
    ],
)

While you can provide an api_key keyword argument, we recommend using python-dotenv to add KNOWHERE_API_KEY="sk_..." to your .env file so that your API key is not stored in source control.

Short-lived dashboard tokens can use auth_token_provider instead of a static key. If api_key is also set, the static key wins.

client = knowhere.Knowhere(auth_token_provider=lambda: current_access_token())

Parse a local file

from pathlib import Path

result = client.parse(
    file=Path("report.pdf"),
    parsing_params={"model": "advanced", "ocr_enabled": True},
)

print(result.manifest.source_file_name)  # "report.pdf"
print(len(result.chunks))                # 152
print(result.namespace)                  # "default" or your explicit namespace
print(result.document_id)                # Published canonical document id

Bring your own LLM keys (BYOK)

Pass OpenAI-compatible credentials for parsing or agentic retrieval.

Flat root applies to both channels (one multimodal model). Use models for different model ids on the same endpoint, or text / vision for different provider endpoints:

# Multimodal shorthand — one model for text + vision
llm_config = {
    "api_key": "sk-...",
    "model": "gpt-4o",
    "base_url": "https://api.openai.com/v1",
}

# Same endpoint, different models per channel
llm_config = {
    "api_key": "sk-...",
    "base_url": "https://api.openai.com/v1",
    "models": {"text": "gpt-4o-mini", "vision": "gpt-4o"},
}

# Or two different endpoints
llm_config = {
    "text": {
        "api_key": "sk-...",
        "model": "gpt-4o-mini",
        "base_url": "https://api.openai.com/v1",
    },
    "vision": {
        "api_key": "sk-ali-...",
        "model": "qwen-vl-max",
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
    },
}

result = client.parse(file=Path("report.pdf"), llm_config=llm_config)

response = client.retrieval.query(
    namespace="support-center",
    query="refund policy",
    use_agentic=True,
    llm_config=llm_config,
)

Access different chunk types

result = client.parse(url="https://example.com/report.pdf")

# Text chunks
for chunk in result.text_chunks:
    print(chunk.metadata.keywords)
    print(chunk.metadata.summary)

# Page chunks (v2 page-memory results)
for chunk in result.page_chunks:
    print(chunk.content_source)      # "summary"
    print(chunk.content[:120])
    print(chunk.metadata.page_nums)  # citation pages
    print(chunk.metadata.entities)

# Image chunks (raw bytes loaded from ZIP)
for chunk in result.image_chunks:
    print(chunk.file_path)
    print(len(chunk.data))       # bytes
    chunk.save("./output/")      # writes image to disk

# Table chunks (HTML loaded from ZIP)
for chunk in result.table_chunks:
    print(chunk.file_path)
    print(chunk.html[:100])

Save all results to disk

result = client.parse(file=Path("report.pdf"))
result.save("./output/report/")

Async usage

import asyncio
import knowhere

async def main():
    async with knowhere.AsyncKnowhere(api_key="sk_...") as client:
        result = await client.parse(url="https://example.com/report.pdf")
        print(result.statistics.total_chunks)

        for chunk in result.text_chunks:
            print(chunk.summary)

asyncio.run(main())

Step-by-step control

For granular control over the parsing workflow, use the jobs resource directly:

from pathlib import Path

# Step 1: Create a parsing job
job = client.jobs.create(
    source_type="file",
    file_name="report.pdf",
    namespace="support-center",
    parsing_params={"model": "advanced", "ocr_enabled": True},
)

# Step 2: Upload file to presigned URL
client.jobs.upload(job, file=Path("report.pdf"))

# Step 3: Poll until done (adaptive backoff)
job_result = client.jobs.wait(job.job_id, poll_interval=10.0, poll_timeout=1800.0)

print(job_result.document_id)  # Persist this to update/archive the document later.

# Step 4: Download and parse results
result = client.jobs.load(job_result)
print(result.statistics)

Handling errors

All errors inherit from knowhere.KnowhereError.

import knowhere

try:
    result = client.parse(url="https://example.com/report.pdf")
except knowhere.AuthenticationError:
    print("Invalid API key")
except knowhere.APIStatusError as e:
    print(f"{e.status_code}: {e.message}")

Configuration

The SDK reads configuration from constructor arguments, environment variables, or defaults (in that priority order):

Variable Description Default
KNOWHERE_API_KEY API key (required) —
KNOWHERE_BASE_URL API base URL https://api.knowhereto.ai
KNOWHERE_LOG_LEVEL Log level WARNING
# Uses environment variables automatically
client = knowhere.Knowhere()

# Or configure explicitly
client = knowhere.Knowhere(
    api_key="sk_...",
    base_url="https://api.knowhereto.ai",
    timeout=30.0,           # HTTP request timeout (default: 60s)
    upload_timeout=300.0,   # File upload timeout (default: 600s)
    max_retries=3,          # Max retry attempts (default: 5)
)

Retries

Connection errors, 429 Rate Limit, and >=500 Internal errors are automatically retried with exponential backoff.

client = knowhere.Knowhere(
    api_key="sk_...",
    max_retries=3,  # default is 5
)

Determining the installed version

import knowhere
print(knowhere.__version__)

Versioning

This package follows Semantic Versioning.

We publish stable releases to PyPI. To install the latest unreleased changes directly from the repository: https://github.com/Ontos-AI/knowhere-python-sdk

Requirements

Community

License

MIT

Metadata

Release files for knowhere-python-sdk 2.0.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 knowhere-python-sdk 2.0.0
File Size Uploaded
knowhere_python_sdk-2.0.0.tar.gz 539.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for knowhere-python-sdk 2.0.0
File Interpreter ABI Platform
knowhere_python_sdk-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 580.6 kB

Release files / knowhere_python_sdk-2.0.0.tar.gz

Download URL knowhere_python_sdk-2.0.0.tar.gz
Size 539.1 kB
Tags Source
SHA-256 checksum
How to use checksums
88232a456b26323407d012f4f7aaad2e436a2202b71c170a9a336bd638987949
BLAKE2b-256 checksum
How to use checksums
28de7fb95618b18d5eda34903f674eab087cbb8fa97c49a81b52c8363640cf8c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / knowhere_python_sdk-2.0.0-py3-none-any.whl

Download URL knowhere_python_sdk-2.0.0-py3-none-any.whl
Size 41.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cff8d7e9c809a250e623894cf2849bfde1d4950f75268387826e04988c1b7cb0
BLAKE2b-256 checksum
How to use checksums
8595f2e88497fd6433b7f83fa10636469951623483560040f84d4ba0c4826613
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

2.2.0

2 release files

2.1.0

2 release files

This release

2.0.0 This release

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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