Skip to content

Commit 576ebc5

Browse files
committed
update deploy templates
1 parent 11e79a4 commit 576ebc5

File tree

14 files changed

+428
-225
lines changed

14 files changed

+428
-225
lines changed

veadk/cli/cli_web.py

Lines changed: 90 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,95 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15+
1516
import click
1617

18+
from veadk.memory.long_term_memory import LongTermMemory
19+
from veadk.memory.short_term_memory import ShortTermMemory
20+
21+
22+
def _get_stm_from_module(module) -> ShortTermMemory:
23+
return module.agent_run_config.short_term_memory
24+
25+
26+
def _get_stm_from_env() -> ShortTermMemory:
27+
import os
28+
29+
from veadk.utils.logger import get_logger
30+
31+
logger = get_logger(__name__)
32+
33+
short_term_memory_backend = os.getenv("SHORT_TERM_MEMORY_BACKEND")
34+
if not short_term_memory_backend: # prevent None or empty string
35+
short_term_memory_backend = "local"
36+
logger.info(f"Short term memory: backend={short_term_memory_backend}")
37+
38+
return ShortTermMemory(backend=short_term_memory_backend) # type: ignore
39+
40+
41+
def _get_ltm_from_module(module) -> LongTermMemory | None:
42+
agent = module.agent_run_config.agent
43+
44+
if not hasattr(agent, "long_term_memory"):
45+
return None
46+
else:
47+
return agent.long_term_memory
48+
49+
50+
def _get_ltm_from_env() -> LongTermMemory | None:
51+
import os
52+
53+
from veadk.utils.logger import get_logger
54+
55+
logger = get_logger(__name__)
56+
57+
long_term_memory_backend = os.getenv("LONG_TERM_MEMORY_BACKEND")
58+
59+
if long_term_memory_backend:
60+
logger.info(f"Long term memory: backend={long_term_memory_backend}")
61+
return LongTermMemory(backend=long_term_memory_backend) # type: ignore
62+
else:
63+
logger.warning("No long term memory backend settings detected.")
64+
return None
65+
66+
67+
def _get_memory(
68+
module_path: str,
69+
) -> tuple[ShortTermMemory, LongTermMemory | None]:
70+
from veadk.utils.logger import get_logger
71+
from veadk.utils.misc import load_module_from_file
72+
73+
logger = get_logger(__name__)
74+
75+
# 1. load user module
76+
try:
77+
module_file_path = module_path
78+
module = load_module_from_file(
79+
module_name="agent_and_mem", file_path=f"{module_file_path}/agent.py"
80+
)
81+
except Exception as e:
82+
logger.error(
83+
f"Failed to get memory config from `agent.py`: {e}. Fallback to get memory from environment variables."
84+
)
85+
return _get_stm_from_env(), _get_ltm_from_env()
86+
87+
if not hasattr(module, "agent_run_config"):
88+
logger.error(
89+
"You must export `agent_run_config` as a global variable in `agent.py`. Fallback to get memory from environment variables."
90+
)
91+
return _get_stm_from_env(), _get_ltm_from_env()
92+
93+
# 2. try to get short term memory
94+
# short term memory must exist in user code, as we use `default_factory` to init it
95+
short_term_memory = _get_stm_from_module(module)
96+
97+
# 3. try to get long term memory
98+
long_term_memory = _get_ltm_from_module(module)
99+
if not long_term_memory:
100+
long_term_memory = _get_ltm_from_env()
101+
102+
return short_term_memory, long_term_memory
103+
17104

18105
@click.command()
19106
@click.option("--host", default="127.0.0.1", help="Host to run the web server on")
@@ -24,7 +111,6 @@ def web(host: str) -> None:
24111

25112
from google.adk.cli.utils.shared_value import SharedValue
26113

27-
from veadk.memory.short_term_memory import ShortTermMemory
28114
from veadk.utils.logger import get_logger
29115

