ahnlich-client-py 0.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.
Files changed (32) hide show
  1. ahnlich_client_py-0.0.0/PKG-INFO +708 -0
  2. ahnlich_client_py-0.0.0/README.md +690 -0
  3. ahnlich_client_py-0.0.0/VERSION +2 -0
  4. ahnlich_client_py-0.0.0/ahnlich_client_py/__init__.py +5 -0
  5. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/__init__.py +10 -0
  6. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/ai.py +174 -0
  7. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/db.py +163 -0
  8. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/non_blocking/__init__.py +2 -0
  9. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/non_blocking/ai.py +16 -0
  10. ahnlich_client_py-0.0.0/ahnlich_client_py/builders/non_blocking/db.py +16 -0
  11. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/__init__.py +2 -0
  12. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/ai.py +224 -0
  13. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/db.py +224 -0
  14. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/non_blocking/__init__.py +2 -0
  15. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/non_blocking/ai.py +226 -0
  16. ahnlich_client_py-0.0.0/ahnlich_client_py/clients/non_blocking/db.py +225 -0
  17. ahnlich_client_py-0.0.0/ahnlich_client_py/config.py +18 -0
  18. ahnlich_client_py-0.0.0/ahnlich_client_py/exceptions.py +10 -0
  19. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/__init__.py +0 -0
  20. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/ai_query.py +532 -0
  21. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/ai_response.py +461 -0
  22. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/async_base_client.py +90 -0
  23. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/base_client.py +84 -0
  24. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/bincode/__init__.py +77 -0
  25. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/db_query.py +381 -0
  26. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/db_response.py +340 -0
  27. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/pool_wrapper.py +46 -0
  28. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/protocol.py +143 -0
  29. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/serde_binary/__init__.py +418 -0
  30. ahnlich_client_py-0.0.0/ahnlich_client_py/internals/serde_types/__init__.py +75 -0
  31. ahnlich_client_py-0.0.0/ahnlich_client_py/libs.py +23 -0
  32. ahnlich_client_py-0.0.0/pyproject.toml +43 -0
