veadk-python 0.2.4__tar.gz → 0.2.5__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.
Potentially problematic release.
This version of veadk-python might be problematic. Click here for more details.
- {veadk_python-0.2.4 → veadk_python-0.2.5}/PKG-INFO +1 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/pyproject.toml +1 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_agent.py +7 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_cloud.py +6 -3
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_runner.py +2 -2
- veadk_python-0.2.5/tests/test_tos.py +110 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/agent.py +28 -8
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/cli_deploy.py +3 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cloud/cloud_app.py +21 -6
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/consts.py +14 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/viking/viking_database.py +3 -3
- veadk_python-0.2.5/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +4 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +11 -1
- veadk_python-0.2.5/veadk/integrations/ve_tos/ve_tos.py +176 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/runner.py +107 -34
- veadk_python-0.2.5/veadk/tools/builtin_tools/image_edit.py +236 -0
- veadk_python-0.2.5/veadk/tools/builtin_tools/image_generate.py +236 -0
- veadk_python-0.2.5/veadk/tools/builtin_tools/video_generate.py +326 -0
- veadk_python-0.2.5/veadk/tools/sandbox/browser_sandbox.py +37 -0
- veadk_python-0.2.5/veadk/tools/sandbox/code_sandbox.py +40 -0
- veadk_python-0.2.4/veadk/tools/sandbox/code_sandbox.py → veadk_python-0.2.5/veadk/tools/sandbox/computer_sandbox.py +15 -11
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/base_tracer.py +0 -19
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +65 -6
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +20 -14
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/inmemory_exporter.py +3 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/opentelemetry_tracer.py +4 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/telemetry.py +113 -24
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/misc.py +40 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/version.py +1 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/PKG-INFO +1 -1
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/SOURCES.txt +6 -0
- veadk_python-0.2.4/veadk/tools/sandbox/browser_sandbox.py +0 -27
- veadk_python-0.2.4/veadk/tools/sandbox/computer_sandbox.py +0 -27
- {veadk_python-0.2.4 → veadk_python-0.2.5}/LICENSE +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/README.md +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/setup.cfg +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_agent_card.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_evaluator.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_knowledgebase.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_long_term_memory.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_multiple_agents.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_runtime_data_collecting.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_short_term_memory.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/tests/test_tracing.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/agent_card.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/remote_ve_agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/ve_a2a_server.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/ve_agent_executor.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/a2a/ve_task_store.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/agents/loop_agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/agents/parallel_agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/agents/sequential_agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/cli.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/cli_init.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/cli_prompt.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cli/cli_web.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cloud/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/cloud/cloud_agent_engine.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/config.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/base_database.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/database_adapter.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/database_factory.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/kv/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/kv/redis_database.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/local_database.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/relational/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/relational/mysql_database.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/vector/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/vector/opensearch_vector_database.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/vector/type.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/viking/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/database/viking/viking_memory_db.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/adk_evaluator/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/adk_evaluator/adk_evaluator.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/base_evaluator.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/deepeval_evaluator/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/eval_set_file_loader.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/eval_set_recorder.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/types.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/evaluation/utils/prometheus.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_apig/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_apig/ve_apig.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_apig/ve_apig_utils.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/cookiecutter.json +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name|replace('-', '_') }}/agent.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/ve_faas.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_faas/ve_faas_utils.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_prompt_pilot/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/knowledgebase/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/knowledgebase/knowledgebase.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/memory/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/memory/long_term_memory.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/memory/short_term_memory.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/memory/short_term_memory_processor.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/prompts/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/prompts/agent_default_prompt.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/prompts/prompt_evaluator.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/prompts/prompt_memory_processor.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/prompts/prompt_optimization.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/lark.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/las.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/mcp_router.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/vesearch.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/web_scraper.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/builtin_tools/web_search.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/demo_tools.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/load_knowledgebase_tool.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tools/sandbox/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/attributes/attributes.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/attributes/extractors/types.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/apmplus_exporter.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/base_exporter.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/cozeloop_exporter.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/tracing/telemetry/exporters/tls_exporter.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/types.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/__init__.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/logger.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/mcp_utils.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/patches.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk/utils/volcengine_sign.py +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/dependency_links.txt +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/entry_points.txt +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/requires.txt +0 -0
- {veadk_python-0.2.4 → veadk_python-0.2.5}/veadk_python.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: veadk-python
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: Volcengine agent development kit, integrations with Volcengine cloud services.
|
|
5
5
|
Author-email: Yaozheng Fang <fangyozheng@gmail.com>, Guodong Li <cu.eric.lee@gmail.com>, Zhi Han <sliverydayday@gmail.com>, Meng Wang <mengwangwm@gmail.com>
|
|
6
6
|
License: Apache License
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
from google.adk.tools import load_memory
|
|
16
16
|
|
|
17
17
|
from veadk import Agent
|
|
18
|
+
from veadk.consts import DEFAULT_MODEL_EXTRA_HEADERS
|
|
18
19
|
from veadk.knowledgebase import KnowledgeBase
|
|
19
20
|
from veadk.memory.long_term_memory import LongTermMemory
|
|
20
21
|
from veadk.tools import load_knowledgebase_tool
|
|
@@ -26,11 +27,14 @@ def test_agent():
|
|
|
26
27
|
long_term_memory = LongTermMemory(backend="local")
|
|
27
28
|
tracer = OpentelemetryTracer()
|
|
28
29
|
|
|
30
|
+
model_extra_headers = {"test-header": "test-value"}
|
|
31
|
+
|
|
29
32
|
agent = Agent(
|
|
30
33
|
model_name="test_model_name",
|
|
31
34
|
model_provider="test_model_provider",
|
|
32
35
|
model_api_key="test_model_api_key",
|
|
33
36
|
model_api_base="test_model_api_base",
|
|
37
|
+
model_extra_headers=model_extra_headers,
|
|
34
38
|
tools=[],
|
|
35
39
|
sub_agents=[],
|
|
36
40
|
knowledgebase=knowledgebase,
|
|
@@ -39,7 +43,10 @@ def test_agent():
|
|
|
39
43
|
serve_url="",
|
|
40
44
|
)
|
|
41
45
|
|
|
46
|
+
model_extra_headers |= DEFAULT_MODEL_EXTRA_HEADERS
|
|
47
|
+
|
|
42
48
|
assert agent.model.model == f"{agent.model_provider}/{agent.model_name}"
|
|
49
|
+
assert agent.model_extra_headers == model_extra_headers
|
|
43
50
|
|
|
44
51
|
assert agent.knowledgebase == knowledgebase
|
|
45
52
|
assert agent.knowledgebase.backend == "local"
|
|
@@ -115,9 +115,12 @@ async def test_cloud():
|
|
|
115
115
|
mock_vefaas_client = Mock()
|
|
116
116
|
mock_vefaas_in_app.return_value = mock_vefaas_client
|
|
117
117
|
mock_vefaas_client.delete.return_value = None
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
118
|
+
with patch.object(
|
|
119
|
+
cloud_app, "_get_vefaas_application_id_by_name"
|
|
120
|
+
) as mock_get_id_by_name:
|
|
121
|
+
mock_get_id_by_name.return_value = None
|
|
122
|
+
cloud_app.delete_self()
|
|
123
|
+
mock_vefaas_client.delete.assert_called_with("app-123")
|
|
121
124
|
|
|
122
125
|
# Verify all mocks were called as expected
|
|
123
126
|
mock_vefaas_service.deploy.assert_called_once()
|
|
@@ -28,7 +28,7 @@ def _test_convert_messages(runner):
|
|
|
28
28
|
role="user",
|
|
29
29
|
)
|
|
30
30
|
]
|
|
31
|
-
actual_message = runner._convert_messages(message)
|
|
31
|
+
actual_message = runner._convert_messages(message, session_id="test_session_id")
|
|
32
32
|
assert actual_message == expected_message
|
|
33
33
|
|
|
34
34
|
message = ["test message 1", "test message 2"]
|
|
@@ -42,7 +42,7 @@ def _test_convert_messages(runner):
|
|
|
42
42
|
role="user",
|
|
43
43
|
),
|
|
44
44
|
]
|
|
45
|
-
actual_message = runner._convert_messages(message)
|
|
45
|
+
actual_message = runner._convert_messages(message, session_id="test_session_id")
|
|
46
46
|
assert actual_message == expected_message
|
|
47
47
|
|
|
48
48
|
|
|
@@ -0,0 +1,110 @@
|
|
|
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
|
+
import pytest
|
|
16
|
+
from unittest import mock
|
|
17
|
+
import veadk.integrations.ve_tos.ve_tos as tos_mod
|
|
18
|
+
|
|
19
|
+
# 使用 pytest-asyncio
|
|
20
|
+
pytest_plugins = ("pytest_asyncio",)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.fixture
|
|
24
|
+
def mock_client(monkeypatch):
|
|
25
|
+
fake_client = mock.Mock()
|
|
26
|
+
|
|
27
|
+
monkeypatch.setenv("DATABASE_TOS_REGION", "test-region")
|
|
28
|
+
monkeypatch.setenv("VOLCENGINE_ACCESS_KEY", "test-access-key")
|
|
29
|
+
monkeypatch.setenv("VOLCENGINE_SECRET_KEY", "test-secret-key")
|
|
30
|
+
monkeypatch.setenv("DATABASE_TOS_BUCKET", "test-bucket")
|
|
31
|
+
|
|
32
|
+
monkeypatch.setattr(tos_mod.tos, "TosClientV2", lambda *a, **k: fake_client)
|
|
33
|
+
|
|
34
|
+
class FakeExceptions:
|
|
35
|
+
class TosServerError(Exception):
|
|
36
|
+
def __init__(self, msg):
|
|
37
|
+
super().__init__(msg)
|
|
38
|
+
self.status_code = None
|
|
39
|
+
|
|
40
|
+
monkeypatch.setattr(tos_mod.tos, "exceptions", FakeExceptions)
|
|
41
|
+
monkeypatch.setattr(
|
|
42
|
+
tos_mod.tos,
|
|
43
|
+
"StorageClassType",
|
|
44
|
+
type("S", (), {"Storage_Class_Standard": "STANDARD"}),
|
|
45
|
+
)
|
|
46
|
+
monkeypatch.setattr(
|
|
47
|
+
tos_mod.tos, "ACLType", type("A", (), {"ACL_Private": "private"})
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return fake_client
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest.fixture
|
|
54
|
+
def tos_client(mock_client):
|
|
55
|
+
return tos_mod.VeTOS()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def test_create_bucket_exists(tos_client, mock_client):
|
|
59
|
+
mock_client.head_bucket.return_value = None # head_bucket 正常返回表示存在
|
|
60
|
+
result = tos_client.create_bucket()
|
|
61
|
+
assert result is True
|
|
62
|
+
mock_client.create_bucket.assert_not_called()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_create_bucket_not_exists(tos_client, mock_client):
|
|
66
|
+
exc = tos_mod.tos.exceptions.TosServerError("not found")
|
|
67
|
+
exc.status_code = 404
|
|
68
|
+
mock_client.head_bucket.side_effect = exc
|
|
69
|
+
|
|
70
|
+
result = tos_client.create_bucket()
|
|
71
|
+
assert result is True
|
|
72
|
+
mock_client.create_bucket.assert_called_once()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@pytest.mark.asyncio
|
|
76
|
+
async def test_upload_bytes_success(tos_client, mock_client):
|
|
77
|
+
mock_client.head_bucket.return_value = True
|
|
78
|
+
data = b"hello world"
|
|
79
|
+
|
|
80
|
+
result = await tos_client.upload("obj-key", data)
|
|
81
|
+
assert result is True
|
|
82
|
+
mock_client.put_object.assert_called_once()
|
|
83
|
+
mock_client.close.assert_called_once()
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@pytest.mark.asyncio
|
|
87
|
+
async def test_upload_file_success(tmp_path, tos_client, mock_client):
|
|
88
|
+
mock_client.head_bucket.return_value = True
|
|
89
|
+
file_path = tmp_path / "file.txt"
|
|
90
|
+
file_path.write_text("hello file")
|
|
91
|
+
|
|
92
|
+
result = await tos_client.upload("obj-key", str(file_path))
|
|
93
|
+
assert result is True
|
|
94
|
+
mock_client.put_object_from_file.assert_called_once()
|
|
95
|
+
mock_client.close.assert_called_once()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_download_success(tmp_path, tos_client, mock_client):
|
|
99
|
+
save_path = tmp_path / "out.txt"
|
|
100
|
+
mock_client.get_object.return_value = [b"abc", b"def"]
|
|
101
|
+
|
|
102
|
+
result = tos_client.download("obj-key", str(save_path))
|
|
103
|
+
assert result is True
|
|
104
|
+
assert save_path.read_bytes() == b"abcdef"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def test_download_fail(tos_client, mock_client):
|
|
108
|
+
mock_client.get_object.side_effect = Exception("boom")
|
|
109
|
+
result = tos_client.download("obj-key", "somewhere.txt")
|
|
110
|
+
assert result is False
|
|
@@ -28,9 +28,10 @@ from typing_extensions import Any
|
|
|
28
28
|
|
|
29
29
|
from veadk.config import getenv
|
|
30
30
|
from veadk.consts import (
|
|
31
|
-
|
|
31
|
+
DEFAULT_MODEL_AGENT_PROVIDER,
|
|
32
32
|
DEFAULT_MODEL_AGENT_API_BASE,
|
|
33
33
|
DEFAULT_MODEL_AGENT_NAME,
|
|
34
|
+
DEFAULT_MODEL_EXTRA_HEADERS,
|
|
34
35
|
)
|
|
35
36
|
from veadk.evaluation import EvalSetRecorder
|
|
36
37
|
from veadk.knowledgebase import KnowledgeBase
|
|
@@ -64,7 +65,7 @@ class Agent(LlmAgent):
|
|
|
64
65
|
model_name: str = getenv("MODEL_AGENT_NAME", DEFAULT_MODEL_AGENT_NAME)
|
|
65
66
|
"""The name of the model for agent running."""
|
|
66
67
|
|
|
67
|
-
model_provider: str = getenv("MODEL_AGENT_PROVIDER",
|
|
68
|
+
model_provider: str = getenv("MODEL_AGENT_PROVIDER", DEFAULT_MODEL_AGENT_PROVIDER)
|
|
68
69
|
"""The provider of the model for agent running."""
|
|
69
70
|
|
|
70
71
|
model_api_base: str = getenv("MODEL_AGENT_API_BASE", DEFAULT_MODEL_AGENT_API_BASE)
|
|
@@ -73,6 +74,9 @@ class Agent(LlmAgent):
|
|
|
73
74
|
model_api_key: str = Field(default_factory=lambda: getenv("MODEL_AGENT_API_KEY"))
|
|
74
75
|
"""The api key of the model for agent running."""
|
|
75
76
|
|
|
77
|
+
model_extra_config: dict = Field(default_factory=dict)
|
|
78
|
+
"""The extra config to include in the model requests."""
|
|
79
|
+
|
|
76
80
|
tools: list[ToolUnion] = []
|
|
77
81
|
"""The tools provided to agent."""
|
|
78
82
|
|
|
@@ -96,11 +100,27 @@ class Agent(LlmAgent):
|
|
|
96
100
|
|
|
97
101
|
def model_post_init(self, __context: Any) -> None:
|
|
98
102
|
super().model_post_init(None) # for sub_agents init
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
103
|
+
|
|
104
|
+
# add model request source (veadk) in extra headers
|
|
105
|
+
if self.model_extra_config and "extra_headers" in self.model_extra_config:
|
|
106
|
+
self.model_extra_config["extra_headers"] |= DEFAULT_MODEL_EXTRA_HEADERS
|
|
107
|
+
else:
|
|
108
|
+
self.model_extra_config["extra_headers"] = DEFAULT_MODEL_EXTRA_HEADERS
|
|
109
|
+
|
|
110
|
+
if not self.model:
|
|
111
|
+
self.model = LiteLlm(
|
|
112
|
+
model=f"{self.model_provider}/{self.model_name}",
|
|
113
|
+
api_key=self.model_api_key,
|
|
114
|
+
api_base=self.model_api_base,
|
|
115
|
+
**self.model_extra_config,
|
|
116
|
+
)
|
|
117
|
+
logger.debug(
|
|
118
|
+
f"LiteLLM client created with config: {self.model_extra_config}"
|
|
119
|
+
)
|
|
120
|
+
else:
|
|
121
|
+
logger.warning(
|
|
122
|
+
"You are trying to use your own LiteLLM client, some default request headers may be missing."
|
|
123
|
+
)
|
|
104
124
|
|
|
105
125
|
if self.knowledgebase:
|
|
106
126
|
from veadk.tools import load_knowledgebase_tool
|
|
@@ -117,7 +137,7 @@ class Agent(LlmAgent):
|
|
|
117
137
|
|
|
118
138
|
logger.info(f"{self.__class__.__name__} `{self.name}` init done.")
|
|
119
139
|
logger.debug(
|
|
120
|
-
f"Agent: {self.model_dump(include={'name', 'model_name', 'model_api_base', 'tools'
|
|
140
|
+
f"Agent: {self.model_dump(include={'name', 'model_name', 'model_api_base', 'tools'})}"
|
|
121
141
|
)
|
|
122
142
|
|
|
123
143
|
async def _run(
|
|
@@ -29,7 +29,9 @@ TEMP_PATH = "/tmp"
|
|
|
29
29
|
default=None,
|
|
30
30
|
help="Volcengine secret key",
|
|
31
31
|
)
|
|
32
|
-
@click.option(
|
|
32
|
+
@click.option(
|
|
33
|
+
"--vefaas-app-name", required=True, help="Expected Volcengine FaaS application name"
|
|
34
|
+
)
|
|
33
35
|
@click.option(
|
|
34
36
|
"--veapig-instance-name", default="", help="Expected Volcengine APIG instance name"
|
|
35
37
|
)
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
|
+
import time
|
|
16
17
|
from typing import Any
|
|
17
18
|
from uuid import uuid4
|
|
18
19
|
|
|
@@ -60,9 +61,11 @@ class CloudApp:
|
|
|
60
61
|
if not vefaas_endpoint:
|
|
61
62
|
self.vefaas_endpoint = self._get_vefaas_endpoint()
|
|
62
63
|
|
|
63
|
-
if
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
if (
|
|
65
|
+
self.vefaas_endpoint
|
|
66
|
+
and not self.vefaas_endpoint.startswith("http")
|
|
67
|
+
and not self.vefaas_endpoint.startswith("https")
|
|
68
|
+
):
|
|
66
69
|
raise ValueError(
|
|
67
70
|
f"Invalid endpoint: {vefaas_endpoint}. The endpoint must start with `http` or `https`."
|
|
68
71
|
)
|
|
@@ -92,12 +95,13 @@ class CloudApp:
|
|
|
92
95
|
raise ValueError(
|
|
93
96
|
f"VeFaaS CloudAPP with application_id `{self.vefaas_application_id}` or application_name `{self.vefaas_application_name}` not found."
|
|
94
97
|
)
|
|
95
|
-
cloud_resource = json.loads(app["CloudResource"])
|
|
96
98
|
|
|
97
99
|
try:
|
|
100
|
+
cloud_resource = json.loads(app["CloudResource"])
|
|
98
101
|
vefaas_endpoint = cloud_resource["framework"]["url"]["system_url"]
|
|
99
102
|
except Exception as e:
|
|
100
|
-
|
|
103
|
+
logger.warning(f"VeFaaS cloudAPP could not get endpoint. Error: {e}")
|
|
104
|
+
vefaas_endpoint = ""
|
|
101
105
|
return vefaas_endpoint
|
|
102
106
|
|
|
103
107
|
def _get_vefaas_application_id_by_name(self) -> str:
|
|
@@ -167,7 +171,18 @@ class CloudApp:
|
|
|
167
171
|
|
|
168
172
|
vefaas_client = VeFaaS(access_key=volcengine_ak, secret_key=volcengine_sk)
|
|
169
173
|
vefaas_client.delete(self.vefaas_application_id)
|
|
170
|
-
print(
|
|
174
|
+
print(
|
|
175
|
+
f"Cloud app {self.vefaas_application_id} delete request has been sent to VeFaaS"
|
|
176
|
+
)
|
|
177
|
+
while True:
|
|
178
|
+
try:
|
|
179
|
+
id = self._get_vefaas_application_id_by_name()
|
|
180
|
+
if not id:
|
|
181
|
+
break
|
|
182
|
+
time.sleep(3)
|
|
183
|
+
except Exception as _:
|
|
184
|
+
break
|
|
185
|
+
print("Delete application done.")
|
|
171
186
|
|
|
172
187
|
async def message_send(
|
|
173
188
|
self, message: str, session_id: str, user_id: str, timeout: float = 600.0
|
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
from veadk.version import VERSION
|
|
16
|
+
|
|
15
17
|
DEFAULT_MODEL_AGENT_NAME = "doubao-seed-1-6-250615"
|
|
16
|
-
|
|
18
|
+
DEFAULT_MODEL_AGENT_PROVIDER = "openai"
|
|
17
19
|
DEFAULT_MODEL_AGENT_API_BASE = "https://ark.cn-beijing.volces.com/api/v3/"
|
|
20
|
+
DEFAULT_MODEL_EXTRA_HEADERS = {"veadk-source": "veadk", "veadk-version": VERSION}
|
|
21
|
+
|
|
22
|
+
DEFAULT_APMPLUS_OTEL_EXPORTER_ENDPOINT = "http://apmplus-cn-beijing.volces.com:4317"
|
|
23
|
+
DEFAULT_APMPLUS_OTEL_EXPORTER_SERVICE_NAME = "veadk_tracing"
|
|
24
|
+
|
|
25
|
+
DEFAULT_COZELOOP_OTEL_EXPORTER_ENDPOINT = (
|
|
26
|
+
"https://api.coze.cn/v1/loop/opentelemetry/v1/traces"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
DEFAULT_TLS_OTEL_EXPORTER_ENDPOINT = "https://tls-cn-beijing.volces.com:4318/v1/traces"
|
|
30
|
+
DEFAULT_TLS_OTEL_EXPORTER_REGION = "cn-beijing"
|
|
@@ -387,9 +387,9 @@ class VikingDatabase(BaseModel, BaseDatabase):
|
|
|
387
387
|
logger.error(f"Error in list_collections: {result['message']}")
|
|
388
388
|
raise ValueError(f"Error in list_collections: {result['message']}")
|
|
389
389
|
|
|
390
|
-
collections = result["data"]
|
|
391
|
-
if
|
|
392
|
-
|
|
390
|
+
collections = result["data"].get("collection_list", [])
|
|
391
|
+
if len(collections) == 0:
|
|
392
|
+
return False
|
|
393
393
|
|
|
394
394
|
collection_list = set()
|
|
395
395
|
|
veadk_python-0.2.5/veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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 veadk.cloud.cloud_app import CloudApp
|
|
16
|
+
|
|
17
|
+
def main() -> None:
|
|
18
|
+
cloud_app = CloudApp(vefaas_application_name="{{cookiecutter.vefaas_application_name}}")
|
|
19
|
+
cloud_app.delete_self()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
if __name__ == "__main__":
|
|
23
|
+
main()
|
|
@@ -26,6 +26,7 @@ from fastmcp import FastMCP
|
|
|
26
26
|
from starlette.routing import Route
|
|
27
27
|
|
|
28
28
|
from google.adk.a2a.utils.agent_card_builder import AgentCardBuilder
|
|
29
|
+
from a2a.types import AgentProvider
|
|
29
30
|
|
|
30
31
|
from veadk.a2a.ve_a2a_server import init_app
|
|
31
32
|
from veadk.runner import Runner
|
|
@@ -46,7 +47,9 @@ app_name = agent_run_config.app_name
|
|
|
46
47
|
agent = agent_run_config.agent
|
|
47
48
|
short_term_memory = agent_run_config.short_term_memory
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
VEFAAS_REGION = os.getenv("APP_REGION", "cn-beijing")
|
|
51
|
+
VEFAAS_FUNC_ID = os.getenv("_FAAS_FUNC_ID", "")
|
|
52
|
+
agent_card_builder = AgentCardBuilder(agent=agent, provider=AgentProvider(organization="Volcengine Agent Development Kit (VeADK)", url=f"https://console.volcengine.com/vefaas/region:vefaas+{VEFAAS_REGION}/function/detail/{VEFAAS_FUNC_ID}"))
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
def load_tracer() -> None:
|
|
@@ -34,7 +34,17 @@ while [[ $# -gt 0 ]]; do
|
|
|
34
34
|
done
|
|
35
35
|
|
|
36
36
|
# in case of deployment deps not installed in user's requirements.txt
|
|
37
|
-
|
|
37
|
+
if pip list | grep -q "^fastapi \|^uvicorn "; then
|
|
38
|
+
echo "fastapi and uvicorn already installed"
|
|
39
|
+
else
|
|
40
|
+
python3 -m pip install uvicorn[standard] fastapi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Check if MODEL_AGENT_API_KEY is set
|
|
44
|
+
if [ -z "$MODEL_AGENT_API_KEY" ]; then
|
|
45
|
+
echo "MODEL_AGENT_API_KEY is not set. Please set it in your environment variables."
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
38
48
|
|
|
39
49
|
USE_ADK_WEB=${USE_ADK_WEB:-False}
|
|
40
50
|
|
|
@@ -0,0 +1,176 @@
|
|
|
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
|
+
import os
|
|
16
|
+
from veadk.config import getenv
|
|
17
|
+
from veadk.utils.logger import get_logger
|
|
18
|
+
import tos
|
|
19
|
+
import asyncio
|
|
20
|
+
from typing import Union
|
|
21
|
+
from pydantic import BaseModel, Field
|
|
22
|
+
from typing import Any
|
|
23
|
+
from urllib.parse import urlparse
|
|
24
|
+
from datetime import datetime
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TOSConfig(BaseModel):
|
|
30
|
+
region: str = Field(
|
|
31
|
+
default_factory=lambda: getenv("DATABASE_TOS_REGION"),
|
|
32
|
+
description="TOS region",
|
|
33
|
+
)
|
|
34
|
+
ak: str = Field(
|
|
35
|
+
default_factory=lambda: getenv("VOLCENGINE_ACCESS_KEY"),
|
|
36
|
+
description="Volcengine access key",
|
|
37
|
+
)
|
|
38
|
+
sk: str = Field(
|
|
39
|
+
default_factory=lambda: getenv("VOLCENGINE_SECRET_KEY"),
|
|
40
|
+
description="Volcengine secret key",
|
|
41
|
+
)
|
|
42
|
+
bucket_name: str = Field(
|
|
43
|
+
default_factory=lambda: getenv("DATABASE_TOS_BUCKET"),
|
|
44
|
+
description="TOS bucket name",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class VeTOS(BaseModel):
|
|
49
|
+
config: TOSConfig = Field(default_factory=TOSConfig)
|
|
50
|
+
|
|
51
|
+
def model_post_init(self, __context: Any) -> None:
|
|
52
|
+
try:
|
|
53
|
+
self._client = tos.TosClientV2(
|
|
54
|
+
self.config.ak,
|
|
55
|
+
self.config.sk,
|
|
56
|
+
endpoint=f"tos-{self.config.region}.volces.com",
|
|
57
|
+
region=self.config.region,
|
|
58
|
+
)
|
|
59
|
+
logger.info("Connected to TOS successfully.")
|
|
60
|
+
except Exception as e:
|
|
61
|
+
logger.error(f"Client initialization failed:{e}")
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
def create_bucket(self) -> bool:
|
|
65
|
+
"""If the bucket does not exist, create it"""
|
|
66
|
+
try:
|
|
67
|
+
self._client.head_bucket(self.config.bucket_name)
|
|
68
|
+
logger.info(f"Bucket {self.config.bucket_name} already exists")
|
|
69
|
+
return True
|
|
70
|
+
except tos.exceptions.TosServerError as e:
|
|
71
|
+
if e.status_code == 404:
|
|
72
|
+
self._client.create_bucket(
|
|
73
|
+
bucket=self.config.bucket_name,
|
|
74
|
+
storage_class=tos.StorageClassType.Storage_Class_Standard,
|
|
75
|
+
acl=tos.ACLType.ACL_Private,
|
|
76
|
+
)
|
|
77
|
+
logger.info(f"Bucket {self.config.bucket_name} created successfully")
|
|
78
|
+
return True
|
|
79
|
+
except Exception as e:
|
|
80
|
+
logger.error(f"Bucket creation failed: {str(e)}")
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
def build_tos_url(
|
|
84
|
+
self, user_id: str, app_name: str, session_id: str, data_path: str
|
|
85
|
+
) -> tuple[str, str]:
|
|
86
|
+
"""generate TOS object key"""
|
|
87
|
+
parsed_url = urlparse(data_path)
|
|
88
|
+
|
|
89
|
+
if parsed_url.scheme and parsed_url.scheme in ("http", "https", "ftp", "ftps"):
|
|
90
|
+
file_name = os.path.basename(parsed_url.path)
|
|
91
|
+
else:
|
|
92
|
+
file_name = os.path.basename(data_path)
|
|
93
|
+
|
|
94
|
+
timestamp: str = datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
|
|
95
|
+
object_key: str = f"{app_name}-{user_id}-{session_id}/{timestamp}-{file_name}"
|
|
96
|
+
tos_url: str = f"https://{self.config.bucket_name}.tos-{self.config.region}.volces.com/{object_key}"
|
|
97
|
+
|
|
98
|
+
return object_key, tos_url
|
|
99
|
+
|
|
100
|
+
def upload(
|
|
101
|
+
self,
|
|
102
|
+
object_key: str,
|
|
103
|
+
data: Union[str, bytes],
|
|
104
|
+
):
|
|
105
|
+
if isinstance(data, str):
|
|
106
|
+
data_type = "file"
|
|
107
|
+
elif isinstance(data, bytes):
|
|
108
|
+
data_type = "bytes"
|
|
109
|
+
else:
|
|
110
|
+
error_msg = f"Upload failed: data type error. Only str (file path) and bytes are supported, got {type(data)}"
|
|
111
|
+
logger.error(error_msg)
|
|
112
|
+
raise ValueError(error_msg)
|
|
113
|
+
if data_type == "file":
|
|
114
|
+
return asyncio.to_thread(self._do_upload_file, object_key, data)
|
|
115
|
+
elif data_type == "bytes":
|
|
116
|
+
return asyncio.to_thread(self._do_upload_bytes, object_key, data)
|
|
117
|
+
|
|
118
|
+
def _do_upload_bytes(self, object_key: str, bytes: bytes) -> bool:
|
|
119
|
+
try:
|
|
120
|
+
if not self._client:
|
|
121
|
+
return False
|
|
122
|
+
if not self.create_bucket():
|
|
123
|
+
return False
|
|
124
|
+
self._client.put_object(
|
|
125
|
+
bucket=self.config.bucket_name, key=object_key, content=bytes
|
|
126
|
+
)
|
|
127
|
+
logger.debug(f"Upload success, object_key: {object_key}")
|
|
128
|
+
self._close()
|
|
129
|
+
return True
|
|
130
|
+
except Exception as e:
|
|
131
|
+
logger.error(f"Upload failed: {e}")
|
|
132
|
+
self._close()
|
|
133
|
+
return False
|
|
134
|
+
|
|
135
|
+
def _do_upload_file(self, object_key: str, file_path: str) -> bool:
|
|
136
|
+
try:
|
|
137
|
+
if not self._client:
|
|
138
|
+
return False
|
|
139
|
+
if not self.create_bucket():
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
self._client.put_object_from_file(
|
|
143
|
+
bucket=self.config.bucket_name, key=object_key, file_path=file_path
|
|
144
|
+
)
|
|
145
|
+
self._close()
|
|
146
|
+
logger.debug(f"Upload success, object_key: {object_key}")
|
|
147
|
+
return True
|
|
148
|
+
except Exception as e:
|
|
149
|
+
logger.error(f"Upload failed: {e}")
|
|
150
|
+
self._close()
|
|
151
|
+
return False
|
|
152
|
+
|
|
153
|
+
def download(self, object_key: str, save_path: str) -> bool:
|
|
154
|
+
"""download image from TOS"""
|
|
155
|
+
try:
|
|
156
|
+
object_stream = self._client.get_object(self.config.bucket_name, object_key)
|
|
157
|
+
|
|
158
|
+
save_dir = os.path.dirname(save_path)
|
|
159
|
+
if save_dir and not os.path.exists(save_dir):
|
|
160
|
+
os.makedirs(save_dir, exist_ok=True)
|
|
161
|
+
|
|
162
|
+
with open(save_path, "wb") as f:
|
|
163
|
+
for chunk in object_stream:
|
|
164
|
+
f.write(chunk)
|
|
165
|
+
|
|
166
|
+
logger.debug(f"Image download success, saved to: {save_path}")
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
except Exception as e:
|
|
170
|
+
logger.error(f"Image download failed: {str(e)}")
|
|
171
|
+
|
|
172
|
+
return False
|
|
173
|
+
|
|
174
|
+
def _close(self):
|
|
175
|
+
if self._client:
|
|
176
|
+
self._client.close()
|