veadk-python 0.2.5__py3-none-any.whl → 0.2.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of veadk-python might be problematic. Click here for more details.

Files changed (94) hide show
  1. veadk/agent.py +29 -22
  2. veadk/agent_builder.py +94 -0
  3. veadk/auth/__init__.py +13 -0
  4. veadk/auth/base_auth.py +22 -0
  5. veadk/auth/veauth/__init__.py +13 -0
  6. veadk/auth/veauth/apmplus_veauth.py +65 -0
  7. veadk/auth/veauth/ark_veauth.py +77 -0
  8. veadk/auth/veauth/base_veauth.py +50 -0
  9. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  10. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  11. veadk/auth/veauth/vesearch_veauth.py +62 -0
  12. veadk/cli/cli.py +2 -0
  13. veadk/cli/cli_deploy.py +5 -2
  14. veadk/cli/cli_init.py +25 -6
  15. veadk/cli/cli_pipeline.py +220 -0
  16. veadk/cli/cli_prompt.py +4 -4
  17. veadk/config.py +45 -81
  18. veadk/configs/__init__.py +13 -0
  19. veadk/configs/database_configs.py +83 -0
  20. veadk/configs/model_configs.py +42 -0
  21. veadk/configs/tool_configs.py +42 -0
  22. veadk/configs/tracing_configs.py +110 -0
  23. veadk/consts.py +32 -1
  24. veadk/database/database_adapter.py +256 -3
  25. veadk/database/kv/redis_database.py +47 -0
  26. veadk/database/local_database.py +23 -4
  27. veadk/database/relational/mysql_database.py +58 -0
  28. veadk/database/vector/opensearch_vector_database.py +6 -3
  29. veadk/database/viking/viking_database.py +272 -36
  30. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  31. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  32. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  33. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  34. veadk/integrations/ve_cr/__init__.py +13 -0
  35. veadk/integrations/ve_cr/ve_cr.py +220 -0
  36. veadk/integrations/ve_faas/template/cookiecutter.json +3 -2
  37. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +2 -2
  38. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +1 -1
  39. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +24 -1
  40. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -1
  41. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +1 -12
  42. veadk/integrations/ve_faas/ve_faas.py +352 -35
  43. veadk/integrations/ve_faas/web_template/cookiecutter.json +17 -0
  44. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  45. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  46. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  47. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +41 -0
  48. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  49. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  50. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  51. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  52. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  53. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  54. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  55. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  56. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  57. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  58. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  59. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  60. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  61. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  62. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  63. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +6 -3
  64. veadk/integrations/ve_tls/__init__.py +13 -0
  65. veadk/integrations/ve_tls/utils.py +117 -0
  66. veadk/integrations/ve_tls/ve_tls.py +208 -0
  67. veadk/integrations/ve_tos/ve_tos.py +128 -73
  68. veadk/knowledgebase/knowledgebase.py +116 -20
  69. veadk/memory/long_term_memory.py +20 -21
  70. veadk/memory/short_term_memory_processor.py +9 -4
  71. veadk/runner.py +213 -223
  72. veadk/tools/builtin_tools/vesearch.py +2 -2
  73. veadk/tools/builtin_tools/video_generate.py +27 -20
  74. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +5 -0
  75. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +253 -129
  76. veadk/tracing/telemetry/attributes/extractors/types.py +15 -4
  77. veadk/tracing/telemetry/exporters/apmplus_exporter.py +158 -12
  78. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +4 -9
  79. veadk/tracing/telemetry/exporters/tls_exporter.py +4 -10
  80. veadk/tracing/telemetry/opentelemetry_tracer.py +11 -5
  81. veadk/tracing/telemetry/telemetry.py +23 -5
  82. veadk/utils/logger.py +1 -1
  83. veadk/utils/misc.py +48 -0
  84. veadk/utils/volcengine_sign.py +6 -2
  85. veadk/version.py +1 -1
  86. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/METADATA +2 -1
  87. veadk_python-0.2.7.dist-info/RECORD +172 -0
  88. veadk_python-0.2.5.dist-info/RECORD +0 -127
  89. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/__init__.py +0 -0
  90. /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/agent.py +0 -0
  91. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/WHEEL +0 -0
  92. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/entry_points.txt +0 -0
  93. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/licenses/LICENSE +0 -0
  94. {veadk_python-0.2.5.dist-info → veadk_python-0.2.7.dist-info}/top_level.txt +0 -0
