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.
Files changed (218) hide show
  1. veadk/__init__.py +37 -0
  2. veadk/a2a/__init__.py +13 -0
  3. veadk/a2a/agent_card.py +45 -0
  4. veadk/a2a/remote_ve_agent.py +390 -0
  5. veadk/a2a/utils/__init__.py +13 -0
  6. veadk/a2a/utils/agent_to_a2a.py +170 -0
  7. veadk/a2a/ve_a2a_server.py +93 -0
  8. veadk/a2a/ve_agent_executor.py +78 -0
  9. veadk/a2a/ve_middlewares.py +313 -0
  10. veadk/a2a/ve_task_store.py +37 -0
  11. veadk/agent.py +402 -0
  12. veadk/agent_builder.py +93 -0
  13. veadk/agents/loop_agent.py +68 -0
  14. veadk/agents/parallel_agent.py +72 -0
  15. veadk/agents/sequential_agent.py +64 -0
  16. veadk/auth/__init__.py +13 -0
  17. veadk/auth/base_auth.py +22 -0
  18. veadk/auth/ve_credential_service.py +203 -0
  19. veadk/auth/veauth/__init__.py +13 -0
  20. veadk/auth/veauth/apmplus_veauth.py +58 -0
  21. veadk/auth/veauth/ark_veauth.py +75 -0
  22. veadk/auth/veauth/base_veauth.py +50 -0
  23. veadk/auth/veauth/cozeloop_veauth.py +13 -0
  24. veadk/auth/veauth/opensearch_veauth.py +75 -0
  25. veadk/auth/veauth/postgresql_veauth.py +75 -0
  26. veadk/auth/veauth/prompt_pilot_veauth.py +60 -0
  27. veadk/auth/veauth/speech_veauth.py +54 -0
  28. veadk/auth/veauth/utils.py +69 -0
  29. veadk/auth/veauth/vesearch_veauth.py +62 -0
  30. veadk/auth/veauth/viking_mem0_veauth.py +91 -0
  31. veadk/cli/__init__.py +13 -0
  32. veadk/cli/cli.py +58 -0
  33. veadk/cli/cli_clean.py +87 -0
  34. veadk/cli/cli_create.py +163 -0
  35. veadk/cli/cli_deploy.py +233 -0
  36. veadk/cli/cli_eval.py +215 -0
  37. veadk/cli/cli_init.py +214 -0
  38. veadk/cli/cli_kb.py +110 -0
  39. veadk/cli/cli_pipeline.py +285 -0
  40. veadk/cli/cli_prompt.py +86 -0
  41. veadk/cli/cli_update.py +106 -0
  42. veadk/cli/cli_uploadevalset.py +139 -0
  43. veadk/cli/cli_web.py +143 -0
  44. veadk/cloud/__init__.py +13 -0
  45. veadk/cloud/cloud_agent_engine.py +485 -0
  46. veadk/cloud/cloud_app.py +475 -0
  47. veadk/config.py +115 -0
  48. veadk/configs/__init__.py +13 -0
  49. veadk/configs/auth_configs.py +133 -0
  50. veadk/configs/database_configs.py +132 -0
  51. veadk/configs/model_configs.py +78 -0
  52. veadk/configs/tool_configs.py +54 -0
  53. veadk/configs/tracing_configs.py +110 -0
  54. veadk/consts.py +74 -0
  55. veadk/evaluation/__init__.py +17 -0
  56. veadk/evaluation/adk_evaluator/__init__.py +17 -0
  57. veadk/evaluation/adk_evaluator/adk_evaluator.py +302 -0
  58. veadk/evaluation/base_evaluator.py +642 -0
  59. veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
  60. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +339 -0
  61. veadk/evaluation/eval_set_file_loader.py +48 -0
  62. veadk/evaluation/eval_set_recorder.py +146 -0
  63. veadk/evaluation/types.py +65 -0
  64. veadk/evaluation/utils/prometheus.py +196 -0
  65. veadk/integrations/__init__.py +13 -0
  66. veadk/integrations/ve_apig/__init__.py +13 -0
  67. veadk/integrations/ve_apig/ve_apig.py +349 -0
  68. veadk/integrations/ve_apig/ve_apig_utils.py +332 -0
  69. veadk/integrations/ve_code_pipeline/__init__.py +13 -0
  70. veadk/integrations/ve_code_pipeline/ve_code_pipeline.py +431 -0
  71. veadk/integrations/ve_cozeloop/__init__.py +13 -0
  72. veadk/integrations/ve_cozeloop/ve_cozeloop.py +96 -0
  73. veadk/integrations/ve_cr/__init__.py +13 -0
  74. veadk/integrations/ve_cr/ve_cr.py +220 -0
  75. veadk/integrations/ve_faas/__init__.py +13 -0
  76. veadk/integrations/ve_faas/template/cookiecutter.json +15 -0
  77. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  78. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  79. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/config.yaml.example +6 -0
  80. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +106 -0
  81. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/__init__.py +13 -0
  82. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +25 -0
  83. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/app.py +202 -0
  84. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/requirements.txt +3 -0
  85. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +49 -0
  86. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/__init__.py +14 -0
  87. veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{ cookiecutter.app_name }}/agent.py +27 -0
  88. veadk/integrations/ve_faas/ve_faas.py +754 -0
  89. veadk/integrations/ve_faas/ve_faas_utils.py +408 -0
  90. veadk/integrations/ve_faas/web_template/cookiecutter.json +20 -0
  91. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/__init__.py +13 -0
  92. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/clean.py +23 -0
  93. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/config.yaml.example +2 -0
  94. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/deploy.py +44 -0
  95. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/Dockerfile +23 -0
  96. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/app.py +123 -0
  97. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/init_db.py +46 -0
  98. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/models.py +36 -0
  99. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/requirements.txt +4 -0
  100. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/run.sh +21 -0
  101. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/css/style.css +368 -0
  102. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/static/js/admin.js +0 -0
  103. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/dashboard.html +21 -0
  104. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/edit_post.html +24 -0
  105. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/login.html +21 -0
  106. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/admin/posts.html +53 -0
  107. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/base.html +45 -0
  108. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/index.html +29 -0
  109. veadk/integrations/ve_faas/web_template/{{cookiecutter.local_dir_name}}/src/templates/post.html +14 -0
  110. veadk/integrations/ve_identity/__init__.py +110 -0
  111. veadk/integrations/ve_identity/auth_config.py +261 -0
  112. veadk/integrations/ve_identity/auth_mixins.py +650 -0
  113. veadk/integrations/ve_identity/auth_processor.py +385 -0
  114. veadk/integrations/ve_identity/function_tool.py +158 -0
  115. veadk/integrations/ve_identity/identity_client.py +864 -0
  116. veadk/integrations/ve_identity/mcp_tool.py +181 -0
  117. veadk/integrations/ve_identity/mcp_toolset.py +431 -0
  118. veadk/integrations/ve_identity/models.py +228 -0
  119. veadk/integrations/ve_identity/token_manager.py +188 -0
  120. veadk/integrations/ve_identity/utils.py +151 -0
  121. veadk/integrations/ve_prompt_pilot/__init__.py +13 -0
  122. veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +85 -0
  123. veadk/integrations/ve_tls/__init__.py +13 -0
  124. veadk/integrations/ve_tls/utils.py +116 -0
  125. veadk/integrations/ve_tls/ve_tls.py +212 -0
  126. veadk/integrations/ve_tos/ve_tos.py +710 -0
  127. veadk/integrations/ve_viking_db_memory/__init__.py +13 -0
  128. veadk/integrations/ve_viking_db_memory/ve_viking_db_memory.py +308 -0
  129. veadk/knowledgebase/__init__.py +17 -0
  130. veadk/knowledgebase/backends/__init__.py +13 -0
  131. veadk/knowledgebase/backends/base_backend.py +72 -0
  132. veadk/knowledgebase/backends/in_memory_backend.py +91 -0
  133. veadk/knowledgebase/backends/opensearch_backend.py +162 -0
  134. veadk/knowledgebase/backends/redis_backend.py +172 -0
  135. veadk/knowledgebase/backends/utils.py +92 -0
  136. veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +608 -0
  137. veadk/knowledgebase/entry.py +25 -0
  138. veadk/knowledgebase/knowledgebase.py +307 -0
  139. veadk/memory/__init__.py +35 -0
  140. veadk/memory/long_term_memory.py +365 -0
  141. veadk/memory/long_term_memory_backends/__init__.py +13 -0
  142. veadk/memory/long_term_memory_backends/base_backend.py +35 -0
  143. veadk/memory/long_term_memory_backends/in_memory_backend.py +67 -0
  144. veadk/memory/long_term_memory_backends/mem0_backend.py +155 -0
  145. veadk/memory/long_term_memory_backends/opensearch_backend.py +124 -0
  146. veadk/memory/long_term_memory_backends/redis_backend.py +140 -0
  147. veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +189 -0
  148. veadk/memory/short_term_memory.py +252 -0
  149. veadk/memory/short_term_memory_backends/__init__.py +13 -0
  150. veadk/memory/short_term_memory_backends/base_backend.py +31 -0
  151. veadk/memory/short_term_memory_backends/mysql_backend.py +49 -0
  152. veadk/memory/short_term_memory_backends/postgresql_backend.py +49 -0
  153. veadk/memory/short_term_memory_backends/sqlite_backend.py +55 -0
  154. veadk/memory/short_term_memory_processor.py +100 -0
  155. veadk/processors/__init__.py +26 -0
  156. veadk/processors/base_run_processor.py +120 -0
  157. veadk/prompts/__init__.py +13 -0
  158. veadk/prompts/agent_default_prompt.py +30 -0
  159. veadk/prompts/prompt_evaluator.py +20 -0
  160. veadk/prompts/prompt_memory_processor.py +55 -0
  161. veadk/prompts/prompt_optimization.py +150 -0
  162. veadk/runner.py +732 -0
  163. veadk/tools/__init__.py +13 -0
  164. veadk/tools/builtin_tools/__init__.py +13 -0
  165. veadk/tools/builtin_tools/agent_authorization.py +94 -0
  166. veadk/tools/builtin_tools/generate_image.py +23 -0
  167. veadk/tools/builtin_tools/image_edit.py +300 -0
  168. veadk/tools/builtin_tools/image_generate.py +446 -0
  169. veadk/tools/builtin_tools/lark.py +67 -0
  170. veadk/tools/builtin_tools/las.py +24 -0
  171. veadk/tools/builtin_tools/link_reader.py +66 -0
  172. veadk/tools/builtin_tools/llm_shield.py +381 -0
  173. veadk/tools/builtin_tools/load_knowledgebase.py +97 -0
  174. veadk/tools/builtin_tools/mcp_router.py +29 -0
  175. veadk/tools/builtin_tools/run_code.py +113 -0
  176. veadk/tools/builtin_tools/tts.py +253 -0
  177. veadk/tools/builtin_tools/vesearch.py +49 -0
  178. veadk/tools/builtin_tools/video_generate.py +363 -0
  179. veadk/tools/builtin_tools/web_scraper.py +76 -0
  180. veadk/tools/builtin_tools/web_search.py +83 -0
  181. veadk/tools/demo_tools.py +58 -0
  182. veadk/tools/load_knowledgebase_tool.py +149 -0
  183. veadk/tools/sandbox/__init__.py +13 -0
  184. veadk/tools/sandbox/browser_sandbox.py +37 -0
  185. veadk/tools/sandbox/code_sandbox.py +40 -0
  186. veadk/tools/sandbox/computer_sandbox.py +34 -0
  187. veadk/tracing/__init__.py +13 -0
  188. veadk/tracing/base_tracer.py +58 -0
  189. veadk/tracing/telemetry/__init__.py +13 -0
  190. veadk/tracing/telemetry/attributes/attributes.py +29 -0
  191. veadk/tracing/telemetry/attributes/extractors/common_attributes_extractors.py +180 -0
  192. veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +858 -0
  193. veadk/tracing/telemetry/attributes/extractors/tool_attributes_extractors.py +152 -0
  194. veadk/tracing/telemetry/attributes/extractors/types.py +164 -0
  195. veadk/tracing/telemetry/exporters/__init__.py +13 -0
  196. veadk/tracing/telemetry/exporters/apmplus_exporter.py +558 -0
  197. veadk/tracing/telemetry/exporters/base_exporter.py +39 -0
  198. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +129 -0
  199. veadk/tracing/telemetry/exporters/inmemory_exporter.py +248 -0
  200. veadk/tracing/telemetry/exporters/tls_exporter.py +139 -0
  201. veadk/tracing/telemetry/opentelemetry_tracer.py +320 -0
  202. veadk/tracing/telemetry/telemetry.py +411 -0
  203. veadk/types.py +47 -0
  204. veadk/utils/__init__.py +13 -0
  205. veadk/utils/audio_manager.py +95 -0
  206. veadk/utils/auth.py +294 -0
  207. veadk/utils/logger.py +59 -0
  208. veadk/utils/mcp_utils.py +44 -0
  209. veadk/utils/misc.py +184 -0
  210. veadk/utils/patches.py +101 -0
  211. veadk/utils/volcengine_sign.py +205 -0
  212. veadk/version.py +15 -0
  213. veadk_python-0.2.27.dist-info/METADATA +373 -0
  214. veadk_python-0.2.27.dist-info/RECORD +218 -0
  215. veadk_python-0.2.27.dist-info/WHEEL +5 -0
  216. veadk_python-0.2.27.dist-info/entry_points.txt +2 -0
  217. veadk_python-0.2.27.dist-info/licenses/LICENSE +201 -0
  218. veadk_python-0.2.27.dist-info/top_level.txt +1 -0
@@ -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