vectoramp 0.1.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.
- vectoramp/__init__.py +45 -0
- vectoramp/client.py +133 -0
- vectoramp/connections.py +123 -0
- vectoramp/embeddings.py +39 -0
- vectoramp/exceptions.py +22 -0
- vectoramp/py.typed +0 -0
- vectoramp/resources.py +1531 -0
- vectoramp/sources.py +506 -0
- vectoramp/transport.py +198 -0
- vectoramp/types.py +145 -0
- vectoramp-0.1.0.dist-info/METADATA +464 -0
- vectoramp-0.1.0.dist-info/RECORD +15 -0
- vectoramp-0.1.0.dist-info/WHEEL +4 -0
- vectoramp-0.1.0.dist-info/licenses/LICENSE +201 -0
- vectoramp-0.1.0.dist-info/licenses/NOTICE +8 -0
vectoramp/types.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Public type aliases used by the VectorAmp SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, List, Literal, Mapping, Optional, Sequence, TypedDict, Union
|
|
6
|
+
|
|
7
|
+
JSON = Dict[str, Any]
|
|
8
|
+
Metadata = Mapping[str, Any]
|
|
9
|
+
Metric = Literal["cosine", "dot", "euclidean"]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class EmbeddingConfig(TypedDict):
|
|
13
|
+
provider: str
|
|
14
|
+
model: str
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# A vector record id may be a string or an integer. Integer ids are serialized
|
|
18
|
+
# as JSON numbers (not coerced to strings) so the API preserves them verbatim.
|
|
19
|
+
VectorId = Union[str, int]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Vector(TypedDict, total=False):
|
|
23
|
+
id: VectorId
|
|
24
|
+
values: Sequence[float]
|
|
25
|
+
metadata: Metadata
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ConversationTurn(TypedDict):
|
|
29
|
+
role: Literal["user", "assistant", "system"]
|
|
30
|
+
content: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class Page(TypedDict):
|
|
34
|
+
total: int
|
|
35
|
+
limit: int
|
|
36
|
+
offset: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class DatasetPage(Page, total=False):
|
|
40
|
+
datasets: List[JSON]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SourcePage(Page, total=False):
|
|
44
|
+
sources: List[JSON]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class JobPage(Page, total=False):
|
|
48
|
+
jobs: List[JSON]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
FilterValue = Union[str, int, float, bool, None]
|
|
52
|
+
Filters = Mapping[str, FilterValue]
|
|
53
|
+
AdvancedFilter = Mapping[str, Any]
|
|
54
|
+
OptionalJSON = Optional[Mapping[str, Any]]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class SourceChunk(TypedDict, total=False):
|
|
59
|
+
chunk_id: str
|
|
60
|
+
score: float
|
|
61
|
+
text: str
|
|
62
|
+
chunk_index: int
|
|
63
|
+
sheet_name: str
|
|
64
|
+
row_start: int
|
|
65
|
+
row_end: int
|
|
66
|
+
column_names: List[str]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class SourceCitation(TypedDict, total=False):
|
|
70
|
+
name: str
|
|
71
|
+
path: str
|
|
72
|
+
url: str
|
|
73
|
+
dataset_id: str
|
|
74
|
+
dataset_document_id: str
|
|
75
|
+
source_type: str
|
|
76
|
+
content_type: str
|
|
77
|
+
relevance: float
|
|
78
|
+
pages: List[int]
|
|
79
|
+
sheet_names: List[str]
|
|
80
|
+
chunk_count: int
|
|
81
|
+
preview: str
|
|
82
|
+
chunks: List[SourceChunk]
|
|
83
|
+
timestamp_start: Union[int, float, str]
|
|
84
|
+
timestamp_end: Union[int, float, str]
|
|
85
|
+
file_id: str
|
|
86
|
+
thumbnail_url: str
|
|
87
|
+
preview_ref: str
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class RAGChunk(TypedDict, total=False):
|
|
91
|
+
id: str
|
|
92
|
+
text: str
|
|
93
|
+
score: float
|
|
94
|
+
source: str
|
|
95
|
+
source_url: str
|
|
96
|
+
page: Union[int, str]
|
|
97
|
+
metadata: JSON
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class QueryResponse(TypedDict, total=False):
|
|
101
|
+
answer: str
|
|
102
|
+
sources: List[SourceCitation]
|
|
103
|
+
chunks: List[RAGChunk]
|
|
104
|
+
message: Optional[str]
|
|
105
|
+
metadata: JSON
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class SessionCreateRequest(TypedDict, total=False):
|
|
109
|
+
title: str
|
|
110
|
+
workspace_id: str
|
|
111
|
+
dataset_id: str
|
|
112
|
+
metadata: JSON
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class IntelligenceSession(TypedDict, total=False):
|
|
116
|
+
id: str
|
|
117
|
+
title: str
|
|
118
|
+
workspace_id: str
|
|
119
|
+
dataset_id: str
|
|
120
|
+
metadata: JSON
|
|
121
|
+
created_at: str
|
|
122
|
+
updated_at: str
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class SessionMessageCreateRequest(TypedDict, total=False):
|
|
126
|
+
role: Literal["user", "assistant", "system", "tool"]
|
|
127
|
+
content: str
|
|
128
|
+
metadata: JSON
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class SessionMessage(TypedDict, total=False):
|
|
132
|
+
id: str
|
|
133
|
+
session_id: str
|
|
134
|
+
role: Literal["user", "assistant", "system", "tool"]
|
|
135
|
+
content: str
|
|
136
|
+
metadata: JSON
|
|
137
|
+
created_at: str
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
class SessionList(TypedDict, total=False):
|
|
141
|
+
sessions: List[IntelligenceSession]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class MessageList(TypedDict, total=False):
|
|
145
|
+
messages: List[SessionMessage]
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vectoramp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the VectorAmp API
|
|
5
|
+
Project-URL: Homepage, https://vectoramp.com
|
|
6
|
+
Project-URL: Documentation, https://docs.vectoramp.com
|
|
7
|
+
Project-URL: Repository, https://github.com/VectorAmp/vectoramp-python
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/VectorAmp/vectoramp-python/issues
|
|
9
|
+
Author: VectorAmp, Inc.
|
|
10
|
+
License-Expression: Apache-2.0
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
License-File: NOTICE
|
|
13
|
+
Keywords: rag,sable,vector database,vectoramp
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Requires-Dist: httpx<1,>=0.25
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
<div align="center">
|
|
32
|
+
<a href="https://vectoramp.com/">
|
|
33
|
+
<picture>
|
|
34
|
+
<source media="(prefers-color-scheme: light)" srcset=".github/images/logo-full-light.svg">
|
|
35
|
+
<source media="(prefers-color-scheme: dark)" srcset=".github/images/logo-full-dark.svg">
|
|
36
|
+
<img alt="VectorAmp Logo" src=".github/images/logo-full-dark.svg" width="50%">
|
|
37
|
+
</picture>
|
|
38
|
+
</a>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
# VectorAmp Python SDK
|
|
42
|
+
|
|
43
|
+
Python client for the VectorAmp API. It is package-ready, typed, and defaults to `https://api.vectoramp.com`.
|
|
44
|
+
|
|
45
|
+
Licensed under the [Apache License 2.0](LICENSE).
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install vectoramp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For local development:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
git clone https://github.com/VectorAmp/vectoramp-python.git
|
|
57
|
+
cd vectoramp-python
|
|
58
|
+
pip install -e '.[dev]'
|
|
59
|
+
pytest
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Authentication
|
|
63
|
+
|
|
64
|
+
The SDK sends API keys with the `X-API-Key` header.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from vectoramp import VectorAmp
|
|
68
|
+
|
|
69
|
+
client = VectorAmp(api_key="va_...")
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or use the environment variable:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
export VECTORAMP_API_KEY=va_...
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
client = VectorAmp()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Configure a non-production API host with `base_url`:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
client = VectorAmp(api_key="va_...", base_url="http://localhost:8080")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Datasets
|
|
89
|
+
|
|
90
|
+
Dataset creation always requests the SABLE index. The SDK intentionally does **not** expose an `index_type` option. Built-in helpers infer dimensions for VectorAmp 4B and OpenAI `text-embedding-3-small`/`text-embedding-3-large`.
|
|
91
|
+
|
|
92
|
+
The only required argument is `name`. The default embedding is `VectorAmp-Embedding-4B` (`dim=2560`, `metric="cosine"`):
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
dataset = client.datasets.create("product-docs")
|
|
96
|
+
|
|
97
|
+
dataset_id = dataset.id # also available as dataset["id"] for compatibility
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Enable hybrid (dense + sparse) indexing with `hybrid=True`:
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
dataset = client.datasets.create("product-docs", hybrid=True)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Bring your own embedding model with the `openai` helper (dimension is inferred):
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from vectoramp import openai
|
|
110
|
+
|
|
111
|
+
dataset = client.datasets.create(
|
|
112
|
+
"product-docs",
|
|
113
|
+
embedding=openai("small"), # or openai("large")
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
For a custom/unknown model you must pass `dim` explicitly:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
dataset = client.datasets.create(
|
|
121
|
+
"product-docs",
|
|
122
|
+
embedding={"provider": "acme", "model": "acme-embed-v1"},
|
|
123
|
+
dim=1024,
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Create/get/list return `Dataset` resource objects. They keep the raw API payload and
|
|
128
|
+
carry the client/services needed for instance methods:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
dataset = client.datasets.get(dataset_id)
|
|
132
|
+
print(dataset.id, dataset.raw_data)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
List methods return the API pagination envelope with `Dataset` objects in the `datasets` field:
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
page = client.datasets.list(limit=50, offset=0)
|
|
139
|
+
for dataset in page["datasets"]:
|
|
140
|
+
print(dataset.id, dataset.raw_data)
|
|
141
|
+
print(page["total"], page["limit"], page["offset"])
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Service-style methods are still available for callers that prefer passing `dataset_id` explicitly.
|
|
145
|
+
Get or delete a dataset:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
client.datasets.get(dataset_id)
|
|
149
|
+
client.datasets.delete(dataset_id)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Insert vectors and texts
|
|
153
|
+
|
|
154
|
+
Insert raw vectors. A record `id` may be a string **or** an integer; integer ids
|
|
155
|
+
are sent as JSON numbers, not coerced to strings:
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
dataset.insert(
|
|
159
|
+
[
|
|
160
|
+
{
|
|
161
|
+
"id": "doc-001",
|
|
162
|
+
"values": [0.1, 0.2, 0.3],
|
|
163
|
+
"metadata": {"title": "Intro", "source": "manual"},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"id": 42, # preserved as a JSON number
|
|
167
|
+
"values": [0.4, 0.5, 0.6],
|
|
168
|
+
"metadata": {"title": "Appendix"},
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Embed text with the dataset's configured model and insert the resulting vectors:
|
|
175
|
+
|
|
176
|
+
```python
|
|
177
|
+
dataset.add_texts("VectorAmp uses SABLE for high-performance vector search.")
|
|
178
|
+
|
|
179
|
+
# Optional IDs and metadata are still supported for batches.
|
|
180
|
+
dataset.add_texts(
|
|
181
|
+
["VectorAmp uses SABLE for high-performance vector search."],
|
|
182
|
+
ids=["sable-note"],
|
|
183
|
+
metadatas=[{"source": "readme"}],
|
|
184
|
+
)
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Search
|
|
188
|
+
|
|
189
|
+
Search by text:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
results = dataset.search("How does SABLE work?", top_k=10, include_documents=True)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Search by vector:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
results = dataset.search([0.1, 0.2, 0.3], top_k=5)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Hybrid and filtered search:
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
results = dataset.search(
|
|
205
|
+
text="wireless headphones",
|
|
206
|
+
top_k=10,
|
|
207
|
+
filters={"category": "electronics"},
|
|
208
|
+
advanced_filters=[{"field": "price", "op": "lt", "value": 100}],
|
|
209
|
+
hybrid=True,
|
|
210
|
+
sparse_query="wireless headphones",
|
|
211
|
+
alpha=0.7,
|
|
212
|
+
rerank={"enabled": True}, # vectoramp / VectorAmp-Rerank-v1
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Ingestion
|
|
217
|
+
|
|
218
|
+
Start ingestion from an existing source:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
job = dataset.ingest_source("source-uuid")
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Or pass a typed source builder. The SDK creates the source, extracts its returned ID,
|
|
225
|
+
and starts the ingestion job for the dataset:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from vectoramp import WebSource
|
|
229
|
+
|
|
230
|
+
job = dataset.ingest_source(
|
|
231
|
+
WebSource(
|
|
232
|
+
start_urls=["https://docs.example.com/"],
|
|
233
|
+
max_depth=1,
|
|
234
|
+
)
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The same one-liner works for any source type, e.g. Confluence:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from vectoramp import ConfluenceSource
|
|
242
|
+
|
|
243
|
+
job = dataset.ingest_source(
|
|
244
|
+
ConfluenceSource(
|
|
245
|
+
base_url="https://acme.atlassian.net",
|
|
246
|
+
username="user@example.com",
|
|
247
|
+
api_token="…",
|
|
248
|
+
spaces=["ENG"],
|
|
249
|
+
)
|
|
250
|
+
)
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
List jobs with pagination:
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
jobs = client.ingestion.list_jobs(dataset_id=dataset_id, limit=50, offset=0)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Create sources with typed helpers. `client.sources` is an alias for the ingestion
|
|
260
|
+
source APIs, so existing `client.ingestion.create_source(...)` code still works:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
web = client.sources.create_web(
|
|
264
|
+
start_urls=["https://docs.example.com/"],
|
|
265
|
+
max_depth=1,
|
|
266
|
+
include_assets=True,
|
|
267
|
+
max_assets_per_page=5,
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
s3 = client.sources.create_s3(
|
|
271
|
+
bucket="my-bucket",
|
|
272
|
+
prefix="documents/",
|
|
273
|
+
role_arn="arn:aws:iam::123456789012:role/vectoramp-ingestion",
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
gcs = client.sources.create_gcs(bucket="my-gcs-bucket", prefix="documents/")
|
|
277
|
+
|
|
278
|
+
jira = client.sources.create_jira(
|
|
279
|
+
cloud_id="atlassian-cloud-id",
|
|
280
|
+
project_keys=["ENG"],
|
|
281
|
+
include_comments=True, # default
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
confluence = client.sources.create_confluence(
|
|
285
|
+
cloud_id="atlassian-cloud-id", # or base_url="https://acme.atlassian.net"
|
|
286
|
+
username="user@example.com",
|
|
287
|
+
api_token="…", # auth_mode defaults to "basic"
|
|
288
|
+
spaces=["ENG", "DOCS"], # empty/omitted = all accessible spaces
|
|
289
|
+
include_attachments=True, # default False
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
gdrive = client.sources.create_google_drive(
|
|
293
|
+
folder_ids=["drive-folder-id"],
|
|
294
|
+
include_shared_drives=True,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
upload_source = client.sources.create_file_upload()
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`sync_mode` is omitted unless you set it, so the server applies its default of
|
|
301
|
+
`"incremental"` for the connectors that support it. Pass `sync_mode="full"` to
|
|
302
|
+
force a full re-sync.
|
|
303
|
+
|
|
304
|
+
The supported typed source classes are `WebSource`, `S3Source`, `GCSSource`,
|
|
305
|
+
`GoogleDriveSource` (`source_type="gdrive"`), `JiraSource`, `ConfluenceSource`,
|
|
306
|
+
and `FileUploadSource` (`source_type="file_upload"`). Use `GenericSource` as an
|
|
307
|
+
escape hatch when the API supports a source type before the SDK has a dedicated
|
|
308
|
+
class:
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
from vectoramp import GenericSource
|
|
312
|
+
|
|
313
|
+
source = client.sources.create(
|
|
314
|
+
GenericSource(
|
|
315
|
+
name="custom-source",
|
|
316
|
+
source_type="custom",
|
|
317
|
+
config={"any_api_field": "value"},
|
|
318
|
+
)
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
The low-level create API is preserved:
|
|
323
|
+
|
|
324
|
+
```python
|
|
325
|
+
source = client.ingestion.create_source(
|
|
326
|
+
name="docs-site",
|
|
327
|
+
source_type="web",
|
|
328
|
+
config={"start_urls": ["https://docs.example.com/"], "max_depth": 1},
|
|
329
|
+
)
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Upload local files through the REST upload flow. The SDK creates a `file_upload` source with a generated name when `source_name` is omitted, initializes presigned uploads, uploads bytes to the returned URLs, and completes the upload job:
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
job = dataset.ingest_files(["./docs/whitepaper.pdf", "./docs/overview.txt"])
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Pass `source_name="product-docs-upload"` only when you want a specific source name.
|
|
339
|
+
|
|
340
|
+
## Intelligence / RAG
|
|
341
|
+
|
|
342
|
+
Non-streaming query:
|
|
343
|
+
|
|
344
|
+
```python
|
|
345
|
+
answer = dataset.ask("What are the key product features?", top_k=5)
|
|
346
|
+
print(answer["answer"])
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Streaming SSE query:
|
|
350
|
+
|
|
351
|
+
```python
|
|
352
|
+
for event in client.ask_stream("Summarize the docs", dataset_id=dataset_id):
|
|
353
|
+
if event["chunk_type"] == "text":
|
|
354
|
+
print(event["content"], end="")
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Transport abstraction
|
|
358
|
+
|
|
359
|
+
`VectorAmp` depends on a small transport interface. `RestTransport` is provided today; a future gRPC transport can implement the same `request`, `stream`, and `close` methods without changing resource UX.
|
|
360
|
+
|
|
361
|
+
## Development
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
pip install -e '.[dev]'
|
|
365
|
+
ruff check .
|
|
366
|
+
mypy src
|
|
367
|
+
pytest
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
CI runs Ruff, mypy, and pytest with coverage on every change.
|
|
371
|
+
|
|
372
|
+
## Dataset documents
|
|
373
|
+
|
|
374
|
+
Datasets expose retained source documents when ingestion stored originals:
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
page = client.datasets.list_documents("dataset_id", limit=50, cursor=None, status="ready")
|
|
378
|
+
for document in page.get("documents", []):
|
|
379
|
+
print(document["id"], document.get("file_name"))
|
|
380
|
+
|
|
381
|
+
content = client.datasets.download_document("dataset_id", "document_id")
|
|
382
|
+
open("document.bin", "wb").write(content)
|
|
383
|
+
|
|
384
|
+
# Resource-style calls work too:
|
|
385
|
+
dataset = client.datasets.get("dataset_id")
|
|
386
|
+
dataset.list_documents()
|
|
387
|
+
dataset.download_document("document_id")
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Intelligence sessions
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
session = client.intelligence.create_session(title="Planning", dataset_id=dataset.id)
|
|
394
|
+
client.intelligence.append_message(session["id"], role="user", content="Summarize the docs")
|
|
395
|
+
messages = client.intelligence.list_messages(session["id"], limit=100)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Intelligence answers return `sources[]` and `chunks[]`. Inline `[1]` citations refer to `sources[0]`; `preview_ref` is an opaque preview token, not a storage key.
|
|
399
|
+
|
|
400
|
+
## Method reference
|
|
401
|
+
|
|
402
|
+
Both access styles work everywhere the SDK allows it:
|
|
403
|
+
`client.datasets.search(id, …)` and `dataset.search(…)`. Required arguments are
|
|
404
|
+
listed first; optional arguments show their default.
|
|
405
|
+
|
|
406
|
+
### Client (`VectorAmp`)
|
|
407
|
+
|
|
408
|
+
- `VectorAmp(api_key=None, *, base_url="https://api.vectoramp.com", timeout=30.0)` — `api_key` falls back to `VECTORAMP_API_KEY`.
|
|
409
|
+
- `client.ask(query, *, dataset_id=None, top_k=5, conversation_history=None, include_sources=True)`
|
|
410
|
+
- `client.ask_stream(query, *, dataset_id=None, top_k=5, conversation_history=None, include_sources=True)` — iterator of SSE chunks.
|
|
411
|
+
- `client.close()` (also a context manager).
|
|
412
|
+
|
|
413
|
+
### Datasets (`client.datasets` / `Dataset`)
|
|
414
|
+
|
|
415
|
+
- `create(name, *, dim=None, metric="cosine", embedding=None, embedding_provider="vectoramp", embedding_model="VectorAmp-Embedding-4B", hybrid=False, filters=None, metadata_schema=None, tuning=None)` → `Dataset`. Always SABLE. `dim` inferred for built-in models; required for custom models.
|
|
416
|
+
- `list(*, limit=50, offset=0)` → page with `Dataset` objects.
|
|
417
|
+
- `get(dataset_id)` → `Dataset`.
|
|
418
|
+
- `delete(dataset_id)` / `dataset.delete()`.
|
|
419
|
+
- `stats(dataset_id)` / `dataset.stats()`.
|
|
420
|
+
- `search(dataset_id, query=None, *, vector=None, text=None, search_text=None, top_k=10, filters=None, advanced_filters=None, embedding_provider=None, embedding_model=None, nprobe_override=None, rerank_depth_override=None, hybrid=None, sparse_query=None, alpha=None, include_embeddings=None, include_documents=None, include_metadata=None, rerank=None)` / `dataset.search(…)`. `query` accepts a string (text) or float sequence (vector); `top_k` defaults to 10.
|
|
421
|
+
- `insert(dataset_id, vectors)` and `insert_vectors(dataset_id, vectors)` / `dataset.insert(vectors)`. Record `id` may be `str` or `int` (integers stay JSON numbers).
|
|
422
|
+
- `embed(dataset_id, *, text=None, texts=None)` / `dataset.embed(…)`.
|
|
423
|
+
- `add_texts(dataset_id, texts, *, ids=None, metadatas=None)` / `dataset.add_texts(texts, …)`. Single string or list; ids auto-generated when omitted; copies the text into `metadata.text`.
|
|
424
|
+
- `list_documents(dataset_id, *, limit=50, cursor=None, status=None)` / `dataset.list_documents(…)`.
|
|
425
|
+
- `download_document(dataset_id, document_id)` / `dataset.download_document(document_id)` → bytes.
|
|
426
|
+
- `ensure_engine(dataset_id)`.
|
|
427
|
+
- `dataset.ask(query, *, top_k=5, conversation_history=None, include_sources=True)`.
|
|
428
|
+
- `dataset.ingest_source(source, *, pipeline_id=None)` — `source` is an id or a source builder.
|
|
429
|
+
- `dataset.ingest_files(paths, *, source_name=None, description=None)`.
|
|
430
|
+
|
|
431
|
+
### Sources / ingestion (`client.sources` is an alias of `client.ingestion`)
|
|
432
|
+
|
|
433
|
+
- `create(source)` / `create_source(source=None, *, name=None, source_type=None, config=None, description=None, metadata=None)`.
|
|
434
|
+
- `create_web(*, start_urls, name=None, max_depth=None, max_pages=None, allowed_domains=None, include_patterns=None, exclude_patterns=None, crawl_delay_seconds=None, include_assets=None, max_assets_per_page=None, sync_mode omitted via builder, description=None, metadata=None, config_extra=None)`.
|
|
435
|
+
- `create_s3(*, bucket, name=None, region="us-east-1", prefix=None, sync_mode=None, access_key_id=None, secret_access_key=None, role_arn=None, endpoint_url=None, file_patterns=None, max_file_size_mb=None, …)`.
|
|
436
|
+
- `create_gcs(*, bucket, name=None, prefix=None, project_id=None, credentials_json=None, sync_mode=None, file_patterns=None, max_file_size_mb=None, …)`.
|
|
437
|
+
- `create_jira(*, cloud_id, name=None, access_token=None, project_keys=None, jql=None, include_comments=True, sync_mode=None, …)`.
|
|
438
|
+
- `create_confluence(*, cloud_id=None, base_url=None, name=None, auth_mode="basic", username=None, api_token=None, oauth_credentials=None, spaces=None, include_attachments=False, sync_mode=None, …)` — requires `cloud_id` or `base_url`.
|
|
439
|
+
- `create_google_drive(*, name=None, folder_ids=None, file_ids=None, auth_mode="oauth", oauth_credentials=None, include_shared_drives=None, sync_mode=None, service_account_json=None, credentials_json=None, …)`.
|
|
440
|
+
- `create_file_upload(*, name="vectoramp-python-upload", storage_provider="s3", sync_mode="full", …)`.
|
|
441
|
+
- `list_sources(*, limit=50, offset=0)`, `get_source(source_id)`.
|
|
442
|
+
- `start_job(*, source_id, dataset_id, pipeline_id=None)`, `list_jobs(*, dataset_id=None, limit=50, offset=0)`, `get_job(job_id)`, `retry_job(job_id)`.
|
|
443
|
+
- `ingest_files(*, dataset_id, paths, source_name=None, description=None)`, `init_upload(source_id, files)`, `complete_upload(source_id, *, job_id, file_ids)`.
|
|
444
|
+
|
|
445
|
+
Builder classes: `WebSource`, `S3Source`, `GCSSource`, `GoogleDriveSource`, `JiraSource`, `ConfluenceSource`, `FileUploadSource`, `GenericSource` (escape hatch). `sync_mode` is omitted unless set, so the server default (`"incremental"`) applies.
|
|
446
|
+
|
|
447
|
+
### Schedules (`client.schedules`)
|
|
448
|
+
|
|
449
|
+
- `list(*, limit=50, offset=0)`, `get(schedule_id)`.
|
|
450
|
+
- `create(*, source_id, dataset_id, cron, timezone=None, pipeline_id=None, enabled=None, name=None, metadata=None)`.
|
|
451
|
+
- `update(schedule_id, *, cron=None, timezone=None, pipeline_id=None, enabled=None, name=None, metadata=None)` — only passed fields change.
|
|
452
|
+
- `delete(schedule_id)`, `trigger(schedule_id)`.
|
|
453
|
+
|
|
454
|
+
### Intelligence (`client.intelligence`)
|
|
455
|
+
|
|
456
|
+
- `query(query, *, dataset_id=None, top_k=5, conversation_history=None, include_sources=True)`.
|
|
457
|
+
- `stream(query, *, …)` — iterator of SSE chunks.
|
|
458
|
+
- `create_session(*, title=None, workspace_id=None, dataset_id=None, metadata=None)`.
|
|
459
|
+
- `list_sessions(*, limit=50)`, `get_session(session_id)`.
|
|
460
|
+
- `append_message(session_id, *, role, content, metadata=None)`, `list_messages(session_id, *, limit=100)`.
|
|
461
|
+
|
|
462
|
+
## License
|
|
463
|
+
|
|
464
|
+
Apache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
vectoramp/__init__.py,sha256=5i3v0R7IVbtVLGXfccgdkg0eivUqNFMDyoNvL15AjOc,949
|
|
2
|
+
vectoramp/client.py,sha256=reHf_A72K0VmNd1-x5pF0SKUXIDbRdvp4r9wmyklr1I,4692
|
|
3
|
+
vectoramp/connections.py,sha256=DvsSrEao065otFvxu76ZOTyOpGrar3NCsGrE6OC8J7U,4798
|
|
4
|
+
vectoramp/embeddings.py,sha256=ekWa-lAOKWkVIC520UdUz-g1FQuJMdbvBTrjCRRG5BE,1093
|
|
5
|
+
vectoramp/exceptions.py,sha256=2Hc1fVLiS60hn4N_tXs1tg-TMhmEUmMfKxHWq8t3eqE,571
|
|
6
|
+
vectoramp/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
vectoramp/resources.py,sha256=ExpFaw_UM4TikTodagWai1Ipd_oZjOibntMvR1Q5TLc,57362
|
|
8
|
+
vectoramp/sources.py,sha256=spSNg-hcr8lz9h3PieXR8tqqAiLBMRlDaHSNJ9GSQXU,19973
|
|
9
|
+
vectoramp/transport.py,sha256=_WvbTxsv4wjWqSmfNnu0NMHwYbRz56PcmKWEwTDj_M8,6167
|
|
10
|
+
vectoramp/types.py,sha256=EAnQOfco6sIn-Gni15VIo6B_oH9MVGq1Xcy58TzmmrM,2992
|
|
11
|
+
vectoramp-0.1.0.dist-info/METADATA,sha256=Q4-DFjlwxkHIBxbwJ2rsww4MxAwH95xj_YmfOBE0prk,16441
|
|
12
|
+
vectoramp-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
13
|
+
vectoramp-0.1.0.dist-info/licenses/LICENSE,sha256=pToQoiFdpl-aQJ0kCxONCNoVvUQ_9usIzPZZ4hRFDzE,11345
|
|
14
|
+
vectoramp-0.1.0.dist-info/licenses/NOTICE,sha256=CxFpSV5g6ap8_7YW_4OxdNIxJYpr4QwUM6kboKFLP-E,229
|
|
15
|
+
vectoramp-0.1.0.dist-info/RECORD,,
|