veadk/consts.py CHANGED
@@ -12,12 +12,32 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ import time
16
+
17
+ from veadk.utils.misc import getenv
15
18
  from veadk.version import VERSION
16
19
 
20
+ DEFAULT_AGENT_NAME = "veAgent"
21
+
17
22
  DEFAULT_MODEL_AGENT_NAME = "doubao-seed-1-6-250615"
18
23
  DEFAULT_MODEL_AGENT_PROVIDER = "openai"
19
24
  DEFAULT_MODEL_AGENT_API_BASE = "https://ark.cn-beijing.volces.com/api/v3/"
20
- DEFAULT_MODEL_EXTRA_HEADERS = {"veadk-source": "veadk", "veadk-version": VERSION}
25
+ DEFAULT_MODEL_EXTRA_CONFIG = {
26
+ "extra_headers": {
27
+ "x-is-encrypted": getenv("MODEL_AGENT_ENCRYPTED", "true"),
28
+ "veadk-source": "veadk",
29
+ "veadk-version": VERSION,
30
+ },
31
+ "extra_body": {
32
+ "caching": {
33
+ "type": getenv("MODEL_AGENT_CACHING", "enabled"),
34
+ },
35
+ "thinking": {
36
+ "type": "disabled"
37
+ }, # disable thinking for token saving and shorter TTFT by default
38
+ "expire_at": int(time.time()) + 3600, # expire after 1 hour
39
+ },
40
+ }
21
41
 
22
42
  DEFAULT_APMPLUS_OTEL_EXPORTER_ENDPOINT = "http://apmplus-cn-beijing.volces.com:4317"
23
43
  DEFAULT_APMPLUS_OTEL_EXPORTER_SERVICE_NAME = "veadk_tracing"