30116
logger = get_logger(__name__)
@@ -51,26 +137,9 @@ def init_for_veadk(
51137
self.current_app_name_ref = SharedValue(value="")
52138
self.runner_dict = {}
53139

54-
short_term_memory_backend = os.getenv("SHORT_TERM_MEMORY_BACKEND")
55-
if not short_term_memory_backend: # prevent None or empty string
56-
short_term_memory_backend = "local"
57-
logger.info(f"Short term memory: backend={short_term_memory_backend}")
58-
59-
long_term_memory_backend = os.getenv("LONG_TERM_MEMORY_BACKEND")
60-
long_term_memory = None
61-
62-
if long_term_memory_backend:
63-
from veadk.memory.long_term_memory import LongTermMemory
64-
65-
logger.info(f"Long term memory: backend={long_term_memory_backend}")
66-
long_term_memory = LongTermMemory(backend=long_term_memory_backend) # type: ignore
67-
else:
68-
logger.info("No long term memory backend settings detected.")
69-
70-
self.session_service = ShortTermMemory(
71-
backend=short_term_memory_backend # type: ignore
72-
).session_service
73-
140+
# parse VeADK memories
141+
short_term_memory, long_term_memory = _get_memory(module_path=agents_dir)
142+
self.session_service = short_term_memory.session_service
74143
self.memory_service = long_term_memory
75144

76145
import google.adk.cli.adk_web_server

veadk/cloud/cloud_agent_engine.py

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
# limitations under the License.
1414

1515
import os
16+
import socket
17+
import subprocess
18+
import time
1619
from pathlib import Path
1720
from typing import Any
1821

@@ -22,7 +25,7 @@
2225
from veadk.config import getenv
2326
from veadk.integrations.ve_faas.ve_faas import VeFaaS
2427
from veadk.utils.logger import get_logger
25-
from veadk.utils.misc import formatted_timestamp
28+
from veadk.utils.misc import formatted_timestamp, load_module_from_file
2629

2730
logger = get_logger(__name__)
2831

@@ -65,9 +68,9 @@ def _prepare(self, path: str, name: str):
6568
# prepare template files if not have
6669
template_files = [
6770
"app.py",
68-
"studio_app.py",
71+
# "studio_app.py",
6972
"run.sh",
70-
"requirements.txt",
73+
# "requirements.txt",
7174
"__init__.py",
7275
]
7376
for template_file in template_files:
@@ -88,6 +91,70 @@ def _prepare(self, path: str, name: str):
8891

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

94+
# copy user's requirements.txt
95+
if os.path.exists(os.path.join(path, "requirements.txt")):
96+
logger.warning(
97+
f"Local agent project path `{path}` contains a `requirements.txt` file. Skip copy requirements."
98+
)
99+
return
100+
101+
module = load_module_from_file(
102+
module_name="agent_source", file_path=f"{path}/agent.py"
103+
)
104+
105+
requirement_file_path = module.agent_run_config.requirement_file_path
106+
shutil.copy(requirement_file_path, os.path.join(path, "requirements.txt"))
107+
108+
logger.info(
109+
f"Copy requirement file: from {requirement_file_path} to {path}/requirements.txt"
110+
)
111+
112+
def _try_launch_fastapi_server(self, path: str):
113+
"""Try to launch a fastapi server for tests according to user's configuration.
114+
115+
Args:
116+
path (str): Local agent project path.
117+
"""
118+
RUN_SH = f"{path}/run.sh"
119+
120+
HOST = "0.0.0.0"
121+
PORT = 8000
122+
123+
# Prepare environment variables
124+
os.environ["_FAAS_FUNC_TIMEOUT"] = "900"
125+
env = os.environ.copy()
126+
127+
process = subprocess.Popen(
128+
["bash", RUN_SH],
129+
stdout=subprocess.PIPE,
130+
stderr=subprocess.STDOUT,
131+
text=True,
132+
env=env,
133+
bufsize=1,
134+
)
135+
136+
timeout = 30
137+
start_time = time.time()
138+
139+
for line in process.stdout: # type: ignore
140+
print(line, end="")
141+
142+
if time.time() - start_time > timeout:
143+
process.terminate()
144+
raise RuntimeError(f"FastAPI server failed to start on {HOST}:{PORT}")
145+
try:
146+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
147+
s.settimeout(0.1)
148+
s.connect(("127.0.0.1", PORT))
149+
logger.info(f"FastAPI server is listening on {HOST}:{PORT}")
150+
logger.info("Local deplyment test successfully.")
151+
break
152+
except (ConnectionRefusedError, socket.timeout):
153+
continue
154+
155+
process.terminate()
156+
process.wait()
157+
91158
def deploy(
92159
self,
93160
application_name: str,
@@ -97,15 +164,22 @@ def deploy(
97164
gateway_upstream_name: str = "",
98165
use_studio: bool = False,
99166
use_adk_web: bool = False,
167+
local_test: bool = False,
100168
) -> CloudApp:
101169
"""Deploy local agent project to Volcengine FaaS platform.
102170
103171
Args:
172+
application_name (str): Expected VeFaaS application name.
104173
path (str): Local agent project path.
105-
name (str): Volcengine FaaS function name.
174+
gateway_name (str): Gateway name.
175+
gateway_service_name (str): Gateway service name.
176+
gateway_upstream_name (str): Gateway upstream name.
177+
use_studio (bool): Whether to use Studio [deprecated].
178+
use_adk_web (bool): Whether to use ADK Web.
179+
local_test (bool): Whether to run local test for FastAPI Server.
106180
107181
Returns:
108-
str: Volcengine FaaS function endpoint.
182+
CloudApp: The deployed cloud application instance.
109183
"""
110184
assert not (use_studio and use_adk_web), (
111185
"use_studio and use_adk_web can not be True at the same time."
@@ -136,6 +210,9 @@ def deploy(
136210
path = str(Path(path).resolve())
137211
self._prepare(path, application_name)
138212

213+
if local_test:
214+
self._try_launch_fastapi_server(path)
215+
139216
if not gateway_name:
140217
gateway_name = f"{application_name}-gw-{formatted_timestamp()}"
141218
if not gateway_service_name:

0 commit comments

Comments
 (0)