lance-context 0.3.2__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {lance_context-0.3.2 → lance_context-0.4.0}/PKG-INFO +10 -6
  2. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-api/src/lib.rs +189 -0
  3. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/Cargo.toml +1 -1
  4. lance_context-0.4.0/crates/lance-context-core/src/api_impl.rs +418 -0
  5. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/src/lib.rs +5 -3
  6. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/src/record.rs +164 -16
  7. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/src/store.rs +1472 -79
  8. {lance_context-0.3.2 → lance_context-0.4.0}/pyproject.toml +19 -7
  9. {lance_context-0.3.2 → lance_context-0.4.0}/python/Cargo.toml +1 -1
  10. {lance_context-0.3.2 → lance_context-0.4.0}/python/lance_context/api.py +329 -4
  11. {lance_context-0.3.2 → lance_context-0.4.0}/python/src/lib.rs +311 -88
  12. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_async.py +19 -0
  13. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_compaction.py +8 -7
  14. lance_context-0.4.0/python/tests/test_distance_metric.py +77 -0
  15. lance_context-0.4.0/python/tests/test_packaging_metadata.py +47 -0
  16. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_persistence.py +209 -3
  17. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_search.py +569 -24
  18. {lance_context-0.3.2 → lance_context-0.4.0}/python/uv.lock +18 -8
  19. lance_context-0.3.2/crates/lance-context-core/src/api_impl.rs +0 -180
  20. {lance_context-0.3.2 → lance_context-0.4.0}/Cargo.toml +0 -0
  21. {lance_context-0.3.2 → lance_context-0.4.0}/LICENSE +0 -0
  22. {lance_context-0.3.2 → lance_context-0.4.0}/README.md +0 -0
  23. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-api/Cargo.toml +0 -0
  24. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/README.md +0 -0
  25. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/src/context.rs +0 -0
  26. {lance_context-0.3.2 → lance_context-0.4.0}/crates/lance-context-core/src/serde.rs +0 -0
  27. {lance_context-0.3.2 → lance_context-0.4.0}/python/Cargo.lock +0 -0
  28. {lance_context-0.3.2 → lance_context-0.4.0}/python/LICENSE +0 -0
  29. {lance_context-0.3.2 → lance_context-0.4.0}/python/README.md +0 -0
  30. {lance_context-0.3.2 → lance_context-0.4.0}/python/lance_context/__init__.py +0 -0
  31. {lance_context-0.3.2 → lance_context-0.4.0}/python/python/tests/test_context.py +0 -0
  32. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_add_many.py +0 -0
  33. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_delete.py +0 -0
  34. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_external_id.py +0 -0
  35. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_gcs_persistence.py +0 -0
  36. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_id_index.py +0 -0
  37. {lance_context-0.3.2 → lance_context-0.4.0}/python/tests/test_storage_options.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lance-context
3
- Version: 0.3.2
3
+ Version: 0.4.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Science/Research
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -8,26 +8,30 @@ Classifier: Operating System :: OS Independent
8
8
  Classifier: Programming Language :: Python
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3 :: Only
11
- Classifier: Programming Language :: Python :: 3.9
12
- Classifier: Programming Language :: Python :: 3.10
13
11
  Classifier: Programming Language :: Python :: 3.11
14
12
  Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
15
14
  Classifier: Programming Language :: Rust
16
15
  Classifier: Topic :: Scientific/Engineering
17
- Requires-Dist: pylance==7.0.0
18
- Requires-Dist: lancedb==0.27.1
19
- Requires-Dist: lance-namespace==0.7.7
16
+ Requires-Dist: pyarrow>=14
20
17
  Requires-Dist: ruff ; extra == 'dev'
21
18
  Requires-Dist: pyright ; extra == 'dev'
22
19
  Requires-Dist: lance-graph==0.5.4 ; extra == 'graph'
20
+ Requires-Dist: pylance>=7.0.0,<8 ; extra == 'lance-python'
21
+ Requires-Dist: lance-namespace>=0.7.7,<0.8 ; extra == 'lance-python'
22
+ Requires-Dist: lancedb==0.27.1 ; extra == 'lance-python'
23
23
  Requires-Dist: pytest ; extra == 'tests'
24
24
  Requires-Dist: pytest-asyncio ; extra == 'tests'
25
25
  Requires-Dist: ruff ; extra == 'tests'
26
26
  Requires-Dist: moto[s3,server] ; extra == 'tests'
