knowledge2 0.4.1__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. {knowledge2-0.4.1 → knowledge2-0.7.0}/CHANGELOG.md +67 -2
  2. knowledge2-0.7.0/MANIFEST.in +5 -0
  3. knowledge2-0.7.0/PKG-INFO +318 -0
  4. knowledge2-0.7.0/README.md +289 -0
  5. {knowledge2-0.4.1 → knowledge2-0.7.0}/_async_base.py +48 -2
  6. {knowledge2-0.4.1 → knowledge2-0.7.0}/_base.py +48 -2
  7. {knowledge2-0.4.1 → knowledge2-0.7.0}/_validation_response.py +2 -2
  8. {knowledge2-0.4.1 → knowledge2-0.7.0}/_version.py +1 -1
  9. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_client.py +12 -8
  10. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/__init__.py +2 -6
  11. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/agents.py +44 -3
  12. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/console.py +0 -4
  13. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/corpora.py +0 -62
  14. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/documents.py +354 -9
  15. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/feeds.py +138 -0
  16. knowledge2-0.7.0/async_resources/generation_models.py +29 -0
  17. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/indexes.py +57 -4
  18. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/onboarding.py +16 -11
  19. {knowledge2-0.4.1 → knowledge2-0.7.0}/client.py +12 -37
  20. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/batch_operations.py +4 -2
  21. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/document_upload.py +3 -2
  22. knowledge2-0.7.0/examples/e2e_lifecycle.py +152 -0
  23. knowledge2-0.7.0/examples/retrieval_quickstart.py +58 -0
  24. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/__init__.py +6 -6
  25. knowledge2-0.7.0/knowledge2.egg-info/PKG-INFO +318 -0
  26. {knowledge2-0.4.1 → knowledge2-0.7.0}/knowledge2.egg-info/SOURCES.txt +11 -30
  27. {knowledge2-0.4.1 → knowledge2-0.7.0}/knowledge2.egg-info/requires.txt +2 -1
  28. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/__init__.py +4 -6
  29. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/_registry.py +27 -48
  30. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/agents.py +38 -0
  31. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/console.py +0 -3
  32. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/corpora.py +1 -6
  33. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/documents.py +26 -0
  34. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/feeds.py +31 -3
  35. knowledge2-0.7.0/models/generation_models.py +16 -0
  36. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/indexes.py +5 -2
  37. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/onboarding.py +13 -5
  38. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/projects.py +0 -3
  39. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/search.py +1 -34
  40. {knowledge2-0.4.1 → knowledge2-0.7.0}/namespaces.py +25 -110
  41. {knowledge2-0.4.1 → knowledge2-0.7.0}/pyproject.toml +4 -3
  42. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/__init__.py +2 -6
  43. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/agents.py +44 -3
  44. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/corpora.py +0 -57
  45. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/documents.py +356 -9
  46. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/feeds.py +193 -0
  47. knowledge2-0.7.0/resources/generation_models.py +29 -0
  48. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/indexes.py +62 -4
  49. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/onboarding.py +16 -12
  50. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/__init__.py +22 -32
  51. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/agents.py +58 -2
  52. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/corpora.py +0 -1
  53. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/documents.py +26 -0
  54. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/feeds.py +27 -0
  55. knowledge2-0.7.0/types/generation_models.py +14 -0
  56. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/indexes.py +6 -1
  57. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/onboarding.py +13 -5
  58. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/projects.py +0 -1
  59. knowledge2-0.4.1/AGENTS.md +0 -31
  60. knowledge2-0.4.1/PKG-INFO +0 -662
  61. knowledge2-0.4.1/README.md +0 -634
  62. knowledge2-0.4.1/async_resources/deployments.py +0 -106
  63. knowledge2-0.4.1/async_resources/models.py +0 -102
  64. knowledge2-0.4.1/async_resources/training.py +0 -357
  65. knowledge2-0.4.1/examples/e2e_lifecycle.py +0 -213
  66. knowledge2-0.4.1/knowledge2.egg-info/PKG-INFO +0 -662
  67. knowledge2-0.4.1/models/deployments.py +0 -13
  68. knowledge2-0.4.1/models/evaluation.py +0 -17
  69. knowledge2-0.4.1/models/models.py +0 -26
  70. knowledge2-0.4.1/models/training.py +0 -57
  71. knowledge2-0.4.1/resources/deployments.py +0 -105
  72. knowledge2-0.4.1/resources/models.py +0 -99
  73. knowledge2-0.4.1/resources/training.py +0 -358
  74. knowledge2-0.4.1/specification.md +0 -129
  75. knowledge2-0.4.1/types/deployments.py +0 -11
  76. knowledge2-0.4.1/types/evaluation.py +0 -15
  77. knowledge2-0.4.1/types/models.py +0 -22
  78. knowledge2-0.4.1/types/training.py +0 -55
  79. {knowledge2-0.4.1 → knowledge2-0.7.0}/.github/workflows/pypi-release.yml +0 -0
  80. {knowledge2-0.4.1 → knowledge2-0.7.0}/__init__.py +0 -0
  81. {knowledge2-0.4.1 → knowledge2-0.7.0}/_async_paging.py +0 -0
  82. {knowledge2-0.4.1 → knowledge2-0.7.0}/_logging.py +0 -0
  83. {knowledge2-0.4.1 → knowledge2-0.7.0}/_paging.py +0 -0
  84. {knowledge2-0.4.1 → knowledge2-0.7.0}/_preview.py +0 -0
  85. {knowledge2-0.4.1 → knowledge2-0.7.0}/_raw_response.py +0 -0
  86. {knowledge2-0.4.1 → knowledge2-0.7.0}/_request_options.py +0 -0
  87. {knowledge2-0.4.1 → knowledge2-0.7.0}/_transport.py +0 -0
  88. {knowledge2-0.4.1 → knowledge2-0.7.0}/_validation.py +0 -0
  89. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/_mixin_base.py +0 -0
  90. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/a2a.py +0 -0
  91. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/audit.py +0 -0
  92. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/auth.py +0 -0
  93. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/jobs.py +0 -0
  94. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/metadata.py +0 -0
  95. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/orgs.py +0 -0
  96. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/pipelines.py +0 -0
  97. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/projects.py +0 -0
  98. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/search.py +0 -0
  99. {knowledge2-0.4.1 → knowledge2-0.7.0}/async_resources/usage.py +0 -0
  100. {knowledge2-0.4.1 → knowledge2-0.7.0}/config.py +0 -0
  101. {knowledge2-0.4.1 → knowledge2-0.7.0}/errors.py +0 -0
  102. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/auth_factory.py +0 -0
  103. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/error_handling.py +0 -0
  104. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/pagination.py +0 -0
  105. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/quickstart.py +0 -0
  106. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/request_options.py +0 -0
  107. {knowledge2-0.4.1 → knowledge2-0.7.0}/examples/search.py +0 -0
  108. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/_client.py +0 -0
  109. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/langchain/__init__.py +0 -0
  110. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/langchain/retriever.py +0 -0
  111. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/langchain/tools.py +0 -0
  112. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/llamaindex/__init__.py +0 -0
  113. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/llamaindex/filters.py +0 -0
  114. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/llamaindex/retriever.py +0 -0
  115. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/llamaindex/tools.py +0 -0
  116. {knowledge2-0.4.1 → knowledge2-0.7.0}/integrations/llamaindex/vector_store.py +0 -0
  117. {knowledge2-0.4.1 → knowledge2-0.7.0}/knowledge2.egg-info/dependency_links.txt +0 -0
  118. {knowledge2-0.4.1 → knowledge2-0.7.0}/knowledge2.egg-info/top_level.txt +0 -0
  119. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/_base.py +0 -0
  120. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/a2a.py +0 -0
  121. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/audit.py +0 -0
  122. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/auth.py +0 -0
  123. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/chunks.py +0 -0
  124. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/common.py +0 -0
  125. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/embeddings.py +0 -0
  126. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/feedback.py +0 -0
  127. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/jobs.py +0 -0
  128. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/orgs.py +0 -0
  129. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/pipelines.py +0 -0
  130. {knowledge2-0.4.1 → knowledge2-0.7.0}/models/usage.py +0 -0
  131. {knowledge2-0.4.1 → knowledge2-0.7.0}/py.typed +0 -0
  132. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/_mixin_base.py +0 -0
  133. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/a2a.py +0 -0
  134. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/audit.py +0 -0
  135. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/auth.py +0 -0
  136. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/console.py +0 -0
  137. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/jobs.py +0 -0
  138. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/metadata.py +0 -0
  139. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/orgs.py +0 -0
  140. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/pipeline_builder.py +0 -0
  141. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/pipelines.py +0 -0
  142. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/projects.py +0 -0
  143. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/search.py +0 -0
  144. {knowledge2-0.4.1 → knowledge2-0.7.0}/resources/usage.py +0 -0
  145. {knowledge2-0.4.1 → knowledge2-0.7.0}/setup.cfg +0 -0
  146. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/a2a.py +0 -0
  147. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/audit.py +0 -0
  148. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/auth.py +0 -0
  149. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/chunks.py +0 -0
  150. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/common.py +0 -0
  151. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/console.py +0 -0
  152. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/embeddings.py +0 -0
  153. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/feedback.py +0 -0
  154. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/jobs.py +0 -0
  155. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/orgs.py +0 -0
  156. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/pipelines.py +0 -0
  157. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/search.py +0 -0
  158. {knowledge2-0.4.1 → knowledge2-0.7.0}/types/usage.py +0 -0