@@ -0,0 +1,708 @@
1
+ Metadata-Version: 2.1
2
+ Name: ahnlich-client-py
3
+ Version: 0.0.0
4
+ Summary: A python client for interacting with Ahnlich DB and AI
5
+ Author: David Onuh
6
+ Author-email: davidonuh1@gmail.com
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Requires-Dist: bump2version (>=1.0.1,<2.0.0)
12
+ Requires-Dist: generic-connection-pool (>=0.7.0,<0.8.0)
13
+ Requires-Dist: numpy (>=1.26.4,<2.0.0)
14
+ Requires-Dist: pytest-asyncio (>=0.24.0,<0.25.0)
15
+ Requires-Dist: toml (>=0.10.2,<0.11.0)
16
+ Description-Content-Type: text/markdown
17
+
18
+ ## Ahnlich Client PY
19
+
20
+ A Python client that interacts with both ahnlich DB and AI
21
+
22
+
23
+ [![Ahnlich TestSuite](https://github.com/deven96/ahnlich/actions/workflows/test.yml/badge.svg)](https://github.com/deven96/ahnlich/actions/workflows/test.yml)
24
+ [![Ahnlich Python Client Tag and Deploy](https://github.com/deven96/ahnlich/actions/workflows/python_tag_and_deploy.yml/badge.svg)](https://github.com/deven96/ahnlich/actions/workflows/python_tag_and_deploy.yml)
25
+
26
+ ## Usage Overview
27
+
28
+ The following topics are covered:
29
+ * [Installation](#installation)
30
+ * [Package Information](#package-information)
31
+ * [Server Response](#server-response)
32
+ * [Initialization](#initialization)
33
+ * [Client](#client)
34
+
35
+ * [Connection Pooling](#connection-pooling)
36
+ * [Requests - DB](#requests---db)
37
+ * [Ping](#ping)
38
+ * [Info Server](#info-server)
39
+ * [List Connected Clients](#list-connected-clients)
40
+ * [List Stores](#list-stores)
41
+ * [Create Store](#create-store)
42
+ * [Set](#set)
43
+ * [Drop Store](#drop-store)
44
+ * [Get Sim N](#get-sim-n)
45
+ * [Get Key](#get-key)
46
+ * [Get By Predicate](#get-by-predicate)
47
+ * [Create Predicate Index](#create-predicate-index)
48
+ * [Drop Predicate Index](#drop-predicate-index)
49
+ * [Create Non Linear Algorithm Index](#create-non-linear-algorithm-index)
50
+ * [Drop Non Linear Algorithm Index](#drop-non-linear-algorithm-index)
51
+ * [Delete Key](#delete-key)
52
+ * [Delete Predicate](#delete-predicate)
53
+
54
+ * [Requests - AI](#requests---ai)
55
+ * [Ping](#ping-1)
56
+ * [Info Server](#info-server-1)
57
+ * [List Stores](#list-stores-1)
58
+ * [Create Store](#create-store-1)
59
+ * [Set](#set-1)
60
+ * [Drop Store](#drop-store-1)
61
+ * [Get Sim N](#get-sim-n-1)
62
+ * [Get By Predicate](#get-by-predicate-1)
63
+ * [Create Predicate Index](#create-predicate-index-1)
64
+ * [Drop Predicate Index](#drop-predicate-index-1)
65
+ * [Create Non Linear Algorithm Index](#create-non-linear-algorithm-index-1)
66
+ * [Drop Non Linear Algorithm Index](#drop-non-linear-algorithm-index-1)
67
+ * [Delete Key](#delete-key-1)
68
+
69
+ * [Bulk Requests](#bulk-requests)
70
+ * [Client As Context Manager](#client-as-context-manager)
71
+ * [How to Deploy to Artifactory](#deploy-to-artifactory)
72
+ * [Type Meanings](#type-meanings)
73
+ * [Change Log](#change-log)
74
+
75
+ ## Installation
76
+
77
+ - Using Poetry
78
+ ```bash
79
+ poetry add ahnlich-client-py
80
+ ```
81
+ - Using pip
82
+ ```bash
83
+ pip3 install ahnlich-client-py
84
+ ```
85
+
86
+ ## Package Information
87
+ The ahnlich client has some noteworthy modules that should provide some context
88
+ - Bincode
89
+ - Serde Types
90
+ - Serde Binary
91
+
92
+ The above mentioned are classes generated by `serde_generate` to help represent the primitive rust types and provide a base bincode serialization capabilities
93
+
94
+ - Query: Generated from the spec document, contains all the types used by to send a request to the ahnlich database
95
+ - Server Response: Generated from the spec document, contains all the possible server response.
96
+ - Builders:
97
+ - Exceptions: Possible Client Exceptions
98
+ - Libs: Contains helpers, such as `create_store_key`
99
+
100
+
101
+ ## Server Response
102
+
103
+ All query types have an associating server response, all which can be found
104
+ ```py
105
+ from ahnlich_client_py import server_response
106
+ ```
107
+
108
+ ## Initialization
109
+
110
+ ### Client
111
+
112
+ - Blocking clients
113
+ ```py
114
+ from ahnlich_client_py import AhnlichDBClient
115
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
116
+ ```
117
+ - Nonblocking clients
118
+ ```py
119
+ from ahnlich_client_py.non_blocking_client import AhnlichDBClient
120
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
121
+ ```
122
+
123
+ ## Connection Pooling
124
+
125
+ The ahnlich client has the ability to reuse connections. Configurations can be changed by overiding the default class initialization.
126
+
127
+ ```py
128
+
129
+ @dataclass
130
+ class AhnlichDBPoolSettings:
131
+ idle_timeout: float = 30.0
132
+ max_lifetime: float = 600.0
133
+ min_idle_connections: int = 3
134
+ max_pool_size: int = 10
135
+ enable_background_collector: bool = True
136
+ dispose_batch_size: int = 0
137
+
138
+ ```
139
+ Where:
140
+
141
+
142
+ - **enable_background_collector** -> `defaults 1`: if True starts a background worker that disposes expired and idle connections maintaining requested pool state. If False the connections will be disposed on each connection release.
143
+
144
+ - **idle_timeout** -> `defaults 30.0`: inactivity time (`in seconds`) after which an extra connection will be disposed (a connection considered as extra if the number of endpoint connection exceeds min_idle).
145
+
146
+ - **max_lifetime** -> `defaults 600.0`: number of seconds after which any connection will be disposed.
147
+
148
+ - **min_idle_connections** -> `default 3`: minimum number of connections for the ahnlich db endpoint the pool tries to hold. Connections that exceed that number will be considered as extra and disposed after idle_timeout seconds of inactivity.
149
+
150
+ - **max_pool_size** -> `defaults 10`: maximum number of connections in the pool.
151
+
152
+ - **dispose_batch_size**: maximum number of expired and idle connections to be disposed on connection release (if background collector is started the parameter is ignored).
153
+
154
+ ## Requests - DB
155
+
156
+ ### Ping
157
+
158
+ ```py
159
+ from ahnlich_client_py import AhnlichDBClient
160
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
161
+
162
+ tracing_id = "00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01"
163
+ response = client.ping(tracing_id)
164
+ ```
165
+
166
+ ### Info Server
167
+
168
+ ```py
169
+ from ahnlich_client_py import AhnlichDBClient
170
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
171
+
172
+ response = client.info_server()
173
+ ```
174
+
175
+ ### List Connected Clients
176
+
177
+ ```py
178
+ from ahnlich_client_py import AhnlichDBClient
179
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
180
+
181
+ response = client.list_clients()
182
+ ```
183
+
184
+ ### List Stores
185
+
186
+ ```py
187
+ from ahnlich_client_py import AhnlichDBClient
188
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
189
+
190
+ tracing_id = "00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01"
191
+ response = client.list_stores(tracing_id)
192
+ ```
193
+
194
+ ### Create Store
195
+
196
+ ```py
197
+ from ahnlich_client_py import AhnlichDBClient
198
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
199
+
200
+ response = client.create_store(
201
+ store_name = "test store",
202
+ dimension = 5,
203
+ create_predicates = [
204
+ "job"
205
+ ],
206
+ error_if_exists=True
207
+ )
208
+ ```
209
+ Once store dimension is fixed, all `store_keys` must confirm with said dimension.
210
+ Note we only accept 1 dimensional arrays/vectors of length N.
211
+ Store dimensions is a one dimensional array of length N
212
+
213
+
214
+ ### Set
215
+ ```py
216
+ from libs import create_store_key
217
+ from ahnlich_client_py import AhnlichDBClient
218
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
219
+
220
+ store_key = create_store_key(data=[5.0, 3.0, 4.0, 3.9, 4.9])
221
+ store_value = {"rank": query.MetadataValue__RawString(value="chunin")}
222
+
223
+
224
+ response = client.set(
225
+ store_name = "test store",
226
+ inputs=[(store_key, store_value)]
227
+ )
228
+ ```
229
+
230
+
231
+ ### Drop store
232
+ ```py
233
+ from ahnlich_client_py import AhnlichDBClient
234
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
235
+
236
+ response = client.drop_store(
237
+ store_name = "test store",
238
+ error_if_not_exists=True
239
+ )
240
+
241
+
242
+ ```
243
+
244
+
245
+ ### Get Sim N
246
+ Returns an array of tuple of (store_key, store_value) of Maximum specified N
247
+
248
+ ```py
249
+ from ahnlich_client_py import AhnlichDBClient
250
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
251
+
252
+
253
+
254
+ response = client.get_sim_n(
255
+ store_name = "test store",
256
+ search_input = key,
257
+ closest_n = 3,
258
+ algorithm = query.Algorithm__CosineSimilarity(),
259
+ condition = None,
260
+ tracing_id=None,
261
+ )
262
+ ```
263
+ <u>*Closest_n is a Nonzero integer value*</u>
264
+
265
+
266
+
267
+ ### Get Key
268
+ Returns an array of tuple of (store_key, store_value)
269
+
270
+ ```py
271
+ from ahnlich_client_py import AhnlichDBClient
272
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
273
+
274
+ key = some_store_key
275
+ response = client.get_key(
276
+ store_name = "test store",
277
+ keys=[key]
278
+ )
279
+ ```
280
+
281
+
282
+ ### Get By Predicate
283
+ Same as Get_key but returns results based defined conditions
284
+
285
+ ```py
286
+ from ahnlich_client_py import AhnlichDBClient
287
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
288
+
289
+ condition = query.PredicateCondition__Value(
290
+ query.Predicate__Equals(
291
+ key="job",
292
+ value=query.MetadataValue__RawString(value="sorcerer")
293
+ )
294
+ )
295
+ response = client.get_by_predicate(
296
+ store_name = "test store",
297
+ condition=conditon
298
+ )
299
+ ```
300
+
301
+ ### Create Predicate Index
302
+ ```py
303
+ from ahnlich_client_py import AhnlichDBClient
304
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
305
+
306
+ response = client.create_pred_index(
307
+ store_name = "test store",
308
+ predicates=["job", "rank"]
309
+ )
310
+ ```
311
+
312
+ ### Drop Predicate Index
313
+ ```py
314
+ from ahnlich_client_py import AhnlichDBClient
315
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
316
+
317
+ response = client.drop_pred_index(
318
+ store_name = "test store",
319
+ predicates=["job"],
320
+ error_if_not_exists=True
321
+ )
322
+ ```
323
+
324
+ ### Create Non Linear Algorithm Index
325
+ ```py
326
+ from ahnlich_client_py import AhnlichDBClient
327
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
328
+
329
+ response = client.create_non_linear_algorithm_index(
330
+ store_name = "test store",
331
+ non_linear_indices=[NonLinearAlgorithm__KDTree],
332
+ tracing_id = None
333
+ )
334
+ ```
335
+
336
+ ### Drop Non Linear Algorithm Index
337
+ ```py
338
+ from ahnlich_client_py import AhnlichDBClient
339
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
340
+
341
+ response = client.drop_non_linear_algorithm_index(
342
+ store_name = "test store",
343
+ non_linear_indices=[NonLinearAlgorithm__KDTree],
344
+ error_if_not_exists=True,
345
+ tracing_id = None
346
+ )
347
+ ```
348
+
349
+
350
+ ### Delete Key
351
+ ```py
352
+ from ahnlich_client_py.libs import create_store_key
353
+ from ahnlich_client_py import AhnlichDBClient
354
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
355
+
356
+
357
+
358
+ store_key = create_store_key(data=[5.0, 3.0, 4.0, 3.9, 4.9])
359
+
360
+
361
+ response = client.delete_key(
362
+ store_name = "test store",
363
+ keys=[store_key]
364
+ )
365
+ ```
366
+
367
+ ### Delete Predicate
368
+ ```py
369
+ from ahnlich_client_py import AhnlichDBClient
370
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
371
+
372
+ condition = query.PredicateCondition__Value(
373
+ query.Predicate__Equals(
374
+ key="job",
375
+ value=query.MetadataValue__RawString(value="sorcerer")
376
+ )
377
+ )
378
+
379
+
380
+ response = client.delete_predicate(
381
+ store_name = "test store",
382
+ condition = condition
383
+ )
384
+ ```
385
+
386
+
387
+ ## Requests - AI
388
+
389
+
390
+ ### Ping
391
+
392
+ ```py
393
+ from ahnlich_client_py import AhnlichAIClient
394
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
395
+
396
+ response = client.ping(tracing_id)
397
+ ```
398
+
399
+ ### Info Server
400
+
401
+ ```py
402
+ from ahnlich_client_py import AhnlichAIClient
403
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
404
+
405
+ response = client.info_server(tracing_id)
406
+ ```
407
+
408
+ ### List Stores
409
+
410
+ ```py
411
+ from ahnlich_client_py import AhnlichAIClient
412
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
413
+
414
+ response = client.list_stores(tracing_id)
415
+ ```
416
+
417
+ ### Create Store
418
+
419
+ ```py
420
+ from ahnlich_client_py import AhnlichAIClient
421
+ from ahnlich_client_py.internals import ai_query
422
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
423
+
424
+ response = client.create_store(
425
+ store_name = "test store",
426
+ model = ai_query.AIModel__AllMiniLML6V2(),
427
+ store_type = ai_query.AIStoreType__RawString(),
428
+ predicates = [
429
+ "job"
430
+ ],
431
+ non_linear_indices= [],
432
+ error_if_exists = True,
433
+ # Store original controls if we choose to store the raw inputs
434
+ # within the DB in order to be able to retrieve the originals again
435
+ # during query, else only store values are returned
436
+ store_original = True,
437
+ tracing_id=None,
438
+ )
439
+
440
+ ```
441
+
442
+
443
+ ### Set
444
+ ```py
445
+
446
+ from ahnlich_client_py import AhnlichAIClient
447
+ from ahnlich_client_py.internals import ai_query
448
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
449
+
450
+ store_inputs = [
451
+ (
452
+ ai_query.StoreInput__RawString("Jordan One"),
453
+ {"brand": ai_query.MetadataValue__RawString("Nike")},
454
+ ),
455
+ (
456
+ ai_query.StoreInput__RawString("Yeezey"),
457
+ {"brand": ai_query.MetadataValue__RawString("Adidas")},
458
+ ),
459
+ ]
460
+
461
+
462
+ response = client.set(
463
+ store_name = "test store",
464
+ inputs=store_inputs,
465
+ tracing_id=None
466
+ )
467
+ ```
468
+
469
+
470
+ ### Drop store
471
+ ```py
472
+ from ahnlich_client_py import AhnlichAIClient
473
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
474
+
475
+ response = client.drop_store(
476
+ store_name = "test store",
477
+ error_if_not_exists=True,
478
+ tracing_id=None
479
+ )
480
+
481
+
482
+ ```
483
+
484
+
485
+ ### Get Sim N
486
+ Returns an array of tuple of (store_key, store_value) of Maximum specified N
487
+
488
+ ```py
489
+ from ahnlich_client_py import AhnlichAIClient
490
+ from ahnlich_client_py.internals import ai_query
491
+
492
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
493
+
494
+
495
+ search_input = ai_query.StoreInput__RawString("Jordan")
496
+
497
+ response = client.get_sim_n(
498
+ store_name = "test store",
499
+ search_input = search_input,
500
+ closest_n = 3,
501
+ algorithm = query.Algorithm__CosineSimilarity(),
502
+ condition = None,
503
+ tracing_id=None
504
+ )
505
+ ```
506
+ <u>*Closest_n is a Nonzero integer value*</u>
507
+
508
+
509
+ ### Get By Predicate
510
+ Same as Get_key but returns results based defined conditions
511
+
512
+ ```py
513
+ from ahnlich_client_py import AhnlichAIClient
514
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
515
+
516
+ condition = query.PredicateCondition__Value(
517
+ query.Predicate__Equals(
518
+ key="brand",
519
+ value=query.MetadataValue__RawString(value="Nike")
520
+ )
521
+ )
522
+ response = client.get_by_predicate(
523
+ store_name = "test store",
524
+ condition=conditon,
525
+ tracing_id=None,
526
+ )
527
+ ```
528
+
529
+ ### Create Predicate Index
530
+ ```py
531
+ from ahnlich_client_py import AhnlichAIClient
532
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
533
+
534
+ response = client.create_pred_index(
535
+ store_name = "test store",
536
+ predicates=["job", "rank"],
537
+ tracing_id=None,
538
+ )
539
+ ```
540
+
541
+ ### Drop Predicate Index
542
+ ```py
543
+ from ahnlich_client_py import AhnlichAIClient
544
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
545
+
546
+ response = client.drop_pred_index(
547
+ store_name = "test store",
548
+ predicates=["job"],
549
+ error_if_not_exists=True,
550
+ tracing_id=None,
551
+ )
552
+ ```
553
+
554
+ ### Create Non Linear Algorithm Index
555
+ ```py
556
+ from ahnlich_client_py import AhnlichAIClient
557
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
558
+
559
+ response = client.create_non_linear_algorithm_index(
560
+ store_name = "test store",
561
+ non_linear_indices=[NonLinearAlgorithm__KDTree],
562
+ tracing_id = None
563
+ )
564
+ ```
565
+
566
+ ### Drop Non Linear Algorithm Index
567
+ ```py
568
+ from ahnlich_client_py import AhnlichAIClient
569
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
570
+
571
+ response = client.drop_non_linear_algorithm_index(
572
+ store_name = "test store",
573
+ non_linear_indices=[NonLinearAlgorithm__KDTree],
574
+ error_if_not_exists=True,
575
+ tracing_id = None
576
+ )
577
+ ```
578
+
579
+
580
+
581
+ ### Delete Key
582
+ ```py
583
+
584
+ from ahnlich_client_py import AhnlichAIClient
585
+ client = AhnlichAIClient(address="127.0.0.1", port=port)
586
+
587
+
588
+
589
+ key = ai_query.StoreInput__RawString("Custom Made Jordan 4")
590
+
591
+
592
+ response = client.delete_key(
593
+ store_name = "test store",
594
+ keys=[key],
595
+ tracing_id=None
596
+ )
597
+ ```
598
+
599
+
600
+
601
+ ## Bulk Requests
602
+ Clients have the ability to send multiple requests at once, and these requests will be handled sequentially. The builder class takes care of this. The response is a list of all individual request responses.
603
+
604
+
605
+ ```py
606
+ from ahnlich_client_py import AhnlichDBClient
607
+ client = AhnlichDBClient(address="127.0.0.1", port=port)
608
+
609
+ request_builder = client.pipeline()
610
+ request_builder.ping()
611
+ request_builder.info_server()
612
+ request_builder.list_clients()
613
+ request_builder.list_stores()
614
+
615
+ response: server_response.ServerResult = client.exec()
616
+ ```
617
+ *Sample applies to the AIclient*
618
+
619
+
620
+ ## Client As Context Manager
621
+
622
+ The DB and AI client class can be used as a context manager hereby closing the connection pool automatically upon context end.
623
+
624
+
625
+ ```py
626
+ from ahnlich_client_py import AhnlichDBClient
627
+
628
+
629
+ with client.AhnlichDBClient(address="127.0.0.1", port=port) as db_client:
630
+ response: server_response.ServerResult = db_client.ping()
631
+
632
+ ```
633
+ However, closing the connection pool can be done by calling `cleanup()` on the client.
634
+
635
+
636
+
637
+ ## Deploy to Artifactory
638
+
639
+ Replace the contents of `MSG_TAG` file with your new tag message
640
+
641
+ From Feature branch, either use the makefile :
642
+ ```bash
643
+ make bump-py-client BUMP_RULE=[major, minor, patch]
644
+ ```
645
+ or
646
+ ```bash
647
+ poetry run bumpversion [major, minor, patch]
648
+ ```
649
+
650
+ When Your PR is made, changes in the client version file would trigger a release build to Pypi
651
+
652
+
653
+ ## Type Meanings
654
+
655
+ - Store Key: A one dimensional vector
656
+ - Store Value: A Dictionary containing texts or binary associated with a storekey
657
+ - Store Predicates: Or Predicate indices are basically indices that improves the filtering of store_values
658
+ - Predicates: These are operations that can be used to filter data(Equals, NotEquals, Contains, etc)
659
+ - PredicateConditions: They are conditions that utilize one predicate or tie Multiple predicates together using the AND, OR or Value operation. Where Value means just a predicate.
660
+ Example:
661
+ Value
662
+ ```py
663
+ condition = db_query.PredicateCondition__Value(
664
+ db_query.Predicate__Equals(key="job", value=db_query.MetadataValue__RawString(value="sorcerer"))
665
+ )
666
+ ```
667
+ Metadatavalue can also be a binary(list of u8s)
668
+
669
+ ```py
670
+ condition = db_query.PredicateCondition__Value(
671
+ db_query.Predicate__Equals(key="image_data", value=db_query.MetadataValue__Image(value=[2,2,3,4,5,6,7]))
672
+ )
673
+ ```
674
+
675
+
676
+ AND
677
+
678
+
679
+
680
+ ```py
681
+ # And[tuples[predicate_conditions]]
682
+ condition = db_query.PredicateCondition__AND(
683
+ (
684
+ db_query.PredicateCondition__Value(
685
+ db_query.Predicate__Equals(key="job", db_query.MetadataValue__RawString(value="sorcerer"))
686
+ ),
687
+ db_query.PredicateCondition__Value(
688
+ db_query.Predicate__Equals(key="rank", value=db_query.MetadataValue__RawString(value="chunin"))
689
+ )
690
+ )
691
+ )
692
+
693
+ ```
694
+
695
+ - Search Input: A string or binary file that can be stored by the aiproxy. Note, the binary file depends on the supported models used in a store or supported by Ahnlich AI
696
+
697
+ - AIModels: Supported AI models used by ahnlich ai
698
+ - AIStoreType: A type of store to be created. Either a Binary or String
699
+
700
+ ## Change Log
701
+
702
+ | Version| Description |
703
+ | -------|:-------------:|
704
+ | 0.0.0 | Base Python clients (Async and Sync) to connect to ahnlich db and AI, with connection pooling and Bincode serialization and deserialization |
705
+
706
+
707
+
708
+