@@ -28,3 +48,14 @@ DEFAULT_COZELOOP_OTEL_EXPORTER_ENDPOINT = (
28
48
 
29
49
  DEFAULT_TLS_OTEL_EXPORTER_ENDPOINT = "https://tls-cn-beijing.volces.com:4318/v1/traces"
30
50
  DEFAULT_TLS_OTEL_EXPORTER_REGION = "cn-beijing"
51
+
52
+ DEFAULT_CR_INSTANCE_NAME = "veadk-user-instance"
53
+ DEFAULT_CR_NAMESPACE_NAME = "veadk-user-namespace"
54
+ DEFAULT_CR_REPO_NAME = "veadk-user-repo"
55
+
56
+ DEFAULT_TLS_LOG_PROJECT_NAME = "veadk-logs"
57
+ DEFAULT_TLS_TRACING_INSTANCE_NAME = "veadk-tracing"
58
+
59
+ DEFAULT_TOS_BUCKET_NAME = "veadk-default-bucket"
60
+
61
+ DEFAULT_COZELOOP_SPACE_NAME = "VeADK Space"
@@ -28,7 +28,26 @@ class KVDatabaseAdapter:
28
28
 
29
29
  self.client: RedisDatabase = client
30
30
 
31
- def add(self, data: list[str], index: str):
31
+ def index_exists(self, index: str) -> bool:
32
+ """
33
+ Check if the index (key) exists in Redis.
34
+
35
+ Args:
36
+ index: The Redis key to check
37
+
38
+ Returns:
39
+ bool: True if the key exists, False otherwise
40
+ """
41
+ try:
42
+ # Use Redis EXISTS command to check if key exists
43
+ return bool(self.client._client.exists(index))
44
+ except Exception as e:
45
+ logger.error(
46
+ f"Failed to check if key exists in Redis: index={index} error={e}"
47
+ )
48
+ return False
49
+
50
+ def add(self, data: list[str], index: str, **kwargs):
32
51
  logger.debug(f"Adding documents to Redis database: index={index}")
33
52
 
34
53
  try:
@@ -54,6 +73,44 @@ class KVDatabaseAdapter:
54
73
  logger.error(f"Failed to search from Redis: index={index} error={e}")
55
74
  raise e
56
75
 
76
+ def delete(self, index: str) -> bool:
77
+ logger.debug(f"Deleting key from Redis database: index={index}")
78
+ try:
79
+ self.client.delete(key=index)
80
+ return True
81
+ except Exception as e:
82
+ logger.error(
83
+ f"Failed to delete key from Redis database: index={index} error={e}"
84
+ )
85
+ return False
86
+
87
+ def delete_doc(self, index: str, id: str) -> bool:
88
+ logger.debug(f"Deleting document from Redis database: index={index} id={id}")
89
+ try:
90
+ # For Redis, we need to handle deletion differently since RedisDatabase.delete_doc
91
+ # takes a key and a single id
92
+ result = self.client.delete_doc(key=index, id=id)
93
+ return result
94
+ except Exception as e:
95
+ logger.error(
96
+ f"Failed to delete document from Redis database: index={index} id={id} error={e}"
97
+ )
98
+ return False
99
+
100
+ def list_chunks(self, index: str, offset: int = 0, limit: int = 100) -> list[dict]:
101
+ logger.debug(f"Listing documents from Redis database: index={index}")
102
+ try:
103
+ # Get all documents from Redis
104
+ docs = self.client.list_docs(key=index)
105
+
106
+ # Apply offset and limit for pagination
107
+ return docs[offset : offset + limit]
108
+ except Exception as e:
109
+ logger.error(
110
+ f"Failed to list documents from Redis database: index={index} error={e}"
111
+ )
112
+ return []
113
+
57
114
 
58
115
  class RelationalDatabaseAdapter:
59
116
  def __init__(self, client):
@@ -61,6 +118,24 @@ class RelationalDatabaseAdapter:
61
118
 
62
119
  self.client: MysqlDatabase = client
63
120
 
121
+ def index_exists(self, index: str) -> bool:
122
+ """
123
+ Check if the table (index) exists in MySQL database.
124
+
125
+ Args:
126
+ index: The table name to check
127
+
128
+ Returns:
129
+ bool: True if the table exists, False otherwise
130
+ """
131
+ try:
132
+ return self.client.table_exists(index)
133
+ except Exception as e:
134
+ logger.error(
135
+ f"Failed to check if table exists in MySQL: index={index} error={e}"
136
+ )
137
+ return False
138
+
64
139
  def create_table(self, table_name: str):
65
140
  logger.debug(f"Creating table for SQL database: table_name={table_name}")
66
141
 
@@ -73,7 +148,7 @@ class RelationalDatabaseAdapter:
73
148
  """
74
149
  self.client.add(sql)
75
150
 
76
- def add(self, data: list[str], index: str):
151
+ def add(self, data: list[str], index: str, **kwargs):
77
152
  logger.debug(
78
153
  f"Adding documents to SQL database: table_name={index} data_len={len(data)}"
79
154
  )
@@ -108,6 +183,39 @@ class RelationalDatabaseAdapter:
108
183
 
109
184
  return [item["data"] for item in results]
110
185
 
186
+ def delete(self, index: str) -> bool:
187
+ logger.debug(f"Deleting table from SQL database: table_name={index}")
188
+ try:
189
+ self.client.delete(table=index)
190
+ return True
191
+ except Exception as e:
192
+ logger.error(
193
+ f"Failed to delete table from SQL database: table_name={index} error={e}"
194
+ )
195
+ return False
196
+
197
+ def delete_doc(self, index: str, id: str) -> bool:
198
+ logger.debug(f"Deleting document from SQL database: table_name={index} id={id}")
199
+ try:
200
+ # Convert single id to list for the client method
201
+ result = self.client.delete_doc(table=index, ids=[int(id)])
202
+ return result
203
+ except Exception as e:
204
+ logger.error(
205
+ f"Failed to delete document from SQL database: table_name={index} id={id} error={e}"
206
+ )
207
+ return False
208
+
209
+ def list_docs(self, index: str, offset: int = 0, limit: int = 100) -> list[dict]:
210
+ logger.debug(f"Listing documents from SQL database: table_name={index}")
211
+ try:
212
+ return self.client.list_docs(table=index, offset=offset, limit=limit)
213
+ except Exception as e:
214
+ logger.error(
215
+ f"Failed to list documents from SQL database: table_name={index} error={e}"
216
+ )
217
+ return []
218
+
111
219
 
112
220
  class VectorDatabaseAdapter:
113
221
  def __init__(self, client):
@@ -117,6 +225,25 @@ class VectorDatabaseAdapter:
117
225
 
118
226
  self.client: OpenSearchVectorDatabase = client
119
227
 
228
+ def index_exists(self, index: str) -> bool:
229
+ """
230
+ Check if the collection (index) exists in OpenSearch.
231
+
232
+ Args:
233
+ index: The collection name to check
234
+
235
+ Returns:
236
+ bool: True if the collection exists, False otherwise
237
+ """
238
+ try:
239
+ self._validate_index(index)
240
+ return self.client.collection_exists(index)
241
+ except Exception as e:
242
+ logger.error(
243
+ f"Failed to check if collection exists in OpenSearch: index={index} error={e}"
244
+ )
245
+ return False
246
+
120
247
  def _validate_index(self, index: str):
121
248
  """
122
249
  Verify whether the string conforms to the naming rules of index_name in OpenSearch.
@@ -132,7 +259,7 @@ class VectorDatabaseAdapter:
132
259
  "The index name does not conform to the naming rules of OpenSearch"
133
260
  )