@@ -1,10 +1,75 @@
1
1
  # Changelog
2
2
 
3
- All notable changes to the Knowledge2 Python SDK will be documented in this file.
3
+ All notable changes to the Knowledge² Python SDK will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.7.0] - 2026-04-23
9
+
10
+ ### Added
11
+
12
+ - Feed draft lifecycle on both `Knowledge2` and `AsyncKnowledge2`:
13
+ `create_feed_draft`, `get_feed_draft`, `activate_feed_draft`,
14
+ `discard_feed_draft`. Activation returns the updated **parent** feed;
15
+ the draft is deleted server-side.
16
+ - `list_feed_subscriptions(feed_id)` — read-only view of the subscriptions
17
+ embedded on the feed record. Handles validated and raw-response modes,
18
+ passing `with_raw_response` errors through unchanged and re-wrapping
19
+ successful responses so status/headers survive.
20
+ - Feed feedback helpers: `submit_feed_feedback(feed_id, *, rating,
21
+ chunk_id, feed_run_id)` and `get_feed_feedback_stats(feed_id, *,
22
+ feed_run_id=None)`. `rating` is validated client-side to be `0` or `1`.
23
+ - New response types `FeedFeedbackSubmitResponse` and
24
+ `FeedFeedbackStatsResponse` exported from `sdk.types`, with matching
25
+ strict Pydantic models registered for `validate_responses=True`.
26
+ - `FeedSubscriptionResponse` (and its Pydantic model) now include
27
+ `match_spec` and `match_spec_description` — the routing metadata
28
+ returned by the feed-side subscription schema for `explicit` and
29
+ `nl_semantic` subscriptions.
30
+
31
+ ### Changed
32
+
33
+ - `FeedResponseModel.subscriptions` now always validates to a list
34
+ (previously `list | None = None`). The server contract guarantees a
35
+ list — empty by default — so validated clients can iterate without a
36
+ None check. A legacy response containing `null` for `subscriptions`
37
+ will now raise `ValidationError` instead of producing a `None` field.
38
+ - `FeedSubscriptionResponseModel.agent_id` and `role` are now required
39
+ (previously `str | None = None`) to match the server schema and catch
40
+ malformed subscription payloads in validated clients.
41
+
42
+ ## [0.6.1] - 2026-04-17
43
+
44
+ ### Added
45
+
46
+ - `upload_documents_batch_and_wait(...)` as the canonical blocking helper for raw-text batch ingestion
47
+ - `wait_for_document_batch(...)` for callers that intentionally enqueue first and resolve the batch later
48
+
49
+ ### Changed
50
+
51
+ - base installs now include `pydantic`, so `pip install knowledge2` is import-clean and supports validated response models without an extra
52
+ - `knowledge2[pydantic]` remains accepted as a compatibility alias for older install commands
53
+ - batch wait helpers now enforce a single end-to-end timeout budget and support `with_raw_response` correctly
54
+ - `get_document_batch(...)` now surfaces stable `doc_ids` and live counters once a batch is visible, instead of waiting for terminal aggregation
55
+ - refreshed the primary onboarding docs and examples to prefer the blocking batch helper and the released public contract
56
+ - clarified early auth and quota guidance for the supported retrieval workflow
57
+
58
+ ## [0.6.0] - 2026-04-16
59
+
60
+ ### Changed
61
+
62
+ - `upload_documents_batch(..., wait=False)` returns an enqueue handle with `job_id`, `batch_id`, and `count`
63
+ - `get_document_batch(...)` is the supported batch-status lookup for raw-text uploads, including final `doc_ids` and per-item errors
64
+ - refreshed public SDK release notes to align with the current batch-upload surface
65
+
66
+ ## [0.5.0] - 2026-04-13
67
+
68
+ ### Changed
69
+
70
+ - aligned the published Python SDK support matrix with the public customer-facing surface
71
+ - refreshed README guidance, examples, and optimize-related test coverage for the current SDK capabilities
72
+
8
73
  ## [0.4.1] - 2026-04-03
