veadk-python 0.2.6__py3-none-any.whl → 0.2.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of veadk-python might be problematic. Click here for more details.
- veadk/agent.py +11 -18
- veadk/agent_builder.py +94 -0
- veadk/{database/__init__.py → auth/base_auth.py} +7 -2
- veadk/auth/veauth/apmplus_veauth.py +65 -0
- veadk/auth/veauth/ark_veauth.py +77 -0
- veadk/auth/veauth/base_veauth.py +50 -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/vesearch_veauth.py +62 -0
- veadk/cli/cli.py +4 -0
- veadk/cli/cli_deploy.py +3 -2
- veadk/cli/cli_eval.py +160 -0
- veadk/cli/cli_init.py +1 -1
- veadk/cli/cli_pipeline.py +220 -0
- veadk/cli/cli_prompt.py +4 -4
- veadk/cli/cli_web.py +3 -1
- veadk/config.py +45 -81
- veadk/configs/database_configs.py +117 -0
- veadk/configs/model_configs.py +74 -0
- veadk/configs/tool_configs.py +42 -0
- veadk/configs/tracing_configs.py +110 -0
- veadk/consts.py +13 -1
- veadk/evaluation/base_evaluator.py +60 -44
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +18 -12
- veadk/evaluation/eval_set_recorder.py +2 -2
- 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/ve_cr.py +20 -5
- veadk/integrations/ve_faas/template/cookiecutter.json +1 -1
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/deploy.py +2 -2
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/agent.py +1 -1
- veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/run.sh +1 -5
- veadk/integrations/ve_faas/ve_faas.py +351 -36
- veadk/integrations/ve_prompt_pilot/ve_prompt_pilot.py +6 -3
- veadk/integrations/ve_tls/__init__.py +13 -0
- veadk/integrations/ve_tls/utils.py +117 -0
- veadk/integrations/ve_tls/ve_tls.py +208 -0
- veadk/integrations/ve_tos/ve_tos.py +71 -75
- veadk/knowledgebase/backends/__init__.py +13 -0
- veadk/knowledgebase/backends/base_backend.py +59 -0
- veadk/knowledgebase/backends/in_memory_backend.py +82 -0
- veadk/knowledgebase/backends/opensearch_backend.py +136 -0
- veadk/knowledgebase/backends/redis_backend.py +144 -0
- veadk/knowledgebase/backends/utils.py +91 -0
- veadk/knowledgebase/backends/vikingdb_knowledge_backend.py +412 -0
- veadk/knowledgebase/knowledgebase.py +109 -55
- veadk/memory/__init__.py +22 -0
- veadk/memory/long_term_memory.py +120 -51
- veadk/memory/long_term_memory_backends/__init__.py +13 -0
- veadk/{database/base_database.py → memory/long_term_memory_backends/base_backend.py} +10 -22
- veadk/memory/long_term_memory_backends/in_memory_backend.py +65 -0
- veadk/memory/long_term_memory_backends/opensearch_backend.py +120 -0
- veadk/memory/long_term_memory_backends/redis_backend.py +127 -0
- veadk/memory/long_term_memory_backends/vikingdb_memory_backend.py +148 -0
- veadk/memory/short_term_memory.py +80 -72
- 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 +41 -0
- veadk/memory/short_term_memory_backends/postgresql_backend.py +41 -0
- veadk/memory/short_term_memory_backends/sqlite_backend.py +48 -0
- veadk/memory/short_term_memory_processor.py +9 -4
- veadk/runner.py +204 -247
- veadk/tools/builtin_tools/vesearch.py +2 -2
- veadk/tools/builtin_tools/video_generate.py +27 -20
- veadk/tools/builtin_tools/web_scraper.py +1 -1
- veadk/tools/builtin_tools/web_search.py +7 -7
- veadk/tools/load_knowledgebase_tool.py +1 -1
- veadk/tracing/telemetry/attributes/extractors/llm_attributes_extractors.py +20 -2
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +178 -14
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +6 -9
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +22 -8
- veadk/tracing/telemetry/exporters/tls_exporter.py +6 -10
- veadk/tracing/telemetry/opentelemetry_tracer.py +5 -8
- veadk/tracing/telemetry/telemetry.py +66 -60
- veadk/utils/logger.py +1 -1
- veadk/utils/misc.py +63 -0
- veadk/utils/volcengine_sign.py +6 -2
- veadk/version.py +1 -1
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/METADATA +16 -3
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/RECORD +93 -64
- veadk/database/database_adapter.py +0 -368
- veadk/database/database_factory.py +0 -80
- veadk/database/kv/redis_database.py +0 -159
- veadk/database/local_database.py +0 -61
- veadk/database/relational/mysql_database.py +0 -173
- veadk/database/vector/opensearch_vector_database.py +0 -263
- veadk/database/vector/type.py +0 -50
- veadk/database/viking/viking_database.py +0 -471
- veadk/database/viking/viking_memory_db.py +0 -525
- /veadk/{database/kv → auth}/__init__.py +0 -0
- /veadk/{database/relational → auth/veauth}/__init__.py +0 -0
- /veadk/{database/vector/__init__.py → auth/veauth/cozeloop_veauth.py} +0 -0
- /veadk/{database/viking → configs}/__init__.py +0 -0
- /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/__init__.py +0 -0
- /veadk/integrations/ve_faas/template/{{cookiecutter.local_dir_name}}/src/{{{ cookiecutter.app_name|replace('-', '_') }} → {{ cookiecutter.app_name }}}/agent.py +0 -0
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/WHEEL +0 -0
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/entry_points.txt +0 -0
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/licenses/LICENSE +0 -0
- {veadk_python-0.2.6.dist-info → veadk_python-0.2.8.dist-info}/top_level.txt +0 -0
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import json
|
|
16
|
+
import os
|
|
16
17
|
import time
|
|
17
18
|
|
|
18
19
|
import requests
|
|
19
|
-
import typer
|
|
20
20
|
import volcenginesdkcore
|
|
21
21
|
import volcenginesdkvefaas
|
|
22
22
|
from volcenginesdkvefaas.models.env_for_create_function_input import (
|
|
@@ -118,6 +118,7 @@ class VeFaaS:
|
|
|
118
118
|
runtime="native-python3.10/v1",
|
|
119
119
|
request_timeout=1800,
|
|
120
120
|
envs=envs,
|
|
121
|
+
memory_mb=2048,
|
|
121
122
|
)
|
|
122
123
|
)
|
|
123
124
|
|
|
@@ -141,6 +142,8 @@ class VeFaaS:
|
|
|
141
142
|
upstream_name: str,
|
|
142
143
|
service_name: str,
|
|
143
144
|
):
|
|
145
|
+
enable_key_auth = os.getenv("VEFAAS_ENABLE_KEY_AUTH", "true").lower() == "true"
|
|
146
|
+
|
|
144
147
|
response = ve_request(
|
|
145
148
|
request_body={
|
|
146
149
|
"Name": application_name,
|
|
@@ -152,7 +155,7 @@ class VeFaaS:
|
|
|
152
155
|
"GatewayName": gateway_name,
|
|
153
156
|
"ServiceName": service_name,
|
|
154
157
|
"UpstreamName": upstream_name,
|
|
155
|
-
"EnableKeyAuth":
|
|
158
|
+
"EnableKeyAuth": enable_key_auth,
|
|
156
159
|
"EnableMcpSession": True,
|
|
157
160
|
},
|
|
158
161
|
"TemplateId": self.template_id,
|
|
@@ -191,16 +194,27 @@ class VeFaaS:
|
|
|
191
194
|
time.sleep(10)
|
|
192
195
|
status, full_response = self._get_application_status(app_id)
|
|
193
196
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
197
|
+
if status == "deploy_success":
|
|
198
|
+
cloud_resource = full_response["Result"]["CloudResource"]
|
|
199
|
+
cloud_resource = json.loads(cloud_resource)
|
|
200
|
+
url = cloud_resource["framework"]["url"]["system_url"]
|
|
201
|
+
return url
|
|
202
|
+
else:
|
|
203
|
+
logger.error(
|
|
204
|
+
f"Release application failed. Application ID: {app_id}, Status: {status}"
|
|
205
|
+
)
|
|
206
|
+
import re
|
|
207
|
+
|
|
208
|
+
logs = "\n".join(self._get_application_logs(app_id=app_id))
|
|
209
|
+
log_text = re.sub(
|
|
210
|
+
r'([{"\']?(key|secret|token|pass|auth|credential|access|api|ak|sk|doubao|volces|coze)[^"\'\s]*["\']?\s*[:=]\s*)(["\']?)([^"\'\s]+)(["\']?)|([A-Za-z0-9+/=]{20,})',
|
|
211
|
+
lambda m: f"{m.group(1)}{m.group(3)}******{m.group(5)}"
|
|
212
|
+
if m.group(1)
|
|
213
|
+
else "******",
|
|
214
|
+
logs,
|
|
215
|
+
flags=re.IGNORECASE,
|
|
216
|
+
)
|
|
217
|
+
raise Exception(f"Release application failed. Logs:\n{log_text}")
|
|
204
218
|
|
|
205
219
|
def _get_application_status(self, app_id: str):
|
|
206
220
|
response = ve_request(
|
|
@@ -215,18 +229,51 @@ class VeFaaS:
|
|
|
215
229
|
)
|
|
216
230
|
return response["Result"]["Status"], response
|
|
217
231
|
|
|
218
|
-
def _list_application(self):
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
)
|
|
229
|
-
|
|
232
|
+
def _list_application(self, app_id: str = None, app_name: str = None):
|
|
233
|
+
# firt match app_id. if app_id is None,then match app_name and remove app_id
|
|
234
|
+
request_body = {
|
|
235
|
+
"OrderBy": {"Key": "CreateTime", "Ascend": False},
|
|
236
|
+
"FunctionId": app_id if app_id else None,
|
|
237
|
+
"Filters": [{"Item": {"Key": "Name", "Value": [app_name]}}]
|
|
238
|
+
if app_name and not app_id
|
|
239
|
+
else None,
|
|
240
|
+
}
|
|
241
|
+
# remove None
|
|
242
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
|
243
|
+
|
|
244
|
+
page_size = 50
|
|
245
|
+
page_number = 1
|
|
246
|
+
all_items = []
|
|
247
|
+
total_page = None
|
|
248
|
+
while True:
|
|
249
|
+
try:
|
|
250
|
+
request_body.update({"PageNumber": page_number, "PageSize": page_size})
|
|
251
|
+
response = ve_request(
|
|
252
|
+
request_body=request_body,
|
|
253
|
+
action="ListApplications",
|
|
254
|
+
ak=self.ak,
|
|
255
|
+
sk=self.sk,
|
|
256
|
+
service="vefaas",
|
|
257
|
+
version="2021-03-03",
|
|
258
|
+
region="cn-beijing",
|
|
259
|
+
host="open.volcengineapi.com",
|
|
260
|
+
)
|
|
261
|
+
result = response.get("Result", {})
|
|
262
|
+
items = result.get("Items", [])
|
|
263
|
+
all_items.extend(items)
|
|
264
|
+
|
|
265
|
+
if total_page is None:
|
|
266
|
+
total = result.get("Total", 0)
|
|
267
|
+
total_page = (total + page_size - 1) // page_size
|
|
268
|
+
|
|
269
|
+
if page_number >= total_page or not items:
|
|
270
|
+
break
|
|
271
|
+
page_number += 1
|
|
272
|
+
except Exception as e:
|
|
273
|
+
raise ValueError(
|
|
274
|
+
f"List application failed. Error: {str(e)}. Response: {response}."
|
|
275
|
+
)
|
|
276
|
+
return all_items
|
|
230
277
|
|
|
231
278
|
def _update_function_code(
|
|
232
279
|
self,
|
|
@@ -255,10 +302,6 @@ class VeFaaS:
|
|
|
255
302
|
|
|
256
303
|
# Get application status and extract function info
|
|
257
304
|
status, full_response = self._get_application_status(app_id)
|
|
258
|
-
if status == "deploy_fail":
|
|
259
|
-
raise ValueError(
|
|
260
|
-
f"Cannot update failed application. Current status: {status}"
|
|
261
|
-
)
|
|
262
305
|
|
|
263
306
|
# Extract function name from application config
|
|
264
307
|
cloud_resource = full_response["Result"]["CloudResource"]
|
|
@@ -302,7 +345,7 @@ class VeFaaS:
|
|
|
302
345
|
def get_application_details(self, app_id: str = None, app_name: str = None):
|
|
303
346
|
if not app_id and not app_name:
|
|
304
347
|
raise ValueError("app_id and app_name cannot be both empty.")
|
|
305
|
-
apps = self._list_application()
|
|
348
|
+
apps = self._list_application(app_id=app_id, app_name=app_name)
|
|
306
349
|
if app_id:
|
|
307
350
|
for app in apps:
|
|
308
351
|
if app["Id"] == app_id:
|
|
@@ -314,7 +357,7 @@ class VeFaaS:
|
|
|
314
357
|
return app
|
|
315
358
|
|
|
316
359
|
def find_app_id_by_name(self, name: str):
|
|
317
|
-
apps = self._list_application()
|
|
360
|
+
apps = self._list_application(app_name=name)
|
|
318
361
|
for app in apps:
|
|
319
362
|
if app["Name"] == name:
|
|
320
363
|
return app["Id"]
|
|
@@ -334,12 +377,7 @@ class VeFaaS:
|
|
|
334
377
|
host="open.volcengineapi.com",
|
|
335
378
|
)
|
|
336
379
|
except Exception as e:
|
|
337
|
-
|
|
338
|
-
typer.style(
|
|
339
|
-
f"Delete application failed. Response: {e}",
|
|
340
|
-
fg=typer.colors.BRIGHT_RED,
|
|
341
|
-
)
|
|
342
|
-
)
|
|
380
|
+
logger.error(f"Delete application failed. Response: {e}")
|
|
343
381
|
|
|
344
382
|
def deploy(
|
|
345
383
|
self,
|
|
@@ -411,3 +449,280 @@ class VeFaaS:
|
|
|
411
449
|
logger.info(f"VeFaaS application {name} with ID {app_id} deployed on {url}.")
|
|
412
450
|
|
|
413
451
|
return url, app_id, function_id
|
|
452
|
+
|
|
453
|
+
def _create_image_function(self, function_name: str, image: str):
|
|
454
|
+
"""Create function using container image instead of code upload."""
|
|
455
|
+
# Read environment variables from veadk configuration
|
|
456
|
+
envs = []
|
|
457
|
+
for key, value in veadk.config.veadk_environments.items():
|
|
458
|
+
envs.append(EnvForCreateFunctionInput(key=key, value=value))
|
|
459
|
+
logger.info(
|
|
460
|
+
f"Fetch {len(envs)} environment variables for image function.",
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
# Create function with container image source configuration
|
|
464
|
+
res = self.client.create_function(
|
|
465
|
+
volcenginesdkvefaas.CreateFunctionRequest(
|
|
466
|
+
command="bash ./run.sh", # Custom startup command
|
|
467
|
+
name=function_name,
|
|
468
|
+
description="Created by VeADK (Volcengine Agent Development Kit)",
|
|
469
|
+
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
|
|
470
|
+
runtime="native/v1", # Native runtime required for container images
|
|
471
|
+
source_type="image", # Set source type to container image
|
|
472
|
+
source=image, # Container image URL
|
|
473
|
+
request_timeout=1800, # Request timeout in seconds
|
|
474
|
+
envs=envs, # Environment variables from configuration
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
|
|
478
|
+
# Log function creation success without exposing sensitive information
|
|
479
|
+
logger.debug(
|
|
480
|
+
f"Function creation in {res.project_name} project with ID {res.id}"
|
|
481
|
+
)
|
|
482
|
+
|
|
483
|
+
function_id = res.id
|
|
484
|
+
logger.info(
|
|
485
|
+
f"Function {function_name} created with image {image} and ID {function_id}"
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
return function_name, function_id
|
|
489
|
+
|
|
490
|
+
def query_user_cr_vpc_tunnel(
|
|
491
|
+
self, registry_name: str, max_attempts: int = 6
|
|
492
|
+
) -> bool:
|
|
493
|
+
"""Query and enable CR VPC tunnel for user registry access."""
|
|
494
|
+
logger.info(f"Setting up CR VPC tunnel for registry: {registry_name}")
|
|
495
|
+
waiting_times = 30
|
|
496
|
+
|
|
497
|
+
try:
|
|
498
|
+
for attempt in range(max_attempts):
|
|
499
|
+
# Check current status
|
|
500
|
+
logger.info(
|
|
501
|
+
f"Checking tunnel status (attempt {attempt + 1}/{max_attempts})"
|
|
502
|
+
)
|
|
503
|
+
query_resp = ve_request(
|
|
504
|
+
request_body={"Registry": registry_name},
|
|
505
|
+
action="QueryUserCrVpcTunnel",
|
|
506
|
+
ak=self.ak,
|
|
507
|
+
sk=self.sk,
|
|
508
|
+
service="vefaas",
|
|
509
|
+
version="2021-03-03",
|
|
510
|
+
region="cn-beijing",
|
|
511
|
+
host="open.volcengineapi.com",
|
|
512
|
+
)
|
|
513
|
+
|
|
514
|
+
current_status = query_resp.get("Result", {}).get("Ready", False)
|
|
515
|
+
logger.info(f"Current tunnel status: {current_status}")
|
|
516
|
+
|
|
517
|
+
# Always try to enable
|
|
518
|
+
logger.info("Enable VPC tunnel")
|
|
519
|
+
enable_resp = ve_request(
|
|
520
|
+
request_body={"Registry": registry_name},
|
|
521
|
+
action="EnableUserCrVpcTunnel",
|
|
522
|
+
ak=self.ak,
|
|
523
|
+
sk=self.sk,
|
|
524
|
+
service="vefaas",
|
|
525
|
+
version="2021-03-03",
|
|
526
|
+
region="cn-beijing",
|
|
527
|
+
host="open.volcengineapi.com",
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
# Handle EnableUserCrVpcTunnel response correctly
|
|
531
|
+
enable_result = enable_resp.get("Result", {})
|
|
532
|
+
enable_status = enable_result.get("Status", "")
|
|
533
|
+
enable_message = enable_result.get("Message", "")
|
|
534
|
+
|
|
535
|
+
if enable_status == "success":
|
|
536
|
+
logger.info("Enable tunnel succeeded")
|
|
537
|
+
elif enable_status == "failed":
|
|
538
|
+
logger.warning(f"Enable tunnel failed: {enable_message}")
|
|
539
|
+
else:
|
|
540
|
+
logger.warning(f"Enable tunnel unknown status: {enable_status}")
|
|
541
|
+
|
|
542
|
+
# Verify final status
|
|
543
|
+
logger.info("Verifying tunnel status")
|
|
544
|
+
verify_resp = ve_request(
|
|
545
|
+
request_body={"Registry": registry_name},
|
|
546
|
+
action="QueryUserCrVpcTunnel",
|
|
547
|
+
ak=self.ak,
|
|
548
|
+
sk=self.sk,
|
|
549
|
+
service="vefaas",
|
|
550
|
+
version="2021-03-03",
|
|
551
|
+
region="cn-beijing",
|
|
552
|
+
host="open.volcengineapi.com",
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
final_status = verify_resp.get("Result", {}).get("Ready", False)
|
|
556
|
+
logger.info(f"Final tunnel status: {final_status}")
|
|
557
|
+
|
|
558
|
+
if final_status:
|
|
559
|
+
logger.info(
|
|
560
|
+
f"CR VPC tunnel successfully enabled for {registry_name}"
|
|
561
|
+
)
|
|
562
|
+
return True
|
|
563
|
+
|
|
564
|
+
# If not ready and not last attempt, wait and retry
|
|
565
|
+
if attempt < max_attempts - 1:
|
|
566
|
+
logger.warning(
|
|
567
|
+
f"Tunnel not ready, waiting {waiting_times}s before retry"
|
|
568
|
+
)
|
|
569
|
+
time.sleep(waiting_times)
|
|
570
|
+
|
|
571
|
+
except Exception as e:
|
|
572
|
+
raise ValueError(f"Failed to setup CR VPC tunnel: {str(e)}")
|
|
573
|
+
|
|
574
|
+
return False
|
|
575
|
+
|
|
576
|
+
def _create_image_function(self, function_name: str, image: str):
|
|
577
|
+
"""Create function using container image instead of code upload."""
|
|
578
|
+
# Read environment variables from veadk configuration
|
|
579
|
+
envs = []
|
|
580
|
+
for key, value in veadk.config.veadk_environments.items():
|
|
581
|
+
envs.append(EnvForCreateFunctionInput(key=key, value=value))
|
|
582
|
+
logger.info(
|
|
583
|
+
f"Fetch {len(envs)} environment variables for image function.",
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
# Create function with container image source configuration
|
|
587
|
+
res = self.client.create_function(
|
|
588
|
+
volcenginesdkvefaas.CreateFunctionRequest(
|
|
589
|
+
command="bash ./run.sh", # Custom startup command
|
|
590
|
+
name=function_name,
|
|
591
|
+
description="Created by VeADK (Volcengine Agent Development Kit)",
|
|
592
|
+
tags=[TagForCreateFunctionInput(key="provider", value="veadk")],
|
|
593
|
+
runtime="native/v1", # Native runtime required for container images
|
|
594
|
+
source_type="image", # Set source type to container image
|
|
595
|
+
source=image, # Container image URL
|
|
596
|
+
request_timeout=1800, # Request timeout in seconds
|
|
597
|
+
envs=envs, # Environment variables from configuration
|
|
598
|
+
)
|
|
599
|
+
)
|
|
600
|
+
|
|
601
|
+
# Log function creation success without exposing sensitive information
|
|
602
|
+
logger.debug(
|
|
603
|
+
f"Function creation in {res.project_name} project with ID {res.id}"
|
|
604
|
+
)
|
|
605
|
+
|
|
606
|
+
function_id = res.id
|
|
607
|
+
logger.info(
|
|
608
|
+
f"Function {function_name} created with image {image} and ID {function_id}"
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
return function_name, function_id
|
|
612
|
+
|
|
613
|
+
def deploy_image(
|
|
614
|
+
self,
|
|
615
|
+
name: str,
|
|
616
|
+
image: str,
|
|
617
|
+
registry_name: str,
|
|
618
|
+
gateway_name: str = "",
|
|
619
|
+
gateway_service_name: str = "",
|
|
620
|
+
gateway_upstream_name: str = "",
|
|
621
|
+
) -> tuple[str, str, str]:
|
|
622
|
+
"""Deploy application using container image.
|
|
623
|
+
|
|
624
|
+
Args:
|
|
625
|
+
name (str): Application name.
|
|
626
|
+
image (str): Container image URL.
|
|
627
|
+
gateway_name (str, optional): Gateway name. Defaults to "".
|
|
628
|
+
gateway_service_name (str, optional): Gateway service name. Defaults to "".
|
|
629
|
+
gateway_upstream_name (str, optional): Gateway upstream name. Defaults to "".
|
|
630
|
+
|
|
631
|
+
Returns:
|
|
632
|
+
tuple[str, str, str]: (url, app_id, function_id)
|
|
633
|
+
"""
|
|
634
|
+
# Validate application name format
|
|
635
|
+
is_ready = self.query_user_cr_vpc_tunnel(registry_name)
|
|
636
|
+
if not is_ready:
|
|
637
|
+
raise ValueError("CR VPC tunnel is not ready")
|
|
638
|
+
|
|
639
|
+
if "_" in name:
|
|
640
|
+
raise ValueError("Function or Application name cannot contain '_'.")
|
|
641
|
+
|
|
642
|
+
# Generate default gateway names with timestamp if not provided
|
|
643
|
+
if not gateway_name:
|
|
644
|
+
gateway_name = f"{name}-gw-{formatted_timestamp()}"
|
|
645
|
+
|
|
646
|
+
# Check for existing serverless gateways to reuse
|
|
647
|
+
existing_gateways = self.apig_client.list_gateways()
|
|
648
|
+
for gateway_instance in existing_gateways.items:
|
|
649
|
+
if (
|
|
650
|
+
gateway_instance.type == "serverless"
|
|
651
|
+
and gateway_instance.name != gateway_name
|
|
652
|
+
):
|
|
653
|
+
logger.warning(
|
|
654
|
+
f"You have at least one serverless gateway {gateway_instance.name}, but not {gateway_name}. Using {gateway_instance.name} instead."
|
|
655
|
+
)
|
|
656
|
+
gateway_name = gateway_instance.name
|
|
657
|
+
break
|
|
658
|
+
|
|
659
|
+
# Set default gateway service and upstream names
|
|
660
|
+
if not gateway_service_name:
|
|
661
|
+
gateway_service_name = f"{name}-gw-svr-{formatted_timestamp()}"
|
|
662
|
+
if not gateway_upstream_name:
|
|
663
|
+
gateway_upstream_name = f"{name}-gw-us-{formatted_timestamp()}"
|
|
664
|
+
|
|
665
|
+
function_name = f"{name}-fn"
|
|
666
|
+
|
|
667
|
+
# Log deployment start with image information
|
|
668
|
+
logger.info(
|
|
669
|
+
f"Start to create VeFaaS function {function_name} with image {image}. Gateway: {gateway_name}, Gateway Service: {gateway_service_name}, Gateway Upstream: {gateway_upstream_name}."
|
|
670
|
+
)
|
|
671
|
+
|
|
672
|
+
# Create function using container image method
|
|
673
|
+
function_name, function_id = self._create_image_function(function_name, image)
|
|
674
|
+
logger.info(f"VeFaaS function {function_name} with ID {function_id} created.")
|
|
675
|
+
|
|
676
|
+
# Create application using existing application creation logic
|
|
677
|
+
logger.info(f"Start to create VeFaaS application {name}.")
|
|
678
|
+
app_id = self._create_application(
|
|
679
|
+
name,
|
|
680
|
+
function_name,
|
|
681
|
+
gateway_name,
|
|
682
|
+
gateway_upstream_name,
|
|
683
|
+
gateway_service_name,
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
# Release application and get deployment URL
|
|
687
|
+
logger.info(f"VeFaaS application {name} with ID {app_id} created.")
|
|
688
|
+
logger.info(f"Start to release VeFaaS application {app_id}.")
|
|
689
|
+
# Release application with retry
|
|
690
|
+
max_attempts = 5
|
|
691
|
+
attempt = 0
|
|
692
|
+
while True:
|
|
693
|
+
try:
|
|
694
|
+
url = self._release_application(app_id)
|
|
695
|
+
logger.info(f"VeFaaS application {name} with ID {app_id} released.")
|
|
696
|
+
break
|
|
697
|
+
except Exception:
|
|
698
|
+
attempt += 1
|
|
699
|
+
if attempt < max_attempts:
|
|
700
|
+
wait_time = 30 * attempt
|
|
701
|
+
logger.info(
|
|
702
|
+
f"Image sync still in progress. Waiting {wait_time} seconds before retry {attempt}/{max_attempts}."
|
|
703
|
+
)
|
|
704
|
+
time.sleep(wait_time)
|
|
705
|
+
else:
|
|
706
|
+
raise
|
|
707
|
+
|
|
708
|
+
logger.info(f"VeFaaS application {name} with ID {app_id} deployed on {url}.")
|
|
709
|
+
|
|
710
|
+
return url, app_id, function_id
|
|
711
|
+
|
|
712
|
+
def _get_application_logs(self, app_id: str) -> list[str]:
|
|
713
|
+
response = _ = ve_request(
|
|
714
|
+
request_body={"Id": app_id, "Limit": 99999, "RevisionNumber": 1},
|
|
715
|
+
action="GetApplicationRevisionLog",
|
|
716
|
+
ak=self.ak,
|
|
717
|
+
sk=self.sk,
|
|
718
|
+
service="vefaas",
|
|
719
|
+
version="2021-03-03",
|
|
720
|
+
region="cn-beijing",
|
|
721
|
+
host="open.volcengineapi.com",
|
|
722
|
+
)
|
|
723
|
+
|
|
724
|
+
try:
|
|
725
|
+
logs = response["Result"]["LogLines"]
|
|
726
|
+
return logs
|
|
727
|
+
except Exception as _:
|
|
728
|
+
raise ValueError(f"Get application log failed. Response: {response}")
|
|
@@ -65,12 +65,15 @@ class VePromptPilot:
|
|
|
65
65
|
api_key=self.api_key,
|
|
66
66
|
): # stream chunks of optimized prompt
|
|
67
67
|
# Process each chunk as it arrives
|
|
68
|
-
optimized_prompt += chunk.data.content
|
|
68
|
+
optimized_prompt += chunk.data.content if chunk.data else ""
|
|
69
69
|
# print(chunk.data.content, end="", flush=True)
|
|
70
70
|
if chunk.event == "usage":
|
|
71
|
-
usage = chunk.data.usage
|
|
71
|
+
usage = chunk.data.usage if chunk.data else 0
|
|
72
72
|
optimized_prompt = optimized_prompt.replace("\\n", "\n")
|
|
73
73
|
print(f"Optimized prompt for agent {agent.name}:\n{optimized_prompt}")
|
|
74
|
-
|
|
74
|
+
if usage:
|
|
75
|
+
logger.info(f"Token usage: {usage['total_tokens']}")
|
|
76
|
+
else:
|
|
77
|
+
logger.warning("No usage data.")
|
|
75
78
|
|
|
76
79
|
return optimized_prompt
|
|
@@ -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,117 @@
|
|
|
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 hashlib
|
|
16
|
+
import json
|
|
17
|
+
from typing import Any, Literal
|
|
18
|
+
|
|
19
|
+
import httpx
|
|
20
|
+
from volcengine.ApiInfo import ApiInfo
|
|
21
|
+
from volcengine.auth.SignerV4 import SignerV4
|
|
22
|
+
from volcengine.tls.const import (
|
|
23
|
+
APPLICATION_JSON,
|
|
24
|
+
CONTENT_MD5,
|
|
25
|
+
CONTENT_TYPE,
|
|
26
|
+
DATA,
|
|
27
|
+
WEB_TRACKS,
|
|
28
|
+
)
|
|
29
|
+
from volcengine.tls.TLSService import TLSService
|
|
30
|
+
|
|
31
|
+
from veadk.utils.logger import get_logger
|
|
32
|
+
|
|
33
|
+
logger = get_logger(__name__)
|
|
34
|
+
|
|
35
|
+
HEADER_API_VERSION = "x-tls-apiversion"
|
|
36
|
+
API_VERSION_V_0_3_0 = "0.3.0"
|
|
37
|
+
|
|
38
|
+
API_INFO = {
|
|
39
|
+
"CreateProject": ApiInfo("POST", "/CreateProject", {}, {}, {}),
|
|
40
|
+
"DescribeProjects": ApiInfo("GET", "/DescribeProjects", {}, {}, {}),
|
|
41
|
+
"CreateTraceInstance": ApiInfo("POST", "/CreateTraceInstance", {}, {}, {}),
|
|
42
|
+
"DescribeTraceInstances": ApiInfo("GET", "/DescribeTraceInstances", {}, {}, {}),
|
|
43
|
+
"DescribeTraceInstance": ApiInfo("GET", "/DescribeTraceInstance", {}, {}, {}),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def __prepare_request(
|
|
48
|
+
client: TLSService,
|
|
49
|
+
api: str,
|
|
50
|
+
params: dict | None = None,
|
|
51
|
+
body: Any | None = None,
|
|
52
|
+
request_headers: dict | None = None,
|
|
53
|
+
):
|
|
54
|
+
if params is None:
|
|
55
|
+
params = {}
|
|
56
|
+
if body is None:
|
|
57
|
+
body = {}
|
|
58
|
+
|
|
59
|
+
request = client.prepare_request(API_INFO[api], params)
|
|
60
|
+
|
|
61
|
+
if request_headers is None:
|
|
62
|
+
request_headers = {CONTENT_TYPE: APPLICATION_JSON}
|
|
63
|
+
request.headers.update(request_headers)
|
|
64
|
+
|
|
65
|
+
if "json" in request.headers[CONTENT_TYPE] and api != WEB_TRACKS:
|
|
66
|
+
request.body = json.dumps(body)
|
|
67
|
+
else:
|
|
68
|
+
request.body = body[DATA]
|
|
69
|
+
|
|
70
|
+
if len(request.body) != 0:
|
|
71
|
+
if isinstance(request.body, str):
|
|
72
|
+
request.headers[CONTENT_MD5] = hashlib.md5(
|
|
73
|
+
request.body.encode("utf-8")
|
|
74
|
+
).hexdigest()
|
|
75
|
+
else:
|
|
76
|
+
request.headers[CONTENT_MD5] = hashlib.md5(request.body).hexdigest()
|
|
77
|
+
|
|
78
|
+
SignerV4.sign(request, client.service_info.credentials)
|
|
79
|
+
|
|
80
|
+
return request
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def ve_tls_request(
|
|
84
|
+
client: TLSService,
|
|
85
|
+
api: str,
|
|
86
|
+
params: dict | None = None,
|
|
87
|
+
body: dict | None = None,
|
|
88
|
+
request_headers: dict | None = None,
|
|
89
|
+
method: Literal["POST", "GET", "PUT", "DELETE"] = "POST",
|
|
90
|
+
):
|
|
91
|
+
"""Customize a standard HTTP request to the Volcengine TLS API"""
|
|
92
|
+
|
|
93
|
+
if request_headers is None:
|
|
94
|
+
request_headers = {HEADER_API_VERSION: API_VERSION_V_0_3_0}
|
|
95
|
+
elif HEADER_API_VERSION not in request_headers:
|
|
96
|
+
request_headers[HEADER_API_VERSION] = API_VERSION_V_0_3_0
|
|
97
|
+
if CONTENT_TYPE not in request_headers:
|
|
98
|
+
request_headers[CONTENT_TYPE] = APPLICATION_JSON
|
|
99
|
+
request = __prepare_request(client, api, params, body, request_headers)
|
|
100
|
+
|
|
101
|
+
url = request.build()
|
|
102
|
+
|
|
103
|
+
with httpx.Client() as session:
|
|
104
|
+
while True:
|
|
105
|
+
try:
|
|
106
|
+
response = session.request(
|
|
107
|
+
method=method,
|
|
108
|
+
url=url,
|
|
109
|
+
headers=request.headers,
|
|
110
|
+
data=request.body, # type: ignore
|
|
111
|
+
timeout=60,
|
|
112
|
+
)
|
|
113
|
+
return response.json()
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.error(
|
|
116
|
+
f"Error occurred while making {method} request to {url}: {e}. Response: {response}"
|
|
117
|
+
)
|