134
261
 
135
- def add(self, data: list[str], index: str):
262
+ def add(self, data: list[str], index: str, **kwargs):
136
263
  self._validate_index(index)
137
264
 
138
265
  logger.debug(
@@ -152,6 +279,35 @@ class VectorDatabaseAdapter:
152
279
  top_k=top_k,
153
280
  )
154
281
 
282
+ def delete(self, index: str) -> bool:
283
+ self._validate_index(index)
284
+ logger.debug(f"Deleting collection from vector database: index={index}")
285
+ try:
286
+ self.client.delete(collection_name=index)
287
+ return True
288
+ except Exception as e:
289
+ logger.error(
290
+ f"Failed to delete collection from vector database: index={index} error={e}"
291
+ )
292
+ return False
293
+
294
+ def delete_doc(self, index: str, id: str) -> bool:
295
+ self._validate_index(index)
296
+ logger.debug(f"Deleting documents from vector database: index={index} id={id}")
297
+ try:
298
+ self.client.delete_by_id(collection_name=index, id=id)
299
+ return True
300
+ except Exception as e:
301
+ logger.error(
302
+ f"Failed to delete document from vector database: index={index} id={id} error={e}"
303
+ )
304
+ return False
305
+
306
+ def list_chunks(self, index: str, offset: int = 0, limit: int = 1000) -> list[dict]:
307
+ self._validate_index(index)
308
+ logger.debug(f"Listing documents from vector database: index={index}")
309
+ return self.client.list_docs(collection_name=index, offset=offset, limit=limit)
310
+
155
311
 
156
312
  class VikingDatabaseAdapter:
157
313
  def __init__(self, client):
@@ -159,6 +315,25 @@ class VikingDatabaseAdapter:
159
315
 
160
316
  self.client: VikingDatabase = client
161
317
 
318
+ def index_exists(self, index: str) -> bool:
319
+ """
320
+ Check if the collection (index) exists in VikingDB.
321
+
322
+ Args:
323
+ index: The collection name to check
324
+
325
+ Returns:
326
+ bool: True if the collection exists, False otherwise
327
+ """
328
+ try:
329
+ self._validate_index(index)
330
+ return self.client.collection_exists(index)
331
+ except Exception as e:
332
+ logger.error(
333
+ f"Failed to check if collection exists in VikingDB: index={index} error={e}"
334
+ )
335
+ return False
336
+
162
337
  def _validate_index(self, index: str):
