agentscope-runtime 0.1.5b1__py3-none-any.whl → 0.1.6__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.
Files changed (90) hide show
  1. agentscope_runtime/engine/agents/agentscope_agent.py +447 -0
  2. agentscope_runtime/engine/agents/agno_agent.py +19 -18
  3. agentscope_runtime/engine/agents/autogen_agent.py +13 -8
  4. agentscope_runtime/engine/agents/utils.py +53 -0
  5. agentscope_runtime/engine/deployers/__init__.py +0 -13
  6. agentscope_runtime/engine/deployers/local_deployer.py +501 -356
  7. agentscope_runtime/engine/helpers/helper.py +60 -41
  8. agentscope_runtime/engine/runner.py +11 -36
  9. agentscope_runtime/engine/schemas/agent_schemas.py +2 -70
  10. agentscope_runtime/engine/services/sandbox_service.py +62 -70
  11. agentscope_runtime/engine/services/tablestore_memory_service.py +304 -0
  12. agentscope_runtime/engine/services/tablestore_rag_service.py +143 -0
  13. agentscope_runtime/engine/services/tablestore_session_history_service.py +293 -0
  14. agentscope_runtime/engine/services/utils/tablestore_service_utils.py +352 -0
  15. agentscope_runtime/sandbox/__init__.py +2 -0
  16. agentscope_runtime/sandbox/box/base/__init__.py +4 -0
  17. agentscope_runtime/sandbox/box/base/base_sandbox.py +4 -3
  18. agentscope_runtime/sandbox/box/browser/__init__.py +4 -0
  19. agentscope_runtime/sandbox/box/browser/browser_sandbox.py +8 -13
  20. agentscope_runtime/sandbox/box/dummy/__init__.py +4 -0
  21. agentscope_runtime/sandbox/box/filesystem/__init__.py +4 -0
  22. agentscope_runtime/sandbox/box/filesystem/filesystem_sandbox.py +8 -6
  23. agentscope_runtime/sandbox/box/gui/__init__.py +4 -0
  24. agentscope_runtime/sandbox/box/gui/gui_sandbox.py +80 -0
  25. agentscope_runtime/sandbox/box/sandbox.py +5 -2
  26. agentscope_runtime/sandbox/box/shared/routers/generic.py +20 -1
  27. agentscope_runtime/sandbox/box/training_box/__init__.py +4 -0
  28. agentscope_runtime/sandbox/box/training_box/training_box.py +10 -15
  29. agentscope_runtime/sandbox/build.py +143 -58
  30. agentscope_runtime/sandbox/client/http_client.py +43 -49
  31. agentscope_runtime/sandbox/client/training_client.py +0 -1
  32. agentscope_runtime/sandbox/constant.py +24 -1
  33. agentscope_runtime/sandbox/custom/custom_sandbox.py +5 -5
  34. agentscope_runtime/sandbox/custom/example.py +2 -2
  35. agentscope_runtime/sandbox/enums.py +1 -0
  36. agentscope_runtime/sandbox/manager/collections/in_memory_mapping.py +11 -6
  37. agentscope_runtime/sandbox/manager/collections/redis_mapping.py +25 -9
  38. agentscope_runtime/sandbox/manager/container_clients/__init__.py +0 -10
  39. agentscope_runtime/sandbox/manager/container_clients/agentrun_client.py +1098 -0
  40. agentscope_runtime/sandbox/manager/container_clients/docker_client.py +33 -205
  41. agentscope_runtime/sandbox/manager/container_clients/kubernetes_client.py +8 -555
  42. agentscope_runtime/sandbox/manager/sandbox_manager.py +187 -88
  43. agentscope_runtime/sandbox/manager/server/app.py +82 -14
  44. agentscope_runtime/sandbox/manager/server/config.py +50 -3
  45. agentscope_runtime/sandbox/model/container.py +6 -23
  46. agentscope_runtime/sandbox/model/manager_config.py +93 -5
  47. agentscope_runtime/sandbox/tools/gui/__init__.py +7 -0
  48. agentscope_runtime/sandbox/tools/gui/tool.py +77 -0
  49. agentscope_runtime/sandbox/tools/mcp_tool.py +6 -2
  50. agentscope_runtime/sandbox/utils.py +124 -0
  51. agentscope_runtime/version.py +1 -1
  52. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/METADATA +168 -77
  53. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/RECORD +59 -78
  54. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/entry_points.txt +0 -1
  55. agentscope_runtime/engine/agents/agentscope_agent/__init__.py +0 -6
  56. agentscope_runtime/engine/agents/agentscope_agent/agent.py +0 -401
  57. agentscope_runtime/engine/agents/agentscope_agent/hooks.py +0 -169
  58. agentscope_runtime/engine/agents/llm_agent.py +0 -51
  59. agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +0 -2886
  60. agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +0 -51
  61. agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +0 -314
  62. agentscope_runtime/engine/deployers/cli_fc_deploy.py +0 -143
  63. agentscope_runtime/engine/deployers/kubernetes_deployer.py +0 -265
  64. agentscope_runtime/engine/deployers/modelstudio_deployer.py +0 -626
  65. agentscope_runtime/engine/deployers/utils/deployment_modes.py +0 -14
  66. agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +0 -8
  67. agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +0 -429
  68. agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +0 -240
  69. agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +0 -297
  70. agentscope_runtime/engine/deployers/utils/package_project_utils.py +0 -932
  71. agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +0 -9
  72. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +0 -504
  73. agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +0 -157
  74. agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +0 -268
  75. agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +0 -75
  76. agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +0 -220
  77. agentscope_runtime/engine/deployers/utils/wheel_packager.py +0 -389
  78. agentscope_runtime/engine/helpers/agent_api_builder.py +0 -651
  79. agentscope_runtime/engine/llms/__init__.py +0 -3
  80. agentscope_runtime/engine/llms/base_llm.py +0 -60
  81. agentscope_runtime/engine/llms/qwen_llm.py +0 -47
  82. agentscope_runtime/engine/schemas/embedding.py +0 -37
  83. agentscope_runtime/engine/schemas/modelstudio_llm.py +0 -310
  84. agentscope_runtime/engine/schemas/oai_llm.py +0 -538
  85. agentscope_runtime/engine/schemas/realtime.py +0 -254
  86. /agentscope_runtime/engine/{deployers/adapter/responses → services/utils}/__init__.py +0 -0
  87. /agentscope_runtime/{engine/deployers/utils → sandbox/box/gui/box}/__init__.py +0 -0
  88. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/WHEEL +0 -0
  89. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/licenses/LICENSE +0 -0
  90. {agentscope_runtime-0.1.5b1.dist-info → agentscope_runtime-0.1.6.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,447 @@
1
+ # -*- coding: utf-8 -*-
2
+ # pylint:disable=too-many-nested-blocks, too-many-branches, too-many-statements
3
+ # pylint:disable=line-too-long, protected-access
4
+ import copy
5
+ import logging
6
+ import json
7
+ import traceback
8
+ from functools import partial
9
+ from typing import Optional, Type, List
10
+
11
+ from agentscope import setup_logger
12
+ from agentscope.agent import AgentBase, ReActAgent
13
+ from agentscope.formatter import (
14
+ FormatterBase,
15
+ DashScopeChatFormatter,
16
+ OpenAIChatFormatter,
17
+ AnthropicChatFormatter,
18
+ OllamaChatFormatter,
19
+ GeminiChatFormatter,
20
+ )
21
+ from agentscope.memory import InMemoryMemory
22
+ from agentscope.message import (
23
+ Msg,
24
+ ToolUseBlock,
25
+ ToolResultBlock,
26
+ TextBlock,
27
+ ImageBlock,
28
+ # AudioBlock, # TODO: support
29
+ # VideoBlock, # TODO: support
30
+ URLSource,
31
+ )
32
+ from agentscope.model import (
33
+ ChatModelBase,
34
+ DashScopeChatModel,
35
+ OpenAIChatModel,
36
+ AnthropicChatModel,
37
+ OllamaChatModel,
38
+ GeminiChatModel,
39
+ )
40
+ from agentscope.pipeline import stream_printing_messages
41
+ from agentscope.tool import (
42
+ Toolkit,
43
+ ToolResponse,
44
+ )
45
+ from agentscope.tool._toolkit import RegisteredToolFunction
46
+
47
+
48
+ from .utils import build_agent
49
+ from ..agents import Agent
50
+ from ..schemas.agent_schemas import (
51
+ Message,
52
+ TextContent,
53
+ DataContent,
54
+ FunctionCall,
55
+ FunctionCallOutput,
56
+ MessageType,
57
+ )
58
+ from ..schemas.context import Context
59
+
60
+ # Disable logging from agentscope
61
+ setup_logger(level="CRITICAL")
62
+ logger = logging.getLogger(__name__)
63
+
64
+
65
+ class AgentScopeContextAdapter:
66
+ def __init__(self, context: Context, attr: dict):
67
+ self.context = context
68
+ self.attr = attr
69
+
70
+ # Adapted attribute
71
+ self.toolkit = None
72
+ self.model = None
73
+ self.memory = None
74
+ self.new_message = None
75
+
76
+ async def initialize(self):
77
+ self.model, self.formatter = await self.adapt_model()
78
+ self.memory = await self.adapt_memory()
79
+ self.new_message = await self.adapt_new_message()
80
+ self.toolkit = await self.adapt_tools()
81
+
82
+ async def adapt_memory(self):
83
+ memory = self.attr["agent_config"].get("memory", InMemoryMemory())
84
+ messages = []
85
+
86
+ # Build context
87
+ for msg in self.context.session.messages[:-1]: # Exclude the last one
88
+ messages.append(AgentScopeContextAdapter.converter(msg))
89
+
90
+ state_dict = {"content": [_.to_dict() for _ in messages]}
91
+ memory.load_state_dict(state_dict)
92
+
93
+ return memory
94
+
95
+ @staticmethod
96
+ def converter(message: Message) -> Msg:
97
+ if message.role not in ["user", "system", "assistant"]:
98
+ role_label = "user"
99
+ else:
100
+ role_label = message.role
101
+
102
+ result = {
103
+ "name": message.role,
104
+ "role": role_label,
105
+ "invocation_id": message.id,
106
+ }
107
+
108
+ if message.type in (
109
+ MessageType.PLUGIN_CALL,
110
+ MessageType.FUNCTION_CALL,
111
+ ):
112
+ # convert PLUGIN_CALL, FUNCTION_CALL to ToolUseBlock
113
+ result["content"] = [
114
+ ToolUseBlock(
115
+ type="tool_use",
116
+ id=message.content[0].data["call_id"],
117
+ name=message.role,
118
+ input=json.loads(message.content[0].data["arguments"]),
119
+ ),
120
+ ]
121
+ elif message.type in (
122
+ MessageType.PLUGIN_CALL_OUTPUT,
123
+ MessageType.FUNCTION_CALL_OUTPUT,
124
+ ):
125
+ # convert PLUGIN_CALL_OUTPUT, FUNCTION_CALL_OUTPUT to
126
+ # ToolResultBlock
127
+ result["content"] = [
128
+ ToolResultBlock(
129
+ type="tool_result",
130
+ id=message.content[0].data["call_id"],
131
+ name=message.role,
132
+ output=message.content[0].data["output"],
133
+ ),
134
+ ]
135
+ else:
136
+ type_mapping = {
137
+ "text": (TextBlock, "text", None),
138
+ "image": (ImageBlock, "image_url", True),
139
+ # "audio": (AudioBlock, "audio_url", True), # TODO: support
140
+ # "video": (VideoBlock, "video_url", True), # TODO: support
141
+ }
142
+
143
+ msg_content = []
144
+ for cnt in message.content:
145
+ cnt_type = cnt.type or "text"
146
+
147
+ if cnt_type not in type_mapping:
148
+ raise ValueError(f"Unsupported message type: {cnt_type}")
149
+
150
+ block_cls, attr_name, is_url = type_mapping[cnt_type]
151
+ value = getattr(cnt, attr_name)
152
+
153
+ if is_url:
154
+ url_source = URLSource(type="url", url=value)
155
+ msg_content.append(
156
+ block_cls(type=cnt_type, source=url_source),
157
+ )
158
+ else:
159
+ msg_content.append(block_cls(type=cnt_type, text=value))
160
+
161
+ result["content"] = msg_content
162
+ return Msg(**result)
163
+
164
+ async def adapt_new_message(self):
165
+ last_message = self.context.session.messages[-1]
166
+ return AgentScopeContextAdapter.converter(last_message)
167
+
168
+ async def adapt_model(self):
169
+ model = self.attr["model"]
170
+ formatter = self.attr["agent_config"].get("formatter")
171
+ if formatter and isinstance(formatter, FormatterBase):
172
+ return model, formatter
173
+
174
+ if isinstance(model, OpenAIChatModel):
175
+ formatter = OpenAIChatFormatter()
176
+ elif isinstance(model, DashScopeChatModel):
177
+ formatter = DashScopeChatFormatter()
178
+ elif isinstance(model, AnthropicChatModel):
179
+ formatter = AnthropicChatFormatter()
180
+ elif isinstance(model, OllamaChatModel):
181
+ formatter = OllamaChatFormatter()
182
+ elif isinstance(model, GeminiChatModel):
183
+ formatter = GeminiChatFormatter()
184
+
185
+ return model, formatter
186
+
187
+ async def adapt_tools(self):
188
+ def func_wrapper(func, **kwargs):
189
+ func_res = func(**kwargs)
190
+ return ToolResponse(
191
+ content=func_res["content"],
192
+ )
193
+
194
+ toolkit = self.attr["agent_config"].get("toolkit", Toolkit())
195
+
196
+ # Deepcopy to avoid modify the original toolkit
197
+ try:
198
+ toolkit = copy.deepcopy(toolkit)
199
+ except Exception as e:
200
+ logger.warning(
201
+ f"Failed to deepcopy toolkit for agent "
202
+ f"'{self.attr.get('agent_config', {}).get('name')}' "
203
+ f"Error: {e}\nTraceback:\n{traceback.format_exc()}",
204
+ )
205
+
206
+ tools = self.attr["tools"]
207
+
208
+ # in case, tools is None and tools == []
209
+ if not tools:
210
+ return toolkit
211
+
212
+ if self.context.activate_tools:
213
+ # Only add activated tool
214
+ activated_tools = self.context.activate_tools
215
+ else:
216
+ # Lazy import
217
+ from ...sandbox.tools.utils import setup_tools
218
+
219
+ activated_tools = setup_tools(
220
+ tools=self.attr["tools"],
221
+ environment_manager=self.context.environment_manager,
222
+ session_id=self.context.session.id,
223
+ user_id=self.context.session.user_id,
224
+ include_schemas=False,
225
+ )
226
+
227
+ for tool in activated_tools:
228
+ function = RegisteredToolFunction(
229
+ name=tool.name,
230
+ source="mcp_server",
231
+ mcp_name=tool.tool_type,
232
+ original_func=partial(
233
+ func_wrapper,
234
+ tool,
235
+ ),
236
+ json_schema=tool.schema,
237
+ group="basic",
238
+ )
239
+ toolkit.tools[tool.name] = function
240
+
241
+ return toolkit
242
+
243
+
244
+ class AgentScopeAgent(Agent):
245
+ def __init__(
246
+ self,
247
+ name: str,
248
+ model: ChatModelBase,
249
+ tools=None,
250
+ agent_config=None,
251
+ agent_builder: Optional[Type[AgentBase]] = ReActAgent,
252
+ ):
253
+ super().__init__(name=name, agent_config=agent_config)
254
+ assert isinstance(
255
+ model,
256
+ ChatModelBase,
257
+ ), "model must be a subclass of ChatModelBase in AgentScope"
258
+
259
+ # Set default agent_builder
260
+ if agent_builder is None:
261
+ agent_builder = ReActAgent
262
+
263
+ assert issubclass(
264
+ agent_builder,
265
+ AgentBase,
266
+ ), "agent_builder must be a subclass of AgentBase in AgentScope"
267
+
268
+ # Replace name if not exists
269
+ self.agent_config["name"] = self.agent_config.get("name") or name
270
+
271
+ self._attr = {
272
+ "model": model,
273
+ "tools": tools,
274
+ "agent_config": self.agent_config,
275
+ "agent_builder": agent_builder,
276
+ }
277
+ self.tools = tools
278
+
279
+ def copy(self) -> "AgentScopeAgent":
280
+ return AgentScopeAgent(**self._attr)
281
+
282
+ def build(self, as_context) -> AgentBase:
283
+ params = {
284
+ **self._attr["agent_config"],
285
+ **{
286
+ "model": as_context.model,
287
+ "formatter": self._attr["agent_config"].get(
288
+ "formatter",
289
+ as_context.formatter,
290
+ ),
291
+ "memory": as_context.memory,
292
+ "toolkit": as_context.toolkit,
293
+ },
294
+ }
295
+
296
+ builder_cls = self._attr["agent_builder"]
297
+ _agent = build_agent(builder_cls, params)
298
+ _agent.set_console_output_enabled(False)
299
+
300
+ return _agent
301
+
302
+ async def run_async(
303
+ self,
304
+ context,
305
+ **kwargs,
306
+ ):
307
+ as_context = AgentScopeContextAdapter(context=context, attr=self._attr)
308
+ await as_context.initialize()
309
+ local_truncate_memory = ""
310
+
311
+ # We should always build a new agent since the state is manage outside
312
+ # the agent
313
+ _agent = self.build(as_context)
314
+
315
+ # Yield new Msg instances as they are logged
316
+ last_content = ""
317
+
318
+ message = Message(type=MessageType.MESSAGE, role="assistant")
319
+ yield message.in_progress()
320
+ index = None
321
+
322
+ # Run agent
323
+ async for msg, last in stream_printing_messages(
324
+ agents=[_agent],
325
+ coroutine_task=_agent(as_context.new_message),
326
+ ):
327
+ # deepcopy required to avoid modifying the original message object
328
+ # which may be used elsewhere in the streaming pipeline
329
+ msg = copy.deepcopy(msg)
330
+
331
+ # Filter out unfinished tool_use messages
332
+ if not last:
333
+ new_blocks = []
334
+ if isinstance(msg.content, List):
335
+ for block in msg.content:
336
+ if block.get("type", "") != "tool_use":
337
+ new_blocks.append(block)
338
+ msg.content = new_blocks
339
+
340
+ if not msg.content:
341
+ continue
342
+
343
+ # TODO: make this as a message converter
344
+ content = msg.content
345
+ if isinstance(content, str):
346
+ last_content = content
347
+ else:
348
+ for element in content:
349
+ if isinstance(element, str) and element:
350
+ text_delta_content = TextContent(
351
+ delta=True,
352
+ index=index,
353
+ text=element,
354
+ )
355
+ text_delta_content = message.add_delta_content(
356
+ new_content=text_delta_content,
357
+ )
358
+ index = text_delta_content.index
359
+ yield text_delta_content
360
+ elif isinstance(element, dict):
361
+ if element.get("type") == "text":
362
+ text = element.get(
363
+ "text",
364
+ "",
365
+ )
366
+ if text:
367
+ text_delta_content = TextContent(
368
+ delta=True,
369
+ index=index,
370
+ text=text.removeprefix(
371
+ local_truncate_memory,
372
+ ),
373
+ )
374
+ local_truncate_memory = element.get(
375
+ "text",
376
+ "",
377
+ )
378
+ text_delta_content = message.add_delta_content(
379
+ new_content=text_delta_content,
380
+ )
381
+ index = text_delta_content.index
382
+
383
+ # Only yield valid text
384
+ if text_delta_content.text:
385
+ yield text_delta_content
386
+
387
+ if last:
388
+ yield message.completed()
389
+ message = Message(
390
+ type=MessageType.MESSAGE,
391
+ role="assistant",
392
+ )
393
+ index = None
394
+
395
+ elif element.get("type") == "tool_use":
396
+ json_str = json.dumps(element.get("input"))
397
+ data_delta_content = DataContent(
398
+ index=index,
399
+ data=FunctionCall(
400
+ call_id=element.get("id"),
401
+ name=element.get("name"),
402
+ arguments=json_str,
403
+ ).model_dump(),
404
+ )
405
+ plugin_call_message = Message(
406
+ type=MessageType.PLUGIN_CALL,
407
+ role="assistant",
408
+ content=[data_delta_content],
409
+ )
410
+ yield plugin_call_message.completed()
411
+ elif element.get("type") == "tool_result":
412
+ data_delta_content = DataContent(
413
+ index=index,
414
+ data=FunctionCallOutput(
415
+ call_id=element.get("id"),
416
+ output=str(element.get("output")),
417
+ ).model_dump(),
418
+ )
419
+ plugin_output_message = Message(
420
+ type=MessageType.PLUGIN_CALL_OUTPUT,
421
+ role="assistant",
422
+ content=[data_delta_content],
423
+ )
424
+ yield plugin_output_message.completed()
425
+ else:
426
+ text_delta_content = TextContent(
427
+ delta=True,
428
+ index=index,
429
+ text=f"{element}",
430
+ )
431
+ text_delta_content = message.add_delta_content(
432
+ new_content=text_delta_content,
433
+ )
434
+ index = text_delta_content.index
435
+ yield text_delta_content
436
+
437
+ if last_content:
438
+ text_delta_content = TextContent(
439
+ delta=True,
440
+ index=index,
441
+ text=last_content,
442
+ )
443
+ text_delta_content = message.add_delta_content(
444
+ new_content=text_delta_content,
445
+ )
446
+ yield text_delta_content
447
+ yield message.completed()
@@ -12,6 +12,7 @@ from agno.run.response import (
12
12
  )
13
13
  from agno.tools.function import Function
14
14
 
15
+ from .utils import build_agent
15
16
  from ..agents import Agent
16
17
  from ..schemas.context import Context
17
18
  from ..schemas.agent_schemas import (
@@ -64,7 +65,7 @@ class AgnoContextAdapter:
64
65
  return self.attr["model"]
65
66
 
66
67
  async def adapt_tools(self):
67
- toolkit = self.attr["agent_config"].get("toolkit", [])
68
+ toolkit = self.attr["agent_config"].get("tools", [])
68
69
  tools = self.attr["tools"]
69
70
 
70
71
  # in case, tools is None and tools == []
@@ -131,30 +132,38 @@ class AgnoAgent(Agent):
131
132
  "agent_config": self.agent_config,
132
133
  "agent_builder": agent_builder,
133
134
  }
134
- self._agent = None
135
135
  self.tools = tools
136
136
 
137
137
  def copy(self) -> "AgnoAgent":
138
138
  return AgnoAgent(**self._attr)
139
139
 
140
140
  def build(self, as_context):
141
- self._agent = self._attr["agent_builder"](
141
+ params = {
142
142
  **self._attr["agent_config"],
143
- model=as_context.model,
144
- tools=as_context.toolkit,
145
- )
143
+ **{
144
+ "model": as_context.model,
145
+ "tools": as_context.toolkit,
146
+ }, # Context will be added at `_agent.arun`
147
+ }
146
148
 
147
- return self._agent
149
+ builder_cls = self._attr["agent_builder"]
150
+ _agent = build_agent(builder_cls, params)
148
151
 
149
- async def run(self, context):
152
+ return _agent
153
+
154
+ async def run_async(
155
+ self,
156
+ context,
157
+ **kwargs,
158
+ ):
150
159
  ag_context = AgnoContextAdapter(context=context, attr=self._attr)
151
160
  await ag_context.initialize()
152
161
 
153
162
  # We should always build a new agent since the state is manage outside
154
163
  # the agent
155
- self._agent = self.build(ag_context)
164
+ _agent = self.build(ag_context)
156
165
 
157
- resp = await self._agent.arun(
166
+ resp = await _agent.arun(
158
167
  ag_context.new_message,
159
168
  messages=ag_context.memory,
160
169
  stream=True,
@@ -211,11 +220,3 @@ class AgnoAgent(Agent):
211
220
  if is_text_delta:
212
221
  yield text_message.content_completed(text_delta_content.index)
213
222
  yield text_message.completed()
214
-
215
- async def run_async(
216
- self,
217
- context,
218
- **kwargs,
219
- ):
220
- async for event in self.run(context):
221
- yield event
@@ -11,6 +11,7 @@ from autogen_agentchat.messages import (
11
11
  ModelClientStreamingChunkEvent,
12
12
  )
13
13
 
14
+ from .utils import build_agent
14
15
  from ..agents import Agent
15
16
  from ..schemas.context import Context
16
17
  from ..schemas.agent_schemas import (
@@ -136,20 +137,24 @@ class AutogenAgent(Agent):
136
137
  "agent_config": self.agent_config,
137
138
  "agent_builder": agent_builder,
138
139
  }
139
- self._agent = None
140
140
  self.tools = tools
141
141
 
142
142
  def copy(self) -> "AutogenAgent":
143
143
  return AutogenAgent(**self._attr)
144
144
 
145
145
  def build(self, as_context):
146
- self._agent = self._attr["agent_builder"](
146
+ params = {
147
147
  **self._attr["agent_config"],
148
- model_client=as_context.model,
149
- tools=as_context.toolkit,
150
- )
148
+ **{
149
+ "model_client": as_context.model,
150
+ "tools": as_context.toolkit,
151
+ }, # Context will be added at `_agent.run_stream`
152
+ }
153
+
154
+ builder_cls = self._attr["agent_builder"]
155
+ _agent = build_agent(builder_cls, params)
151
156
 
152
- return self._agent
157
+ return _agent
153
158
 
154
159
  async def run(self, context):
155
160
  ag_context = AutogenContextAdapter(context=context, attr=self._attr)
@@ -157,9 +162,9 @@ class AutogenAgent(Agent):
157
162
 
158
163
  # We should always build a new agent since the state is manage outside
159
164
  # the agent
160
- self._agent = self.build(ag_context)
165
+ _agent = self.build(ag_context)
161
166
 
162
- resp = self._agent.run_stream(
167
+ resp = _agent.run_stream(
163
168
  task=ag_context.memory + [ag_context.new_message],
164
169
  )
165
170
 
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ import inspect
3
+ import logging
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ def build_agent(builder_cls, params):
9
+ """
10
+ Filters out unsupported parameters based on the __init__ signature of
11
+ builder_cls
12
+ and instantiates the class.
13
+
14
+ Args:
15
+ builder_cls (type): The class to instantiate.
16
+ params (dict): Dictionary of parameters to pass to the constructor.
17
+
18
+ Returns:
19
+ object: An instance of builder_cls.
20
+ """
21
+ try:
22
+ # Get the signature of the __init__ method
23
+ sig = inspect.signature(builder_cls.__init__)
24
+ allowed_params = set(sig.parameters.keys())
25
+ # Remove 'self' from the list of allowed parameters
26
+ allowed_params.discard("self")
27
+ except (TypeError, ValueError):
28
+ # If signature cannot be inspected, allow all given params
29
+ allowed_params = set(params.keys())
30
+
31
+ filtered_params = {} # Parameters that are accepted by the constructor
32
+ unsupported = [] # Parameters that are not accepted
33
+
34
+ # Separate supported and unsupported parameters
35
+ for k, v in params.items():
36
+ if k in allowed_params:
37
+ filtered_params[k] = v
38
+ else:
39
+ unsupported.append(f"{k}={v!r}")
40
+
41
+ # Log a warning if there are unsupported parameters
42
+ if unsupported:
43
+ unsupported_str = ", ".join(unsupported)
44
+ logger.warning(
45
+ f"The following parameters are not supported by "
46
+ f"{builder_cls.__name__} and have been ignored: "
47
+ f"{unsupported_str}. If you require these parameters, "
48
+ f"please update the `__init__` method of "
49
+ f"{builder_cls.__name__} to accept and handle them.",
50
+ )
51
+
52
+ # Instantiate the class with only supported parameters
53
+ return builder_cls(**filtered_params)
@@ -1,16 +1,3 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  from .base import DeployManager
3
3
  from .local_deployer import LocalDeployManager
4
- from .kubernetes_deployer import (
5
- KubernetesDeployManager,
6
- )
7
- from .modelstudio_deployer import (
8
- ModelstudioDeployManager,
9
- )
10
-
11
- __all__ = [
12
- "DeployManager",
13
- "LocalDeployManager",
14
- "KubernetesDeployManager",
15
- "ModelstudioDeployManager",
16
- ]