Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ exclude = ["assets*", "ide*", "tests*"]
include-package-data = true

[tool.setuptools.package-data]
"veadk.cli.studio.web" = ["_next/**/*"]
"veadk" = ["**/*"]
6 changes: 5 additions & 1 deletion veadk/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ def web(
None,
"--session_service_uri",
),
host: str = typer.Option(
"127.0.0.1",
"--host",
),
):
from google.adk.memory import in_memory_memory_service

Expand All @@ -144,7 +148,7 @@ def web(
session_service_uri = ""

cli_tools_click.cli_web.main(
args=[agents_dir, "--session_service_uri", session_service_uri]
args=[agents_dir, "--session_service_uri", session_service_uri, "--host", host]
)


Expand Down
13 changes: 13 additions & 0 deletions veadk/cli/services/vefaas/template/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
4 changes: 3 additions & 1 deletion veadk/cli/services/vefaas/template/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
USER_ID = "cloud_app_test_user"

USE_STUDIO = False
USE_ADK_WEB = False


async def main():
Expand All @@ -29,10 +30,11 @@ async def main():
path=str(Path(__file__).parent / "src"),
name="weather-reporter", # <--- set your application name
use_studio=USE_STUDIO,
use_adk_web=USE_ADK_WEB,
# gateway_name="", # <--- set your gateway instance name if you have one
)

if not USE_STUDIO:
if not USE_STUDIO and not USE_ADK_WEB:
response_message = await cloud_app.message_send(
"How is the weather like in Beijing?", SESSION_ID, USER_ID
)
Expand Down
14 changes: 14 additions & 0 deletions veadk/cli/services/vefaas/template/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from . import agent # noqa F401
2 changes: 2 additions & 0 deletions veadk/cli/services/vefaas/template/src/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@
short_term_memory: ShortTermMemory = (
ShortTermMemory()
) # <--- export your short term memory

root_agent = agent
1 change: 1 addition & 0 deletions veadk/cli/services/vefaas/template/src/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
veadk-python[eval] @ git+https://github.com/volcengine/veadk-python.git # extra eval for prompt optimization in veadk studio
opensearch-py==2.8.0
agent-pilot-sdk>=0.0.9 # extra dep for prompt optimization in veadk studio
uvicorn[standard]
fastapi
22 changes: 13 additions & 9 deletions veadk/cli/services/vefaas/template/src/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,25 @@ python3 -m pip install uvicorn[standard]
python3 -m pip install fastapi

USE_STUDIO=${USE_STUDIO:-False}
USE_ADK_WEB=${USE_ADK_WEB:-False}

if [ "$USE_STUDIO" = "True" ]; then
echo "USE_STUDIO is True, running veadk studio"
# running veadk studio
exec python3 -m uvicorn studio_app:app --host $HOST --port $PORT --timeout-graceful-shutdown $TIMEOUT --loop asyncio
elif [ "$USE_STUDIO" = "False" ]; then
echo "USE_STUDIO is False, running a2a server"

# running a2a server
exec python3 -m uvicorn app:app --host $HOST --port $PORT --timeout-graceful-shutdown $TIMEOUT --loop asyncio
echo "USE_STUDIO is False"

if [ "$USE_ADK_WEB" = "True" ]; then
echo "USE_ADK_WEB is True, running veadk web"
# running veadk web
cd ../
exec python3 -m veadk.cli.main web --host "0.0.0.0"
else
echo "USE_ADK_WEB is False, running a2a server"
exec python3 -m uvicorn app:app --host $HOST --port $PORT --timeout-graceful-shutdown $TIMEOUT --loop asyncio
fi
else
echo "USE_STUDIO is an invalid value: $USE_STUDIO, running a2a server."

# running a2a server
exec python3 -m uvicorn app:app --host $HOST --port $PORT --timeout-graceful-shutdown $TIMEOUT --loop asyncio
fi


fi
97 changes: 42 additions & 55 deletions veadk/cli/services/vefaas/vefaas.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
TagForCreateFunctionInput,
)