27
27
  Requires-Dist: boto3 ; extra == 'tests'
28
28
  Requires-Dist: botocore ; extra == 'tests'
29
+ Requires-Dist: pylance>=7.0.0,<8 ; extra == 'tests'
30
+ Requires-Dist: lance-namespace>=0.7.7,<0.8 ; extra == 'tests'
31
+ Requires-Dist: lancedb==0.27.1 ; extra == 'tests'
29
32
  Provides-Extra: dev
30
33
  Provides-Extra: graph
34
+ Provides-Extra: lance-python
31
35
  Provides-Extra: tests
32
36
  License-File: LICENSE
33
37
  Summary: Multimodal, versioned context storage for agentic workflows
@@ -34,20 +34,60 @@ pub trait ContextStoreApi {
34
34
  records: &[AddRecordRequest],
35
35
  ) -> impl Future<Output = ContextResult<AddRecordsResponse>> + Send;
36
36
 
37
+ fn upsert(
38
+ &mut self,
39
+ request: &UpsertRecordRequest,
40
+ ) -> impl Future<Output = ContextResult<UpsertRecordResponse>> + Send;
41
+
42
+ fn update(
43
+ &mut self,
44
+ request: &UpdateRecordRequest,
45
+ ) -> impl Future<Output = ContextResult<UpdateRecordResponse>> + Send;
46
+
37
47
  fn get(&self, id: &str) -> impl Future<Output = ContextResult<Option<RecordDto>>> + Send;
38
48
 
49
+ fn get_by_external_id(
50
+ &self,
51
+ external_id: &str,
52
+ ) -> impl Future<Output = ContextResult<Option<RecordDto>>> + Send;
53
+
54
+ fn delete_by_id(
55
+ &mut self,
56
+ id: &str,
57
+ ) -> impl Future<Output = ContextResult<DeleteRecordResponse>> + Send;
58
+
59
+ fn delete_by_external_id(
60
+ &mut self,
61
+ external_id: &str,
62
+ ) -> impl Future<Output = ContextResult<DeleteRecordResponse>> + Send;
63
+
39
64
  fn list(
40
65
  &self,
41
66
  limit: Option<usize>,
42
67
  offset: Option<usize>,
43
68
  ) -> impl Future<Output = ContextResult<Vec<RecordDto>>> + Send;
44
69
 
70
+ fn related(
71
+ &self,
72
+ target_id: &str,
73
+ relation: Option<&str>,
74
+ limit: Option<usize>,
75
+ include_expired: bool,
76
+ include_retired: bool,
77
+ ) -> impl Future<Output = ContextResult<Vec<RecordDto>>> + Send;
78
+
45
79
  fn search(
46
80
  &self,
47
81
  query: &[f32],
48
82
  limit: Option<usize>,
83
+ include_relationships: bool,
49
84
  ) -> impl Future<Output = ContextResult<Vec<SearchResultDto>>> + Send;
50
85
 
86
+ fn retrieve(
87
+ &self,
88
+ request: &RetrieveRequest,
89
+ ) -> impl Future<Output = ContextResult<Vec<RetrieveResultDto>>> + Send;
90
+
51
91
  fn version(&self) -> u64;
52
92
 
53
93
  fn checkout(&mut self, version: u64) -> impl Future<Output = ContextResult<()>> + Send;
@@ -73,6 +113,10 @@ pub struct CreateContextRequest {
73
113
  pub id_index_type: Option<String>,
74
114
  #[serde(default)]
75
115
  pub blob_columns: Option<Vec<String>>,
116
+ #[serde(default)]
117
+ pub embedding_dim: Option<i32>,
118
+ #[serde(default)]
119
+ pub distance_metric: Option<String>,
76
120
  }
77
121
 
78
122
  #[derive(Debug, Serialize, Deserialize)]
@@ -103,6 +147,14 @@ pub struct StateMetadataDto {
103
147
  pub custom: Option<String>,
104
148
  }
105
149
 
150
+ #[derive(Debug, Clone, Default, Serialize, Deserialize)]
151
+ pub struct RelationshipDto {
152
+ pub target_id: String,
153
+ pub relation: String,
154
+ #[serde(default, skip_serializing_if = "Option::is_none")]
155
+ pub weight: Option<f32>,
156
+ }
157
+
106
158
  #[derive(Debug, Clone, Default, Serialize, Deserialize)]