9
74
 
10
75
  ### Changed
@@ -43,7 +108,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
108
  - **`K2Config` frozen config** (#720): Pydantic-settings based configuration from environment variables (`K2_*` prefix), JSON/YAML files, or named profiles.
44
109
  - **Sub-client namespaces** (#721): `client.documents.*`, `client.corpora.*`, `client.search_ns.*`, etc. Lightweight cached proxies — flat methods still work.
45
110
  - **Parallel uploads** (#722): `upload_documents_parallel()` using `ThreadPoolExecutor` for concurrent document ingestion.
46
- - **Pydantic response validation** (#723): Optional `validate_responses=True` or `Knowledge2Validated` class. Requires `pip install knowledge2[pydantic]`.
111
+ - **Pydantic response validation** (#723): Optional `validate_responses=True` or `Knowledge2Validated` class. Base installs now include the Pydantic model dependency.
47
112
  - **`AsyncKnowledge2` client** (#724): Native async client using `httpx.AsyncClient`. `AsyncPager[T]` for async pagination. Factory methods: `create()`, `from_env()`, `from_file()`, `from_profile()`.
48
113
  - **`RequestOptions`** (#732): Per-call overrides for timeout, retries, and passthrough headers. `request_options` parameter on all public methods.
49
114
  - **`with_raw_response`** (#733): `client.with_raw_response.<method>(...)` returns `RawResponse[T]` with `status_code`, `headers`, and `parsed` body. Thread-safe (sync) and task-safe (async).
@@ -0,0 +1,5 @@
1
+ exclude AGENTS.md
2
+ exclude specification.md
3
+ recursive-exclude .claude *
4
+ recursive-exclude .codex *
5
+ recursive-exclude .skills *
@@ -0,0 +1,318 @@
1
+ Metadata-Version: 2.4
2
+ Name: knowledge2
3
+ Version: 0.7.0
4
+ Summary: Python SDK for the Knowledge² retrieval platform
5
+ Author-email: Knowledge2 <contact@knowledge2.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://knowledge2.ai
8
+ Project-URL: Documentation, https://knowledge2.ai/docs
9
+ Project-URL: Repository, https://github.com/knowledge2-ai/knowledge2-python-sdk
10
+ Project-URL: Changelog, https://github.com/knowledge2-ai/knowledge2-python-sdk/blob/main/CHANGELOG.md
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Typing :: Typed
19
+ Requires-Python: >=3.11
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: httpx>=0.27
22
+ Requires-Dist: pydantic<3,>=2
23
+ Provides-Extra: config
24
+ Requires-Dist: pydantic-settings>=2.0; extra == "config"
25
+ Provides-Extra: pydantic
26
+ Requires-Dist: pydantic<3,>=2; extra == "pydantic"
27
+ Provides-Extra: yaml
28
+ Requires-Dist: pyyaml>=6.0; extra == "yaml"
29
+
30
+ # Knowledge² Python SDK
31
+
32
+ [![PyPI version](https://img.shields.io/pypi/v/knowledge2.svg)](https://pypi.org/project/knowledge2/)
33
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
34
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
35
+
36
+ Official Python client for the Knowledge² retrieval platform. The supported customer journey is:
37
+
38
+ `create corpus -> ingest documents -> build indexes -> search -> optimize retrieval`
39
+
40
+ ## Installation
41
+
42
+ From PyPI:
43
+
44
+ ```bash
45
+ pip install knowledge2
46
+ pip install "knowledge2[config]"
47
+ pip install "knowledge2[yaml]"
48
+ ```
49
+
50
+ From source:
51
+
52
+ ```bash
53
+ pip install -e .
54
+ pip install -e ".[config]"
55
+ pip install -e ".[yaml]"
56
+ ```
57
+
58
+ `pip install knowledge2` now includes the typed response model dependency
59
+ (`pydantic`) out of the box. Install `knowledge2[config]` only if you want
60
+ `K2Config` environment/file loading via `pydantic-settings`.
61
+
62
+ ## Before You Start
63
+
64
+ - Use a normal org-scoped API key for the standard retrieval workflow:
65
+ projects, corpora, documents, indexes, search, and optimize.
66
+ - `optimize_indexes()` and some enterprise/preview surfaces can return
67
+ feature-flag or quota errors (`403`, `409`, `429`) even when the payload is
68
+ correct. Check environment entitlements early.
69
+
70
+ ## Surface Categories
71
+
72
+ | Category | Surface |
73
+ |---|---|
74
+ | Core retrieval workflow | orgs, auth, projects, corpora, documents, indexes, search, jobs, metadata, onboarding, audit, usage, console, generation models |
75
+ | Enterprise capabilities | agents, feeds, pipelines, A2A |
76
+
77
+ The main docs and examples below focus on the core retrieval workflow.
78
+
79
+ ## Quick Start
80
+
81
+ ```python
82
+ from sdk import Knowledge2
83
+
84
+ client = Knowledge2(api_key="k2_...")
85
+
86
+ project = client.create_project("My Project")
87
+ corpus = client.create_corpus(project["id"], "My Corpus")
88
+
89
+ batch = client.upload_documents_batch_and_wait(
90
+ corpus["id"],
91
+ [
92
+ {
93
+ "source_uri": "doc://overview",
94
+ "raw_text": "Knowledge² builds dense and sparse indexes for hybrid retrieval.",
95
+ "metadata": {"topic": "overview"},
96
+ },
97
+ {
98
+ "source_uri": "doc://search",
99
+ "raw_text": "Hybrid retrieval combines semantic similarity with exact keyword matching.",
100
+ "metadata": {"topic": "search"},
101
+ },
102
+ ],
103
+ auto_index=False,
104
+ )
105
+ client.sync_indexes(corpus["id"], wait=True)
106
+
107
+ results = client.search(
108
+ corpus["id"],
109
+ "what is hybrid retrieval",
110
+ top_k=3,
111
+ return_config={"include_text": True, "include_scores": True},
112
+ )
113
+
114
+ for hit in results["results"]:
115
+ print(hit["score"], hit.get("text", "")[:80])
116
+ ```
117
+
118
+ `upload_documents_batch_and_wait(...)` is the canonical onboarding helper for
119
+ raw-text JSON batch ingestion. It blocks until the batch finishes and returns
120
+ the final batch payload, including `doc_ids`.
121
+
122
+ If you intentionally want enqueue-first control, use `wait=False` and then
123
+ resolve the batch with `wait_for_document_batch(...)`:
124
+
125
+ ```python
126
+ docs = [
127
+ {
128
+ "source_uri": "doc://overview",
129
+ "raw_text": "Knowledge² builds dense and sparse indexes for hybrid retrieval.",
130
+ },
131
+ ]
132
+
133
+ enqueue = client.upload_documents_batch(corpus["id"], docs, wait=False)
134
+ batch = client.wait_for_document_batch(corpus["id"], enqueue["batch_id"])
135
+ print(batch["status"], batch["doc_ids"])
136
+ ```
137
+
138
+ For large in-flight imports, `get_document_batch(...)` and
139
+ `wait_for_document_batch(...)` are the canonical batch APIs. Once the batch is
140
+ visible they return stable `doc_ids`, terminal resolution, and live batch
141
+ counters that track admitted documents as processing advances. For broader
142
+ operational context during a large import, you can still pair them with
143
+ `get_corpus_status(...)`, `get_job(...)`, or document-level status checks.
144
+
145
+ ## Improve Retrieval Quality
146
+
147
+ ```python
148
+ profile = client.get_query_profile(corpus["id"])
149
+ print(profile["example_queries"])
150
+
151
+ job = client.optimize_indexes(
152
+ corpus["id"],
153
+ example_queries=[
154
+ "how does hybrid retrieval work",
155
+ "what is bm25 tuning",
156
+ "how does rrf combine dense and sparse search",
157
+ ],
158
+ query_count=25,
159
+ top_k=10,
160
+ metric="ndcg",
161
+ wait=True,
162
+ )
163
+ print(job["job_id"], job["job_type"])
164
+ ```
165
+
166
+ ## Examples
167
+
168
+ - `sdk/examples/retrieval_quickstart.py`: minimal happy path from empty corpus to working hybrid search
169
+ - `sdk/examples/e2e_lifecycle.py`: full retrieval-quality workflow with query profile inspection and `indexes:optimize`
170
+
171
+ Run either example with:
172
+
173
+ ```bash
174
+ export K2_BASE_URL=https://api.knowledge2.ai
175
+ export K2_API_KEY=<api-key>
176
+ python sdk/examples/retrieval_quickstart.py
177
+ python sdk/examples/e2e_lifecycle.py
178
+ ```
179
+
180
+ ## Authentication
181
+
182
+ | Method | Header | Typical use |
183
+ |---|---|---|
184
+ | API key | `X-API-Key` | primary programmatic access for retrieval workflows |
185
+ | Bearer token | `Authorization: Bearer <token>` | console / Auth0 session |
186
+
187
+ ```python
188
+ client = Knowledge2(api_key="k2_...")
189
+ client = Knowledge2.from_env()
190
+ client = Knowledge2(bearer_token="...")
191
+ ```
192
+
193
+ ## Configuration
194
+
195
+ Important constructor knobs:
196
+
197
+ - `api_host`: defaults to `https://api.knowledge2.ai`
198
+ - `api_key`: API key for programmatic access
199
+ - `org_id`: auto-detected from `GET /v1/auth/whoami` when omitted
200
+ - `timeout`: float or `ClientTimeouts`
201
+ - `limits`: connection-pool settings via `ClientLimits`
202
+ - `max_retries`: transient retry budget
203
+ - `validate_responses`: enable Pydantic response validation
204
+ - `http_client`: bring your own `httpx.Client`
205
+
206
+ ```python
207
+ from sdk import ClientTimeouts, Knowledge2
208
+
209
+ client = Knowledge2(
210
+ api_key="k2_...",
211
+ timeout=ClientTimeouts(connect=5, read=120, write=30, pool=10),
212
+ )
213
+ ```
214
+
215
+ ## Namespaces
216
+
217
+ The flat client API is canonical. The sync client also exposes namespace helpers
218
+ that group the same methods without changing behavior:
219
+
220
+ - `client.documents.*`
221
+ - `client.documents.upload_batch_and_wait(...)`
222
+ - `client.documents.wait_for_batch(...)`
223
+ - `client.corpora.*`
224
+ - `client.search_ns.*`
225
+ - `client.jobs.*`
226
+ - `client.auth.*`
227
+
228
+ `AsyncKnowledge2` currently stays flat-only.
229
+
230
+ ## Framework Integrations
231
+
232
+ The SDK ships LangChain and LlamaIndex integration modules in-package. Install the framework dependency separately, then import the adapter:
233
+
234
+ ```python
235
+ from sdk.integrations.langchain import K2LangChainRetriever
236
+ from sdk.integrations.llamaindex import K2LlamaIndexRetriever
237
+ ```
238
+
239
+ ## Enterprise Capabilities
240
+
241
+ Agents, feeds, pipelines, and A2A are available for enterprise deployments. Keep the primary examples focused on the core retrieval flow.
242
+
243
+ ### Subscription Modes (Preview)
244
+
245
+ Agent-feed subscriptions support three authoring modes on `create_subscription`, gated behind the `knowledge_agents_enabled` feature flag:
246
+
247
+ | Mode | Use | Required fields |
248
+ |------|-----|-----------------|
249
+ | `always` | Route every envelope from the feed | `feed_id`, `role` |
250
+ | `explicit` | Evaluate a predicate DSL against the envelope | `feed_id`, `role`, `match_spec` |
251
+ | `nl_semantic` | Describe the match in plain English; compiled server-side into a `semantic_like` predicate against `content` | `feed_id`, `role`, `match_spec_description` (10-500 chars); optional `threshold` (default 0.75) |
252
+
253
+ The create response echoes the compiled `match_spec` and the raw `match_spec_description`, so no separate `/preview` endpoint is required:
254
+
255
+ ```python
256
+ sub = client.create_subscription(
257
+ agent_id,
258
+ feed_id=feed_id,
259
+ role="input",
260
+ mode="nl_semantic",
261
+ match_spec_description="documents about security incidents",
262
+ )
263
+ print(sub["match_spec"]) # compiled semantic_like predicate
264
+ print(sub["match_spec_description"]) # raw NL description (echoed)
265
+ ```
266
+
267
+ ### Feed Drafts, Subscriptions, and Feedback (Preview)
268
+
269
+ In addition to CRUD and `run_feed`, the `Knowledge2` client exposes the full
270
+ editing and feedback surface of the Feeds API as flat methods on `client`
271
+ (the same mixin-based pattern used by every other resource).
272
+
273
+ | Method | Endpoint | Notes |
274
+ |--------|----------|-------|
275
+ | `create_feed_draft(feed_id)` | `POST /v1/feeds/{id}/draft` | Returns a draft feed with `parent_feed_id` set |
276
+ | `get_feed_draft(feed_id)` | `GET /v1/feeds/{id}/draft` | 404 when no draft exists |
277
+ | `activate_feed_draft(feed_id)` | `POST /v1/feeds/{id}/draft/activate` | Returns the updated **parent** feed (draft is deleted) |
278
+ | `discard_feed_draft(feed_id)` | `DELETE /v1/feeds/{id}/draft` | Returns `None` |
279
+ | `list_feed_subscriptions(feed_id)` | Read-only view | Returns subscriptions embedded on the feed record; use `create_subscription` on the Agents mixin to attach new ones |
280
+ | `submit_feed_feedback(feed_id, *, rating, chunk_id, feed_run_id)` | `POST /v1/feeds/{id}/feedback` | `rating` is `1` (thumbs up) or `0` (thumbs down) |
281
+ | `get_feed_feedback_stats(feed_id, *, feed_run_id=None)` | `GET /v1/feeds/{id}/feedback` | Optional `feed_run_id` scopes stats to a single run |
282
+
283
+ ```python
284
+ draft = client.create_feed_draft(feed_id)
285
+ client.update_feed(draft["id"], name="new name")
286
+ client.activate_feed_draft(feed_id) # applies the draft; returns the parent
287
+
288
+ run = client.run_feed(feed_id, return_results=True)
289
+ # `results` is only populated for non-persistent feeds run with
290
+ # `return_results=True`; guard the example for safe use.
291
+ if run.get("results"):
292
+ client.submit_feed_feedback(
293
+ feed_id,
294
+ rating=1,
295
+ chunk_id=run["results"][0]["chunk_id"],
296
+ feed_run_id=run["feed_run_id"],
297
+ )
298
+ stats = client.get_feed_feedback_stats(feed_id) # org-wide for this feed
299
+ ```
300
+
301
+ All three areas are fully mirrored on `AsyncKnowledge2` under the same names.
302
+
303
+ ## Error Handling
304
+
305
+ All SDK exceptions inherit from `Knowledge2Error`.
306
+
307
+ ```python
308
+ from sdk.errors import Knowledge2Error, NotFoundError, RateLimitError
309
+
310
+ try:
311
+ client.get_corpus("missing")
312
+ except NotFoundError:
313
+ ...
314
+ except RateLimitError as exc:
315
+ print(exc.retry_after)
316
+ except Knowledge2Error as exc:
317
+ print(exc)
318
+ ```
@@ -0,0 +1,289 @@
1
+ # Knowledge² Python SDK
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/knowledge2.svg)](https://pypi.org/project/knowledge2/)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Official Python client for the Knowledge² retrieval platform. The supported customer journey is:
8
+
9
+ `create corpus -> ingest documents -> build indexes -> search -> optimize retrieval`
10
+
11
+ ## Installation
12
+
13
+ From PyPI:
14
+
15
+ ```bash
16
+ pip install knowledge2
17
+ pip install "knowledge2[config]"
18
+ pip install "knowledge2[yaml]"
19
+ ```
20
+
21
+ From source:
22
+
23
+ ```bash
24
+ pip install -e .
25
+ pip install -e ".[config]"
26
+ pip install -e ".[yaml]"
27
+ ```
28
+
29
+ `pip install knowledge2` now includes the typed response model dependency
30
+ (`pydantic`) out of the box. Install `knowledge2[config]` only if you want
31
+ `K2Config` environment/file loading via `pydantic-settings`.
32
+
33
+ ## Before You Start
34
+
35
+ - Use a normal org-scoped API key for the standard retrieval workflow:
36
+ projects, corpora, documents, indexes, search, and optimize.
37
+ - `optimize_indexes()` and some enterprise/preview surfaces can return
38
+ feature-flag or quota errors (`403`, `409`, `429`) even when the payload is
39
+ correct. Check environment entitlements early.
40
+
41
+ ## Surface Categories
42
+
43
+ | Category | Surface |
44
+ |---|---|
45
+ | Core retrieval workflow | orgs, auth, projects, corpora, documents, indexes, search, jobs, metadata, onboarding, audit, usage, console, generation models |
46
+ | Enterprise capabilities | agents, feeds, pipelines, A2A |
47
+
48
+ The main docs and examples below focus on the core retrieval workflow.
49
+
50
+ ## Quick Start
51
+
52
+ ```python
53
+ from sdk import Knowledge2
54
+
55
+ client = Knowledge2(api_key="k2_...")
56
+
57
+ project = client.create_project("My Project")
58
+ corpus = client.create_corpus(project["id"], "My Corpus")
59
+
60
+ batch = client.upload_documents_batch_and_wait(
61
+ corpus["id"],
62
+ [
63
+ {
64
+ "source_uri": "doc://overview",
65
+ "raw_text": "Knowledge² builds dense and sparse indexes for hybrid retrieval.",
66
+ "metadata": {"topic": "overview"},
67
+ },
68
+ {
69
+ "source_uri": "doc://search",
70
+ "raw_text": "Hybrid retrieval combines semantic similarity with exact keyword matching.",
71
+ "metadata": {"topic": "search"},
72
+ },
73
+ ],
74
+ auto_index=False,
75
+ )
76
+ client.sync_indexes(corpus["id"], wait=True)
77
+
78
+ results = client.search(
79
+ corpus["id"],
80
+ "what is hybrid retrieval",
81
+ top_k=3,
82
+ return_config={"include_text": True, "include_scores": True},
83
+ )
84
+
85
+ for hit in results["results"]:
86
+ print(hit["score"], hit.get("text", "")[:80])
87
+ ```
88
+
89
+ `upload_documents_batch_and_wait(...)` is the canonical onboarding helper for
90
+ raw-text JSON batch ingestion. It blocks until the batch finishes and returns
91
+ the final batch payload, including `doc_ids`.
92
+
93
+ If you intentionally want enqueue-first control, use `wait=False` and then
94
+ resolve the batch with `wait_for_document_batch(...)`:
95
+
96
+ ```python
97
+ docs = [
98
+ {
99
+ "source_uri": "doc://overview",
100
+ "raw_text": "Knowledge² builds dense and sparse indexes for hybrid retrieval.",
101
+ },
102
+ ]
103
+
104
+ enqueue = client.upload_documents_batch(corpus["id"], docs, wait=False)
105
+ batch = client.wait_for_document_batch(corpus["id"], enqueue["batch_id"])
106
+ print(batch["status"], batch["doc_ids"])
107
+ ```
108
+
109
+ For large in-flight imports, `get_document_batch(...)` and
110
+ `wait_for_document_batch(...)` are the canonical batch APIs. Once the batch is
111
+ visible they return stable `doc_ids`, terminal resolution, and live batch
112
+ counters that track admitted documents as processing advances. For broader
113
+ operational context during a large import, you can still pair them with
114
+ `get_corpus_status(...)`, `get_job(...)`, or document-level status checks.
115
+
116
+ ## Improve Retrieval Quality
117
+
118
+ ```python
119
+ profile = client.get_query_profile(corpus["id"])
120
+ print(profile["example_queries"])
121
+
122
+ job = client.optimize_indexes(
123
+ corpus["id"],
124
+ example_queries=[
125
+ "how does hybrid retrieval work",
126
+ "what is bm25 tuning",
127
+ "how does rrf combine dense and sparse search",
128
+ ],
129
+ query_count=25,
130
+ top_k=10,
131
+ metric="ndcg",
132
+ wait=True,
133
+ )
134
+ print(job["job_id"], job["job_type"])
135
+ ```
136
+
137
+ ## Examples
138
+
139
+ - `sdk/examples/retrieval_quickstart.py`: minimal happy path from empty corpus to working hybrid search
140
+ - `sdk/examples/e2e_lifecycle.py`: full retrieval-quality workflow with query profile inspection and `indexes:optimize`
141
+
142
+ Run either example with:
143
+
144
+ ```bash
145
+ export K2_BASE_URL=https://api.knowledge2.ai
146
+ export K2_API_KEY=<api-key>
147
+ python sdk/examples/retrieval_quickstart.py
148
+ python sdk/examples/e2e_lifecycle.py
149
+ ```
150
+
151
+ ## Authentication
152
+
153
+ | Method | Header | Typical use |
154
+ |---|---|---|
155
+ | API key | `X-API-Key` | primary programmatic access for retrieval workflows |
156
+ | Bearer token | `Authorization: Bearer <token>` | console / Auth0 session |
157
+
158
+ ```python
159
+ client = Knowledge2(api_key="k2_...")
160
+ client = Knowledge2.from_env()
161
+ client = Knowledge2(bearer_token="...")
162
+ ```
163
+
164
+ ## Configuration
165
+
166
+ Important constructor knobs:
167
+
168
+ - `api_host`: defaults to `https://api.knowledge2.ai`
169
+ - `api_key`: API key for programmatic access
170
+ - `org_id`: auto-detected from `GET /v1/auth/whoami` when omitted
171
+ - `timeout`: float or `ClientTimeouts`
172
+ - `limits`: connection-pool settings via `ClientLimits`
173
+ - `max_retries`: transient retry budget
174
+ - `validate_responses`: enable Pydantic response validation
175
+ - `http_client`: bring your own `httpx.Client`
176
+
177
+ ```python
178
+ from sdk import ClientTimeouts, Knowledge2
179
+
180
+ client = Knowledge2(
181
+ api_key="k2_...",
182
+ timeout=ClientTimeouts(connect=5, read=120, write=30, pool=10),
183
+ )
184
+ ```
185
+
186
+ ## Namespaces
187
+
188
+ The flat client API is canonical. The sync client also exposes namespace helpers
189
+ that group the same methods without changing behavior:
190
+
191
+ - `client.documents.*`
192
+ - `client.documents.upload_batch_and_wait(...)`
193
+ - `client.documents.wait_for_batch(...)`
194
+ - `client.corpora.*`
195
+ - `client.search_ns.*`
196
+ - `client.jobs.*`
197
+ - `client.auth.*`
198
+
199
+ `AsyncKnowledge2` currently stays flat-only.
200
+
201
+ ## Framework Integrations
202
+
203
+ The SDK ships LangChain and LlamaIndex integration modules in-package. Install the framework dependency separately, then import the adapter:
204
+
205
+ ```python
206
+ from sdk.integrations.langchain import K2LangChainRetriever
207
+ from sdk.integrations.llamaindex import K2LlamaIndexRetriever
208
+ ```
209
+
210
+ ## Enterprise Capabilities
211
+
212
+ Agents, feeds, pipelines, and A2A are available for enterprise deployments. Keep the primary examples focused on the core retrieval flow.
213
+
214
+ ### Subscription Modes (Preview)
215
+
216
+ Agent-feed subscriptions support three authoring modes on `create_subscription`, gated behind the `knowledge_agents_enabled` feature flag:
217
+
218
+ | Mode | Use | Required fields |
219
+ |------|-----|-----------------|
220
+ | `always` | Route every envelope from the feed | `feed_id`, `role` |
221
+ | `explicit` | Evaluate a predicate DSL against the envelope | `feed_id`, `role`, `match_spec` |
222
+ | `nl_semantic` | Describe the match in plain English; compiled server-side into a `semantic_like` predicate against `content` | `feed_id`, `role`, `match_spec_description` (10-500 chars); optional `threshold` (default 0.75) |
223
+
224
+ The create response echoes the compiled `match_spec` and the raw `match_spec_description`, so no separate `/preview` endpoint is required:
225
+
226
+ ```python
227
+ sub = client.create_subscription(
228
+ agent_id,
229
+ feed_id=feed_id,
230
+ role="input",
231
+ mode="nl_semantic",
232
+ match_spec_description="documents about security incidents",
233
+ )
234
+ print(sub["match_spec"]) # compiled semantic_like predicate
235
+ print(sub["match_spec_description"]) # raw NL description (echoed)
236
+ ```
237
+
238
+ ### Feed Drafts, Subscriptions, and Feedback (Preview)
239
+
240
+ In addition to CRUD and `run_feed`, the `Knowledge2` client exposes the full
241
+ editing and feedback surface of the Feeds API as flat methods on `client`
242
+ (the same mixin-based pattern used by every other resource).
243
+
244
+ | Method | Endpoint | Notes |
245
+ |--------|----------|-------|
246
+ | `create_feed_draft(feed_id)` | `POST /v1/feeds/{id}/draft` | Returns a draft feed with `parent_feed_id` set |
247
+ | `get_feed_draft(feed_id)` | `GET /v1/feeds/{id}/draft` | 404 when no draft exists |
248
+ | `activate_feed_draft(feed_id)` | `POST /v1/feeds/{id}/draft/activate` | Returns the updated **parent** feed (draft is deleted) |
249
+ | `discard_feed_draft(feed_id)` | `DELETE /v1/feeds/{id}/draft` | Returns `None` |
250
+ | `list_feed_subscriptions(feed_id)` | Read-only view | Returns subscriptions embedded on the feed record; use `create_subscription` on the Agents mixin to attach new ones |
251
+ | `submit_feed_feedback(feed_id, *, rating, chunk_id, feed_run_id)` | `POST /v1/feeds/{id}/feedback` | `rating` is `1` (thumbs up) or `0` (thumbs down) |
252
+ | `get_feed_feedback_stats(feed_id, *, feed_run_id=None)` | `GET /v1/feeds/{id}/feedback` | Optional `feed_run_id` scopes stats to a single run |
253
+
254
+ ```python
255
+ draft = client.create_feed_draft(feed_id)
256
+ client.update_feed(draft["id"], name="new name")
257
+ client.activate_feed_draft(feed_id) # applies the draft; returns the parent
258
+
259
+ run = client.run_feed(feed_id, return_results=True)
260
+ # `results` is only populated for non-persistent feeds run with
261
+ # `return_results=True`; guard the example for safe use.
262
+ if run.get("results"):
263
+ client.submit_feed_feedback(
264
+ feed_id,
265
+ rating=1,
266
+ chunk_id=run["results"][0]["chunk_id"],
267
+ feed_run_id=run["feed_run_id"],
268
+ )
269
+ stats = client.get_feed_feedback_stats(feed_id) # org-wide for this feed
270
+ ```
271
+
272
+ All three areas are fully mirrored on `AsyncKnowledge2` under the same names.
273
+
274
+ ## Error Handling
275
+
276
+ All SDK exceptions inherit from `Knowledge2Error`.
277
+
278
+ ```python
279
+ from sdk.errors import Knowledge2Error, NotFoundError, RateLimitError
280
+
281
+ try:
282
+ client.get_corpus("missing")
283
+ except NotFoundError:
284
+ ...
285
+ except RateLimitError as exc:
286
+ print(exc.retry_after)
287
+ except Knowledge2Error as exc:
288
+ print(exc)
289
+ ```