import veadk.config
from veadk.cli.services.veapig.apig import APIGateway
from veadk.utils.logger import get_logger
from veadk.utils.misc import formatted_timestamp
Expand Down Expand Up @@ -58,27 +59,16 @@ def __init__(self, access_key: str, secret_key: str, region: str = "cn-beijing")

self.template_id = "6874f3360bdbc40008ecf8c7"

def _create_function(self, name: str, path: str):
function_name = f"{name}-fn-{formatted_timestamp()}"

# 1. Create a function instance in cloud
typer.echo(
typer.style("Runtime: native-python3.10/v1", fg=typer.colors.BRIGHT_BLACK)
)

def _create_function(self, function_name: str, path: str):
# 1. Read envs
envs = []

import veadk.config

for key, value in veadk.config.veadk_environments.items():
envs.append(EnvForCreateFunctionInput(key=key, value=value))
typer.echo(
typer.style(
f"Fetch {len(envs)} environment variables.",
fg=typer.colors.BRIGHT_BLACK,
)
logger.info(
f"Fetch {len(envs)} environment variables.",
)

# 2. Create function
res = self.client.create_function(
volcenginesdkvefaas.CreateFunctionRequest(
command="./run.sh",
Expand All @@ -88,21 +78,17 @@ def _create_function(self, name: str, path: str):
runtime="native-python3.10/v1",
request_timeout=1800,
envs=envs,
# tls_config=TlsConfigForCreateFunctionInput(enable_log=True),
)
)
function_id = res.id

# 2. Get a temp bucket to store code
# proj_path = get_project_path()
# 3. Get a temp bucket to store code
code_zip_data, code_zip_size, error = zip_and_encode_folder(path)
typer.echo(
typer.style(
f"Zipped project size: {code_zip_size / 1024 / 1024:.2f} MB",
fg=typer.colors.BRIGHT_BLACK,
)
logger.info(
f"Zipped project size: {code_zip_size / 1024 / 1024:.2f} MB",
)

# 4. Upload code to VeFaaS temp bucket
req = volcenginesdkvefaas.GetCodeUploadAddressRequest(
function_id=function_id, content_length=code_zip_size
)
Expand All @@ -113,28 +99,18 @@ def _create_function(self, name: str, path: str):
"Content-Type": "application/zip",
}
response = requests.put(url=upload_url, data=code_zip_data, headers=headers)
if 200 <= response.status_code < 300:
# print(f"Upload successful! Size: {code_zip_size / 1024 / 1024:.2f} MB")
pass
else:
if not (200 <= response.status_code < 300):
error_message = f"Upload failed to {upload_url} with status code {response.status_code}: {response.text}"
raise ValueError(error_message)

# 3. Mount the TOS bucket to function instance
# 5. Mount the TOS bucket to function instance
res = signed_request(
ak=self.ak,
sk=self.sk,
target="CodeUploadCallback",
body={"FunctionId": function_id},
)

typer.echo(
typer.style(
f"Function ID on VeFaaS service: {function_id}",
fg=typer.colors.BRIGHT_BLACK,
)
)

return function_name, function_id

def _create_application(
Expand Down Expand Up @@ -183,23 +159,21 @@ def _release_application(self, app_id: str):
host="open.volcengineapi.com",
)

logger.info(f"Start to release VeFaaS application {app_id}.")
status, full_response = self._get_application_status(app_id)
while status not in ["deploy_success", "deploy_fail"]:
time.sleep(10)
typer.echo(
typer.style(
f"Current status: {status}",
fg=typer.colors.BRIGHT_BLACK,
)
)
status, full_response = self._get_application_status(app_id)

assert status == "deploy_success", (
f"Release application failed. Response: {full_response}"
)

cloud_resource = full_response["Result"]["CloudResource"]
cloud_resource = json.loads(cloud_resource)

url = cloud_resource["framework"]["url"]["system_url"]

return url

def _get_application_status(self, app_id: str):
Expand Down Expand Up @@ -257,15 +231,29 @@ def delete(self, app_id: str):

def deploy(
self,
name: str, # application name
name: str,
path: str,
gateway_name: str = "",
gateway_service_name: str = "",
gateway_upstream_name: str = "",
) -> tuple[str, str, str]:
"""Deploy an agent project to VeFaaS service.

Args:
name (str): Application name (warning: not function name).
path (str): Project path.
gateway_name (str, optional): Gateway name. Defaults to "".
gateway_service_name (str, optional): Gateway service name. Defaults to "".
gateway_upstream_name (str, optional): Gateway upstream name. Defaults to "".

Returns:
tuple[str, str, str]: (url, app_id, function_id)
"""
# Naming check
if "_" in name:
raise ValueError("Function or Application name cannot contain '_'.")

# Give default names
if not gateway_name:
gateway_name = f"{name}-gw-{formatted_timestamp()}"

Expand All @@ -286,14 +274,15 @@ def deploy(
if not gateway_upstream_name:
gateway_upstream_name = f"{name}-gw-us-{formatted_timestamp()}"

typer.echo(
typer.style("[1/3] ", fg=typer.colors.GREEN)
+ "Create VeFaaS service on cloud."
function_name = f"{name}-fn"

logger.info(
f"Start to create VeFaaS function {function_name} with path {path}. Gateway: {gateway_name}, Gateway Service: {gateway_service_name}, Gateway Upstream: {gateway_upstream_name}."
)
typer.echo(typer.style(f"Project path: {path}", fg=typer.colors.BRIGHT_BLACK))
function_name, function_id = self._create_function(name, path)
function_name, function_id = self._create_function(function_name, path)
logger.info(f"VeFaaS function {function_name} with ID {function_id} created.")

typer.echo(typer.style("[2/3] ", fg=typer.colors.GREEN) + "Create application.")
logger.info(f"Start to create VeFaaS application {name}.")
app_id = self._create_application(
name,
function_name,
Expand All @@ -302,13 +291,11 @@ def deploy(
gateway_service_name,
)

typer.echo(
typer.style("[3/3] ", fg=typer.colors.GREEN) + "Release application."
)
logger.info(f"VeFaaS application {name} with ID {app_id} created.")
logger.info(f"Start to release VeFaaS application {app_id}.")
url = self._release_application(app_id)
logger.info(f"VeFaaS application {name} with ID {app_id} released.")

typer.echo(
typer.style(f"\nSuccessfully deployed on:\n\n{url}", fg=typer.colors.BLUE)
)
logger.info(f"VeFaaS application {name} with ID {app_id} deployed on {url}.")

return url, app_id, function_id
1 change: 1 addition & 0 deletions veadk/cli/studio/studio_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ async def evaluate(self):
metrics = [
GEval(
name="Correctness&MatchDegree",
model=self.evaluator.judge_model,
criteria="Judge the correctness and match degree of the model output with the expected output.",
evaluation_params=[
LLMTestCaseParams.INPUT,
Expand Down
13 changes: 13 additions & 0 deletions veadk/cloud/cloud_agent_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ def deploy(
gateway_service_name: str = "",
gateway_upstream_name: str = "",
use_studio: bool = False,
use_adk_web: bool = False,
) -> CloudApp:
"""Deploy local agent project to Volcengine FaaS platform.

Expand All @@ -119,6 +120,9 @@ def deploy(
Returns:
str: Volcengine FaaS function endpoint.
"""
assert not (use_studio and use_adk_web), (
"use_studio and use_adk_web can not be True at the same time."
)
# prevent deepeval writing operations
import veadk.config

Expand All @@ -133,6 +137,15 @@ def deploy(

veadk.config.veadk_environments["USE_STUDIO"] = "False"

if use_adk_web:
import veadk.config

veadk.config.veadk_environments["USE_ADK_WEB"] = "True"
else:
import veadk.config

veadk.config.veadk_environments["USE_ADK_WEB"] = "False"

# convert `path` to absolute path
path = str(Path(path).resolve())
self._prepare(path, name)
Expand Down
1 change: 1 addition & 0 deletions veadk/cloud/template/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@
agent: Agent = ...
app_name: str = ...
short_term_memory: ShortTermMemory = ...
root_agent = agent
Loading