knowledge2 0.4.0__py3-none-any.whl
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.
- knowledge2-0.4.0.dist-info/METADATA +556 -0
- knowledge2-0.4.0.dist-info/RECORD +139 -0
- knowledge2-0.4.0.dist-info/WHEEL +5 -0
- knowledge2-0.4.0.dist-info/top_level.txt +1 -0
- sdk/__init__.py +70 -0
- sdk/_async_base.py +525 -0
- sdk/_async_paging.py +57 -0
- sdk/_base.py +541 -0
- sdk/_logging.py +41 -0
- sdk/_paging.py +73 -0
- sdk/_preview.py +70 -0
- sdk/_raw_response.py +25 -0
- sdk/_request_options.py +51 -0
- sdk/_transport.py +144 -0
- sdk/_validation.py +25 -0
- sdk/_validation_response.py +36 -0
- sdk/_version.py +3 -0
- sdk/async_client.py +320 -0
- sdk/async_resources/__init__.py +45 -0
- sdk/async_resources/_mixin_base.py +42 -0
- sdk/async_resources/a2a.py +230 -0
- sdk/async_resources/agents.py +489 -0
- sdk/async_resources/audit.py +145 -0
- sdk/async_resources/auth.py +133 -0
- sdk/async_resources/console.py +409 -0
- sdk/async_resources/corpora.py +276 -0
- sdk/async_resources/deployments.py +106 -0
- sdk/async_resources/documents.py +592 -0
- sdk/async_resources/feeds.py +248 -0
- sdk/async_resources/indexes.py +208 -0
- sdk/async_resources/jobs.py +165 -0
- sdk/async_resources/metadata.py +48 -0
- sdk/async_resources/models.py +102 -0
- sdk/async_resources/onboarding.py +538 -0
- sdk/async_resources/orgs.py +37 -0
- sdk/async_resources/pipelines.py +523 -0
- sdk/async_resources/projects.py +90 -0
- sdk/async_resources/search.py +262 -0
- sdk/async_resources/training.py +357 -0
- sdk/async_resources/usage.py +91 -0
- sdk/client.py +417 -0
- sdk/config.py +182 -0
- sdk/errors.py +178 -0
- sdk/examples/auth_factory.py +34 -0
- sdk/examples/batch_operations.py +57 -0
- sdk/examples/document_upload.py +56 -0
- sdk/examples/e2e_lifecycle.py +213 -0
- sdk/examples/error_handling.py +61 -0
- sdk/examples/pagination.py +64 -0
- sdk/examples/quickstart.py +36 -0
- sdk/examples/request_options.py +44 -0
- sdk/examples/search.py +64 -0
- sdk/integrations/__init__.py +57 -0
- sdk/integrations/_client.py +101 -0
- sdk/integrations/langchain/__init__.py +6 -0
- sdk/integrations/langchain/retriever.py +166 -0
- sdk/integrations/langchain/tools.py +108 -0
- sdk/integrations/llamaindex/__init__.py +11 -0
- sdk/integrations/llamaindex/filters.py +78 -0
- sdk/integrations/llamaindex/retriever.py +162 -0
- sdk/integrations/llamaindex/tools.py +109 -0
- sdk/integrations/llamaindex/vector_store.py +320 -0
- sdk/models/__init__.py +18 -0
- sdk/models/_base.py +24 -0
- sdk/models/_registry.py +457 -0
- sdk/models/a2a.py +92 -0
- sdk/models/agents.py +109 -0
- sdk/models/audit.py +28 -0
- sdk/models/auth.py +49 -0
- sdk/models/chunks.py +20 -0
- sdk/models/common.py +14 -0
- sdk/models/console.py +103 -0
- sdk/models/corpora.py +48 -0
- sdk/models/deployments.py +13 -0
- sdk/models/documents.py +126 -0
- sdk/models/embeddings.py +24 -0
- sdk/models/evaluation.py +17 -0
- sdk/models/feedback.py +9 -0
- sdk/models/feeds.py +57 -0
- sdk/models/indexes.py +36 -0
- sdk/models/jobs.py +52 -0
- sdk/models/models.py +26 -0
- sdk/models/onboarding.py +323 -0
- sdk/models/orgs.py +11 -0
- sdk/models/pipelines.py +147 -0
- sdk/models/projects.py +19 -0
- sdk/models/search.py +149 -0
- sdk/models/training.py +57 -0
- sdk/models/usage.py +39 -0
- sdk/namespaces.py +386 -0
- sdk/py.typed +0 -0
- sdk/resources/__init__.py +45 -0
- sdk/resources/_mixin_base.py +40 -0
- sdk/resources/a2a.py +230 -0
- sdk/resources/agents.py +487 -0
- sdk/resources/audit.py +144 -0
- sdk/resources/auth.py +138 -0
- sdk/resources/console.py +411 -0
- sdk/resources/corpora.py +269 -0
- sdk/resources/deployments.py +105 -0
- sdk/resources/documents.py +597 -0
- sdk/resources/feeds.py +246 -0
- sdk/resources/indexes.py +210 -0
- sdk/resources/jobs.py +164 -0
- sdk/resources/metadata.py +53 -0
- sdk/resources/models.py +99 -0
- sdk/resources/onboarding.py +542 -0
- sdk/resources/orgs.py +35 -0
- sdk/resources/pipeline_builder.py +257 -0
- sdk/resources/pipelines.py +520 -0
- sdk/resources/projects.py +87 -0
- sdk/resources/search.py +277 -0
- sdk/resources/training.py +358 -0
- sdk/resources/usage.py +92 -0
- sdk/types/__init__.py +366 -0
- sdk/types/a2a.py +88 -0
- sdk/types/agents.py +133 -0
- sdk/types/audit.py +26 -0
- sdk/types/auth.py +45 -0
- sdk/types/chunks.py +18 -0
- sdk/types/common.py +10 -0
- sdk/types/console.py +99 -0
- sdk/types/corpora.py +42 -0
- sdk/types/deployments.py +11 -0
- sdk/types/documents.py +104 -0
- sdk/types/embeddings.py +22 -0
- sdk/types/evaluation.py +15 -0
- sdk/types/feedback.py +7 -0
- sdk/types/feeds.py +61 -0
- sdk/types/indexes.py +30 -0
- sdk/types/jobs.py +50 -0
- sdk/types/models.py +22 -0
- sdk/types/onboarding.py +395 -0
- sdk/types/orgs.py +9 -0
- sdk/types/pipelines.py +177 -0
- sdk/types/projects.py +14 -0
- sdk/types/search.py +116 -0
- sdk/types/training.py +55 -0
- sdk/types/usage.py +37 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""Async model resource mixin for the Knowledge2 SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from sdk._async_paging import AsyncPager
|
|
8
|
+
from sdk._paging import Page
|
|
9
|
+
from sdk._request_options import RequestOptions
|
|
10
|
+
from sdk._validation import require_str
|
|
11
|
+
from sdk.async_resources._mixin_base import AsyncRequesterMixin
|
|
12
|
+
from sdk.errors import ConfirmationRequiredError
|
|
13
|
+
from sdk.types import ModelDeleteResponse
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AsyncModelsMixin(AsyncRequesterMixin):
|
|
17
|
+
async def list_models(
|
|
18
|
+
self,
|
|
19
|
+
limit: int = 100,
|
|
20
|
+
offset: int = 0,
|
|
21
|
+
request_options: RequestOptions | None = None,
|
|
22
|
+
) -> Page[dict[str, Any]]:
|
|
23
|
+
"""List models accessible to the current credentials.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
limit: Maximum number of models to return per page.
|
|
27
|
+
offset: Number of models to skip for pagination.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
A Page containing model records with pagination metadata.
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
Knowledge2Error: If the API request fails.
|
|
34
|
+
"""
|
|
35
|
+
return await self._list_page(
|
|
36
|
+
"GET", "/v1/models", items_key="models", limit=limit, offset=offset
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
def iter_models(
|
|
40
|
+
self,
|
|
41
|
+
*,
|
|
42
|
+
limit: int = 100,
|
|
43
|
+
request_options: RequestOptions | None = None,
|
|
44
|
+
) -> AsyncPager[dict[str, Any]]:
|
|
45
|
+
"""Lazily paginate models, yielding individual model items.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
limit: Page size used for each underlying API request.
|
|
49
|
+
|
|
50
|
+
Yields:
|
|
51
|
+
Individual model dicts.
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
Knowledge2Error: If any underlying API request fails.
|
|
55
|
+
"""
|
|
56
|
+
return self._paginate(
|
|
57
|
+
"GET",
|
|
58
|
+
"/v1/models",
|
|
59
|
+
items_key="models",
|
|
60
|
+
limit=limit,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
async def delete_model(
|
|
64
|
+
self,
|
|
65
|
+
model_id: str,
|
|
66
|
+
*,
|
|
67
|
+
confirm: bool = False,
|
|
68
|
+
force: bool = False,
|
|
69
|
+
request_options: RequestOptions | None = None,
|
|
70
|
+
) -> ModelDeleteResponse:
|
|
71
|
+
"""Delete a model and its associated artifacts.
|
|
72
|
+
|
|
73
|
+
This is an irreversible operation. You must pass ``confirm=True``
|
|
74
|
+
to acknowledge this and proceed.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
model_id: Unique identifier of the model to delete.
|
|
78
|
+
confirm: Safety guard -- must be ``True`` to execute the
|
|
79
|
+
deletion. Raises ``ConfirmationRequiredError`` when ``False``.
|
|
80
|
+
force: If ``True``, delete even if the model is currently
|
|
81
|
+
deployed.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Confirmation of the deletion.
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
ConfirmationRequiredError: If *confirm* is not ``True``.
|
|
88
|
+
NotFoundError: If the model does not exist.
|
|
89
|
+
ConflictError: If *force* is ``False`` and the model has
|
|
90
|
+
active deployments.
|
|
91
|
+
Knowledge2Error: If the API request fails.
|
|
92
|
+
"""
|
|
93
|
+
model_id = require_str(model_id, "model_id")
|
|
94
|
+
if not confirm:
|
|
95
|
+
raise ConfirmationRequiredError("model", model_id)
|
|
96
|
+
data = await self._request(
|
|
97
|
+
"DELETE",
|
|
98
|
+
f"/v1/models/{model_id}",
|
|
99
|
+
params={"force": force},
|
|
100
|
+
request_options=request_options,
|
|
101
|
+
)
|
|
102
|
+
return self._maybe_validate(data, "ModelDeleteResponse")
|
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
"""Async SDK resource for dataset onboarding operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from sdk._async_paging import AsyncPager
|
|
9
|
+
from sdk._paging import Page
|
|
10
|
+
from sdk._request_options import RequestOptions
|
|
11
|
+
from sdk._validation import require_str
|
|
12
|
+
from sdk.async_resources._mixin_base import AsyncRequesterMixin
|
|
13
|
+
from sdk.types import (
|
|
14
|
+
DatasetAnalysisDetails,
|
|
15
|
+
DatasetAnalysisResponse,
|
|
16
|
+
DocumentSummaryResponse,
|
|
17
|
+
EvaluationDetails,
|
|
18
|
+
EvaluationListResponse,
|
|
19
|
+
EvaluationReportResponse,
|
|
20
|
+
EvaluationResponse,
|
|
21
|
+
GoldLabelEntry,
|
|
22
|
+
GoldLabelsUploadResponse,
|
|
23
|
+
OnboardingStatusResponse,
|
|
24
|
+
SummarizationResponse,
|
|
25
|
+
SummarizationStatusResponse,
|
|
26
|
+
SyntheticQueryBatchDetails,
|
|
27
|
+
SyntheticQueryBatchListResponse,
|
|
28
|
+
SyntheticQueryBatchResponse,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AsyncOnboardingMixin(AsyncRequesterMixin):
|
|
33
|
+
"""Async mixin providing dataset onboarding operations."""
|
|
34
|
+
|
|
35
|
+
# =========================================================================
|
|
36
|
+
# Dataset Analysis
|
|
37
|
+
# =========================================================================
|
|
38
|
+
|
|
39
|
+
async def start_analysis(
|
|
40
|
+
self,
|
|
41
|
+
corpus_id: str,
|
|
42
|
+
*,
|
|
43
|
+
description: str | None = None,
|
|
44
|
+
auto_bootstrap: bool = True,
|
|
45
|
+
bootstrap_num_samples: int | None = None,
|
|
46
|
+
queries_per_chunk: int | None = None,
|
|
47
|
+
request_options: RequestOptions | None = None,
|
|
48
|
+
) -> DatasetAnalysisResponse:
|
|
49
|
+
"""Start the dataset analysis pipeline for a corpus.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
corpus_id: ID of the corpus to analyze
|
|
53
|
+
description: Optional dataset description for analysis context
|
|
54
|
+
auto_bootstrap: Automatically bootstrap if no gold labels exist
|
|
55
|
+
bootstrap_num_samples: Override bootstrap sample count
|
|
56
|
+
queries_per_chunk: Override queries per chunk
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
DatasetAnalysisResponse with analysis_id and job_id
|
|
60
|
+
"""
|
|
61
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
62
|
+
payload: dict[str, Any] = {"auto_bootstrap": auto_bootstrap}
|
|
63
|
+
if description is not None:
|
|
64
|
+
payload["description"] = description
|
|
65
|
+
if bootstrap_num_samples is not None:
|
|
66
|
+
payload["bootstrap_num_samples"] = bootstrap_num_samples
|
|
67
|
+
if queries_per_chunk is not None:
|
|
68
|
+
payload["queries_per_chunk"] = queries_per_chunk
|
|
69
|
+
|
|
70
|
+
data = await self._request(
|
|
71
|
+
"POST",
|
|
72
|
+
f"/v1/corpora/{corpus_id}/onboard:analyze",
|
|
73
|
+
json=payload,
|
|
74
|
+
request_options=request_options,
|
|
75
|
+
)
|
|
76
|
+
return self._maybe_validate(data, "DatasetAnalysisResponse")
|
|
77
|
+
|
|
78
|
+
async def get_onboarding_status(
|
|
79
|
+
self,
|
|
80
|
+
corpus_id: str,
|
|
81
|
+
request_options: RequestOptions | None = None,
|
|
82
|
+
) -> OnboardingStatusResponse:
|
|
83
|
+
"""Get current onboarding status for a corpus.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
corpus_id: ID of the corpus
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
OnboardingStatusResponse with latest analysis and counts
|
|
90
|
+
"""
|
|
91
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
92
|
+
data = await self._request(
|
|
93
|
+
"GET", f"/v1/corpora/{corpus_id}/onboard/status", request_options=request_options
|
|
94
|
+
)
|
|
95
|
+
return self._maybe_validate(data, "OnboardingStatusResponse")
|
|
96
|
+
|
|
97
|
+
async def get_analysis(
|
|
98
|
+
self,
|
|
99
|
+
corpus_id: str,
|
|
100
|
+
analysis_id: str,
|
|
101
|
+
request_options: RequestOptions | None = None,
|
|
102
|
+
) -> DatasetAnalysisDetails:
|
|
103
|
+
"""Get detailed results of an analysis run.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
corpus_id: ID of the corpus
|
|
107
|
+
analysis_id: ID of the analysis run
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
DatasetAnalysisDetails with full analysis results
|
|
111
|
+
"""
|
|
112
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
113
|
+
analysis_id = require_str(analysis_id, "analysis_id")
|
|
114
|
+
data = await self._request(
|
|
115
|
+
"GET",
|
|
116
|
+
f"/v1/corpora/{corpus_id}/onboard/analysis/{analysis_id}",
|
|
117
|
+
request_options=request_options,
|
|
118
|
+
)
|
|
119
|
+
return self._maybe_validate(data, "DatasetAnalysisDetails")
|
|
120
|
+
|
|
121
|
+
# =========================================================================
|
|
122
|
+
# Gold Labels
|
|
123
|
+
# =========================================================================
|
|
124
|
+
|
|
125
|
+
async def upload_gold_labels(
|
|
126
|
+
self,
|
|
127
|
+
corpus_id: str,
|
|
128
|
+
labels: list[GoldLabelEntry],
|
|
129
|
+
*,
|
|
130
|
+
description: str | None = None,
|
|
131
|
+
request_options: RequestOptions | None = None,
|
|
132
|
+
) -> GoldLabelsUploadResponse:
|
|
133
|
+
"""Upload gold labels for a corpus.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
corpus_id: ID of the corpus
|
|
137
|
+
labels: List of gold label entries (query-chunk pairs)
|
|
138
|
+
description: Optional description of the labels source
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
GoldLabelsUploadResponse with resolution results
|
|
142
|
+
"""
|
|
143
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
144
|
+
payload: dict[str, Any] = {"labels": labels}
|
|
145
|
+
if description is not None:
|
|
146
|
+
payload["description"] = description
|
|
147
|
+
|
|
148
|
+
data = await self._request(
|
|
149
|
+
"POST",
|
|
150
|
+
f"/v1/corpora/{corpus_id}/onboard:upload-labels",
|
|
151
|
+
json=payload,
|
|
152
|
+
request_options=request_options,
|
|
153
|
+
)
|
|
154
|
+
return self._maybe_validate(data, "GoldLabelsUploadResponse")
|
|
155
|
+
|
|
156
|
+
async def upload_gold_labels_file(
|
|
157
|
+
self,
|
|
158
|
+
corpus_id: str,
|
|
159
|
+
file_path: str | Path,
|
|
160
|
+
*,
|
|
161
|
+
description: str | None = None,
|
|
162
|
+
request_options: RequestOptions | None = None,
|
|
163
|
+
) -> GoldLabelsUploadResponse:
|
|
164
|
+
"""Upload gold labels from a JSONL file.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
corpus_id: ID of the corpus
|
|
168
|
+
file_path: Path to JSONL file with gold labels
|
|
169
|
+
description: Optional description of the labels source
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
GoldLabelsUploadResponse with resolution results
|
|
173
|
+
"""
|
|
174
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
175
|
+
import json
|
|
176
|
+
|
|
177
|
+
labels: list[GoldLabelEntry] = []
|
|
178
|
+
with open(file_path, "r") as f:
|
|
179
|
+
for line in f:
|
|
180
|
+
if line.strip():
|
|
181
|
+
labels.append(json.loads(line))
|
|
182
|
+
|
|
183
|
+
return await self.upload_gold_labels(
|
|
184
|
+
corpus_id, labels, description=description, request_options=request_options
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
async def list_gold_labels(
|
|
188
|
+
self,
|
|
189
|
+
corpus_id: str,
|
|
190
|
+
*,
|
|
191
|
+
limit: int = 100,
|
|
192
|
+
offset: int = 0,
|
|
193
|
+
request_options: RequestOptions | None = None,
|
|
194
|
+
) -> Page[dict[str, Any]]:
|
|
195
|
+
"""List gold labels for a corpus.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
corpus_id: ID of the corpus
|
|
199
|
+
limit: Maximum number of labels to return
|
|
200
|
+
offset: Offset for pagination
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
A Page containing gold label entries with pagination metadata.
|
|
204
|
+
"""
|
|
205
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
206
|
+
return await self._list_page(
|
|
207
|
+
"GET",
|
|
208
|
+
f"/v1/corpora/{corpus_id}/gold-labels",
|
|
209
|
+
items_key="labels",
|
|
210
|
+
limit=limit,
|
|
211
|
+
offset=offset,
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
def iter_gold_labels(
|
|
215
|
+
self,
|
|
216
|
+
corpus_id: str,
|
|
217
|
+
*,
|
|
218
|
+
limit: int = 100,
|
|
219
|
+
request_options: RequestOptions | None = None,
|
|
220
|
+
) -> AsyncPager[dict[str, Any]]:
|
|
221
|
+
"""Iterate over gold labels, automatically paginating."""
|
|
222
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
223
|
+
return self._paginate(
|
|
224
|
+
"GET",
|
|
225
|
+
f"/v1/corpora/{corpus_id}/gold-labels",
|
|
226
|
+
items_key="labels",
|
|
227
|
+
limit=limit,
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
# =========================================================================
|
|
231
|
+
# Synthetic Query Generation
|
|
232
|
+
# =========================================================================
|
|
233
|
+
|
|
234
|
+
async def generate_synthetic_queries(
|
|
235
|
+
self,
|
|
236
|
+
corpus_id: str,
|
|
237
|
+
analysis_id: str,
|
|
238
|
+
*,
|
|
239
|
+
sample_size: int = 0,
|
|
240
|
+
queries_per_chunk: int = 3,
|
|
241
|
+
use_document_context: bool = True,
|
|
242
|
+
eval_sample_size: int | None = None,
|
|
243
|
+
request_options: RequestOptions | None = None,
|
|
244
|
+
) -> SyntheticQueryBatchResponse:
|
|
245
|
+
"""Start synthetic query generation.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
corpus_id: ID of the corpus
|
|
249
|
+
analysis_id: ID of the analysis run to use
|
|
250
|
+
sample_size: Chunks to sample (0 = automatic bounded sample)
|
|
251
|
+
queries_per_chunk: Queries to generate per chunk
|
|
252
|
+
use_document_context: Inject document summaries into prompts
|
|
253
|
+
eval_sample_size: Override eval sample size (None = use default)
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
SyntheticQueryBatchResponse with batch_id and job_id
|
|
257
|
+
"""
|
|
258
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
259
|
+
analysis_id = require_str(analysis_id, "analysis_id")
|
|
260
|
+
payload: dict[str, Any] = {
|
|
261
|
+
"analysis_id": analysis_id,
|
|
262
|
+
"sample_size": sample_size,
|
|
263
|
+
"queries_per_chunk": queries_per_chunk,
|
|
264
|
+
"use_document_context": use_document_context,
|
|
265
|
+
}
|
|
266
|
+
if eval_sample_size is not None:
|
|
267
|
+
payload["eval_sample_size"] = eval_sample_size
|
|
268
|
+
|
|
269
|
+
data = await self._request(
|
|
270
|
+
"POST",
|
|
271
|
+
f"/v1/corpora/{corpus_id}/synthetic-queries:generate",
|
|
272
|
+
json=payload,
|
|
273
|
+
request_options=request_options,
|
|
274
|
+
)
|
|
275
|
+
return self._maybe_validate(data, "SyntheticQueryBatchResponse")
|
|
276
|
+
|
|
277
|
+
async def list_synthetic_batches(
|
|
278
|
+
self,
|
|
279
|
+
corpus_id: str,
|
|
280
|
+
request_options: RequestOptions | None = None,
|
|
281
|
+
) -> SyntheticQueryBatchListResponse:
|
|
282
|
+
"""List synthetic query batches for a corpus.
|
|
283
|
+
|
|
284
|
+
Args:
|
|
285
|
+
corpus_id: ID of the corpus
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
SyntheticQueryBatchListResponse with batches list
|
|
289
|
+
"""
|
|
290
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
291
|
+
data = await self._request(
|
|
292
|
+
"GET",
|
|
293
|
+
f"/v1/corpora/{corpus_id}/synthetic-queries/batches",
|
|
294
|
+
request_options=request_options,
|
|
295
|
+
)
|
|
296
|
+
return self._maybe_validate(data, "SyntheticQueryBatchListResponse")
|
|
297
|
+
|
|
298
|
+
async def get_synthetic_batch(
|
|
299
|
+
self,
|
|
300
|
+
corpus_id: str,
|
|
301
|
+
batch_id: str,
|
|
302
|
+
request_options: RequestOptions | None = None,
|
|
303
|
+
) -> SyntheticQueryBatchDetails:
|
|
304
|
+
"""Get details of a synthetic query batch.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
corpus_id: ID of the corpus
|
|
308
|
+
batch_id: ID of the batch
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
SyntheticQueryBatchDetails with full batch info
|
|
312
|
+
"""
|
|
313
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
314
|
+
batch_id = require_str(batch_id, "batch_id")
|
|
315
|
+
data = await self._request(
|
|
316
|
+
"GET",
|
|
317
|
+
f"/v1/corpora/{corpus_id}/synthetic-queries/batches/{batch_id}",
|
|
318
|
+
request_options=request_options,
|
|
319
|
+
)
|
|
320
|
+
return self._maybe_validate(data, "SyntheticQueryBatchDetails")
|
|
321
|
+
|
|
322
|
+
async def download_synthetic_queries(
|
|
323
|
+
self,
|
|
324
|
+
corpus_id: str,
|
|
325
|
+
batch_id: str,
|
|
326
|
+
output_path: str | Path,
|
|
327
|
+
request_options: RequestOptions | None = None,
|
|
328
|
+
) -> str:
|
|
329
|
+
"""Download synthetic queries from a batch.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
corpus_id: ID of the corpus
|
|
333
|
+
batch_id: ID of the batch
|
|
334
|
+
output_path: Path to save downloaded queries
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Path to the downloaded file
|
|
338
|
+
"""
|
|
339
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
340
|
+
batch_id = require_str(batch_id, "batch_id")
|
|
341
|
+
batch = await self.get_synthetic_batch(corpus_id, batch_id, request_options=request_options)
|
|
342
|
+
|
|
343
|
+
artifact_uri = (
|
|
344
|
+
batch.get("artifact_uri")
|
|
345
|
+
if isinstance(batch, dict)
|
|
346
|
+
else getattr(batch, "artifact_uri", None)
|
|
347
|
+
)
|
|
348
|
+
if not artifact_uri:
|
|
349
|
+
raise ValueError("Batch does not have an artifact URI")
|
|
350
|
+
|
|
351
|
+
return str(artifact_uri)
|
|
352
|
+
|
|
353
|
+
# =========================================================================
|
|
354
|
+
# Evaluation
|
|
355
|
+
# =========================================================================
|
|
356
|
+
|
|
357
|
+
async def evaluate_synthetic_queries(
|
|
358
|
+
self,
|
|
359
|
+
corpus_id: str,
|
|
360
|
+
batch_id: str,
|
|
361
|
+
*,
|
|
362
|
+
sample_size: int | None = None,
|
|
363
|
+
generate_report: bool = True,
|
|
364
|
+
report_formats: list[str] | None = None,
|
|
365
|
+
request_options: RequestOptions | None = None,
|
|
366
|
+
) -> EvaluationResponse:
|
|
367
|
+
"""Start evaluation of synthetic queries.
|
|
368
|
+
|
|
369
|
+
Args:
|
|
370
|
+
corpus_id: ID of the corpus
|
|
371
|
+
batch_id: ID of the synthetic query batch
|
|
372
|
+
sample_size: Sample for evaluation (None or 0 = automatic bounded sample)
|
|
373
|
+
generate_report: Generate HTML/JSON report
|
|
374
|
+
report_formats: Report formats to generate
|
|
375
|
+
|
|
376
|
+
Returns:
|
|
377
|
+
EvaluationResponse with eval_id and job_id
|
|
378
|
+
"""
|
|
379
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
380
|
+
batch_id = require_str(batch_id, "batch_id")
|
|
381
|
+
payload: dict[str, Any] = {
|
|
382
|
+
"batch_id": batch_id,
|
|
383
|
+
"generate_report": generate_report,
|
|
384
|
+
}
|
|
385
|
+
if sample_size is not None:
|
|
386
|
+
payload["sample_size"] = sample_size
|
|
387
|
+
if report_formats is not None:
|
|
388
|
+
payload["report_formats"] = report_formats
|
|
389
|
+
|
|
390
|
+
data = await self._request(
|
|
391
|
+
"POST",
|
|
392
|
+
f"/v1/corpora/{corpus_id}/synthetic-queries:evaluate",
|
|
393
|
+
json=payload,
|
|
394
|
+
request_options=request_options,
|
|
395
|
+
)
|
|
396
|
+
return self._maybe_validate(data, "EvaluationResponse")
|
|
397
|
+
|
|
398
|
+
async def list_evaluations(
|
|
399
|
+
self,
|
|
400
|
+
corpus_id: str,
|
|
401
|
+
request_options: RequestOptions | None = None,
|
|
402
|
+
) -> EvaluationListResponse:
|
|
403
|
+
"""List evaluations for a corpus.
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
corpus_id: ID of the corpus
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
EvaluationListResponse with evaluations list
|
|
410
|
+
"""
|
|
411
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
412
|
+
data = await self._request(
|
|
413
|
+
"GET", f"/v1/corpora/{corpus_id}/evaluations", request_options=request_options
|
|
414
|
+
)
|
|
415
|
+
return self._maybe_validate(data, "EvaluationListResponse")
|
|
416
|
+
|
|
417
|
+
async def get_evaluation(
|
|
418
|
+
self,
|
|
419
|
+
corpus_id: str,
|
|
420
|
+
eval_id: str,
|
|
421
|
+
request_options: RequestOptions | None = None,
|
|
422
|
+
) -> EvaluationDetails:
|
|
423
|
+
"""Get details of an evaluation.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
corpus_id: ID of the corpus
|
|
427
|
+
eval_id: ID of the evaluation
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
EvaluationDetails with full evaluation results
|
|
431
|
+
"""
|
|
432
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
433
|
+
eval_id = require_str(eval_id, "eval_id")
|
|
434
|
+
data = await self._request(
|
|
435
|
+
"GET", f"/v1/corpora/{corpus_id}/evaluations/{eval_id}", request_options=request_options
|
|
436
|
+
)
|
|
437
|
+
return self._maybe_validate(data, "EvaluationDetails")
|
|
438
|
+
|
|
439
|
+
async def get_evaluation_report(
|
|
440
|
+
self,
|
|
441
|
+
corpus_id: str,
|
|
442
|
+
eval_id: str,
|
|
443
|
+
*,
|
|
444
|
+
format: str = "json",
|
|
445
|
+
request_options: RequestOptions | None = None,
|
|
446
|
+
) -> EvaluationReportResponse:
|
|
447
|
+
"""Get evaluation report.
|
|
448
|
+
|
|
449
|
+
Args:
|
|
450
|
+
corpus_id: ID of the corpus
|
|
451
|
+
eval_id: ID of the evaluation
|
|
452
|
+
format: Report format ("json" or "html")
|
|
453
|
+
|
|
454
|
+
Returns:
|
|
455
|
+
EvaluationReportResponse with report URI and metrics
|
|
456
|
+
"""
|
|
457
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
458
|
+
eval_id = require_str(eval_id, "eval_id")
|
|
459
|
+
data = await self._request(
|
|
460
|
+
"GET",
|
|
461
|
+
f"/v1/corpora/{corpus_id}/evaluations/{eval_id}/report",
|
|
462
|
+
params={"format": format},
|
|
463
|
+
request_options=request_options,
|
|
464
|
+
)
|
|
465
|
+
return self._maybe_validate(data, "EvaluationReportResponse")
|
|
466
|
+
|
|
467
|
+
# =========================================================================
|
|
468
|
+
# Document Summarization
|
|
469
|
+
# =========================================================================
|
|
470
|
+
|
|
471
|
+
async def summarize_documents(
|
|
472
|
+
self,
|
|
473
|
+
corpus_id: str,
|
|
474
|
+
*,
|
|
475
|
+
force_regenerate: bool = False,
|
|
476
|
+
request_options: RequestOptions | None = None,
|
|
477
|
+
) -> SummarizationResponse:
|
|
478
|
+
"""Start document summarization.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
corpus_id: ID of the corpus
|
|
482
|
+
force_regenerate: Regenerate summaries for all documents
|
|
483
|
+
|
|
484
|
+
Returns:
|
|
485
|
+
SummarizationResponse with job_id and stats
|
|
486
|
+
"""
|
|
487
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
488
|
+
payload: dict[str, Any] = {"force_regenerate": force_regenerate}
|
|
489
|
+
data = await self._request(
|
|
490
|
+
"POST",
|
|
491
|
+
f"/v1/corpora/{corpus_id}/documents:summarize",
|
|
492
|
+
json=payload,
|
|
493
|
+
request_options=request_options,
|
|
494
|
+
)
|
|
495
|
+
return self._maybe_validate(data, "SummarizationResponse")
|
|
496
|
+
|
|
497
|
+
async def get_summarization_status(
|
|
498
|
+
self,
|
|
499
|
+
corpus_id: str,
|
|
500
|
+
request_options: RequestOptions | None = None,
|
|
501
|
+
) -> SummarizationStatusResponse:
|
|
502
|
+
"""Get summarization status for a corpus.
|
|
503
|
+
|
|
504
|
+
Args:
|
|
505
|
+
corpus_id: ID of the corpus
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
SummarizationStatusResponse with coverage stats
|
|
509
|
+
"""
|
|
510
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
511
|
+
data = await self._request(
|
|
512
|
+
"GET", f"/v1/corpora/{corpus_id}/summaries/status", request_options=request_options
|
|
513
|
+
)
|
|
514
|
+
return self._maybe_validate(data, "SummarizationStatusResponse")
|
|
515
|
+
|
|
516
|
+
async def get_document_summary(
|
|
517
|
+
self,
|
|
518
|
+
corpus_id: str,
|
|
519
|
+
doc_id: str,
|
|
520
|
+
request_options: RequestOptions | None = None,
|
|
521
|
+
) -> DocumentSummaryResponse:
|
|
522
|
+
"""Get summary for a specific document.
|
|
523
|
+
|
|
524
|
+
Args:
|
|
525
|
+
corpus_id: ID of the corpus
|
|
526
|
+
doc_id: ID of the document
|
|
527
|
+
|
|
528
|
+
Returns:
|
|
529
|
+
DocumentSummaryResponse with summary and entities
|
|
530
|
+
"""
|
|
531
|
+
corpus_id = require_str(corpus_id, "corpus_id")
|
|
532
|
+
doc_id = require_str(doc_id, "doc_id")
|
|
533
|
+
data = await self._request(
|
|
534
|
+
"GET",
|
|
535
|
+
f"/v1/corpora/{corpus_id}/documents/{doc_id}/summary",
|
|
536
|
+
request_options=request_options,
|
|
537
|
+
)
|
|
538
|
+
return self._maybe_validate(data, "DocumentSummaryResponse")
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""Async organisation resource mixin for the Knowledge2 SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from sdk._request_options import RequestOptions
|
|
8
|
+
from sdk.async_resources._mixin_base import AsyncRequesterMixin
|
|
9
|
+
from sdk.types import OrgResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AsyncOrgsMixin(AsyncRequesterMixin):
|
|
13
|
+
async def create_org(
|
|
14
|
+
self,
|
|
15
|
+
name: str,
|
|
16
|
+
contact_email: str | None = None,
|
|
17
|
+
request_options: RequestOptions | None = None,
|
|
18
|
+
) -> OrgResponse:
|
|
19
|
+
"""Create a new organisation.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
name: Display name for the organisation.
|
|
23
|
+
contact_email: Optional contact email address for the org.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
The newly created organisation record.
|
|
27
|
+
|
|
28
|
+
Raises:
|
|
29
|
+
Knowledge2Error: If the API request fails.
|
|
30
|
+
"""
|
|
31
|
+
payload: dict[str, Any] = {"name": name}
|
|
32
|
+
if contact_email is not None:
|
|
33
|
+
payload["contact_email"] = contact_email
|
|
34
|
+
data = await self._request(
|
|
35
|
+
"POST", "/v1/orgs", json=payload, request_options=request_options
|
|
36
|
+
)
|
|
37
|
+
return self._maybe_validate(data, "OrgResponse")
|