veadk-python 0.2.27__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.
- veadk/__init__.py +37 -0
- veadk/a2a/__init__.py +13 -0
- veadk/a2a/agent_card.py +45 -0
- veadk/a2a/remote_ve_agent.py +390 -0
- veadk/a2a/utils/__init__.py +13 -0
- veadk/a2a/utils/agent_to_a2a.py +170 -0
- veadk/a2a/ve_a2a_server.py +93 -0
- veadk/a2a/ve_agent_executor.py +78 -0
- veadk/a2a/ve_middlewares.py +313 -0
- veadk/a2a/ve_task_store.py +37 -0
- veadk/agent.py +402 -0
- veadk/agent_builder.py +93 -0
- veadk/agents/loop_agent.py +68 -0
- veadk/agents/parallel_agent.py +72 -0
- veadk/agents/sequential_agent.py +64 -0
- veadk/auth/__init__.py +13 -0
- veadk/auth/base_auth.py +22 -0
- veadk/auth/ve_credential_service.py +203 -0
- veadk/auth/veauth/__init__.py +13 -0
- veadk/auth/veauth/apmplus_veauth.py +58 -0
- veadk/auth/veauth/ark_veauth.py +75 -0
- veadk/auth/veauth/base_veauth.py +50 -0
- veadk/auth/veauth/cozeloop_veauth.py +13 -0
- veadk/auth/veauth/opensearch_veauth.py +75 -0
- veadk/auth/veauth/postgresql_veauth.py +75 -0
- veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
- veadk/auth/veauth/speech_veauth.py +54 -0
- veadk/auth/veauth/utils.py +69 -0
- veadk/auth/veauth/vesearch_veauth.py +62 -0
- veadk/auth/veauth/viking_mem0_veauth.py +91 -0
- veadk/cli/__init__.py +13 -0
- veadk/cli/cli.py +58 -0
- veadk/cli/cli_clean.py +87 -0
- veadk/cli/cli_create.py +163 -0
- veadk/cli/cli_deploy.py +233 -0
- veadk/cli/cli_eval.py +215 -0
- veadk/cli/cli_init.py +214 -0
- veadk/cli/cli_kb.py +110 -0
- veadk/cli/cli_pipeline.py +285 -0
- veadk/cli/cli_prompt.py +86 -0
- veadk/cli/cli_update.py +106 -0
- veadk/cli/cli_uploadevalset.py +139 -0
- veadk/cli/cli_web.py +143 -0
- veadk/cloud/__init__.py +13 -0
- veadk/cloud/cloud_agent_engine.py +485 -0
- veadk/cloud/cloud_app.py +475 -0
- veadk/config.py +115 -0
- veadk/configs/__init__.py +13 -0
- veadk/configs/auth_configs.py +133 -0
- veadk/configs/database_configs.py +132 -0
- veadk/configs/model_configs.py +78 -0
- veadk/configs/tool_configs.py +54 -0
- veadk/configs/tracing_configs.py +110 -0
- veadk/consts.py +74 -0
- veadk/evaluation/__init__.py +17 -0
- veadk/evaluation/adk_evaluator/__init__.py +17 -0
- veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
- veadk/evaluation/base_evaluator.py +642 -0
- veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
- veadk/evaluation/eval_set_file_loader.py +48 -0
- veadk/evaluation/eval_set_recorder.py +146 -0
- veadk/evaluation/types.py +65 -0
- veadk/evaluation/utils/prometheus.py +196 -0
- veadk/integrations/__init__.py +13 -0
- veadk/integrations/ve_apig/__init__.py +13 -0
- veadk/integrations/ve_apig/ve_apig.py +349 -0
- veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
- veadk/integrations/ve_code_pipeline/__init__.py +13 -0
- veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
- veadk/integrations/ve_cozeloop/__init__.py +13 -0
- veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
- veadk/integrations/ve_cr/__init__.py +13 -0
- veadk/integrations/ve_cr/ve_cr.py +220 -0
- veadk/integrations/ve_faas/__init__.py +13 -0
- veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
- veadk/integrations/ve_faas/ve_faas.py +754 -0
- veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
- veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
- veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
- veadk/integrations/ve_identity/__init__.py +110 -0
- veadk/integrations/ve_identity/auth_config.py +261 -0
- veadk/integrations/ve_identity/auth_mixins.py +650 -0
- veadk/integrations/ve_identity/auth_processor.py +385 -0
- veadk/integrations/ve_identity/function_tool.py +158 -0
- veadk/integrations/ve_identity/identity_client.py +864 -0
- veadk/integrations/ve_identity/mcp_tool.py +181 -0
- veadk/integrations/ve_identity/mcp_toolset.py +431 -0
- veadk/integrations/ve_identity/models.py +228 -0
- veadk/integrations/ve_identity/token_manager.py +188 -0
- veadk/integrations/ve_identity/utils.py +151 -0
- veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
- veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
- veadk/integrations/ve_tls/__init__.py +13 -0
- veadk/integrations/ve_tls/utils.py +116 -0
- veadk/integrations/ve_tls/ve_tls.py +212 -0
- veadk/integrations/ve_tos/ve_tos.py +710 -0
- veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
- veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
- veadk/knowledgebase/__init__.py +17 -0
- veadk/knowledgebase/backends/__init__.py +13 -0
- veadk/knowledgebase/backends/base_backend.py +72 -0
- veadk/knowledgebase/backends/in_memory_backend.py +91 -0
- veadk/knowledgebase/backends/opensearch_backend.py +162 -0
- veadk/knowledgebase/backends/redis_backend.py +172 -0
- veadk/knowledgebase/backends/utils.py +92 -0
- veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
- veadk/knowledgebase/entry.py +25 -0
- veadk/knowledgebase/knowledgebase.py +307 -0
- veadk/memory/__init__.py +35 -0
- veadk/memory/long_term_memory.py +365 -0
- veadk/memory/long_term_memory_backends/__init__.py +13 -0
- veadk/memory/long_term_memory_backends/base_backend.py +35 -0
- veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
- veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
- veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
- veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
- veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
- veadk/memory/short_term_memory.py +252 -0
- veadk/memory/short_term_memory_backends/__init__.py +13 -0
- veadk/memory/short_term_memory_backends/base_backend.py +31 -0
- veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
- veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
- veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
- veadk/memory/short_term_memory_processor.py +100 -0
- veadk/processors/__init__.py +26 -0
- veadk/processors/base_run_processor.py +120 -0
- veadk/prompts/__init__.py +13 -0
- veadk/prompts/agent_default_prompt.py +30 -0
- veadk/prompts/prompt_evaluator.py +20 -0
- veadk/prompts/prompt_memory_processor.py +55 -0
- veadk/prompts/prompt_optimization.py +150 -0
- veadk/runner.py +732 -0
- veadk/tools/__init__.py +13 -0
- veadk/tools/builtin_tools/__init__.py +13 -0
- veadk/tools/builtin_tools/agent_authorization.py +94 -0
- veadk/tools/builtin_tools/generate_image.py +23 -0
- veadk/tools/builtin_tools/image_edit.py +300 -0
- veadk/tools/builtin_tools/image_generate.py +446 -0
- veadk/tools/builtin_tools/lark.py +67 -0
- veadk/tools/builtin_tools/las.py +24 -0
- veadk/tools/builtin_tools/link_reader.py +66 -0
- veadk/tools/builtin_tools/llm_shield.py +381 -0
- veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
- veadk/tools/builtin_tools/mcp_router.py +29 -0
- veadk/tools/builtin_tools/run_code.py +113 -0
- veadk/tools/builtin_tools/tts.py +253 -0
- veadk/tools/builtin_tools/vesearch.py +49 -0
- veadk/tools/builtin_tools/video_generate.py +363 -0
- veadk/tools/builtin_tools/web_scraper.py +76 -0
- veadk/tools/builtin_tools/web_search.py +83 -0
- veadk/tools/demo_tools.py +58 -0
- veadk/tools/load_knowledgebase_tool.py +149 -0
- veadk/tools/sandbox/__init__.py +13 -0
- veadk/tools/sandbox/browser_sandbox.py +37 -0
- veadk/tools/sandbox/code_sandbox.py +40 -0
- veadk/tools/sandbox/computer_sandbox.py +34 -0
- veadk/tracing/__init__.py +13 -0
- veadk/tracing/base_tracer.py +58 -0
- veadk/tracing/telemetry/__init__.py +13 -0
- veadk/tracing/telemetry/attributes/attributes.py +29 -0
- veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
- veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
- veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
- veadk/tracing/telemetry/exporters/__init__.py +13 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
- veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
- veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
- veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
- veadk/tracing/telemetry/telemetry.py +411 -0
- veadk/types.py +47 -0
- veadk/utils/__init__.py +13 -0
- veadk/utils/audio_manager.py +95 -0
- veadk/utils/auth.py +294 -0
- veadk/utils/logger.py +59 -0
- veadk/utils/mcp_utils.py +44 -0
- veadk/utils/misc.py +184 -0
- veadk/utils/patches.py +101 -0
- veadk/utils/volcengine_sign.py +205 -0
- veadk/version.py +15 -0
- veadk_python-0.2.27.dist-info/METADATA +373 -0
- veadk_python-0.2.27.dist-info/RECORD +218 -0
- veadk_python-0.2.27.dist-info/WHEEL +5 -0
- veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
- veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
- veadk_python-0.2.27.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from typing import Any, Callable, Literal, Union
|
|
18
|
+
|
|
19
|
+
from pydantic import BaseModel, Field
|
|
20
|
+
|
|
21
|
+
from veadk.knowledgebase.backends.base_backend import BaseKnowledgebaseBackend
|
|
22
|
+
from veadk.knowledgebase.entry import KnowledgebaseEntry
|
|
23
|
+
from veadk.utils.logger import get_logger
|
|
24
|
+
|
|
25
|
+
logger = get_logger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _get_backend_cls(backend: str) -> type[BaseKnowledgebaseBackend]:
|
|
29
|
+
match backend:
|
|
30
|
+
case "local":
|
|
31
|
+
from veadk.knowledgebase.backends.in_memory_backend import (
|
|
32
|
+
InMemoryKnowledgeBackend,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
return InMemoryKnowledgeBackend
|
|
36
|
+
case "opensearch":
|
|
37
|
+
from veadk.knowledgebase.backends.opensearch_backend import (
|
|
38
|
+
OpensearchKnowledgeBackend,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return OpensearchKnowledgeBackend
|
|
42
|
+
case "viking":
|
|
43
|
+
from veadk.knowledgebase.backends.vikingdb_knowledge_backend import (
|
|
44
|
+
VikingDBKnowledgeBackend,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return VikingDBKnowledgeBackend
|
|
48
|
+
case "redis":
|
|
49
|
+
from veadk.knowledgebase.backends.redis_backend import (
|
|
50
|
+
RedisKnowledgeBackend,
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
return RedisKnowledgeBackend
|
|
54
|
+
|
|
55
|
+
raise ValueError(f"Unsupported knowledgebase backend: {backend}")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class KnowledgeBase(BaseModel):
|
|
59
|
+
"""A knowledge base for storing user-related information.
|
|
60
|
+
|
|
61
|
+
This class represents a knowledge base used to store and retrieve user-specific data.
|
|
62
|
+
It supports multiple backend options, including in-memory, OpenSearch, Redis, and Volcengine's
|
|
63
|
+
VikingDB. The knowledge base allows for efficient document retrieval based on similarity,
|
|
64
|
+
with the ability to configure backend-specific settings.
|
|
65
|
+
|
|
66
|
+
Attributes:
|
|
67
|
+
name (str): The name of the knowledge base. Default is "user_knowledgebase".
|
|
68
|
+
description (str): A description of the knowledge base. Default is "This knowledgebase stores some user-related information."
|
|
69
|
+
backend (Union[Literal["local", "opensearch", "viking", "redis"], BaseKnowledgebaseBackend]):
|
|
70
|
+
The type of backend to use for storing and querying the knowledge base. Supported options include:
|
|
71
|
+
- 'local' for in-memory storage (data is lost when the program exits).
|
|
72
|
+
- 'opensearch' for OpenSearch (requires OpenSearch cluster).
|
|
73
|
+
- 'viking' for Volcengine VikingDB (requires VikingDB service).
|
|
74
|
+
- 'redis' for Redis with vector search capability (requires Redis).
|
|
75
|
+
Default is 'local'.
|
|
76
|
+
backend_config (dict): Configuration dictionary for the selected backend.
|
|
77
|
+
top_k (int): The number of top similar documents to retrieve during a search. Default is 10.
|
|
78
|
+
app_name (str): The name of the application associated with the knowledge base. If index is not provided, this value will be set to `index`.
|
|
79
|
+
index (str): The name of the knowledge base index.
|
|
80
|
+
|
|
81
|
+
Notes:
|
|
82
|
+
Please ensure that you have set the embedding-related configurations in environment variables.
|
|
83
|
+
|
|
84
|
+
Examples:
|
|
85
|
+
### Simple backend
|
|
86
|
+
|
|
87
|
+
Create a local knowledgebase:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from veadk import Agent, Runner
|
|
91
|
+
from veadk.knowledgebase.knowledgebase import KnowledgeBase
|
|
92
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
93
|
+
|
|
94
|
+
app_name = "veadk_playground_app"
|
|
95
|
+
user_id = "veadk_playground_user"
|
|
96
|
+
session_id = "veadk_playground_session"
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
knowledgebase = KnowledgeBase(backend="opensearch", app_name=app_name)
|
|
100
|
+
knowledgebase.add_from_files(files=[knowledgebase_file])
|
|
101
|
+
|
|
102
|
+
agent = Agent(knowledgebase=knowledgebase)
|
|
103
|
+
|
|
104
|
+
runner = Runner(
|
|
105
|
+
agent=agent,
|
|
106
|
+
short_term_memory=ShortTermMemory(),
|
|
107
|
+
app_name=app_name,
|
|
108
|
+
user_id=user_id,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
response = await runner.run(
|
|
112
|
+
messages="Tell me the secret of green.", session_id=session_id
|
|
113
|
+
)
|
|
114
|
+
print(response)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Initialize knowledgebase with metadata
|
|
118
|
+
|
|
119
|
+
```python
|
|
120
|
+
from veadk.knowledgebase import KnowledgeBase
|
|
121
|
+
|
|
122
|
+
knowledgebase = KnowledgeBase(
|
|
123
|
+
name="user_data",
|
|
124
|
+
description="A knowledgebase contains user hobbies.",
|
|
125
|
+
index="my_app",
|
|
126
|
+
)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Initialize knowledgebase with backend instance
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
import veadk.config # noqa
|
|
133
|
+
|
|
134
|
+
from veadk.knowledgebase import KnowledgeBase
|
|
135
|
+
from veadk.knowledgebase.backends.in_memory_backend import InMemoryKnowledgeBackend
|
|
136
|
+
|
|
137
|
+
backend = InMemoryKnowledgeBackend(
|
|
138
|
+
index="my_app",
|
|
139
|
+
embedding_config=...,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
knowledgebase = KnowledgeBase(
|
|
143
|
+
name="user_data",
|
|
144
|
+
description="A knowledgebase contains user hobbies.",
|
|
145
|
+
backend=backend,
|
|
146
|
+
)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Initialize knowledgebase with backend config
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from veadk.knowledgebase import KnowledgeBase
|
|
153
|
+
|
|
154
|
+
knowledgebase = KnowledgeBase(
|
|
155
|
+
name="user_data",
|
|
156
|
+
description="A knowledgebase contains user hobbies.",
|
|
157
|
+
backend="local",
|
|
158
|
+
backend_config={"index": "user_app"},
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
name: str = "user_knowledgebase"
|
|
164
|
+
|
|
165
|
+
description: str = "This knowledgebase stores some user-related information."
|
|
166
|
+
|
|
167
|
+
backend: Union[
|
|
168
|
+
Literal["local", "opensearch", "viking", "redis"], BaseKnowledgebaseBackend
|
|
169
|
+
] = "local"
|
|
170
|
+
|
|
171
|
+
backend_config: dict = Field(default_factory=dict)
|
|
172
|
+
|
|
173
|
+
top_k: int = 10
|
|
174
|
+
|
|
175
|
+
app_name: str = ""
|
|
176
|
+
|
|
177
|
+
index: str = ""
|
|
178
|
+
|
|
179
|
+
def model_post_init(self, __context: Any) -> None:
|
|
180
|
+
if isinstance(self.backend, BaseKnowledgebaseBackend):
|
|
181
|
+
self._backend = self.backend
|
|
182
|
+
self.index = self._backend.index
|
|
183
|
+
logger.info(
|
|
184
|
+
f"Initialized knowledgebase with provided backend instance {self._backend.__class__.__name__}"
|
|
185
|
+
)
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
# Once user define backend config, use it directly
|
|
189
|
+
if self.backend_config:
|
|
190
|
+
self._backend = _get_backend_cls(self.backend)(**self.backend_config)
|
|
191
|
+
return
|
|
192
|
+
|
|
193
|
+
self.index = self.index or self.app_name
|
|
194
|
+
if not self.index:
|
|
195
|
+
raise ValueError("Either `index` or `app_name` must be provided.")
|
|
196
|
+
|
|
197
|
+
logger.info(
|
|
198
|
+
f"Initializing knowledgebase: backend={self.backend} index={self.index} top_k={self.top_k}"
|
|
199
|
+
)
|
|
200
|
+
self._backend = _get_backend_cls(self.backend)(index=self.index)
|
|
201
|
+
logger.info(
|
|
202
|
+
f"Initialized knowledgebase with backend {self._backend.__class__.__name__}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def add_from_directory(self, directory: str, **kwargs) -> bool:
|
|
206
|
+
"""Add knowledge from file path to knowledgebase.
|
|
207
|
+
|
|
208
|
+
Add the files in the directory to knowledgebase backend.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
directory (str): The directory path that needs to store.
|
|
212
|
+
|
|
213
|
+
Returns:
|
|
214
|
+
bool: True if successfully store the knowledgebase, False otherwise.
|
|
215
|
+
|
|
216
|
+
Examples:
|
|
217
|
+
Store a directory to knowledgebase:
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
knowledgebase = Knowledgebase(backend="local")
|
|
221
|
+
|
|
222
|
+
if knowledgebase.add_from_directory("./knowledgebase"):
|
|
223
|
+
# add successfully
|
|
224
|
+
...
|
|
225
|
+
else:
|
|
226
|
+
raise RuntimeError("Uploaded directory failed.")
|
|
227
|
+
```
|
|
228
|
+
"""
|
|
229
|
+
return self._backend.add_from_directory(directory=directory, **kwargs)
|
|
230
|
+
|
|
231
|
+
def add_from_files(self, files: list[str], **kwargs) -> bool:
|
|
232
|
+
"""Add knowledge files to knowledgebase.
|
|
233
|
+
|
|
234
|
+
Add a list of files to knowledgebase backend.
|
|
235
|
+
|
|
236
|
+
Args:
|
|
237
|
+
files (str): The list of files.
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
bool: True if successfully store the knowledgebase, False otherwise.
|
|
241
|
+
|
|
242
|
+
Examples:
|
|
243
|
+
Store files to knowledgebase:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
knowledgebase = Knowledgebase(backend="local")
|
|
247
|
+
|
|
248
|
+
if knowledgebase.add_from_files("./knowledgebase"):
|
|
249
|
+
# add successfully
|
|
250
|
+
...
|
|
251
|
+
else:
|
|
252
|
+
raise RuntimeError("Uploaded files failed.")
|
|
253
|
+
```
|
|
254
|
+
"""
|
|
255
|
+
return self._backend.add_from_files(files=files, **kwargs)
|
|
256
|
+
|
|
257
|
+
def add_from_text(self, text: str | list[str], **kwargs) -> bool:
|
|
258
|
+
"""Add a piece of text or a list of text to knowledgebase.
|
|
259
|
+
|
|
260
|
+
The `text` can be a string or a list of string. The text will be embedded and stored by the corresponding backend.
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
text (str | list[str]): The text string or a list of text strings.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
bool: True if successfully store the knowledgebase, False otherwise.
|
|
267
|
+
|
|
268
|
+
Examples:
|
|
269
|
+
Store a string or a list of string to knowledgebase:
|
|
270
|
+
|
|
271
|
+
```python
|
|
272
|
+
knowledgebase = Knowledgebase(backend="local")
|
|
273
|
+
|
|
274
|
+
if knowledgebase.add_from_text("./knowledgebase"):
|
|
275
|
+
# add successfully
|
|
276
|
+
...
|
|
277
|
+
else:
|
|
278
|
+
raise RuntimeError("Uploaded text failed.")
|
|
279
|
+
```
|
|
280
|
+
"""
|
|
281
|
+
return self._backend.add_from_text(text=text, **kwargs)
|
|
282
|
+
|
|
283
|
+
def search(self, query: str, top_k: int = 0, **kwargs) -> list[KnowledgebaseEntry]:
|
|
284
|
+
"""Search knowledge from knowledgebase"""
|
|
285
|
+
top_k = top_k if top_k != 0 else self.top_k
|
|
286
|
+
|
|
287
|
+
_entries = self._backend.search(query=query, top_k=top_k, **kwargs)
|
|
288
|
+
|
|
289
|
+
entries = []
|
|
290
|
+
for entry in _entries:
|
|
291
|
+
if isinstance(entry, KnowledgebaseEntry):
|
|
292
|
+
entries.append(entry)
|
|
293
|
+
elif isinstance(entry, str):
|
|
294
|
+
entries.append(KnowledgebaseEntry(content=entry))
|
|
295
|
+
else:
|
|
296
|
+
logger.error(
|
|
297
|
+
f"Unsupported entry type from backend search method: {type(entry)} with {entry}. Expected `KnowledgebaseEntry` or `str`. Skip for this entry."
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
return entries
|
|
301
|
+
|
|
302
|
+
def __getattr__(self, name) -> Callable:
|
|
303
|
+
"""In case of knowledgebase have no backends' methods (`delete`, `list_chunks`, etc)
|
|
304
|
+
|
|
305
|
+
For example, knowledgebase.delete(...) -> self._backend.delete(...)
|
|
306
|
+
"""
|
|
307
|
+
return getattr(self._backend, name)
|
veadk/memory/__init__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from veadk.memory.long_term_memory import LongTermMemory
|
|
19
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Lazy loading for classes
|
|
23
|
+
def __getattr__(name):
|
|
24
|
+
if name == "ShortTermMemory":
|
|
25
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
26
|
+
|
|
27
|
+
return ShortTermMemory
|
|
28
|
+
if name == "LongTermMemory":
|
|
29
|
+
from veadk.memory.long_term_memory import LongTermMemory
|
|
30
|
+
|
|
31
|
+
return LongTermMemory
|
|
32
|
+
raise AttributeError(f"module 'veadk.memory' has no attribute '{name}'")
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
__all__ = ["ShortTermMemory", "LongTermMemory"]
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# adapted from Google ADK memory service adk-python/src/google/adk/memory/vertex_ai_memory_bank_service.py at 0a9e67dbca67789247e882d16b139dbdc76a329a · google/adk-python
|
|
16
|
+
|
|
17
|
+
import json
|
|
18
|
+
from typing import Any, Literal
|
|
19
|
+
|
|
20
|
+
from google.adk.events.event import Event
|
|
21
|
+
from google.adk.memory.base_memory_service import (
|
|
22
|
+
BaseMemoryService,
|
|
23
|
+
SearchMemoryResponse,
|
|
24
|
+
)
|
|
25
|
+
from google.adk.memory.memory_entry import MemoryEntry
|
|
26
|
+
from google.adk.sessions import Session
|
|
27
|
+
from google.genai import types
|
|
28
|
+
from pydantic import BaseModel, Field
|
|
29
|
+
from typing_extensions import Union, override
|
|
30
|
+
|
|
31
|
+
from veadk.memory.long_term_memory_backends.base_backend import (
|
|
32
|
+
BaseLongTermMemoryBackend,
|
|
33
|
+
)
|
|
34
|
+
from veadk.utils.logger import get_logger
|
|
35
|
+
|
|
36
|
+
logger = get_logger(__name__)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _get_backend_cls(backend: str) -> type[BaseLongTermMemoryBackend]:
|
|
40
|
+
match backend:
|
|
41
|
+
case "local":
|
|
42
|
+
from veadk.memory.long_term_memory_backends.in_memory_backend import (
|
|
43
|
+
InMemoryLTMBackend,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
return InMemoryLTMBackend
|
|
47
|
+
case "opensearch":
|
|
48
|
+
from veadk.memory.long_term_memory_backends.opensearch_backend import (
|
|
49
|
+
OpensearchLTMBackend,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return OpensearchLTMBackend
|
|
53
|
+
case "viking":
|
|
54
|
+
from veadk.memory.long_term_memory_backends.vikingdb_memory_backend import (
|
|
55
|
+
VikingDBLTMBackend,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return VikingDBLTMBackend
|
|
59
|
+
case "redis":
|
|
60
|
+
from veadk.memory.long_term_memory_backends.redis_backend import (
|
|
61
|
+
RedisLTMBackend,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return RedisLTMBackend
|
|
65
|
+
case "mem0":
|
|
66
|
+
from veadk.memory.long_term_memory_backends.mem0_backend import (
|
|
67
|
+
Mem0LTMBackend,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return Mem0LTMBackend
|
|
71
|
+
|
|
72
|
+
raise ValueError(f"Unsupported long term memory backend: {backend}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class LongTermMemory(BaseMemoryService, BaseModel):
|
|
76
|
+
"""Manages long-term memory storage and retrieval for applications.
|
|
77
|
+
|
|
78
|
+
This class provides an interface to store, retrieve, and manage long-term
|
|
79
|
+
contextual information using different backend types (e.g., OpenSearch, Redis).
|
|
80
|
+
It supports configuration of the backend service and retrieval behavior.
|
|
81
|
+
|
|
82
|
+
Attributes:
|
|
83
|
+
backend (Union[Literal["local", "opensearch", "redis", "viking", "viking_mem", "mem0"], BaseLongTermMemoryBackend]):
|
|
84
|
+
The type or instance of the long-term memory backend. Defaults to "opensearch".
|
|
85
|
+
|
|
86
|
+
backend_config (dict):
|
|
87
|
+
Configuration parameters for the selected backend. Defaults to an empty dictionary.
|
|
88
|
+
|
|
89
|
+
top_k (int):
|
|
90
|
+
The number of top similar documents to retrieve during search. Defaults to 5.
|
|
91
|
+
|
|
92
|
+
index (str):
|
|
93
|
+
The name of the index or collection used for storing memory items. Defaults to an empty string.
|
|
94
|
+
|
|
95
|
+
app_name (str):
|
|
96
|
+
The name of the application that owns this memory instance. Defaults to an empty string.
|
|
97
|
+
|
|
98
|
+
user_id (str):
|
|
99
|
+
Deprecated attribute. Retained for backward compatibility. Defaults to an empty string.
|
|
100
|
+
|
|
101
|
+
Notes:
|
|
102
|
+
Please ensure that you have set the embedding-related configurations in environment variables.
|
|
103
|
+
|
|
104
|
+
Examples:
|
|
105
|
+
### Simple long-term memory
|
|
106
|
+
|
|
107
|
+
Once create a long-term memory withou any arguments, all configurations are come from **environment variables**.
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import asyncio
|
|
111
|
+
|
|
112
|
+
from veadk import Agent, Runner
|
|
113
|
+
from veadk.memory.long_term_memory import LongTermMemory
|
|
114
|
+
from veadk.memory.short_term_memory import ShortTermMemory
|
|
115
|
+
|
|
116
|
+
app_name = "veadk_playground_app"
|
|
117
|
+
user_id = "veadk_playground_user"
|
|
118
|
+
|
|
119
|
+
long_term_memory = LongTermMemory(backend="local", app_name=app_name)
|
|
120
|
+
|
|
121
|
+
agent = Agent(long_term_memory=long_term_memory)
|
|
122
|
+
|
|
123
|
+
runner = Runner(
|
|
124
|
+
agent=agent,
|
|
125
|
+
app_name=app_name,
|
|
126
|
+
user_id=user_id,
|
|
127
|
+
short_term_memory=ShortTermMemory(),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# ===== add memory =====
|
|
131
|
+
session_id = "veadk_playground_session"
|
|
132
|
+
teaching_prompt = "I brought an ice-cream last week."
|
|
133
|
+
|
|
134
|
+
asyncio.run(runner.run(messages=teaching_prompt, session_id=session_id))
|
|
135
|
+
asyncio.run(
|
|
136
|
+
runner.save_session_to_long_term_memory(session_id=session_id)
|
|
137
|
+
) # save session to long-term memory
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
# ===== check memory =====
|
|
141
|
+
session_id = "veadk_playground_session_2" # use a new session
|
|
142
|
+
student_prompt = "What I brought last week?"
|
|
143
|
+
|
|
144
|
+
response = asyncio.run(runner.run(messages=student_prompt, session_id=session_id))
|
|
145
|
+
|
|
146
|
+
print(response)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Create with a backend instance
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
from veadk.memory.long_term_memory import LongTermMemory
|
|
153
|
+
from veadk.memory.long_term_memory.backends import LongTermMemory
|
|
154
|
+
|
|
155
|
+
long_term_memory = LongTermMemory(backend=...)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Create with backend configurations
|
|
159
|
+
|
|
160
|
+
```python
|
|
161
|
+
from veadk.memory.long_term_memory import LongTermMemory
|
|
162
|
+
|
|
163
|
+
long_term_memory = LongTermMemory(backend="", backend_config={})
|
|
164
|
+
```
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
backend: Union[
|
|
168
|
+
Literal["local", "opensearch", "redis", "viking", "viking_mem", "mem0"],
|
|
169
|
+
BaseLongTermMemoryBackend,
|
|
170
|
+
] = "opensearch"
|
|
171
|
+
|
|
172
|
+
backend_config: dict = Field(default_factory=dict)
|
|
173
|
+
|
|
174
|
+
top_k: int = 5
|
|
175
|
+
|
|
176
|
+
index: str = ""
|
|
177
|
+
|
|
178
|
+
app_name: str = ""
|
|
179
|
+
|
|
180
|
+
user_id: str = ""
|
|
181
|
+
|
|
182
|
+
def model_post_init(self, __context: Any) -> None:
|
|
183
|
+
# Once user define a backend instance, use it directly
|
|
184
|
+
if isinstance(self.backend, BaseLongTermMemoryBackend):
|
|
185
|
+
self._backend = self.backend
|
|
186
|
+
self.index = self._backend.index
|
|
187
|
+
logger.info(
|
|
188
|
+
f"Initialized long term memory with provided backend instance {self._backend.__class__.__name__}, index={self.index}"
|
|
189
|
+
)
|
|
190
|
+
return
|
|
191
|
+
|
|
192
|
+
# Once user define backend config, use it directly
|
|
193
|
+
if self.backend_config:
|
|
194
|
+
if "index" not in self.backend_config:
|
|
195
|
+
logger.warning(
|
|
196
|
+
"Attribute `index` not provided in backend_config, use `index` or `app_name` instead."
|
|
197
|
+
)
|
|
198
|
+
self.backend_config["index"] = self.index or self.app_name
|
|
199
|
+
|
|
200
|
+
logger.debug(
|
|
201
|
+
f"Init {self.backend}, Use provided backend config: {self.backend_config}"
|
|
202
|
+
)
|
|
203
|
+
self._backend = _get_backend_cls(self.backend)(**self.backend_config)
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
# Check index
|
|
207
|
+
self.index = self.index or self.app_name
|
|
208
|
+
if not self.index:
|
|
209
|
+
logger.warning(
|
|
210
|
+
"Attribute `index` or `app_name` not provided, use `default_app` instead."
|
|
211
|
+
)
|
|
212
|
+
self.index = "default_app"
|
|
213
|
+
|
|
214
|
+
# Forward compliance
|
|
215
|
+
if self.backend == "viking_mem":
|
|
216
|
+
logger.warning(
|
|
217
|
+
"The `viking_mem` backend is deprecated, change to `viking` instead."
|
|
218
|
+
)
|
|
219
|
+
self.backend = "viking"
|
|
220
|
+
|
|
221
|
+
self._backend = _get_backend_cls(self.backend)(index=self.index)
|
|
222
|
+
|
|
223
|
+
logger.info(
|
|
224
|
+
f"Initialized long term memory with provided backend instance {self._backend.__class__.__name__}, index={self.index}"
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
def _filter_and_convert_events(self, events: list[Event]) -> list[str]:
|
|
228
|
+
final_events = []
|
|
229
|
+
for event in events:
|
|
230
|
+
# filter: bad event
|
|
231
|
+
if not event.content or not event.content.parts:
|
|
232
|
+
continue
|
|
233
|
+
|
|
234
|
+
# filter: only add user event to memory to enhance retrieve performance
|
|
235
|
+
if not event.author == "user":
|
|
236
|
+
continue
|
|
237
|
+
|
|
238
|
+
# filter: discard function call and function response
|
|
239
|
+
if not event.content.parts[0].text:
|
|
240
|
+
continue
|
|
241
|
+
|
|
242
|
+
# convert: to string-format for storage
|
|
243
|
+
message = event.content.model_dump(exclude_none=True, mode="json")
|
|
244
|
+
|
|
245
|
+
final_events.append(json.dumps(message, ensure_ascii=False))
|
|
246
|
+
return final_events
|
|
247
|
+
|
|
248
|
+
@override
|
|
249
|
+
async def add_session_to_memory(
|
|
250
|
+
self,
|
|
251
|
+
session: Session,
|
|
252
|
+
):
|
|
253
|
+
"""Add a chat session's events to the long-term memory backend.
|
|
254
|
+
|
|
255
|
+
This method extracts and filters the events from a given `Session` object,
|
|
256
|
+
converts them into serialized strings, and stores them into the long-term
|
|
257
|
+
memory system. It is typically called after a chat session ends or when
|
|
258
|
+
important contextual data needs to be persisted for future retrieval.
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
session (Session):
|
|
262
|
+
The session object containing user ID and a list of events to persist.
|
|
263
|
+
|
|
264
|
+
Examples:
|
|
265
|
+
```python
|
|
266
|
+
session = Session(
|
|
267
|
+
user_id="user_123",
|
|
268
|
+
events=[
|
|
269
|
+
Event(role="user", content="I like Go and Rust."),
|
|
270
|
+
Event(role="assistant", content="Got it! I'll remember that."),
|
|
271
|
+
]
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
await memory_service.add_session_to_memory(session)
|
|
275
|
+
# Logs:
|
|
276
|
+
# Adding 2 events to long term memory: index=main
|
|
277
|
+
# Added 2 events to long term memory: index=main, user_id=user_123
|
|
278
|
+
```
|
|
279
|
+
"""
|
|
280
|
+
user_id = session.user_id
|
|
281
|
+
event_strings = self._filter_and_convert_events(session.events)
|
|
282
|
+
|
|
283
|
+
logger.info(
|
|
284
|
+
f"Adding {len(event_strings)} events to long term memory: index={self.index}"
|
|
285
|
+
)
|
|
286
|
+
self._backend.save_memory(user_id=user_id, event_strings=event_strings)
|
|
287
|
+
logger.info(
|
|
288
|
+
f"Added {len(event_strings)} events to long term memory: index={self.index}, user_id={user_id}"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
@override
|
|
292
|
+
async def search_memory(
|
|
293
|
+
self, *, app_name: str, user_id: str, query: str
|
|
294
|
+
) -> SearchMemoryResponse:
|
|
295
|
+
"""Search memory entries for a given user and query.
|
|
296
|
+
|
|
297
|
+
This method queries the memory backend to retrieve the most relevant stored
|
|
298
|
+
memory chunks for a given user and text query. It then converts those raw
|
|
299
|
+
memory chunks into structured `MemoryEntry` objects to be returned to the caller.
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
app_name (str): Name of the application requesting the memory search.
|
|
303
|
+
user_id (str): Unique identifier for the user whose memory is being queried.
|
|
304
|
+
query (str): The text query to match against stored memory content.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
SearchMemoryResponse:
|
|
308
|
+
An object containing a list of `MemoryEntry` items representing
|
|
309
|
+
the retrieved memory snippets relevant to the query.
|
|
310
|
+
|
|
311
|
+
Examples:
|
|
312
|
+
```python
|
|
313
|
+
response = await memory_service.search_memory(
|
|
314
|
+
app_name="chat_app",
|
|
315
|
+
user_id="user_123",
|
|
316
|
+
query="favorite programming language"
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
for memory in response.memories:
|
|
320
|
+
print(memory.content.parts[0].text)
|
|
321
|
+
# Output:
|
|
322
|
+
# User likes Python and TypeScript for backend development.
|
|
323
|
+
```
|
|
324
|
+
"""
|
|
325
|
+
logger.info(f"Search memory with query={query}")
|
|
326
|
+
|
|
327
|
+
memory_chunks = []
|
|
328
|
+
try:
|
|
329
|
+
memory_chunks = self._backend.search_memory(
|
|
330
|
+
query=query, top_k=self.top_k, user_id=user_id
|
|
331
|
+
)
|
|
332
|
+
except Exception as e:
|
|
333
|
+
logger.error(
|
|
334
|
+
f"Exception orrcus during memory search: {e}. Return empty memory chunks"
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
memory_events = []
|
|
338
|
+
for memory in memory_chunks:
|
|
339
|
+
try:
|
|
340
|
+
memory_dict = json.loads(memory)
|
|
341
|
+
try:
|
|
342
|
+
text = memory_dict["parts"][0]["text"]
|
|
343
|
+
role = memory_dict["role"]
|
|
344
|
+
except KeyError as _:
|
|
345
|
+
# prevent not a standard text-based event
|
|
346
|
+
logger.warning(
|
|
347
|
+
f"Memory content: {memory_dict}. Skip return this memory."
|
|
348
|
+
)
|
|
349
|
+
continue
|
|
350
|
+
except json.JSONDecodeError:
|
|
351
|
+
# prevent the memory string is not dumped by `Event` class
|
|
352
|
+
text = memory
|
|
353
|
+
role = "user"
|
|
354
|
+
|
|
355
|
+
memory_events.append(
|
|
356
|
+
MemoryEntry(
|
|
357
|
+
author="user",
|
|
358
|
+
content=types.Content(parts=[types.Part(text=text)], role=role),
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
logger.info(
|
|
363
|
+
f"Return {len(memory_events)} memory events for query: {query} index={self.index} user_id={user_id}"
|
|
364
|
+
)
|
|
365
|
+
return SearchMemoryResponse(memories=memory_events)
|