107
159
  pub struct AddRecordRequest {
108
160
  #[serde(default = "default_role")]
@@ -130,6 +182,8 @@ pub struct AddRecordRequest {
130
182
  pub state_metadata: Option<StateMetadataDto>,
131
183
  #[serde(default, skip_serializing_if = "Option::is_none")]
132
184
  pub metadata: Option<Value>,
185
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
186
+ pub relationships: Vec<RelationshipDto>,
133
187
  #[serde(default, skip_serializing_if = "Option::is_none")]
134
188
  pub expires_at: Option<DateTime<Utc>>,
135
189
  #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -150,6 +204,82 @@ pub struct AddRecordsResponse {
150
204
  pub count: usize,
151
205
  }
152
206
 
207
+ #[derive(Debug, Serialize, Deserialize)]
208
+ pub struct UpsertRecordRequest {
209
+ pub record: AddRecordRequest,
210
+ #[serde(default = "default_upsert_key")]
211
+ pub key: String,
212
+ }
213
+
214
+ #[derive(Debug, Serialize, Deserialize)]
215
+ pub struct UpsertRecordResponse {
216
+ pub version: u64,
217
+ pub inserted: bool,
218
+ #[serde(default, skip_serializing_if = "Option::is_none")]
219
+ pub replaced_id: Option<String>,
220
+ pub record: RecordDto,
221
+ }
222
+
223
+ #[derive(Debug, Clone, Default, Serialize, Deserialize)]
224
+ pub struct RecordPatchDto {
225
+ #[serde(default, skip_serializing_if = "Option::is_none")]
226
+ pub bot_id: Option<String>,
227
+ #[serde(default, skip_serializing_if = "Option::is_none")]
228
+ pub session_id: Option<String>,
229
+ #[serde(default, skip_serializing_if = "Option::is_none")]
230
+ pub state_metadata: Option<StateMetadataDto>,
231
+ #[serde(default, skip_serializing_if = "Option::is_none")]
232
+ pub metadata: Option<Value>,
233
+ #[serde(default, skip_serializing_if = "Option::is_none")]
234
+ pub relationships: Option<Vec<RelationshipDto>>,
235
+ #[serde(default, skip_serializing_if = "Option::is_none")]
236
+ pub expires_at: Option<DateTime<Utc>>,
237
+ #[serde(default, skip_serializing_if = "Option::is_none")]
238
+ pub retention_policy: Option<String>,
239
+ #[serde(default, skip_serializing_if = "Option::is_none")]
240
+ pub lifecycle_status: Option<String>,
241
+ #[serde(default, skip_serializing_if = "Option::is_none")]
242
+ pub retired_at: Option<DateTime<Utc>>,
243
+ #[serde(default, skip_serializing_if = "Option::is_none")]
244
+ pub retired_reason: Option<String>,
245
+ }
246
+
247
+ impl RecordPatchDto {
248
+ #[must_use]
249
+ pub fn is_empty(&self) -> bool {
250
+ self.bot_id.is_none()
251
+ && self.session_id.is_none()
252
+ && self.state_metadata.is_none()
253
+ && self.metadata.is_none()
254
+ && self.relationships.is_none()
255
+ && self.expires_at.is_none()
256
+ && self.retention_policy.is_none()
257
+ && self.lifecycle_status.is_none()
258
+ && self.retired_at.is_none()
259
+ && self.retired_reason.is_none()
260
+ }
261
+ }
262
+
263
+ #[derive(Debug, Serialize, Deserialize)]
264
+ pub struct UpdateRecordRequest {
265
+ #[serde(default, skip_serializing_if = "Option::is_none")]
266
+ pub id: Option<String>,
267
+ #[serde(default, skip_serializing_if = "Option::is_none")]
268
+ pub external_id: Option<String>,
269
+ #[serde(default)]
270
+ pub patch: RecordPatchDto,
271
+ }
272
+
273
+ #[derive(Debug, Serialize, Deserialize)]
274
+ pub struct UpdateRecordResponse {
275
+ pub version: u64,
276
+ pub updated: bool,
277
+ #[serde(default, skip_serializing_if = "Option::is_none")]
278
+ pub replaced_id: Option<String>,
279
+ #[serde(default, skip_serializing_if = "Option::is_none")]
280
+ pub record: Option<RecordDto>,
281
+ }
282
+
153
283
  #[derive(Debug, Clone, Serialize, Deserialize)]
154
284
  pub struct RecordDto {
155
285
  pub id: String,
@@ -178,6 +308,8 @@ pub struct RecordDto {
178
308
  pub state_metadata: Option<StateMetadataDto>,
179
309
  #[serde(default, skip_serializing_if = "Option::is_none")]
180
310
  pub metadata: Option<Value>,
311
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
312
+ pub relationships: Vec<RelationshipDto>,
181
313
  #[serde(default, skip_serializing_if = "Option::is_none")]
182
314
  pub expires_at: Option<DateTime<Utc>>,
183
315
  #[serde(default, skip_serializing_if = "Option::is_none")]
@@ -207,6 +339,12 @@ pub struct GetRecordResponse {
207
339
  pub record: Option<RecordDto>,
208
340
  }
209
341
 
342
+ #[derive(Debug, Serialize, Deserialize)]
343
+ pub struct DeleteRecordResponse {
344
+ pub deleted: bool,
345
+ pub version: u64,
346
+ }
347
+
210
348
  // ---------------------------------------------------------------------------
211
349
  // Search
212
350
  // ---------------------------------------------------------------------------
@@ -216,6 +354,8 @@ pub struct SearchRequest {
216
354
  pub query: Vec<f32>,
217
355
  #[serde(default = "default_search_limit")]
218
356
  pub limit: usize,
357
+ #[serde(default)]
358
+ pub include_relationships: bool,
219
359
  }
220
360
 
221
361
  #[derive(Debug, Serialize, Deserialize)]
@@ -229,6 +369,47 @@ pub struct SearchResponse {
229
369
  pub results: Vec<SearchResultDto>,
230
370
  }
231
371
 
372
+ // ---------------------------------------------------------------------------
373
+ // Hybrid retrieval
374
+ // ---------------------------------------------------------------------------
375
+
376
+ #[derive(Debug, Serialize, Deserialize)]
377
+ pub struct RetrieveRequest {
378
+ #[serde(default, skip_serializing_if = "Option::is_none")]
379
+ pub text: Option<String>,
380
+ #[serde(default, skip_serializing_if = "Option::is_none")]
381
+ pub vector: Option<Vec<f32>>,
382
+ #[serde(default = "default_search_limit")]
383
+ pub limit: usize,
384
+ #[serde(default, skip_serializing_if = "Option::is_none")]
385
+ pub filters: Option<Value>,
386
+ #[serde(default)]
387
+ pub include_expired: bool,
388
+ #[serde(default)]
389
+ pub include_retired: bool,
390
+ #[serde(default)]
391
+ pub include_relationships: bool,
392
+ #[serde(default = "default_retrieve_fusion")]
393
+ pub fusion: String,
394
+ }
395
+
396
+ #[derive(Debug, Serialize, Deserialize)]
397
+ pub struct RetrieveResultDto {
398
+ pub record: RecordDto,
399
+ pub score: f32,
400
+ #[serde(default, skip_serializing_if = "Option::is_none")]
401
+ pub vector_distance: Option<f32>,
402
+ #[serde(default, skip_serializing_if = "Option::is_none")]
403
+ pub text_score: Option<f32>,
404
+ #[serde(default, skip_serializing_if = "Vec::is_empty")]
405
+ pub matched_channels: Vec<String>,
406
+ }
407
+
408
+ #[derive(Debug, Serialize, Deserialize)]
409
+ pub struct RetrieveResponse {
410
+ pub results: Vec<RetrieveResultDto>,
411
+ }
412
+
232
413
  // ---------------------------------------------------------------------------
233
414
  // Versioning
234
415
  // ---------------------------------------------------------------------------
@@ -301,10 +482,18 @@ fn default_role() -> String {
301
482
  "user".to_string()
302
483
  }
303
484
 
485
+ fn default_upsert_key() -> String {
486
+ "external_id".to_string()
487
+ }
488
+
304
489
  fn default_search_limit() -> usize {
305
490
  10
306
491
  }
307
492
 
493
+ fn default_retrieve_fusion() -> String {
494
+ "rrf".to_string()
495
+ }
496
+
308
497
  fn serialize_base64_opt<S>(data: &Option<Vec<u8>>, serializer: S) -> Result<S::Ok, S::Error>
309
498
  where
310
499
  S: serde::Serializer,
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "lance-context-core"
3
- version = "0.3.2"
3
+ version = "0.4.0"
4
4
  edition = "2021"
5
5
  license = "Apache-2.0"
6
6
  authors = ["Lance Devs <dev@lancedb.com>"]