Skip to content

Commit 42afa85

Browse files
committed
feat: support nacos in agent update
1 parent eb77b3d commit 42afa85

File tree

3 files changed

+127
-1
lines changed

3 files changed

+127
-1
lines changed

veadk/agent.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
if not os.getenv("LITELLM_LOCAL_MODEL_COST_MAP"):
2525
os.environ["LITELLM_LOCAL_MODEL_COST_MAP"] = "True"
2626

27+
import uuid
28+
2729
from google.adk.agents import LlmAgent, RunConfig
2830
from google.adk.agents.base_agent import BaseAgent
2931
from google.adk.agents.context_cache_config import ContextCacheConfig
@@ -89,6 +91,7 @@ class Agent(LlmAgent):
8991

9092
model_config = ConfigDict(arbitrary_types_allowed=True, extra="allow")
9193

94+
id: str = Field(default_factory=lambda: str(uuid.uuid4()).split("-")[0])
9295
name: str = DEFAULT_AGENT_NAME
9396
description: str = DEFAULT_DESCRIPTION
9497
instruction: Union[str, InstructionProvider] = DEFAULT_INSTRUCTION
@@ -278,7 +281,13 @@ def model_post_init(self, __context: Any) -> None:
278281

279282
logger.info(f"{self.__class__.__name__} `{self.name}` init done.")
280283
logger.debug(
281-
f"Agent: {self.model_dump(include={'name', 'model_name', 'model_api_base', 'tools'})}"
284+
f"Agent: {self.model_dump(include={'id', 'name', 'model_name', 'model_api_base', 'tools'})}"
285+
)
286+
287+
def update_model(self, model_name: str):
288+
logger.info(f"Updating model to {model_name}")
289+
self.model = self.model.model_copy(
290+
update={"model": f"{self.model_provider}/{model_name}"}
282291
)
283292

284293
async def _run(
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import json
2+
import os
3+
4+
from v2.nacos import ClientConfig, NacosConfigService
5+
from v2.nacos.config.model.config_param import ConfigParam
6+
7+
from veadk.agent import Agent
8+
from veadk.consts import DEFAULT_NACOS_GROUP
9+
from veadk.utils.logger import get_logger
10+
11+
logger = get_logger(__name__)
12+
13+
14+
class DynamicConfigManager:
15+
"""
16+
DynamicConfigManager is responsible for creating and publishing dynamic config to nacos.
17+
"""
18+
19+
def __init__(self, agents: list[Agent] | Agent, app_name: str):
20+
"""
21+
Initialize DynamicConfigManager with agents and app_name.
22+
23+
Args:
24+
agents (list[Agent] | Agent): The agent(s) to be included in the dynamic config.
25+
app_name (str): The name of the application, used as the Nacos group id. Defaults to DEFAULT_NACOS_GROUP.
26+
"""
27+
if isinstance(agents, list):
28+
self.agents = agents
29+
else:
30+
self.agents = [agents]
31+
32+
if not app_name:
33+
logger.warning(
34+
f"app_name is not provided, use default value {DEFAULT_NACOS_GROUP}. This may lead to unexpected behavior such as configuration override."
35+
)
36+
self.app_name = app_name or DEFAULT_NACOS_GROUP
37+
38+
logger.debug(
39+
f"DynamicConfigManager init with {len(self.agents)} agent(s) for app {self.app_name}"
40+
)
41+
42+
async def create_config(self, config: dict = {}):
43+
client_config = ClientConfig(
44+
server_addresses=os.getenv("NACOS_SERVER_ADDRESSES"),
45+
namespace_id="",
46+
username=os.getenv("NACOS_USERNAME"),
47+
password=os.getenv("NACOS_PASSWORD"),
48+
)
49+
50+
config_client = await NacosConfigService.create_config_service(
51+
client_config=client_config
52+
)
53+
54+
configs = {
55+
"agent": [
56+
{
57+
"id": agent.id,
58+
"name": agent.name,
59+
"description": agent.description,
60+
"model_name": agent.model_name,
61+
"instruction": agent.instruction,
62+
}
63+
for agent in self.agents
64+
]
65+
}
66+
response = await config_client.publish_config(
67+
param=ConfigParam(
68+
data_id="veadk",
69+
group=self.app_name,
70+
type="json",
71+
content=json.dumps(configs),
72+
)
73+
)
74+
assert response, "publish config to nacos failed"
75+
logger.info("Publish config to nacos success")
76+
77+
await config_client.add_listener(
78+
data_id="veadk",
79+
group="VEADK_GROUP",
80+
listener=self.handle_config_update,
81+
)
82+
logger.info("Add config listener to nacos success")
83+
84+
return config_client
85+
86+
def register_agent(self, agent: list[Agent] | Agent):
87+
if isinstance(agent, list):
88+
self.agents.extend(agent)
89+
else:
90+
self.agents.append(agent)
91+
92+
def update_agent(self, configs: dict):
93+
for agent in self.agents:
94+
for config in configs["agent"]:
95+
if agent.id == config["id"]:
96+
logger.info(f"Update agent {agent.id} with config {config}")
97+
name = config["name"]
98+
description = config["description"]
99+
model_name = config["model_name"]
100+
instruction = config["instruction"]
101+
102+
agent.name = name
103+
agent.description = description
104+
if model_name != agent.model_name:
105+
agent.update_model(model_name=model_name)
106+
agent.instruction = instruction
107+
108+
async def handle_config_update(self, tenant, data_id, group, content) -> None:
109+
logger.debug(
110+
"listen, tenant:{} data_id:{} group:{} content:{}".format(
111+
tenant, data_id, group, content
112+
)
113+
)
114+
content = json.loads(content)
115+
self.update_agent(content)

veadk/consts.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,5 @@
7272
DEFAULT_IMAGE_GENERATE_MODEL_API_BASE = "https://ark.cn-beijing.volces.com/api/v3/"
7373

7474
VEFAAS_IAM_CRIDENTIAL_PATH = "/var/run/secrets/iam/credential"
75+
76+
DEFAULT_NACOS_GROUP = "VEADK_GROUP"

0 commit comments

Comments
 (0)