schift 0.2.0__tar.gz → 0.3.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.
- {schift-0.2.0 → schift-0.3.0}/.gitignore +7 -14
- schift-0.3.0/PKG-INFO +652 -0
- {schift-0.2.0/python → schift-0.3.0}/pyproject.toml +1 -1
- schift-0.3.0/schift/aggregate.py +64 -0
- schift-0.3.0/schift/artifacts.py +93 -0
- schift-0.3.0/schift/benchmark_suites.py +147 -0
- schift-0.3.0/schift/buckets.py +242 -0
- schift-0.3.0/schift/completions.py +176 -0
- schift-0.3.0/schift/drift.py +131 -0
- schift-0.3.0/schift/jobs.py +102 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/schift_client.py +45 -0
- schift-0.3.0/schift/tasks.py +104 -0
- schift-0.3.0/schift/workflows.py +330 -0
- schift-0.2.0/PKG-INFO +0 -15
- schift-0.2.0/README.md +0 -281
- schift-0.2.0/cli/README.md +0 -303
- schift-0.2.0/cli/pyproject.toml +0 -30
- schift-0.2.0/cli/schift_cli/__init__.py +0 -1
- schift-0.2.0/cli/schift_cli/client.py +0 -119
- schift-0.2.0/cli/schift_cli/commands/__init__.py +0 -0
- schift-0.2.0/cli/schift_cli/commands/auth.py +0 -68
- schift-0.2.0/cli/schift_cli/commands/bench.py +0 -65
- schift-0.2.0/cli/schift_cli/commands/catalog.py +0 -74
- schift-0.2.0/cli/schift_cli/commands/db.py +0 -96
- schift-0.2.0/cli/schift_cli/commands/embed.py +0 -104
- schift-0.2.0/cli/schift_cli/commands/migrate.py +0 -127
- schift-0.2.0/cli/schift_cli/commands/query.py +0 -66
- schift-0.2.0/cli/schift_cli/commands/skill.py +0 -110
- schift-0.2.0/cli/schift_cli/commands/usage.py +0 -50
- schift-0.2.0/cli/schift_cli/config.py +0 -58
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/AGENTS.md +0 -77
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/CLAUDE.md +0 -1
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/SKILL.md +0 -89
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/bucket-organization.md +0 -126
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/bucket-upload.md +0 -116
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/chatbot-widget.md +0 -238
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/cost-batching.md +0 -179
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/cost-storage-tiers.md +0 -183
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/deploy-cloudrun.md +0 -140
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/embed-batch-processing.md +0 -86
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/embed-error-handling.md +0 -155
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/embed-multimodal.md +0 -100
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/embed-task-types.md +0 -135
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/rag-chunking.md +0 -173
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/rag-workflow-builder.md +0 -205
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/sdk-async-patterns.md +0 -103
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/sdk-auth-patterns.md +0 -76
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/search-collection-design.md +0 -229
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/search-hybrid.md +0 -163
- schift-0.2.0/cli/schift_cli/data/schift-best-practices/references/search-similarity-tuning.md +0 -134
- schift-0.2.0/cli/schift_cli/display.py +0 -85
- schift-0.2.0/cli/schift_cli/main.py +0 -39
- schift-0.2.0/pyproject.toml +0 -18
- schift-0.2.0/src/schift/__init__.py +0 -26
- schift-0.2.0/src/schift/async_client.py +0 -82
- schift-0.2.0/src/schift/bucket.py +0 -153
- schift-0.2.0/src/schift/client.py +0 -87
- schift-0.2.0/src/schift/collection.py +0 -85
- schift-0.2.0/src/schift/models.py +0 -25
- schift-0.2.0/src/schift/workflow.py +0 -273
- schift-0.2.0/src/schift/workflow_engine.py +0 -332
- schift-0.2.0/src/schift/workflow_models.py +0 -215
- schift-0.2.0/src/schift/workflow_nodes.py +0 -828
- schift-0.2.0/src/schift/workflow_yaml.py +0 -264
- schift-0.2.0/swift/Package.swift +0 -27
- schift-0.2.0/swift/Sources/Schift/Errors.swift +0 -39
- schift-0.2.0/swift/Sources/Schift/HTTP.swift +0 -184
- schift-0.2.0/swift/Sources/Schift/Projection.swift +0 -68
- schift-0.2.0/swift/Sources/Schift/SchiftClient.swift +0 -258
- schift-0.2.0/swift/Sources/Schift/Types.swift +0 -281
- schift-0.2.0/swift/Tests/SchiftTests/SchiftClientTests.swift +0 -158
- schift-0.2.0/tests/test_async_client.py +0 -19
- schift-0.2.0/tests/test_bucket.py +0 -62
- schift-0.2.0/tests/test_client.py +0 -49
- schift-0.2.0/tests/test_workflow.py +0 -109
- schift-0.2.0/tests/test_workflow_engine.py +0 -834
- schift-0.2.0/tests/test_workflow_yaml.py +0 -434
- schift-0.2.0/ts/.github/workflows/publish.yml +0 -45
- schift-0.2.0/ts/README.md +0 -254
- schift-0.2.0/ts/package-lock.json +0 -2517
- schift-0.2.0/ts/package.json +0 -76
- schift-0.2.0/ts/src/__tests__/tools.test.ts +0 -153
- schift-0.2.0/ts/src/client.ts +0 -423
- schift-0.2.0/ts/src/errors.ts +0 -25
- schift-0.2.0/ts/src/index.ts +0 -87
- schift-0.2.0/ts/src/tools.ts +0 -321
- schift-0.2.0/ts/src/types.ts +0 -175
- schift-0.2.0/ts/src/workflow/__tests__/engine.test.ts +0 -820
- schift-0.2.0/ts/src/workflow/__tests__/workflow.test.ts +0 -502
- schift-0.2.0/ts/src/workflow/__tests__/yaml.test.ts +0 -406
- schift-0.2.0/ts/src/workflow/builder.ts +0 -214
- schift-0.2.0/ts/src/workflow/client.ts +0 -243
- schift-0.2.0/ts/src/workflow/engine.ts +0 -349
- schift-0.2.0/ts/src/workflow/index.ts +0 -66
- schift-0.2.0/ts/src/workflow/nodes.ts +0 -904
- schift-0.2.0/ts/src/workflow/types.ts +0 -244
- schift-0.2.0/ts/src/workflow/yaml.ts +0 -409
- schift-0.2.0/ts/src/workflow-editor/adapter.ts +0 -111
- schift-0.2.0/ts/src/workflow-editor/components/BlockConfigPanel.tsx +0 -315
- schift-0.2.0/ts/src/workflow-editor/components/BlockPalette.tsx +0 -138
- schift-0.2.0/ts/src/workflow-editor/components/SchemaBuilder.tsx +0 -354
- schift-0.2.0/ts/src/workflow-editor/components/WorkflowBuilder.tsx +0 -449
- schift-0.2.0/ts/src/workflow-editor/components/WorkflowCanvas.tsx +0 -377
- schift-0.2.0/ts/src/workflow-editor/components/WorkflowEditor.tsx +0 -37
- schift-0.2.0/ts/src/workflow-editor/components/WorkflowList.tsx +0 -303
- schift-0.2.0/ts/src/workflow-editor/context.tsx +0 -80
- schift-0.2.0/ts/src/workflow-editor/defaults.tsx +0 -190
- schift-0.2.0/ts/src/workflow-editor/examples.ts +0 -411
- schift-0.2.0/ts/src/workflow-editor/index.ts +0 -70
- schift-0.2.0/ts/src/workflow-editor/types.ts +0 -141
- schift-0.2.0/ts/src/workflow-editor/utils/workflow-graph.ts +0 -58
- schift-0.2.0/ts/tsconfig.json +0 -18
- schift-0.2.0/ts/tsup.config.ts +0 -24
- schift-0.2.0/uv.lock +0 -474
- {schift-0.2.0/python → schift-0.3.0}/README.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/bench_report.html +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/ADAPTER_INTERFACE_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/CLIENT_AUTH_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/DB_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/DB_RECORD_SCHEMA.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/EMBED_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/MIGRATE_BENCH_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/MIGRATE_FIT_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/MIGRATE_RUN_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/MODEL_CATALOG_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/ROUTING_DECISION_SCHEMA.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/ROUTING_EVENTS_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/ROUTING_POLICY_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/SDK_FUNCTION_INVENTORY.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/SDK_MODULE_BOUNDARIES.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/SEARCH_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/SEARCH_QUERY_SCHEMA.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/docs/USAGE_CONTRACT.md +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/__init__.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/_http.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/_migrate_module.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/__init__.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/base.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/chroma.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/elasticsearch.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/file.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/milvus.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/mongodb.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/pgvector.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/pinecone.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/qdrant.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/redis.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/registry.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/adapters/weaviate.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/bench.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/catalog.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/chat.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/client.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/db.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/embed.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/migrate.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/projection.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/query.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/report.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/rerank.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/routing.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/search.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/tools.py +0 -0
- {schift-0.2.0/python → schift-0.3.0}/schift/usage.py +0 -0
|
@@ -26,7 +26,6 @@ api/.aws-sam/
|
|
|
26
26
|
target/
|
|
27
27
|
web/.test-dist/
|
|
28
28
|
.wrangler/
|
|
29
|
-
research/polarity-and-relation-retrieval-poc/.venv/
|
|
30
29
|
infra/tfplan
|
|
31
30
|
research/korean-legal-bench/kbl/
|
|
32
31
|
research/korean-legal-bench/kcl/
|
|
@@ -36,24 +35,18 @@ scripts/ingest_korean_law/*.log
|
|
|
36
35
|
|
|
37
36
|
# engine runtime data
|
|
38
37
|
engine/data/
|
|
38
|
+
engine/data-sq8/
|
|
39
39
|
|
|
40
40
|
# large binary data
|
|
41
|
+
*.bin
|
|
41
42
|
*.pt
|
|
42
|
-
api/weights/*.npy
|
|
43
|
-
research/**/*.npy
|
|
44
|
-
api/cache/
|
|
45
|
-
research/*/cache/
|
|
46
|
-
research/*/cache-no-xet/
|
|
47
|
-
research/*/gold_data/
|
|
48
|
-
research/beir-mteb/encoded/
|
|
49
|
-
research/beir-mteb/raw/
|
|
50
|
-
research/beir-mteb/pods_active.json
|
|
51
|
-
research/beir-mteb/launch_pods.sh
|
|
52
|
-
research/polarity-and-relation-retrieval-poc/runs/
|
|
53
|
-
*.npz
|
|
54
43
|
*.npy
|
|
44
|
+
*.npz
|
|
55
45
|
*.pkl
|
|
56
|
-
|
|
46
|
+
*.webm
|
|
47
|
+
|
|
48
|
+
# large research data
|
|
49
|
+
research/longmemeval/data/
|
|
57
50
|
|
|
58
51
|
# terraform
|
|
59
52
|
infra/.terraform/
|
schift-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,652 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: schift
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Embedding model migration SDK. Switch models without re-embedding.
|
|
5
|
+
Project-URL: Homepage, https://schift.io
|
|
6
|
+
Project-URL: Documentation, https://docs.schift.io
|
|
7
|
+
Project-URL: Repository, https://github.com/schift-io/schift-py
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/schift-io/schift-py/issues
|
|
9
|
+
Author-email: Schift <hello@schift.io>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: embeddings,migration,projection,rag,vector-database
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Requires-Dist: httpx>=0.24
|
|
23
|
+
Requires-Dist: numpy>=1.24
|
|
24
|
+
Provides-Extra: all
|
|
25
|
+
Requires-Dist: chromadb>=0.4; extra == 'all'
|
|
26
|
+
Requires-Dist: elasticsearch>=8.0; extra == 'all'
|
|
27
|
+
Requires-Dist: pgvector>=0.2; extra == 'all'
|
|
28
|
+
Requires-Dist: pinecone-client>=5.0; extra == 'all'
|
|
29
|
+
Requires-Dist: psycopg[binary]>=3.1; extra == 'all'
|
|
30
|
+
Requires-Dist: pymilvus>=2.4; extra == 'all'
|
|
31
|
+
Requires-Dist: pymongo>=4.7; extra == 'all'
|
|
32
|
+
Requires-Dist: qdrant-client>=1.7; extra == 'all'
|
|
33
|
+
Requires-Dist: redis>=5.0; extra == 'all'
|
|
34
|
+
Requires-Dist: weaviate-client>=4.4; extra == 'all'
|
|
35
|
+
Provides-Extra: chroma
|
|
36
|
+
Requires-Dist: chromadb>=0.4; extra == 'chroma'
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: ruff>=0.1; extra == 'dev'
|
|
40
|
+
Provides-Extra: elasticsearch
|
|
41
|
+
Requires-Dist: elasticsearch>=8.0; extra == 'elasticsearch'
|
|
42
|
+
Provides-Extra: milvus
|
|
43
|
+
Requires-Dist: pymilvus>=2.4; extra == 'milvus'
|
|
44
|
+
Provides-Extra: mongodb
|
|
45
|
+
Requires-Dist: pymongo>=4.7; extra == 'mongodb'
|
|
46
|
+
Provides-Extra: pinecone
|
|
47
|
+
Requires-Dist: pinecone-client>=5.0; extra == 'pinecone'
|
|
48
|
+
Provides-Extra: postgres
|
|
49
|
+
Requires-Dist: pgvector>=0.2; extra == 'postgres'
|
|
50
|
+
Requires-Dist: psycopg[binary]>=3.1; extra == 'postgres'
|
|
51
|
+
Provides-Extra: qdrant
|
|
52
|
+
Requires-Dist: qdrant-client>=1.7; extra == 'qdrant'
|
|
53
|
+
Provides-Extra: redis
|
|
54
|
+
Requires-Dist: redis>=5.0; extra == 'redis'
|
|
55
|
+
Provides-Extra: weaviate
|
|
56
|
+
Requires-Dist: weaviate-client>=4.4; extra == 'weaviate'
|
|
57
|
+
Description-Content-Type: text/markdown
|
|
58
|
+
|
|
59
|
+
# Schift Python SDK
|
|
60
|
+
|
|
61
|
+
Python client and local migration toolkit for Schift.
|
|
62
|
+
|
|
63
|
+
The package currently exposes two public client styles:
|
|
64
|
+
|
|
65
|
+
- `Schift`: modular client for live API operations such as catalog lookup, embedding, routing, search, usage, and hosted collection management.
|
|
66
|
+
- `Client`: legacy projection client for fitting and downloading `Projection` objects that run locally.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
Base package:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install schift
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Optional adapters:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
pip install "schift[postgres]"
|
|
80
|
+
pip install "schift[qdrant]"
|
|
81
|
+
pip install "schift[all]"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Development extras:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install -e ".[dev]"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Authentication And Base URLs
|
|
91
|
+
|
|
92
|
+
The modular client reads `SCHIFT_API_KEY` automatically:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
export SCHIFT_API_KEY=sch_your_key_here
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Equivalent explicit construction:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from schift import Schift
|
|
102
|
+
|
|
103
|
+
client = Schift(
|
|
104
|
+
api_key="sch_your_key_here",
|
|
105
|
+
base_url="https://api.schift.io/v1",
|
|
106
|
+
timeout=60.0,
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Notes:
|
|
111
|
+
|
|
112
|
+
- `Schift` expects a `/v1` base URL.
|
|
113
|
+
- The legacy `Client` defaults to `https://api.schift.io` and appends `/v1/...` internally.
|
|
114
|
+
|
|
115
|
+
## Client Lifecycle
|
|
116
|
+
|
|
117
|
+
`Schift` holds a shared `httpx.Client`, so prefer a context manager for short-lived scripts:
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from schift import Schift
|
|
121
|
+
|
|
122
|
+
with Schift() as client:
|
|
123
|
+
models = client.catalog.list()
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For long-running processes, keep one `Schift` instance and call `close()` during shutdown.
|
|
127
|
+
|
|
128
|
+
## Quickstart
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from schift import Schift
|
|
132
|
+
|
|
133
|
+
with Schift() as client:
|
|
134
|
+
models = client.catalog.list()
|
|
135
|
+
vector = client.embed(
|
|
136
|
+
"quarterly revenue report",
|
|
137
|
+
model="openai/text-embedding-3-small",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
client.db.create_collection(name="finance-docs", dimension=len(vector))
|
|
141
|
+
client.db.upsert(
|
|
142
|
+
collection="finance-docs",
|
|
143
|
+
vectors=[
|
|
144
|
+
{
|
|
145
|
+
"id": "doc-1",
|
|
146
|
+
"values": vector.tolist(),
|
|
147
|
+
"metadata": {"source": "q1-report"},
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
hits = client.query(
|
|
153
|
+
"revenue guidance",
|
|
154
|
+
collection="finance-docs",
|
|
155
|
+
top_k=5,
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
print(models[0]["id"] if models else "no models")
|
|
159
|
+
print(hits[0] if hits else "no hits")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Module Reference
|
|
163
|
+
|
|
164
|
+
### `catalog`
|
|
165
|
+
|
|
166
|
+
List available models and inspect one model by ID.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from schift import Schift
|
|
170
|
+
|
|
171
|
+
with Schift() as client:
|
|
172
|
+
models = client.catalog.list()
|
|
173
|
+
model = client.catalog.get("openai/text-embedding-3-small")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### `embed`
|
|
177
|
+
|
|
178
|
+
The embed module is callable for single-text requests and exposes `batch()` for multiple texts.
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from schift import Schift
|
|
182
|
+
|
|
183
|
+
with Schift() as client:
|
|
184
|
+
one = client.embed(
|
|
185
|
+
"hello world",
|
|
186
|
+
model="openai/text-embedding-3-small",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
many = client.embed.batch(
|
|
190
|
+
texts=["hello", "goodbye"],
|
|
191
|
+
model="openai/text-embedding-3-small",
|
|
192
|
+
dimensions=1024,
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Return values are NumPy arrays.
|
|
197
|
+
|
|
198
|
+
### `routing`
|
|
199
|
+
|
|
200
|
+
Read or update the server-side routing policy used by Schift when a model is omitted.
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from schift import Schift
|
|
204
|
+
|
|
205
|
+
with Schift() as client:
|
|
206
|
+
current = client.routing.get()
|
|
207
|
+
updated = client.routing.set(
|
|
208
|
+
primary="openai/text-embedding-3-small",
|
|
209
|
+
fallback="google/gemini-embedding-001",
|
|
210
|
+
mode="failover",
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### `bench`
|
|
215
|
+
|
|
216
|
+
Run a server-side benchmark between two model IDs. The SDK returns `BenchReport`.
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from schift import Schift
|
|
220
|
+
|
|
221
|
+
with Schift() as client:
|
|
222
|
+
report = client.bench.run(
|
|
223
|
+
source="openai/text-embedding-3-small",
|
|
224
|
+
target="google/gemini-embedding-001",
|
|
225
|
+
data="./eval_queries.jsonl",
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
print(report.verdict)
|
|
229
|
+
print(report.summary())
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### `db`
|
|
233
|
+
|
|
234
|
+
Manage hosted collections and write vectors or raw documents.
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from schift import Schift
|
|
238
|
+
|
|
239
|
+
with Schift() as client:
|
|
240
|
+
vector = client.embed(
|
|
241
|
+
"Schift reduces vector migration downtime.",
|
|
242
|
+
model="openai/text-embedding-3-small",
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
collection = client.db.create_collection(
|
|
246
|
+
name="product-docs",
|
|
247
|
+
dimension=len(vector),
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
client.db.upsert(
|
|
251
|
+
collection="product-docs",
|
|
252
|
+
vectors=[
|
|
253
|
+
{
|
|
254
|
+
"id": "doc-1",
|
|
255
|
+
"values": vector.tolist(),
|
|
256
|
+
"metadata": {"title": "Launch plan"},
|
|
257
|
+
}
|
|
258
|
+
],
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
client.db.upsert_text(
|
|
262
|
+
collection="product-docs",
|
|
263
|
+
documents=[
|
|
264
|
+
{
|
|
265
|
+
"id": "doc-2",
|
|
266
|
+
"text": "Schift reduces vector migration downtime.",
|
|
267
|
+
"metadata": {"title": "Overview"},
|
|
268
|
+
}
|
|
269
|
+
],
|
|
270
|
+
model="openai/text-embedding-3-small",
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
stats = client.db.collection_stats("product-docs")
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Available methods:
|
|
277
|
+
|
|
278
|
+
- `create_collection(name, dimension)`
|
|
279
|
+
- `list_collections()`
|
|
280
|
+
- `get_collection(name)`
|
|
281
|
+
- `collection_stats(name)`
|
|
282
|
+
- `delete_collection(name)`
|
|
283
|
+
- `upsert(collection, vectors)`
|
|
284
|
+
- `upsert_text(collection, documents, model)`
|
|
285
|
+
|
|
286
|
+
### `query`
|
|
287
|
+
|
|
288
|
+
The query module is callable and supports hosted collections or an external DB handle.
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from schift import Schift
|
|
292
|
+
|
|
293
|
+
with Schift() as client:
|
|
294
|
+
hosted = client.query(
|
|
295
|
+
"vector migration rollback plan",
|
|
296
|
+
collection="product-docs",
|
|
297
|
+
top_k=10,
|
|
298
|
+
rerank=True,
|
|
299
|
+
rerank_top_k=5,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
passthrough = client.query(
|
|
303
|
+
"incident response",
|
|
304
|
+
db="prod-search-db",
|
|
305
|
+
model="openai/text-embedding-3-small",
|
|
306
|
+
top_k=5,
|
|
307
|
+
)
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### `rerank`
|
|
311
|
+
|
|
312
|
+
Rerank a list of candidate documents with a cross-encoder style endpoint.
|
|
313
|
+
|
|
314
|
+
```python
|
|
315
|
+
from schift import Schift
|
|
316
|
+
|
|
317
|
+
with Schift() as client:
|
|
318
|
+
reranked = client.rerank(
|
|
319
|
+
"incident response",
|
|
320
|
+
documents=[
|
|
321
|
+
{"id": "doc-1", "text": "..."},
|
|
322
|
+
{"id": "doc-2", "text": "..."},
|
|
323
|
+
],
|
|
324
|
+
top_k=2,
|
|
325
|
+
)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### `usage`
|
|
329
|
+
|
|
330
|
+
Fetch aggregate usage for billing or dashboards.
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
from schift import Schift
|
|
334
|
+
|
|
335
|
+
with Schift() as client:
|
|
336
|
+
usage = client.usage.get(period="30d", granularity="day")
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Workflows
|
|
340
|
+
|
|
341
|
+
Build and run RAG pipelines as composable DAGs.
|
|
342
|
+
|
|
343
|
+
### Quick Start
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
from schift import Schift
|
|
347
|
+
|
|
348
|
+
with Schift() as client:
|
|
349
|
+
# Create from template
|
|
350
|
+
wf = client.workflow.create_rag("Product Search")
|
|
351
|
+
|
|
352
|
+
# Run with inputs
|
|
353
|
+
result = client.workflow.run(wf.id, inputs={"query": "best laptop"})
|
|
354
|
+
print(result.outputs["answer"])
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### CRUD
|
|
358
|
+
|
|
359
|
+
```python
|
|
360
|
+
wf = client.workflow.create("My Pipeline", description="Custom RAG")
|
|
361
|
+
workflows = client.workflow.list()
|
|
362
|
+
wf = client.workflow.get(wf.id)
|
|
363
|
+
wf = client.workflow.update(wf.id, name="Renamed")
|
|
364
|
+
client.workflow.delete(wf.id)
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Building a Graph
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
wf = client.workflow.create("Custom RAG")
|
|
371
|
+
|
|
372
|
+
# Add blocks
|
|
373
|
+
start = client.workflow.add_block(wf.id, "start", title="Start")
|
|
374
|
+
retriever = client.workflow.add_block(wf.id, "retriever", config={
|
|
375
|
+
"collection": "my-docs",
|
|
376
|
+
"top_k": 5,
|
|
377
|
+
"rerank": True,
|
|
378
|
+
"rerank_top_k": 3,
|
|
379
|
+
})
|
|
380
|
+
prompt = client.workflow.add_block(wf.id, "prompt_template", config={
|
|
381
|
+
"template": "Answer based on:\n{{results}}\n\nQuestion: {{query}}",
|
|
382
|
+
})
|
|
383
|
+
llm = client.workflow.add_block(wf.id, "llm", config={
|
|
384
|
+
"model": "openai/gpt-4o-mini", # or "anthropic/claude-sonnet-4-20250514", "gemini-2.5-flash"
|
|
385
|
+
"temperature": 0.7,
|
|
386
|
+
})
|
|
387
|
+
end = client.workflow.add_block(wf.id, "end")
|
|
388
|
+
|
|
389
|
+
# Connect blocks
|
|
390
|
+
client.workflow.add_edge(wf.id, start["id"], retriever["id"])
|
|
391
|
+
client.workflow.add_edge(wf.id, retriever["id"], prompt["id"])
|
|
392
|
+
client.workflow.add_edge(wf.id, prompt["id"], llm["id"])
|
|
393
|
+
client.workflow.add_edge(wf.id, llm["id"], end["id"])
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Multiple Inputs
|
|
397
|
+
|
|
398
|
+
The start node forwards all input variables to downstream blocks:
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
result = client.workflow.run(wf.id, inputs={
|
|
402
|
+
"query": "maternity leave policy",
|
|
403
|
+
"user_id": "u-123",
|
|
404
|
+
"language": "ko",
|
|
405
|
+
})
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
Reference variables in prompt templates with `{{variable}}` syntax.
|
|
409
|
+
|
|
410
|
+
### Validation & Run History
|
|
411
|
+
|
|
412
|
+
```python
|
|
413
|
+
# Validate graph (cycles, missing connections, etc.)
|
|
414
|
+
v = client.workflow.validate(wf.id)
|
|
415
|
+
print(v.valid, v.errors)
|
|
416
|
+
|
|
417
|
+
# List past runs
|
|
418
|
+
runs = client.workflow.runs(wf.id)
|
|
419
|
+
for r in runs:
|
|
420
|
+
print(r.run_id, r.status, r.outputs)
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### YAML Import / Export
|
|
424
|
+
|
|
425
|
+
```python
|
|
426
|
+
# Export to YAML
|
|
427
|
+
yaml_str = client.workflow.to_yaml(wf.id, path="pipeline.yaml")
|
|
428
|
+
|
|
429
|
+
# Load from file
|
|
430
|
+
definition = client.workflow.from_yaml("pipeline.yaml")
|
|
431
|
+
|
|
432
|
+
# Push YAML to create on server
|
|
433
|
+
wf = client.workflow.push_yaml("pipeline.yaml")
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Templates
|
|
437
|
+
|
|
438
|
+
| Method | Template |
|
|
439
|
+
|--------|----------|
|
|
440
|
+
| `create_rag(name)` | Retriever -> Prompt -> LLM |
|
|
441
|
+
| `create_doc_qa(name)` | Document QA with sources |
|
|
442
|
+
| `create_chat(name)` | Conversational RAG |
|
|
443
|
+
| `create_ocr_ingest(name)` | OCR -> Chunk -> Embed |
|
|
444
|
+
|
|
445
|
+
### Async Workflows
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
from schift import AsyncSchift
|
|
449
|
+
|
|
450
|
+
async with AsyncSchift() as client:
|
|
451
|
+
wf = await client.workflow.create_rag("Async RAG")
|
|
452
|
+
result = await client.workflow.run(wf.id, inputs={"query": "hello"})
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
### Block Types
|
|
456
|
+
|
|
457
|
+
| Category | Types |
|
|
458
|
+
|----------|-------|
|
|
459
|
+
| Control | `start`, `end`, `conditional`, `loop` |
|
|
460
|
+
| Retrieval | `retriever` (with rerank toggle), `reranker` |
|
|
461
|
+
| LLM | `llm` (OpenAI/Anthropic/Google), `prompt_template`, `answer` |
|
|
462
|
+
| Data | `document_loader`, `chunker`, `embedder`, `text_processor` |
|
|
463
|
+
| Integration | `api_call`, `webhook`, `code_executor` |
|
|
464
|
+
| Storage | `vector_store`, `cache` |
|
|
465
|
+
|
|
466
|
+
### API Reference
|
|
467
|
+
|
|
468
|
+
| Method | Description |
|
|
469
|
+
|--------|-------------|
|
|
470
|
+
| `workflow.create(name)` | Create workflow |
|
|
471
|
+
| `workflow.get(id)` | Get workflow |
|
|
472
|
+
| `workflow.list()` | List workflows |
|
|
473
|
+
| `workflow.update(id, **kw)` | Update workflow |
|
|
474
|
+
| `workflow.delete(id)` | Delete workflow |
|
|
475
|
+
| `workflow.run(id, inputs)` | Run workflow |
|
|
476
|
+
| `workflow.runs(id)` | List past runs |
|
|
477
|
+
| `workflow.validate(id)` | Validate graph |
|
|
478
|
+
| `workflow.add_block(id, type, config)` | Add block |
|
|
479
|
+
| `workflow.add_edge(id, src, tgt)` | Add edge |
|
|
480
|
+
| `workflow.to_yaml(id)` | Export as YAML |
|
|
481
|
+
| `workflow.from_yaml(path)` | Load YAML definition |
|
|
482
|
+
| `workflow.push_yaml(path)` | Import YAML to server |
|
|
483
|
+
|
|
484
|
+
## Projection Workflow
|
|
485
|
+
|
|
486
|
+
Projection creation still lives in the legacy `Client` API. It returns a local `Projection` object that can transform vectors without further API calls.
|
|
487
|
+
|
|
488
|
+
```python
|
|
489
|
+
from schift import Client
|
|
490
|
+
|
|
491
|
+
legacy = Client(api_key="sch_your_key_here")
|
|
492
|
+
|
|
493
|
+
# Embed the same sample texts with both providers before fitting.
|
|
494
|
+
source_pairs = old_model_embeddings
|
|
495
|
+
target_pairs = new_model_embeddings
|
|
496
|
+
|
|
497
|
+
projection = legacy.fit(
|
|
498
|
+
source=source_pairs,
|
|
499
|
+
target=target_pairs,
|
|
500
|
+
source_model="openai/text-embedding-3-small",
|
|
501
|
+
target_model="google/gemini-embedding-001",
|
|
502
|
+
project_name="openai-to-gemini",
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
converted = projection.transform(source_pairs[:10])
|
|
506
|
+
projection.save("./projection-openai-to-gemini")
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
You can later reload a saved projection:
|
|
510
|
+
|
|
511
|
+
```python
|
|
512
|
+
from schift import Projection
|
|
513
|
+
|
|
514
|
+
projection = Projection.load("./projection-openai-to-gemini")
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
The legacy client also supports:
|
|
518
|
+
|
|
519
|
+
- `fit(...)`
|
|
520
|
+
- `bench(...)`
|
|
521
|
+
- `list_projections()`
|
|
522
|
+
- `get_projection(project_id)`
|
|
523
|
+
|
|
524
|
+
## Local Migration With Adapters
|
|
525
|
+
|
|
526
|
+
The local migration engine reads vectors from a source adapter, applies a `Projection`, and writes to a sink adapter. This path does not depend on hosted collection APIs.
|
|
527
|
+
|
|
528
|
+
```python
|
|
529
|
+
from schift import Projection
|
|
530
|
+
from schift.migrate import migrate
|
|
531
|
+
from schift.adapters.file import NpyAdapter
|
|
532
|
+
|
|
533
|
+
projection = Projection.load("./projection-openai-to-gemini")
|
|
534
|
+
|
|
535
|
+
source = NpyAdapter("old_embeddings.npy")
|
|
536
|
+
sink = NpyAdapter("new_embeddings.npy")
|
|
537
|
+
|
|
538
|
+
result = migrate(
|
|
539
|
+
source=source,
|
|
540
|
+
sink=sink,
|
|
541
|
+
projection=projection,
|
|
542
|
+
batch_size=2048,
|
|
543
|
+
dry_run=True,
|
|
544
|
+
)
|
|
545
|
+
|
|
546
|
+
print(result)
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
The same engine is exposed through `Schift().migrate.run(...)`.
|
|
550
|
+
|
|
551
|
+
### Built-in Adapters
|
|
552
|
+
|
|
553
|
+
#### NumPy files
|
|
554
|
+
|
|
555
|
+
```python
|
|
556
|
+
from schift.adapters.file import NpyAdapter
|
|
557
|
+
|
|
558
|
+
adapter = NpyAdapter("embeddings.npy")
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
#### pgvector
|
|
562
|
+
|
|
563
|
+
Requires `pip install "schift[postgres]"`.
|
|
564
|
+
|
|
565
|
+
```python
|
|
566
|
+
from schift.adapters.pgvector import PgVectorAdapter
|
|
567
|
+
|
|
568
|
+
adapter = PgVectorAdapter(
|
|
569
|
+
conninfo="postgresql://user:password@localhost/mydb",
|
|
570
|
+
table="documents",
|
|
571
|
+
embedding_column="embedding",
|
|
572
|
+
id_column="id",
|
|
573
|
+
)
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
#### Qdrant
|
|
577
|
+
|
|
578
|
+
Requires `pip install "schift[qdrant]"`.
|
|
579
|
+
|
|
580
|
+
```python
|
|
581
|
+
from schift.adapters.qdrant import QdrantAdapter
|
|
582
|
+
|
|
583
|
+
adapter = QdrantAdapter(
|
|
584
|
+
url="http://localhost:6333",
|
|
585
|
+
collection="documents",
|
|
586
|
+
api_key=None,
|
|
587
|
+
)
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
#### Registry Helpers
|
|
591
|
+
|
|
592
|
+
```python
|
|
593
|
+
from schift.adapters import get_adapter, list_adapters
|
|
594
|
+
|
|
595
|
+
print(list_adapters())
|
|
596
|
+
|
|
597
|
+
adapter = get_adapter(
|
|
598
|
+
{
|
|
599
|
+
"type": "npy",
|
|
600
|
+
"path": "embeddings.npy",
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
## Errors
|
|
606
|
+
|
|
607
|
+
Both client styles raise exceptions from `schift.client`:
|
|
608
|
+
|
|
609
|
+
- `AuthError`
|
|
610
|
+
- `QuotaError`
|
|
611
|
+
- `SchiftError`
|
|
612
|
+
|
|
613
|
+
Example:
|
|
614
|
+
|
|
615
|
+
```python
|
|
616
|
+
from schift import Schift
|
|
617
|
+
from schift.client import AuthError, QuotaError, SchiftError
|
|
618
|
+
|
|
619
|
+
try:
|
|
620
|
+
with Schift() as client:
|
|
621
|
+
client.catalog.list()
|
|
622
|
+
except AuthError:
|
|
623
|
+
...
|
|
624
|
+
except QuotaError:
|
|
625
|
+
...
|
|
626
|
+
except SchiftError:
|
|
627
|
+
...
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
## Development
|
|
631
|
+
|
|
632
|
+
From `sdk/python/`:
|
|
633
|
+
|
|
634
|
+
```bash
|
|
635
|
+
python -m pip install -e ".[dev]"
|
|
636
|
+
python -m ruff check .
|
|
637
|
+
python -m pytest
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
## Source Layout
|
|
641
|
+
|
|
642
|
+
```text
|
|
643
|
+
sdk/python/
|
|
644
|
+
├── schift/
|
|
645
|
+
│ ├── schift_client.py # modular SDK entry point
|
|
646
|
+
│ ├── client.py # legacy projection client
|
|
647
|
+
│ ├── projection.py # local projection object
|
|
648
|
+
│ ├── adapters/ # npy, pgvector, qdrant
|
|
649
|
+
│ ├── workflow.py # workflow CRUD, blocks, edges, YAML, templates
|
|
650
|
+
│ └── *.py # catalog, embed, routing, db, query, rerank, usage
|
|
651
|
+
└── docs/ # request/response contracts and schemas
|
|
652
|
+
```
|