rushdb 2.9.0__tar.gz → 3.0.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.
- {rushdb-2.9.0 → rushdb-3.0.0}/.env.example +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/.github/workflows/ci.yml +26 -11
- {rushdb-2.9.0 → rushdb-3.0.0}/.gitignore +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/CODE_OF_CONDUCT.md +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/CONTRIBUTING.md +1 -1
- {rushdb-2.9.0 → rushdb-3.0.0}/LICENSE +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/PKG-INFO +123 -15
- {rushdb-2.9.0 → rushdb-3.0.0}/README.md +120 -1
- {rushdb-2.9.0 → rushdb-3.0.0}/pyproject.toml +8 -22
- {rushdb-2.9.0 → rushdb-3.0.0}/rushdb-logo.svg +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/__init__.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/__init__.py +13 -1
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/__init__.py +4 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/ai.py +59 -26
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/base.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/labels.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/properties.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/query.py +3 -4
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/records.py +153 -34
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/relationship_patterns.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/relationships.py +0 -0
- rushdb-3.0.0/src/rushdb/api/text_indexes.py +63 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/api/transactions.py +7 -3
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/client.py +58 -19
- rushdb-3.0.0/src/rushdb/common.py +65 -0
- rushdb-3.0.0/src/rushdb/direct/__init__.py +5 -0
- rushdb-3.0.0/src/rushdb/direct/capabilities.py +38 -0
- rushdb-3.0.0/src/rushdb/direct/engine.py +79 -0
- rushdb-3.0.0/src/rushdb/direct/router.py +1436 -0
- rushdb-3.0.0/src/rushdb/direct/schema.py +204 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/__init__.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/api_response.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/property.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/record.py +5 -2
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/relationship.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/result.py +20 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/search_query.py +2 -3
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/models/transaction.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/src/rushdb/utils/token_prefix.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/__init__.py +0 -0
- rushdb-3.0.0/tests/test_ai_vector_search.py +117 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/test_base_setup.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/test_create_import.py +0 -0
- rushdb-3.0.0/tests/test_direct_mode.py +585 -0
- rushdb-3.0.0/tests/test_direct_mode_live.py +190 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/test_relationship_patterns.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/test_search_query.py +0 -0
- {rushdb-2.9.0 → rushdb-3.0.0}/tests/test_search_result.py +0 -0
- rushdb-3.0.0/uv.lock +832 -0
- rushdb-2.9.0/src/rushdb/common.py +0 -33
- rushdb-2.9.0/uv.lock +0 -1004
|
File without changes
|
|
@@ -13,7 +13,7 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
strategy:
|
|
15
15
|
matrix:
|
|
16
|
-
python-version: ["3.
|
|
16
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
17
17
|
|
|
18
18
|
steps:
|
|
19
19
|
- uses: actions/checkout@v4
|
|
@@ -43,7 +43,7 @@ jobs:
|
|
|
43
43
|
run: |
|
|
44
44
|
uv run pytest
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
build:
|
|
47
47
|
if: startsWith(github.ref, 'refs/tags/v')
|
|
48
48
|
runs-on: ubuntu-latest
|
|
49
49
|
needs: test
|
|
@@ -61,13 +61,28 @@ jobs:
|
|
|
61
61
|
with:
|
|
62
62
|
version: "latest"
|
|
63
63
|
|
|
64
|
-
- name:
|
|
65
|
-
run:
|
|
66
|
-
uv sync --dev
|
|
64
|
+
- name: Build distributions
|
|
65
|
+
run: uv build
|
|
67
66
|
|
|
68
|
-
- name:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
- name: Upload distributions
|
|
68
|
+
uses: actions/upload-artifact@v4
|
|
69
|
+
with:
|
|
70
|
+
name: dist
|
|
71
|
+
path: dist/
|
|
72
|
+
|
|
73
|
+
publish:
|
|
74
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
needs: build
|
|
77
|
+
permissions:
|
|
78
|
+
id-token: write
|
|
79
|
+
|
|
80
|
+
steps:
|
|
81
|
+
- name: Download distributions
|
|
82
|
+
uses: actions/download-artifact@v4
|
|
83
|
+
with:
|
|
84
|
+
name: dist
|
|
85
|
+
path: dist/
|
|
86
|
+
|
|
87
|
+
- name: Publish to PyPI
|
|
88
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
File without changes
|
|
File without changes
|
|
@@ -15,7 +15,7 @@ When reporting an issue, include the following information:
|
|
|
15
15
|
|
|
16
16
|
- Specify the version of RushDB you are using:
|
|
17
17
|
- **Cloud**: Mention if you are using the latest cloud version.
|
|
18
|
-
- **Self-hosted**: Provide the
|
|
18
|
+
- **Self-hosted engine (direct mode)**: Provide the engine version (`rushdb --version`) and the SDK version.
|
|
19
19
|
|
|
20
20
|
3. **Steps to Reproduce**
|
|
21
21
|
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: rushdb
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: RushDB Python SDK — memory layer for AI agents and modern apps
|
|
5
5
|
Project-URL: Homepage, https://github.com/rush-db/rushdb-python
|
|
6
6
|
Project-URL: Repository, https://github.com/rush-db/rushdb-python
|
|
@@ -9,18 +9,7 @@ Author-email: RushDB Team <hi@rushdb.com>
|
|
|
9
9
|
License: Apache-2.0
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Keywords: agent memory,agent-memory,ai agents,ai memory,ai-agents,ai-memory,cloud,database,embedding,embeddings,graph,graph database,graph-database,json normalization,json-normalization,knowledge graph,knowledge-graph,llm memory,llm-memory,mcp,memory layer,memory-layer,no-schema,persistence,rag,relationships,rest api,rest-api,retrieval augmented generation,rush db,rush-db,rushdb,schema-less,schemaless,self-hosted,vector search,vector-search
|
|
12
|
-
Requires-Python: >=3.
|
|
13
|
-
Requires-Dist: python-dotenv>=1.0.0
|
|
14
|
-
Requires-Dist: requests>=2.31.0
|
|
15
|
-
Provides-Extra: dev
|
|
16
|
-
Requires-Dist: black>=23.7.0; extra == 'dev'
|
|
17
|
-
Requires-Dist: isort>=5.12.0; extra == 'dev'
|
|
18
|
-
Requires-Dist: mypy>=1.4.1; extra == 'dev'
|
|
19
|
-
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
20
|
-
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
21
|
-
Requires-Dist: ruff>=0.0.280; extra == 'dev'
|
|
22
|
-
Requires-Dist: types-python-dateutil>=2.8.19.14; extra == 'dev'
|
|
23
|
-
Requires-Dist: types-requests>=2.31.0.1; extra == 'dev'
|
|
12
|
+
Requires-Python: >=3.10
|
|
24
13
|
Description-Content-Type: text/markdown
|
|
25
14
|
|
|
26
15
|
<div align="center">
|
|
@@ -62,6 +51,64 @@ pip install rushdb
|
|
|
62
51
|
|
|
63
52
|
---
|
|
64
53
|
|
|
54
|
+
## RushDB Cloud or a self-hosted engine
|
|
55
|
+
|
|
56
|
+
The SDK works with RushDB in one of two ways:
|
|
57
|
+
|
|
58
|
+
| | RushDB Cloud | Self-hosted RushDB engine (direct mode) |
|
|
59
|
+
| --- | --- | --- |
|
|
60
|
+
| What you run | nothing: the managed service at [app.rushdb.com](https://app.rushdb.com) | one `rushdb` binary, on your own infrastructure |
|
|
61
|
+
| Connect with | an API key | the engine URL and the engine token |
|
|
62
|
+
|
|
63
|
+
The engine is what you can self-host. RushDB Cloud runs that engine for you and adds the dashboard,
|
|
64
|
+
managed embeddings and the AI features (natural-language search, relationship-pattern suggestions),
|
|
65
|
+
which exist only in RushDB Cloud.
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from rushdb import RushDB
|
|
69
|
+
|
|
70
|
+
# RushDB Cloud
|
|
71
|
+
db = RushDB("RUSHDB_API_KEY")
|
|
72
|
+
|
|
73
|
+
# A self-hosted engine
|
|
74
|
+
db = RushDB(
|
|
75
|
+
"ENGINE_TOKEN",
|
|
76
|
+
direct=True,
|
|
77
|
+
engine_url="http://127.0.0.1:3000",
|
|
78
|
+
scope="tenant-1", # only for an engine started with --multitenant
|
|
79
|
+
)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
What each offers:
|
|
83
|
+
|
|
84
|
+
| Feature | Cloud | Self-hosted engine |
|
|
85
|
+
| --- | :---: | :---: |
|
|
86
|
+
| Records: create, read, update, set, upsert, delete, `find` with `where`, `orderBy`, `select`, `groupBy` | ✓ | ✓ |
|
|
87
|
+
| Relationships: `attach`/`detach`, `relationships.create_many`/`delete_many`/`find` | ✓ | ✓ |
|
|
88
|
+
| Labels, properties, property values | ✓ | ✓ |
|
|
89
|
+
| Import JSON and CSV, export CSV | ✓ | ✓ |
|
|
90
|
+
| External vector indexes; vector search with a `queryVector` you supply | ✓ | ✓ |
|
|
91
|
+
| Raw openCypher (`query.raw`; the engine needs `--languages cypher`) | ✓ | ✓ |
|
|
92
|
+
| Schema (`ai.get_schema`, `ai.get_schema_markdown`) | ✓ | ✓ |
|
|
93
|
+
| Keyword (BM25) search (`records.text_search`), text indexes (`text_indexes.*`), hybrid search | ✓ | ✓ |
|
|
94
|
+
| Transactions | ✓ | record creates, updates, sets, deletes by id, attaches and imports are staged; other writes refuse a transaction |
|
|
95
|
+
| Managed embeddings: managed indexes, `records.vector_search` by text `query` | ✓ | — |
|
|
96
|
+
| Natural-language search (`ai.search`) | ✓ | — |
|
|
97
|
+
| Relationship-pattern suggestions (`relationships.patterns.*`) | ✓ | — |
|
|
98
|
+
| Project settings (`settings.get`), dashboard, team access | ✓ | — |
|
|
99
|
+
|
|
100
|
+
In direct mode a Cloud-only method raises `CloudOnlyError` (with `method` and `reason`) before
|
|
101
|
+
sending anything, and no request ever goes to RushDB Cloud. A write the engine cannot stage into a
|
|
102
|
+
transaction raises `DirectModeError`, also before sending anything. The list is available in code:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from rushdb import CLOUD_ONLY_METHODS, CloudOnlyError, is_cloud_only_method
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`db.engine.execute()` runs any Protocol v1 operation directly.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
65
112
|
## Agent memory in 3 lines
|
|
66
113
|
|
|
67
114
|
Get an API key at [app.rushdb.com](https://app.rushdb.com).
|
|
@@ -227,6 +274,67 @@ if result:
|
|
|
227
274
|
|
|
228
275
|
---
|
|
229
276
|
|
|
277
|
+
## Vector Search And Smart Search
|
|
278
|
+
|
|
279
|
+
Use `db.records.vector_search()` for direct semantic/vector retrieval over an
|
|
280
|
+
embedding index:
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
results = db.records.vector_search({
|
|
284
|
+
'labels': ['MEMORY'],
|
|
285
|
+
'propertyName': 'content',
|
|
286
|
+
'query': 'how agents remember things',
|
|
287
|
+
'where': {'agent_id': 'agent-42'},
|
|
288
|
+
'limit': 5,
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
for record in results:
|
|
292
|
+
print(record.score, record.get('content'))
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Use `db.ai.search()` when you want RushDB to turn a natural-language request
|
|
296
|
+
into a SearchQuery and execute it:
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
results = db.ai.search('Find active memories about Q4 results for agent-42')
|
|
300
|
+
print(results.search_query)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`db.ai.search({...})` still works as a deprecated vector-search alias, but new
|
|
304
|
+
code should use `db.records.vector_search({...})`.
|
|
305
|
+
|
|
306
|
+
## Keyword And Hybrid Search
|
|
307
|
+
|
|
308
|
+
Declare a BM25 text index, then search it by keywords:
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
db.text_indexes.create({'label': 'MEMORY', 'property': 'content'})
|
|
312
|
+
|
|
313
|
+
results = db.records.text_search({
|
|
314
|
+
'query': 'quarterly results',
|
|
315
|
+
'labels': ['MEMORY'],
|
|
316
|
+
'where': {'agent_id': 'agent-42'},
|
|
317
|
+
'limit': 5,
|
|
318
|
+
})
|
|
319
|
+
print(results.total, results.meta['textSearch'])
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
Add a `text` leg to a vector search to fuse keyword and vector ranking. `fusion`
|
|
323
|
+
is `rrf` (default) or `dbsf`; `weight` and `prefetchLimit` tune each leg:
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
results = db.records.vector_search({
|
|
327
|
+
'labels': ['MEMORY'],
|
|
328
|
+
'propertyName': 'content',
|
|
329
|
+
'queryVector': embedding,
|
|
330
|
+
'text': {'query': 'quarterly results', 'weight': 0.5},
|
|
331
|
+
'fusion': 'dbsf',
|
|
332
|
+
'limit': 5,
|
|
333
|
+
})
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
230
338
|
## Record API
|
|
231
339
|
|
|
232
340
|
```python
|
|
@@ -273,7 +381,7 @@ from rushdb import RushDB
|
|
|
273
381
|
|
|
274
382
|
db = RushDB(
|
|
275
383
|
'RUSHDB_API_KEY',
|
|
276
|
-
url='
|
|
384
|
+
url='https://api.rushdb.com/api/v1', # a different RushDB Cloud API endpoint; this is the default
|
|
277
385
|
timeout=30,
|
|
278
386
|
)
|
|
279
387
|
```
|
|
@@ -37,6 +37,64 @@ pip install rushdb
|
|
|
37
37
|
|
|
38
38
|
---
|
|
39
39
|
|
|
40
|
+
## RushDB Cloud or a self-hosted engine
|
|
41
|
+
|
|
42
|
+
The SDK works with RushDB in one of two ways:
|
|
43
|
+
|
|
44
|
+
| | RushDB Cloud | Self-hosted RushDB engine (direct mode) |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| What you run | nothing: the managed service at [app.rushdb.com](https://app.rushdb.com) | one `rushdb` binary, on your own infrastructure |
|
|
47
|
+
| Connect with | an API key | the engine URL and the engine token |
|
|
48
|
+
|
|
49
|
+
The engine is what you can self-host. RushDB Cloud runs that engine for you and adds the dashboard,
|
|
50
|
+
managed embeddings and the AI features (natural-language search, relationship-pattern suggestions),
|
|
51
|
+
which exist only in RushDB Cloud.
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from rushdb import RushDB
|
|
55
|
+
|
|
56
|
+
# RushDB Cloud
|
|
57
|
+
db = RushDB("RUSHDB_API_KEY")
|
|
58
|
+
|
|
59
|
+
# A self-hosted engine
|
|
60
|
+
db = RushDB(
|
|
61
|
+
"ENGINE_TOKEN",
|
|
62
|
+
direct=True,
|
|
63
|
+
engine_url="http://127.0.0.1:3000",
|
|
64
|
+
scope="tenant-1", # only for an engine started with --multitenant
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
What each offers:
|
|
69
|
+
|
|
70
|
+
| Feature | Cloud | Self-hosted engine |
|
|
71
|
+
| --- | :---: | :---: |
|
|
72
|
+
| Records: create, read, update, set, upsert, delete, `find` with `where`, `orderBy`, `select`, `groupBy` | ✓ | ✓ |
|
|
73
|
+
| Relationships: `attach`/`detach`, `relationships.create_many`/`delete_many`/`find` | ✓ | ✓ |
|
|
74
|
+
| Labels, properties, property values | ✓ | ✓ |
|
|
75
|
+
| Import JSON and CSV, export CSV | ✓ | ✓ |
|
|
76
|
+
| External vector indexes; vector search with a `queryVector` you supply | ✓ | ✓ |
|
|
77
|
+
| Raw openCypher (`query.raw`; the engine needs `--languages cypher`) | ✓ | ✓ |
|
|
78
|
+
| Schema (`ai.get_schema`, `ai.get_schema_markdown`) | ✓ | ✓ |
|
|
79
|
+
| Keyword (BM25) search (`records.text_search`), text indexes (`text_indexes.*`), hybrid search | ✓ | ✓ |
|
|
80
|
+
| Transactions | ✓ | record creates, updates, sets, deletes by id, attaches and imports are staged; other writes refuse a transaction |
|
|
81
|
+
| Managed embeddings: managed indexes, `records.vector_search` by text `query` | ✓ | — |
|
|
82
|
+
| Natural-language search (`ai.search`) | ✓ | — |
|
|
83
|
+
| Relationship-pattern suggestions (`relationships.patterns.*`) | ✓ | — |
|
|
84
|
+
| Project settings (`settings.get`), dashboard, team access | ✓ | — |
|
|
85
|
+
|
|
86
|
+
In direct mode a Cloud-only method raises `CloudOnlyError` (with `method` and `reason`) before
|
|
87
|
+
sending anything, and no request ever goes to RushDB Cloud. A write the engine cannot stage into a
|
|
88
|
+
transaction raises `DirectModeError`, also before sending anything. The list is available in code:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from rushdb import CLOUD_ONLY_METHODS, CloudOnlyError, is_cloud_only_method
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`db.engine.execute()` runs any Protocol v1 operation directly.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
40
98
|
## Agent memory in 3 lines
|
|
41
99
|
|
|
42
100
|
Get an API key at [app.rushdb.com](https://app.rushdb.com).
|
|
@@ -202,6 +260,67 @@ if result:
|
|
|
202
260
|
|
|
203
261
|
---
|
|
204
262
|
|
|
263
|
+
## Vector Search And Smart Search
|
|
264
|
+
|
|
265
|
+
Use `db.records.vector_search()` for direct semantic/vector retrieval over an
|
|
266
|
+
embedding index:
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
results = db.records.vector_search({
|
|
270
|
+
'labels': ['MEMORY'],
|
|
271
|
+
'propertyName': 'content',
|
|
272
|
+
'query': 'how agents remember things',
|
|
273
|
+
'where': {'agent_id': 'agent-42'},
|
|
274
|
+
'limit': 5,
|
|
275
|
+
})
|
|
276
|
+
|
|
277
|
+
for record in results:
|
|
278
|
+
print(record.score, record.get('content'))
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Use `db.ai.search()` when you want RushDB to turn a natural-language request
|
|
282
|
+
into a SearchQuery and execute it:
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
results = db.ai.search('Find active memories about Q4 results for agent-42')
|
|
286
|
+
print(results.search_query)
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
`db.ai.search({...})` still works as a deprecated vector-search alias, but new
|
|
290
|
+
code should use `db.records.vector_search({...})`.
|
|
291
|
+
|
|
292
|
+
## Keyword And Hybrid Search
|
|
293
|
+
|
|
294
|
+
Declare a BM25 text index, then search it by keywords:
|
|
295
|
+
|
|
296
|
+
```python
|
|
297
|
+
db.text_indexes.create({'label': 'MEMORY', 'property': 'content'})
|
|
298
|
+
|
|
299
|
+
results = db.records.text_search({
|
|
300
|
+
'query': 'quarterly results',
|
|
301
|
+
'labels': ['MEMORY'],
|
|
302
|
+
'where': {'agent_id': 'agent-42'},
|
|
303
|
+
'limit': 5,
|
|
304
|
+
})
|
|
305
|
+
print(results.total, results.meta['textSearch'])
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Add a `text` leg to a vector search to fuse keyword and vector ranking. `fusion`
|
|
309
|
+
is `rrf` (default) or `dbsf`; `weight` and `prefetchLimit` tune each leg:
|
|
310
|
+
|
|
311
|
+
```python
|
|
312
|
+
results = db.records.vector_search({
|
|
313
|
+
'labels': ['MEMORY'],
|
|
314
|
+
'propertyName': 'content',
|
|
315
|
+
'queryVector': embedding,
|
|
316
|
+
'text': {'query': 'quarterly results', 'weight': 0.5},
|
|
317
|
+
'fusion': 'dbsf',
|
|
318
|
+
'limit': 5,
|
|
319
|
+
})
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
205
324
|
## Record API
|
|
206
325
|
|
|
207
326
|
```python
|
|
@@ -248,7 +367,7 @@ from rushdb import RushDB
|
|
|
248
367
|
|
|
249
368
|
db = RushDB(
|
|
250
369
|
'RUSHDB_API_KEY',
|
|
251
|
-
url='
|
|
370
|
+
url='https://api.rushdb.com/api/v1', # a different RushDB Cloud API endpoint; this is the default
|
|
252
371
|
timeout=30,
|
|
253
372
|
)
|
|
254
373
|
```
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "rushdb"
|
|
3
|
-
version = "
|
|
3
|
+
version = "3.0.0"
|
|
4
4
|
description = "RushDB Python SDK — memory layer for AI agents and modern apps"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "RushDB Team", email = "hi@rushdb.com"}
|
|
7
7
|
]
|
|
8
8
|
license = {text = "Apache-2.0"}
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
11
|
keywords = [
|
|
12
12
|
"rushdb",
|
|
13
13
|
"database",
|
|
@@ -47,28 +47,13 @@ keywords = [
|
|
|
47
47
|
"rush-db",
|
|
48
48
|
"rush db"
|
|
49
49
|
]
|
|
50
|
-
dependencies = [
|
|
51
|
-
"python-dotenv>=1.0.0",
|
|
52
|
-
"requests>=2.31.0"
|
|
53
|
-
]
|
|
50
|
+
dependencies = []
|
|
54
51
|
|
|
55
52
|
[project.urls]
|
|
56
53
|
Homepage = "https://github.com/rush-db/rushdb-python"
|
|
57
54
|
Repository = "https://github.com/rush-db/rushdb-python"
|
|
58
55
|
Documentation = "https://docs.rushdb.com"
|
|
59
56
|
|
|
60
|
-
[project.optional-dependencies]
|
|
61
|
-
dev = [
|
|
62
|
-
"black>=23.7.0",
|
|
63
|
-
"isort>=5.12.0",
|
|
64
|
-
"ruff>=0.0.280",
|
|
65
|
-
"mypy>=1.4.1",
|
|
66
|
-
"pytest>=7.4.0",
|
|
67
|
-
"pytest-cov>=4.1.0",
|
|
68
|
-
"types-requests>=2.31.0.1",
|
|
69
|
-
"types-python-dateutil>=2.8.19.14"
|
|
70
|
-
]
|
|
71
|
-
|
|
72
57
|
[build-system]
|
|
73
58
|
requires = ["hatchling"]
|
|
74
59
|
build-backend = "hatchling.build"
|
|
@@ -84,12 +69,13 @@ profile = "black"
|
|
|
84
69
|
|
|
85
70
|
[dependency-groups]
|
|
86
71
|
dev = [
|
|
87
|
-
"black>=
|
|
72
|
+
"black>=26.3.1",
|
|
88
73
|
"isort>=5.13.2",
|
|
89
74
|
"mypy>=1.14.1",
|
|
90
|
-
"
|
|
75
|
+
"pygments>=2.20.0",
|
|
76
|
+
"pytest>=9.0.3",
|
|
91
77
|
"pytest-cov>=5.0.0",
|
|
92
|
-
"
|
|
78
|
+
"python-dotenv>=1.2.2",
|
|
79
|
+
"ruff>=0.12.1,<0.13",
|
|
93
80
|
"types-python-dateutil>=2.9.0.20241206",
|
|
94
|
-
"types-requests>=2.32.0.20241016",
|
|
95
81
|
]
|
|
File without changes
|
|
File without changes
|
|
@@ -8,8 +8,14 @@ from .api.query import QueryAPI
|
|
|
8
8
|
from .api.records import pick_record_id
|
|
9
9
|
from .api.relationship_patterns import RelationshipPatternsAPI
|
|
10
10
|
from .api.relationships import RelationsAPI
|
|
11
|
+
from .api.text_indexes import TextIndexesAPI
|
|
11
12
|
from .client import RushDB
|
|
12
|
-
from .common import NonUniqueResultError, RushDBError
|
|
13
|
+
from .common import CloudOnlyError, DirectModeError, NonUniqueResultError, RushDBError
|
|
14
|
+
from .direct.capabilities import (
|
|
15
|
+
CLOUD_ONLY_FORMS,
|
|
16
|
+
CLOUD_ONLY_METHODS,
|
|
17
|
+
is_cloud_only_method,
|
|
18
|
+
)
|
|
13
19
|
from .models.api_response import ApiResponse
|
|
14
20
|
from .models.property import Property
|
|
15
21
|
from .models.record import Record, RecordTarget, RelationTarget
|
|
@@ -31,6 +37,11 @@ from .models.search_query import (
|
|
|
31
37
|
from .models.transaction import Transaction
|
|
32
38
|
|
|
33
39
|
__all__ = [
|
|
40
|
+
"CLOUD_ONLY_FORMS",
|
|
41
|
+
"CLOUD_ONLY_METHODS",
|
|
42
|
+
"CloudOnlyError",
|
|
43
|
+
"DirectModeError",
|
|
44
|
+
"is_cloud_only_method",
|
|
34
45
|
"RushDB",
|
|
35
46
|
"RushDBError",
|
|
36
47
|
"NonUniqueResultError",
|
|
@@ -57,4 +68,5 @@ __all__ = [
|
|
|
57
68
|
"RelationshipPatternsAPI",
|
|
58
69
|
"ApiResponse",
|
|
59
70
|
"AIAPI",
|
|
71
|
+
"TextIndexesAPI",
|
|
60
72
|
]
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
from .ai import AIAPI
|
|
1
2
|
from .labels import LabelsAPI
|
|
2
3
|
from .properties import PropertiesAPI
|
|
3
4
|
from .query import QueryAPI
|
|
4
5
|
from .records import RecordsAPI
|
|
5
6
|
from .relationship_patterns import RelationshipPatternsAPI
|
|
6
7
|
from .relationships import RelationsAPI
|
|
8
|
+
from .text_indexes import TextIndexesAPI
|
|
7
9
|
from .transactions import TransactionsAPI
|
|
8
10
|
|
|
9
11
|
__all__ = [
|
|
12
|
+
"AIAPI",
|
|
10
13
|
"RecordsAPI",
|
|
11
14
|
"PropertiesAPI",
|
|
12
15
|
"LabelsAPI",
|
|
@@ -14,4 +17,5 @@ __all__ = [
|
|
|
14
17
|
"QueryAPI",
|
|
15
18
|
"RelationsAPI",
|
|
16
19
|
"RelationshipPatternsAPI",
|
|
20
|
+
"TextIndexesAPI",
|
|
17
21
|
]
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"""AI API for RushDB Python SDK.
|
|
2
2
|
|
|
3
|
-
Provides methods for graph
|
|
3
|
+
Provides methods for AI-assisted graph exploration, smart search,
|
|
4
4
|
and embedding index management.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
import warnings
|
|
8
|
+
from typing import TYPE_CHECKING, Any, Dict, Optional, Union, cast
|
|
8
9
|
|
|
9
10
|
from ..models.api_response import ApiResponse
|
|
10
11
|
from ..models.record import Record
|
|
12
|
+
from ..models.result import RecordSearchResult
|
|
13
|
+
from ..models.search_query import SearchQuery
|
|
11
14
|
from ..models.transaction import Transaction
|
|
12
15
|
from .base import BaseAPI
|
|
13
16
|
|
|
@@ -124,7 +127,12 @@ class AIAPI(BaseAPI):
|
|
|
124
127
|
|
|
125
128
|
>>> db = RushDB(api_key="...")
|
|
126
129
|
>>> schema = db.ai.get_schema()
|
|
127
|
-
>>> results = db.ai.search(
|
|
130
|
+
>>> results = db.ai.search("books about fast cars")
|
|
131
|
+
>>> vectors = db.records.vector_search({
|
|
132
|
+
... "query": "fast cars",
|
|
133
|
+
... "propertyName": "description",
|
|
134
|
+
... "labels": ["Book"],
|
|
135
|
+
... })
|
|
128
136
|
>>> db.ai.indexes.create({"propertyName": "description", "label": "Book"})
|
|
129
137
|
"""
|
|
130
138
|
|
|
@@ -145,7 +153,7 @@ class AIAPI(BaseAPI):
|
|
|
145
153
|
indexes exist for that property — each entry exposes ``id``,
|
|
146
154
|
``sourceType``, ``similarityFunction``, ``dimensions``, ``status``, and
|
|
147
155
|
``modelKey``. A non-empty ``vectorIndexes`` list means the property is
|
|
148
|
-
queryable with ``db.
|
|
156
|
+
queryable with ``db.records.vector_search()``.
|
|
149
157
|
|
|
150
158
|
Args:
|
|
151
159
|
params: Optional filter. Pass ``{"labels": ["Label1"]}`` to scope
|
|
@@ -214,35 +222,60 @@ class AIAPI(BaseAPI):
|
|
|
214
222
|
total=response.get("total"),
|
|
215
223
|
)
|
|
216
224
|
|
|
217
|
-
def search(
|
|
218
|
-
|
|
225
|
+
def search(
|
|
226
|
+
self,
|
|
227
|
+
prompt: Union[str, Dict[str, Any]],
|
|
228
|
+
current_query: Optional[SearchQuery] = None,
|
|
229
|
+
transaction: Optional[Union[Transaction, str]] = None,
|
|
230
|
+
) -> RecordSearchResult:
|
|
231
|
+
"""Perform AI-assisted smart search from natural language.
|
|
219
232
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
233
|
+
RushDB converts ``prompt`` into a SearchQuery using the project schema,
|
|
234
|
+
executes it, and returns matching records with the generated query
|
|
235
|
+
attached to ``result.search_query``.
|
|
223
236
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
Candidates are first narrowed by MATCH/WHERE, then ranked by exact
|
|
227
|
-
cosine similarity.
|
|
237
|
+
Use ``db.records.vector_search({...})`` for direct vector similarity
|
|
238
|
+
over embedding indexes.
|
|
228
239
|
|
|
229
240
|
Args:
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
- ``where`` (dict, optional): Additional property filters.
|
|
236
|
-
- ``limit`` (int, optional): Maximum number of results.
|
|
241
|
+
prompt: Natural-language search request. Passing a dict is
|
|
242
|
+
deprecated and delegates to ``db.records.vector_search``.
|
|
243
|
+
current_query: Optional current SearchQuery context from a
|
|
244
|
+
dashboard/query-builder session.
|
|
245
|
+
transaction: Optional transaction context.
|
|
237
246
|
|
|
238
247
|
Returns:
|
|
239
|
-
|
|
240
|
-
|
|
248
|
+
RecordSearchResult: Matching records. The generated SearchQuery is
|
|
249
|
+
available as ``result.search_query`` and server warnings as
|
|
250
|
+
``result.warnings``.
|
|
241
251
|
"""
|
|
242
|
-
|
|
252
|
+
if isinstance(prompt, dict):
|
|
253
|
+
warnings.warn(
|
|
254
|
+
"db.ai.search({...}) is deprecated for vector search; "
|
|
255
|
+
"use db.records.vector_search({...}) instead.",
|
|
256
|
+
DeprecationWarning,
|
|
257
|
+
stacklevel=2,
|
|
258
|
+
)
|
|
259
|
+
return self.client.records.vector_search(prompt, transaction=transaction)
|
|
260
|
+
|
|
261
|
+
headers = Transaction._build_transaction_header(transaction)
|
|
262
|
+
generated = self.client._make_request(
|
|
263
|
+
"POST",
|
|
264
|
+
"/ai/search-query",
|
|
265
|
+
{"prompt": prompt, "currentQuery": current_query},
|
|
266
|
+
headers,
|
|
267
|
+
)
|
|
268
|
+
generated_data = generated.get("data") or {}
|
|
269
|
+
search_query = generated_data.get("searchQuery") or {}
|
|
270
|
+
|
|
271
|
+
response = self.client._make_request(
|
|
272
|
+
"POST", "/records/search", search_query, headers
|
|
273
|
+
)
|
|
243
274
|
records = [Record(self.client, item) for item in response.get("data", [])]
|
|
244
|
-
return
|
|
275
|
+
return RecordSearchResult(
|
|
245
276
|
data=records,
|
|
246
|
-
|
|
247
|
-
|
|
277
|
+
total=response.get("total", len(records)),
|
|
278
|
+
search_query=cast(SearchQuery, search_query),
|
|
279
|
+
client=self.client,
|
|
280
|
+
warnings=generated_data.get("warnings") or [],
|
|
248
281
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -5,11 +5,10 @@ from .base import BaseAPI
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class QueryAPI(BaseAPI):
|
|
8
|
-
"""API client for executing raw
|
|
8
|
+
"""API client for executing raw openCypher queries.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
RushDB Cloud. It will not function for self-hosted or local-only deployments.
|
|
10
|
+
Works on RushDB Cloud and on a self-hosted RushDB engine in direct mode
|
|
11
|
+
(the engine must be started with ``--languages cypher``).
|
|
13
12
|
|
|
14
13
|
Example:
|
|
15
14
|
>>> from rushdb import RushDB
|