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
veadk/tools/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
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.
|
|
@@ -0,0 +1,13 @@
|
|
|
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.
|
|
@@ -0,0 +1,94 @@
|
|
|
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 Optional
|
|
16
|
+
|
|
17
|
+
from google.genai import types
|
|
18
|
+
from google.adk.agents.callback_context import CallbackContext
|
|
19
|
+
|
|
20
|
+
from veadk.integrations.ve_identity import (
|
|
21
|
+
get_default_identity_client,
|
|
22
|
+
get_workload_token,
|
|
23
|
+
)
|
|
24
|
+
from veadk.utils.logger import get_logger
|
|
25
|
+
from veadk.utils.auth import extract_delegation_chain_from_jwt
|
|
26
|
+
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
identity_client = get_default_identity_client()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def check_agent_authorization(
|
|
33
|
+
callback_context: CallbackContext,
|
|
34
|
+
) -> Optional[types.Content]:
|
|
35
|
+
"""Check if the agent is authorized to run using Agent Identity."""
|
|
36
|
+
try:
|
|
37
|
+
workload_token = await get_workload_token(
|
|
38
|
+
tool_context=callback_context, identity_client=identity_client
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Parse user_id and actors from workload_token
|
|
42
|
+
user_id, actors = extract_delegation_chain_from_jwt(workload_token)
|
|
43
|
+
|
|
44
|
+
if not user_id:
|
|
45
|
+
logger.warning("Failed to extract user_id from JWT token")
|
|
46
|
+
return types.Content(
|
|
47
|
+
parts=[types.Part(text="Failed to verify agent authorization.")],
|
|
48
|
+
role="model",
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
if len(actors) == 0:
|
|
52
|
+
logger.warning("Failed to extract actors from JWT token")
|
|
53
|
+
return types.Content(
|
|
54
|
+
parts=[types.Part(text="Failed to verify agent authorization.")],
|
|
55
|
+
role="model",
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# The first actor in the chain is the agent itself
|
|
59
|
+
role_id = actors[0]
|
|
60
|
+
|
|
61
|
+
principal = {"Type": "user", "Id": user_id}
|
|
62
|
+
operation = {"Type": "action", "Id": "invoke"}
|
|
63
|
+
resource = {"Type": "agent", "Id": role_id}
|
|
64
|
+
original_callers = [{"Type": "agent", "Id": actor} for actor in actors[1:]]
|
|
65
|
+
|
|
66
|
+
allowed = identity_client.check_permission(
|
|
67
|
+
principal=principal,
|
|
68
|
+
operation=operation,
|
|
69
|
+
resource=resource,
|
|
70
|
+
original_callers=original_callers,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
if allowed:
|
|
74
|
+
logger.info(f"Agent {role_id} is authorized to run by user {user_id}.")
|
|
75
|
+
return None
|
|
76
|
+
else:
|
|
77
|
+
logger.warning(
|
|
78
|
+
f"Agent {role_id} is not authorized to run by user {user_id}."
|
|
79
|
+
)
|
|
80
|
+
return types.Content(
|
|
81
|
+
parts=[
|
|
82
|
+
types.Part(
|
|
83
|
+
text=f"Agent {role_id} is not authorized to run by user {user_id}."
|
|
84
|
+
)
|
|
85
|
+
],
|
|
86
|
+
role="model",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.error(f"Authorization check failed with error: {e}")
|
|
91
|
+
return types.Content(
|
|
92
|
+
parts=[types.Part(text="Failed to verify agent authorization.")],
|
|
93
|
+
role="model",
|
|
94
|
+
)
|
|
@@ -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.tools.builtin_tools.image_generate import image_generate # noqa: F401
|
|
16
|
+
from veadk.utils.logger import get_logger
|
|
17
|
+
|
|
18
|
+
logger = get_logger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
logger.warning(
|
|
22
|
+
"The 'generate_image' tool is deprecated and will be removed in future versions. Use `image_generate` tool from `veadk.tools.builtin_tools.image_generate` instead."
|
|
23
|
+
)
|
|
@@ -0,0 +1,300 @@
|
|
|
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 Dict
|
|
16
|
+
from google.adk.tools import ToolContext
|
|
17
|
+
from volcenginesdkarkruntime import Ark
|
|
18
|
+
from veadk.config import getenv, settings
|
|
19
|
+
from veadk.consts import (
|
|
20
|
+
DEFAULT_IMAGE_EDIT_MODEL_API_BASE,
|
|
21
|
+
DEFAULT_IMAGE_EDIT_MODEL_NAME,
|
|
22
|
+
)
|
|
23
|
+
import base64
|
|
24
|
+
from opentelemetry import trace
|
|
25
|
+
import traceback
|
|
26
|
+
import json
|
|
27
|
+
from veadk.version import VERSION
|
|
28
|
+
from opentelemetry.trace import Span
|
|
29
|
+
from veadk.utils.logger import get_logger
|
|
30
|
+
|
|
31
|
+
logger = get_logger(__name__)
|
|
32
|
+
|
|
33
|
+
client = Ark(
|
|
34
|
+
api_key=getenv(
|
|
35
|
+
"MODEL_EDIT_API_KEY", getenv("MODEL_AGENT_API_KEY", settings.model.api_key)
|
|
36
|
+
),
|
|
37
|
+
base_url=getenv("MODEL_EDIT_API_BASE", DEFAULT_IMAGE_EDIT_MODEL_API_BASE),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def image_edit(
|
|
42
|
+
params: list,
|
|
43
|
+
tool_context: ToolContext,
|
|
44
|
+
) -> Dict:
|
|
45
|
+
"""
|
|
46
|
+
Edit images in batch according to prompts and optional settings.
|
|
47
|
+
|
|
48
|
+
Each item in `params` describes a single image-edit request.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
params (list[dict]):
|
|
52
|
+
A list of image editing requests. Each item supports:
|
|
53
|
+
|
|
54
|
+
Required:
|
|
55
|
+
- origin_image (str):
|
|
56
|
+
The URL or Base64 string of the original image to edit.
|
|
57
|
+
Example:
|
|
58
|
+
* URL: "https://example.com/image.png"
|
|
59
|
+
* Base64: "data:image/png;base64,<BASE64>"
|
|
60
|
+
|
|
61
|
+
- prompt (str):
|
|
62
|
+
The textual description/instruction for editing the image.
|
|
63
|
+
Supports English and Chinese.
|
|
64
|
+
|
|
65
|
+
Optional:
|
|
66
|
+
- image_name (str):
|
|
67
|
+
Name/identifier for the generated image.
|
|
68
|
+
|
|
69
|
+
- response_format (str):
|
|
70
|
+
Format of the returned image.
|
|
71
|
+
* "url": JPEG link (default)
|
|
72
|
+
* "b64_json": Base64 string in JSON
|
|
73
|
+
|
|
74
|
+
- guidance_scale (float):
|
|
75
|
+
How strongly the prompt affects the result.
|
|
76
|
+
Range: [1.0, 10.0], default 2.5.
|
|
77
|
+
|
|
78
|
+
- watermark (bool):
|
|
79
|
+
Whether to add watermark.
|
|
80
|
+
Default: True.
|
|
81
|
+
|
|
82
|
+
- seed (int):
|
|
83
|
+
Random seed for reproducibility.
|
|
84
|
+
Range: [-1, 2^31-1], default -1 (random).
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Dict: API response containing generated image metadata.
|
|
88
|
+
Example:
|
|
89
|
+
{
|
|
90
|
+
"status": "success",
|
|
91
|
+
"success_list": [{"image_name": ""}],
|
|
92
|
+
"error_list": [{}]
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Notes:
|
|
96
|
+
- Uses SeedEdit 3.0 model.
|
|
97
|
+
- Provide the same `seed` for consistent outputs across runs.
|
|
98
|
+
- A high `guidance_scale` enforces stricter adherence to text prompt.
|
|
99
|
+
"""
|
|
100
|
+
logger.debug(
|
|
101
|
+
f"Using model: {getenv('MODEL_EDIT_NAME', DEFAULT_IMAGE_EDIT_MODEL_NAME)}"
|
|
102
|
+
)
|
|
103
|
+
success_list = []
|
|
104
|
+
error_list = []
|
|
105
|
+
logger.debug(f"image_edit params: {params}")
|
|
106
|
+
for idx, item in enumerate(params):
|
|
107
|
+
logger.debug(f"image_edit item {idx}: {item}")
|
|
108
|
+
image_name = item.get("image_name", f"generated_image_{idx}")
|
|
109
|
+
prompt = item.get("prompt")
|
|
110
|
+
origin_image = item.get("origin_image")
|
|
111
|
+
response_format = item.get("response_format", "url")
|
|
112
|
+
guidance_scale = item.get("guidance_scale", 2.5)
|
|
113
|
+
watermark = item.get("watermark", True)
|
|
114
|
+
seed = item.get("seed", -1)
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
tracer = trace.get_tracer("gcp.vertex.agent")
|
|
118
|
+
with tracer.start_as_current_span("call_llm") as span:
|
|
119
|
+
inputs = {
|
|
120
|
+
"prompt": prompt,
|
|
121
|
+
"image": origin_image,
|
|
122
|
+
"response_format": response_format,
|
|
123
|
+
"guidance_scale": guidance_scale,
|
|
124
|
+
"watermark": watermark,
|
|
125
|
+
"seed": seed,
|
|
126
|
+
}
|
|
127
|
+
input_part = {
|
|
128
|
+
"role": "user",
|
|
129
|
+
"parts.0.type": "text",
|
|
130
|
+
"parts.0.text": json.dumps(inputs, ensure_ascii=False),
|
|
131
|
+
"parts.1.type": "image_url",
|
|
132
|
+
"parts.1.image_url.name": "origin_image",
|
|
133
|
+
"parts.1.image_url.url": origin_image,
|
|
134
|
+
}
|
|
135
|
+
response = client.images.generate(
|
|
136
|
+
model=getenv("MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME),
|
|
137
|
+
**inputs,
|
|
138
|
+
)
|
|
139
|
+
output_part = None
|
|
140
|
+
if response.data and len(response.data) > 0:
|
|
141
|
+
logger.debug(f"task {idx} Image edit response: {response}")
|
|
142
|
+
for item in response.data:
|
|
143
|
+
if response_format == "url":
|
|
144
|
+
image = item.url
|
|
145
|
+
tool_context.state[f"{image_name}_url"] = image
|
|
146
|
+
output_part = {
|
|
147
|
+
"message.role": "model",
|
|
148
|
+
"message.parts.0.type": "image_url",
|
|
149
|
+
"message.parts.0.image_url.name": image_name,
|
|
150
|
+
"message.parts.0.image_url.url": image,
|
|
151
|
+
}
|
|
152
|
+
elif response_format == "b64_json":
|
|
153
|
+
image = item.b64_json
|
|
154
|
+
image_bytes = base64.b64decode(image)
|
|
155
|
+
|
|
156
|
+
tos_url = _upload_image_to_tos(
|
|
157
|
+
image_bytes=image_bytes, object_key=f"{image_name}.png"
|
|
158
|
+
)
|
|
159
|
+
if tos_url:
|
|
160
|
+
tool_context.state[f"{image_name}_url"] = tos_url
|
|
161
|
+
image = tos_url
|
|
162
|
+
output_part = {
|
|
163
|
+
"message.role": "model",
|
|
164
|
+
"message.parts.0.type": "image_url",
|
|
165
|
+
"message.parts.0.image_url.name": image_name,
|
|
166
|
+
"message.parts.0.image_url.url": image,
|
|
167
|
+
}
|
|
168
|
+
else:
|
|
169
|
+
logger.error(
|
|
170
|
+
f"Upload image to TOS failed: {image_name}"
|
|
171
|
+
)
|
|
172
|
+
error_list.append(image_name)
|
|
173
|
+
continue
|
|
174
|
+
|
|
175
|
+
logger.debug(f"Image saved as ADK artifact: {image_name}")
|
|
176
|
+
logger.debug(
|
|
177
|
+
f"Image {image_name} generated successfully: {image}"
|
|
178
|
+
)
|
|
179
|
+
success_list.append({image_name: image})
|
|
180
|
+
else:
|
|
181
|
+
error_details = f"No images returned by Doubao model: {response}"
|
|
182
|
+
logger.error(error_details)
|
|
183
|
+
error_list.append(image_name)
|
|
184
|
+
|
|
185
|
+
add_span_attributes(
|
|
186
|
+
span,
|
|
187
|
+
tool_context,
|
|
188
|
+
input_part=input_part,
|
|
189
|
+
output_part=output_part,
|
|
190
|
+
output_tokens=response.usage.output_tokens,
|
|
191
|
+
total_tokens=response.usage.total_tokens,
|
|
192
|
+
request_model=getenv(
|
|
193
|
+
"MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME
|
|
194
|
+
),
|
|
195
|
+
response_model=getenv(
|
|
196
|
+
"MODEL_EDIT_NAME", DEFAULT_IMAGE_EDIT_MODEL_NAME
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
except Exception as e:
|
|
201
|
+
error_details = f"No images returned by Doubao model: {e}"
|
|
202
|
+
logger.error(error_details)
|
|
203
|
+
traceback.print_exc()
|
|
204
|
+
error_list.append(image_name)
|
|
205
|
+
|
|
206
|
+
if len(success_list) == 0:
|
|
207
|
+
logger.debug(
|
|
208
|
+
f"image_edit success_list: {success_list}\nerror_list: {error_list}"
|
|
209
|
+
)
|
|
210
|
+
return {
|
|
211
|
+
"status": "error",
|
|
212
|
+
"success_list": success_list,
|
|
213
|
+
"error_list": error_list,
|
|
214
|
+
}
|
|
215
|
+
else:
|
|
216
|
+
logger.debug(
|
|
217
|
+
f"image_edit success_list: {success_list}\nerror_list: {error_list}"
|
|
218
|
+
)
|
|
219
|
+
return {
|
|
220
|
+
"status": "success",
|
|
221
|
+
"success_list": success_list,
|
|
222
|
+
"error_list": error_list,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def add_span_attributes(
|
|
227
|
+
span: Span,
|
|
228
|
+
tool_context: ToolContext,
|
|
229
|
+
input_part: dict = None,
|
|
230
|
+
output_part: dict = None,
|
|
231
|
+
input_tokens: int = None,
|
|
232
|
+
output_tokens: int = None,
|
|
233
|
+
total_tokens: int = None,
|
|
234
|
+
request_model: str = None,
|
|
235
|
+
response_model: str = None,
|
|
236
|
+
):
|
|
237
|
+
try:
|
|
238
|
+
# common attributes
|
|
239
|
+
app_name = tool_context._invocation_context.app_name
|
|
240
|
+
user_id = tool_context._invocation_context.user_id
|
|
241
|
+
agent_name = tool_context.agent_name
|
|
242
|
+
session_id = tool_context._invocation_context.session.id
|
|
243
|
+
span.set_attribute("gen_ai.agent.name", agent_name)
|
|
244
|
+
span.set_attribute("openinference.instrumentation.veadk", VERSION)
|
|
245
|
+
span.set_attribute("gen_ai.app.name", app_name)
|
|
246
|
+
span.set_attribute("gen_ai.user.id", user_id)
|
|
247
|
+
span.set_attribute("gen_ai.session.id", session_id)
|
|
248
|
+
span.set_attribute("agent_name", agent_name)
|
|
249
|
+
span.set_attribute("agent.name", agent_name)
|
|
250
|
+
span.set_attribute("app_name", app_name)
|
|
251
|
+
span.set_attribute("app.name", app_name)
|
|
252
|
+
span.set_attribute("user.id", user_id)
|
|
253
|
+
span.set_attribute("session.id", session_id)
|
|
254
|
+
span.set_attribute("cozeloop.report.source", "veadk")
|
|
255
|
+
|
|
256
|
+
# llm attributes
|
|
257
|
+
span.set_attribute("gen_ai.system", "openai")
|
|
258
|
+
span.set_attribute("gen_ai.operation.name", "chat")
|
|
259
|
+
if request_model:
|
|
260
|
+
span.set_attribute("gen_ai.request.model", request_model)
|
|
261
|
+
if response_model:
|
|
262
|
+
span.set_attribute("gen_ai.response.model", response_model)
|
|
263
|
+
if total_tokens:
|
|
264
|
+
span.set_attribute("gen_ai.usage.total_tokens", total_tokens)
|
|
265
|
+
if output_tokens:
|
|
266
|
+
span.set_attribute("gen_ai.usage.output_tokens", output_tokens)
|
|
267
|
+
if input_tokens:
|
|
268
|
+
span.set_attribute("gen_ai.usage.input_tokens", input_tokens)
|
|
269
|
+
if input_part:
|
|
270
|
+
span.add_event("gen_ai.user.message", input_part)
|
|
271
|
+
if output_part:
|
|
272
|
+
span.add_event("gen_ai.choice", output_part)
|
|
273
|
+
|
|
274
|
+
except Exception:
|
|
275
|
+
traceback.print_exc()
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def _upload_image_to_tos(image_bytes: bytes, object_key: str) -> None:
|
|
279
|
+
try:
|
|
280
|
+
from veadk.integrations.ve_tos.ve_tos import VeTOS
|
|
281
|
+
import os
|
|
282
|
+
from datetime import datetime
|
|
283
|
+
|
|
284
|
+
timestamp: str = datetime.now().strftime("%Y%m%d%H%M%S%f")[:-3]
|
|
285
|
+
object_key = f"{timestamp}-{object_key}"
|
|
286
|
+
bucket_name = os.getenv("DATABASE_TOS_BUCKET")
|
|
287
|
+
ve_tos = VeTOS()
|
|
288
|
+
|
|
289
|
+
tos_url = ve_tos.build_tos_signed_url(
|
|
290
|
+
object_key=object_key, bucket_name=bucket_name
|
|
291
|
+
)
|
|
292
|
+
|
|
293
|
+
ve_tos.upload_bytes(
|
|
294
|
+
data=image_bytes, object_key=object_key, bucket_name=bucket_name
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
return tos_url
|
|
298
|
+
except Exception as e:
|
|
299
|
+
logger.error(f"Upload to TOS failed: {e}")
|
|
300
|
+
return None
|