163
338
  """
164
339
  Only English letters, numbers, and underscores (_) are allowed.
@@ -212,6 +387,28 @@ class VikingDatabaseAdapter:
212
387
 
213
388
  return self.client.query(query, collection_name=index, top_k=top_k)
214
389
 
390
+ def delete(self, index: str) -> bool:
391
+ self._validate_index(index)
392
+ logger.debug(f"Deleting collection from Viking database: index={index}")
393
+ return self.client.delete(name=index)
394
+
395
+ def delete_doc(self, index: str, id: str) -> bool:
396
+ self._validate_index(index)
397
+ logger.debug(f"Deleting documents from vector database: index={index} id={id}")
398
+ return self.client.delete_by_id(collection_name=index, id=id)
399
+
400
+ def list_chunks(self, index: str, offset: int, limit: int) -> list[dict]:
401
+ self._validate_index(index)
402
+ logger.debug(f"Listing documents from vector database: index={index}")
403
+ return self.client.list_chunks(
404
+ collection_name=index, offset=offset, limit=limit
405
+ )
406
+
407
+ def list_docs(self, index: str, offset: int, limit: int) -> list[dict]:
408
+ self._validate_index(index)
409
+ logger.debug(f"Listing documents from vector database: index={index}")
410
+ return self.client.list_docs(collection_name=index, offset=offset, limit=limit)
411
+
215
412
 
216
413
  class VikingMemoryDatabaseAdapter:
217
414
  def __init__(self, client):
@@ -219,6 +416,25 @@ class VikingMemoryDatabaseAdapter:
219
416
 
220
417
  self.client: VikingMemoryDatabase = client
221
418
 
419
+ def index_exists(self, index: str) -> bool:
420
+ """
421
+ Check if the collection (index) exists in VikingMemoryDB.
422
+
423
+ Note:
424
+ VikingMemoryDatabase does not support checking if a collection exists.
425
+ This method always returns False.
426
+
427
+ Args:
428
+ index: The collection name to check
429
+
430
+ Returns:
431
+ bool: Always returns False as VikingMemoryDatabase does not support this functionality
432
+ """
433
+ logger.warning(
434
+ "VikingMemoryDatabase does not support checking if a collection exists"
435
+ )
436
+ raise NotImplementedError("VikingMemoryDatabase does not support index_exists")
437
+
222
438
  def _validate_index(self, index: str):
223
439
  if not (
224
440
  isinstance(index, str)
@@ -248,6 +464,17 @@ class VikingMemoryDatabaseAdapter:
248
464
  result = self.client.query(query, collection_name=index, top_k=top_k, **kwargs)
249
465
  return result
250
466
 
467
+ def delete(self, index: str) -> bool:
468
+ self._validate_index(index)
469
+ logger.debug(f"Deleting collection from Viking database memory: index={index}")
470
+ raise NotImplementedError("VikingMemoryDatabase does not support delete")
471
+
472
+ def delete_docs(self, index: str, ids: list[int]):
473
+ raise NotImplementedError("VikingMemoryDatabase does not support delete_docs")
474
+
475
+ def list_chunks(self, index: str):
476
+ raise NotImplementedError("VikingMemoryDatabase does not support list_docs")
477
+
251
478
 
252
479
  class LocalDatabaseAdapter:
253
480
  def __init__(self, client):
@@ -255,12 +482,38 @@ class LocalDatabaseAdapter:
255
482
 
256
483
  self.client: LocalDataBase = client
257
484
 
485
+ def index_exists(self, index: str) -> bool:
486
+ """
487
+ Check if the index exists in LocalDataBase.
488
+
489
+ Note:
490
+ LocalDataBase does not support checking if an index exists.
491
+ This method always returns False.
492
+
493
+ Args:
494
+ index: The index name to check (not used in LocalDataBase)
495
+
496
+ Returns:
497
+ bool: Always returns False as LocalDataBase does not support this functionality
498
+ """
499
+ logger.warning("LocalDataBase does not support checking if an index exists")
500
+ return True
501
+
258
502
  def add(self, data: list[str], **kwargs):
259
503
  self.client.add(data)
260
504
 
261
505
  def query(self, query: str, **kwargs):
262
506
  return self.client.query(query, **kwargs)
263
507
 
508
+ def delete(self, index: str) -> bool:
509
+ return self.client.delete()
510
+
511
+ def delete_doc(self, index: str, id: str) -> bool:
512
+ return self.client.delete_doc(id)
513
+
514
+ def list_chunks(self, index: str, offset: int = 0, limit: int = 100) -> list[dict]:
515
+ return self.client.list_docs(offset=offset, limit=limit)
516
+
264
517
 
265
518
  MAPPING = {
266
519
  "RedisDatabase": KVDatabaseAdapter,
@@ -110,3 +110,50 @@ class RedisDatabase(BaseModel, BaseDatabase):
110
110
  except Exception as e:
111
111
  logger.error(f"Failed to delete key `{key}`: {e}")
112
112
  raise e
113
+
114
+ def delete_doc(self, key: str, id: str) -> bool:
115
+ """Delete a specific document by ID from a Redis list.
116
+
117
+ Args:
118
+ key: The Redis key (list) to delete from
119
+ id: The ID of the document to delete
120
+
121
+ Returns:
122
+ bool: True if deletion was successful, False otherwise
123
+ """
124
+ try:
125
+ # Get all items in the list
126
+ items = self._client.lrange(key, 0, -1)
127
+
128
+ # Find the index of the item to delete
129
+ for i, item in enumerate(items):
130
+ # Assuming the item is stored as a JSON string with an 'id' field
131
+ # If it's just the content, we'll use the list index as ID
132
+ if str(i) == id:
133
+ self._client.lrem(key, 1, item)
134
+ return True
135
+
136
+ logger.warning(f"Document with id {id} not found in key {key}")
137
+ return False
138
+ except Exception as e:
139
+ logger.error(f"Failed to delete document with id {id} from key {key}: {e}")
140
+ return False
141
+
142
+ def list_docs(self, key: str) -> list[dict]:
143
+ """List all documents in a Redis list.
144
+
145
+ Args:
146
+ key: The Redis key (list) to list documents from
147
+
148
+ Returns:
149
+ list[dict]: List of documents with id and content
150
+ """
151
+ try:
152
+ items = self._client.lrange(key, 0, -1)
153
+ return [
154
+ {"id": str(i), "content": item, "metadata": {}}
155
+ for i, item in enumerate(items)
156
+ ]
157
+ except Exception as e:
158
+ logger.error(f"Failed to list documents from key {key}: {e}")
159
+ return []
@@ -24,20 +24,39 @@ class LocalDataBase(BaseDatabase):
24
24
 
25
25
  def __init__(self, **kwargs):
26
26
  super().__init__()
27
- self.data = []
27
+ self.data = {}
28
28
  self._type = "local"
29
+ self._next_id = 0 # Used to generate unique IDs
29
30
 
30
31
  def add_texts(self, texts: list[str], **kwargs):
31
- self.data.extend(texts)
32
+ for text in texts:
33
+ self.data[str(self._next_id)] = text
34
+ self._next_id += 1
32
35
 
33
36
  def is_empty(self):
34
37
  return len(self.data) == 0
35
38
 
36
39
  def query(self, query: str, **kwargs: Any) -> list[str]:
37
- return self.data
40
+ return list(self.data.values())
38
41
 
39
42
  def delete(self, **kwargs: Any):
40
- self.data = []
43
+ self.data = {}
44
+ return True
41
45
 
42
46
  def add(self, texts: list[str], **kwargs: Any):
43
47
  return self.add_texts(texts)
48
+
49
+ def list_docs(self, **kwargs: Any) -> list[dict]:
50
+ return [
51
+ {"id": id, "content": content, "metadata": {}}
52
+ for id, content in self.data.items()
53
+ ]
54
+
55
+ def delete_doc(self, id: str, **kwargs: Any):
56
+ if id not in self.data:
57
+ raise ValueError(f"id {id} not found")
58
+ try:
59
+ del self.data[id]
60
+ return True
61
+ except Exception:
62
+ return False
@@ -111,5 +111,63 @@ class MysqlDatabase(BaseModel, BaseDatabase):
111
111
  logger.error(f"Failed to drop table {table}: {e}")
112
112
  raise e
113
113
 
114
+ def delete_doc(self, table: str, ids: list[int]) -> bool:
115
+ """Delete documents by IDs from a MySQL table.
116
+
117
+ Args:
118
+ table: The table name to delete from
119
+ ids: List of document IDs to delete
120
+
121
+ Returns:
122
+ bool: True if deletion was successful, False otherwise
123
+ """
124
+ if not self.table_exists(table):
125
+ logger.warning(f"Table {table} does not exist. Skipping delete operation.")
126
+ return False
127
+
128
+ if not ids:
129
+ return True # Nothing to delete
130
+
131
+ try:
132
+ with self._connection.cursor() as cursor:
133
+ # Create placeholders for the IDs
134
+ placeholders = ",".join(["%s"] * len(ids))
135
+ sql = f"DELETE FROM `{table}` WHERE id IN ({placeholders})"
136
+ cursor.execute(sql, ids)
137
+ self._connection.commit()
138
+ logger.info(f"Deleted {cursor.rowcount} documents from table {table}")
139
+ return True
140
+ except Exception as e:
141
+ logger.error(f"Failed to delete documents from table {table}: {e}")
142
+ return False
143
+
144
+ def list_docs(self, table: str, offset: int = 0, limit: int = 100) -> list[dict]:
145
+ """List documents from a MySQL table.
146
+
147
+ Args:
148
+ table: The table name to list documents from
149
+ offset: Offset for pagination
150
+ limit: Limit for pagination
151
+
152
+ Returns:
153
+ list[dict]: List of documents with id and content
154
+ """
155
+ if not self.table_exists(table):
156
+ logger.warning(f"Table {table} does not exist. Returning empty list.")
157
+ return []
158
+
159
+ try:
160
+ with self._connection.cursor() as cursor:
161
+ sql = f"SELECT id, data FROM `{table}` ORDER BY created_at DESC LIMIT %s OFFSET %s"
162
+ cursor.execute(sql, (limit, offset))
163
+ results = cursor.fetchall()
164
+ return [
165
+ {"id": str(row["id"]), "content": row["data"], "metadata": {}}
166
+ for row in results
167
+ ]
168
+ except Exception as e:
169
+ logger.error(f"Failed to list documents from table {table}: {e}")
170
+ return []
171
+
114
172
  def is_empty(self):
115
173
  pass
@@ -219,7 +219,9 @@ class OpenSearchVectorDatabase(BaseModel, BaseDatabase):
219
219
  response = self._opensearch_client.indices.get_alias()
220
220
  return list(response.keys())
221
221
 
222
- def get_all_docs(self, collection_name: str, size: int = 10000) -> list[dict]:
222
+ def list_docs(
223
+ self, collection_name: str, offset: int = 0, limit: int = 10000
224
+ ) -> list[dict]:
223
225
  """Match all docs in one index of OpenSearch"""
224
226
  if not self.collection_exists(collection_name):
225
227
  logger.warning(
@@ -227,12 +229,13 @@ class OpenSearchVectorDatabase(BaseModel, BaseDatabase):
227
229
  )
228
230
  return []
229
231
 
230
- query = {"size": size, "query": {"match_all": {}}}
232
+ query = {"size": limit, "from": offset, "query": {"match_all": {}}}
231
233
  response = self._opensearch_client.search(index=collection_name, body=query)
232
234
  return [
233
235
  {
234
236
  "id": hit["_id"],
235
- "page_content": hit["_source"]["page_content"],
237
+ "content": hit["_source"]["page_content"],
238
+ "metadata": {},
236
239
  }
237
240
  for hit in response["hits"]["hits"]
238
241
  ]