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
80 changes: 76 additions & 4 deletions veadk/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,32 @@
app = typer.Typer(name="vego")


def set_variable_in_file(file_path: str, setting_values: dict):
import ast

with open(file_path, "r", encoding="utf-8") as f:
source_code = f.read()

tree = ast.parse(source_code)

class VariableTransformer(ast.NodeTransformer):
def visit_Assign(self, node: ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id in setting_values:
node.value = ast.Constant(value=setting_values[target.id])
return node

transformer = VariableTransformer()
new_tree = transformer.visit(tree)
ast.fix_missing_locations(new_tree)
new_source_code = ast.unparse(new_tree)

with open(file_path, "w", encoding="utf-8") as f:
f.write(new_source_code)

print("Your project has beed created.")


@app.command()
def init():
"""Init a veadk project that can be deployed to Volcengine VeFaaS."""
Expand All @@ -40,9 +66,9 @@ def init():
cwd = Path.cwd()
template_dir = Path(__file__).parent.resolve() / "services" / "vefaas" / "template"

name = Prompt.ask("Project name", default="veadk-cloud-agent")
local_dir_name = Prompt.ask("Local directory name", default="veadk-cloud-proj")

target_dir = cwd / name
target_dir = cwd / local_dir_name

if target_dir.exists():
response = Confirm.ask(
Expand All @@ -52,11 +78,57 @@ def init():
print("Operation cancelled.")
return
else:
shutil.rmtree(target_dir) # 删除旧目录
shutil.rmtree(target_dir)
print(f"Deleted existing directory: {target_dir}")

vefaas_application_name = Prompt.ask(
"Volcengine FaaS application name", default="veadk-cloud-agent"
)

gateway_name = Prompt.ask(
"Volcengine gateway instance name", default="", show_default=True
)

gateway_service_name = Prompt.ask(
"Volcengine gateway service name", default="", show_default=True
)

gateway_upstream_name = Prompt.ask(
"Volcengine gateway upstream name", default="", show_default=True
)

deploy_mode_options = {
"1": "A2A Server",
"2": "VeADK Studio",
"3": "VeADK Web / Google ADK Web",
}

deploy_mode = Prompt.ask(
"""Choose your deploy mode:
1. A2A Server
2. VeADK Studio
3. VeADK Web / Google ADK Web
""",
default="1",
)

if deploy_mode in deploy_mode_options:
deploy_mode = deploy_mode_options[deploy_mode]
else:
print("Invalid deploy mode, set default to A2A Server")
deploy_mode = deploy_mode_options["1"]

setting_values = {
"VEFAAS_APPLICATION_NAME": vefaas_application_name,
"GATEWAY_NAME": gateway_name,
"GATEWAY_SERVICE_NAME": gateway_service_name,
"GATEWAY_UPSTREAM_NAME": gateway_upstream_name,
"USE_STUDIO": deploy_mode == deploy_mode_options["2"],
"USE_ADK_WEB": deploy_mode == deploy_mode_options["3"],
}

shutil.copytree(template_dir, target_dir)
print(f"Created new project: {name}")
set_variable_in_file(target_dir / "deploy.py", setting_values)


# @app.command()
Expand Down
20 changes: 12 additions & 8 deletions veadk/cli/services/vefaas/template/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,38 @@
SESSION_ID = "cloud_app_test_session"
USER_ID = "cloud_app_test_user"

VEFAAS_APPLICATION_NAME = "weather-reporter"
GATEWAY_NAME = ""
GATEWAY_SERVICE_NAME = ""
GATEWAY_UPSTREAMNAME = ""
USE_STUDIO = False
USE_ADK_WEB = False


async def main():
engine = CloudAgentEngine()

cloud_app = engine.deploy(
path=str(Path(__file__).parent / "src"),
name="weather-reporter", # <--- set your application name
application_name=VEFAAS_APPLICATION_NAME,
gateway_name=GATEWAY_NAME,
gateway_service_name=GATEWAY_SERVICE_NAME,
gateway_upstream_name=GATEWAY_UPSTREAMNAME,
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 and not USE_ADK_WEB:
response_message = await cloud_app.message_send(
"How is the weather like in Beijing?", SESSION_ID, USER_ID
)

print(f"VeFaaS application ID: {cloud_app.vefaas_application_id}")
print(f"Message ID: {response_message.messageId}")

print(
f"Response from {cloud_app.endpoint}: {response_message.parts[0].root.text}"
f"Response from {cloud_app.vefaas_endpoint}: {response_message.parts[0].root.text}"
)

print(f"App ID: {cloud_app.app_id}")
else:
print(f"VeADK Studio URL: {cloud_app.endpoint}")
print(f"Web is running at: {cloud_app.vefaas_endpoint}")


if __name__ == "__main__":
Expand Down
102 changes: 42 additions & 60 deletions veadk/cloud/cloud_agent_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,71 +40,54 @@ def model_post_init(self, context: Any, /) -> None:
)

def _prepare(self, path: str, name: str):
# VeFaaS path check
if "_" in name:
raise ValueError(
f"Invalid Volcengine FaaS function name `{name}`, please use lowercase letters and numbers, or replace it with a `-` char."
)

# project path check
# basic check
assert os.path.exists(path), f"Local agent project path `{path}` not exists."
assert os.path.isdir(path), (
f"Local agent project path `{path}` is not a directory."
)

assert os.path.exists(os.path.join(path, "agent.py")), (
f"Local agent project path `{path}` does not contain `agent.py` file. Please prepare it according to veadk-python/cloud/template/agent.py.example"
)

if os.path.exists(os.path.join(path, "app.py")):
logger.warning(
f"Local agent project path `{path}` contains an `app.py` file. Use your own `app.py` file may cause unexpected behavior."
)
else:
logger.info(
f"No `app.py` detected in local agent project path `{path}`. Prepare it."
)
template_app_py = (
f"{Path(__file__).resolve().parent.resolve()}/template/app.py"
)
import shutil

shutil.copy(template_app_py, os.path.join(path, "app.py"))

if os.path.exists(os.path.join(path, "studio_app.py")):
logger.warning(
f"Local agent project path `{path}` contains an `studio_app.py` file. Use your own `studio_app.py` file may cause unexpected behavior."
)
else:
logger.info(
f"No `studio_app.py` detected in local agent project path `{path}`. Prepare it."
)
template_studio_app_py = (
f"{Path(__file__).resolve().parent.resolve()}/template/studio_app.py"
# VeFaaS application/function name check
if "_" in name:
raise ValueError(
f"Invalid Volcengine FaaS function name `{name}`, please use lowercase letters and numbers, or replace it with a `-` char."
)
import shutil

shutil.copy(template_studio_app_py, os.path.join(path, "studio_app.py"))
# project structure check
assert os.path.exists(os.path.join(path, "agent.py")), (
f"Local agent project path `{path}` does not contain `agent.py` file. Please prepare it according to our document https://volcengine.github.io/veadk-python/deploy.html"
)

if os.path.exists(os.path.join(path, "run.sh")):
if not os.path.exists(os.path.join(path, "config.yaml")):
logger.warning(
f"Local agent project path `{path}` contains a `run.sh` file. Use your own `run.sh` file may cause unexpected behavior."
)
else:
logger.info(
f"No `run.sh` detected in local agent project path `{path}`. Prepare it."
)
template_run_sh = (
f"{Path(__file__).resolve().parent.resolve()}/template/run.sh"
f"Local agent project path `{path}` does not contain `config.yaml` file. Some important config items may not be set."
)
import shutil

shutil.copy(template_run_sh, os.path.join(path, "run.sh"))
# prepare template files if not have
template_files = [
"app.py",
"studio_app.py",
"run.sh",
"requirements.txt",
"__init__.py",
]
for template_file in template_files:
if os.path.exists(os.path.join(path, template_file)):
logger.warning(
f"Local agent project path `{path}` contains a `{template_file}` file. Use your own `{template_file}` file may cause unexpected behavior."
)
else:
logger.info(
f"No `{template_file}` detected in local agent project path `{path}`. Prepare it."
)
template_file_path = f"{Path(__file__).resolve().parent.resolve().parent.resolve()}/cli/services/vefaas/template/src/{template_file}"
import shutil

shutil.copy(template_file_path, os.path.join(path, template_file))

def deploy(
self,
application_name: str,
path: str,
name: str,
gateway_name: str = "",
gateway_service_name: str = "",
gateway_upstream_name: str = "",
Expand All @@ -123,14 +106,13 @@ def deploy(
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

veadk.config.veadk_environments["DEEPEVAL_TELEMETRY_OPT_OUT"] = "YES"

if use_studio:
import veadk.config

veadk.config.veadk_environments["USE_STUDIO"] = "True"
else:
import veadk.config
Expand All @@ -148,29 +130,29 @@ def deploy(

# convert `path` to absolute path
path = str(Path(path).resolve())
self._prepare(path, name)
self._prepare(path, application_name)

if not gateway_name:
gateway_name = f"{name}-gw-{formatted_timestamp()}"
gateway_name = f"{application_name}-gw-{formatted_timestamp()}"
if not gateway_service_name:
gateway_service_name = f"{name}-gw-svr-{formatted_timestamp()}"
gateway_service_name = f"{application_name}-gw-svr-{formatted_timestamp()}"
if not gateway_upstream_name:
gateway_upstream_name = f"{name}-gw-us-{formatted_timestamp()}"
gateway_upstream_name = f"{application_name}-gw-us-{formatted_timestamp()}"

try:
vefaas_application_url, app_id, function_id = self._vefaas_service.deploy(
path=path,
name=name,
name=application_name,
gateway_name=gateway_name,
gateway_service_name=gateway_service_name,
gateway_upstream_name=gateway_upstream_name,
)
_ = function_id # for future use

return CloudApp(
name=name,
endpoint=vefaas_application_url,
app_id=app_id,
vefaas_application_name=application_name,
vefaas_endpoint=vefaas_application_url,
vefaas_application_id=app_id,
)
except Exception as e:
raise ValueError(
Expand Down
Loading