refactor: update agentscope[full] to 1.0.11 (#92)
This commit is contained in:
@@ -288,7 +288,7 @@ The backend server will:
|
|||||||
- Create the initial superuser account (if not exists)
|
- Create the initial superuser account (if not exists)
|
||||||
- Start on `http://localhost:8000` (or the port specified in `.env`)
|
- Start on `http://localhost:8000` (or the port specified in `.env`)
|
||||||
|
|
||||||
Verify the server is running by visiting `http://localhost:8000/api/v1/monitor/health`.
|
Verify the server is running by visiting `http://localhost:8000/api/v1/health`.
|
||||||
|
|
||||||
#### Start the Frontend
|
#### Start the Frontend
|
||||||
|
|
||||||
@@ -361,7 +361,7 @@ Once both servers are running:
|
|||||||
- **Frontend UI**: Open `http://localhost:5173` in your browser
|
- **Frontend UI**: Open `http://localhost:5173` in your browser
|
||||||
- **Backend API**: Available at `http://localhost:8000`
|
- **Backend API**: Available at `http://localhost:8000`
|
||||||
- **API Documentation**: Available at `http://localhost:8000/docs` (Swagger UI) or `http://localhost:8000/api/v1/openapi.json` (OpenAPI JSON)
|
- **API Documentation**: Available at `http://localhost:8000/docs` (Swagger UI) or `http://localhost:8000/api/v1/openapi.json` (OpenAPI JSON)
|
||||||
- **Health Check**: `http://localhost:8000/api/v1/monitor/health`
|
- **Health Check**: `http://localhost:8000/api/v1/health`
|
||||||
|
|
||||||
#### Default Login Credentials
|
#### Default Login Credentials
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ python -m uvicorn alias.server.main:app --host 0.0.0.0 --port 8000 --reload
|
|||||||
- 创建初始超级用户账户(如果不存在)
|
- 创建初始超级用户账户(如果不存在)
|
||||||
- 在 `http://localhost:8000` 启动(或 `.env` 中指定的端口)
|
- 在 `http://localhost:8000` 启动(或 `.env` 中指定的端口)
|
||||||
|
|
||||||
通过访问 `http://localhost:8000/api/v1/monitor/health` 来验证服务器是否正在运行。
|
通过访问 `http://localhost:8000/api/v1/health` 来验证服务器是否正在运行。
|
||||||
|
|
||||||
#### 启动前端
|
#### 启动前端
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ bash script/start_memory_service.sh
|
|||||||
- **前端 UI**:在浏览器中打开 `http://localhost:5173`
|
- **前端 UI**:在浏览器中打开 `http://localhost:5173`
|
||||||
- **后端 API**:可在 `http://localhost:8000` 访问
|
- **后端 API**:可在 `http://localhost:8000` 访问
|
||||||
- **API 文档**:可在 `http://localhost:8000/docs` (Swagger UI) 或 `http://localhost:8000/api/v1/openapi.json` (OpenAPI JSON) 访问
|
- **API 文档**:可在 `http://localhost:8000/docs` (Swagger UI) 或 `http://localhost:8000/api/v1/openapi.json` (OpenAPI JSON) 访问
|
||||||
- **健康检查**:`http://localhost:8000/api/v1/monitor/health`
|
- **健康检查**:`http://localhost:8000/api/v1/health`
|
||||||
|
|
||||||
#### 默认登录凭据
|
#### 默认登录凭据
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ dependencies = [
|
|||||||
"elasticsearch>=9.0.0",
|
"elasticsearch>=9.0.0",
|
||||||
"jinja2>=3.1.6",
|
"jinja2>=3.1.6",
|
||||||
"bcrypt==4.0.1",
|
"bcrypt==4.0.1",
|
||||||
"agentscope[full]==1.0.7",
|
"agentscope[full]==1.0.11",
|
||||||
"tenacity>=8.5.0",
|
"tenacity>=8.5.0",
|
||||||
"apscheduler>=3.11.0",
|
"apscheduler>=3.11.0",
|
||||||
"chardet>=5.2.0",
|
"chardet>=5.2.0",
|
||||||
@@ -42,7 +42,7 @@ dependencies = [
|
|||||||
"alembic>=1.16.1",
|
"alembic>=1.16.1",
|
||||||
"openpyxl>=3.1.5",
|
"openpyxl>=3.1.5",
|
||||||
"sentry-sdk[fastapi]===2.30.0",
|
"sentry-sdk[fastapi]===2.30.0",
|
||||||
"agentscope-runtime==0.2.0",
|
"agentscope-runtime>=1.0.0",
|
||||||
"aiosqlite>=0.21.0",
|
"aiosqlite>=0.21.0",
|
||||||
"asyncpg>=0.30.0",
|
"asyncpg>=0.30.0",
|
||||||
"itsdangerous>=2.2.0"
|
"itsdangerous>=2.2.0"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from agentscope.agent import ReActAgent
|
|||||||
from agentscope.model import ChatModelBase
|
from agentscope.model import ChatModelBase
|
||||||
from agentscope.formatter import FormatterBase
|
from agentscope.formatter import FormatterBase
|
||||||
from agentscope.memory import MemoryBase, LongTermMemoryBase
|
from agentscope.memory import MemoryBase, LongTermMemoryBase
|
||||||
from agentscope.message import Msg, TextBlock, ToolUseBlock, ToolResultBlock
|
from agentscope.message import Msg, ToolUseBlock, ToolResultBlock
|
||||||
|
|
||||||
from alias.agent.tools import AliasToolkit
|
from alias.agent.tools import AliasToolkit
|
||||||
from alias.agent.utils.constants import DEFAULT_PLANNER_NAME
|
from alias.agent.utils.constants import DEFAULT_PLANNER_NAME
|
||||||
@@ -23,24 +23,6 @@ from alias.agent.utils.constants import DEFAULT_BROWSER_WORKER_NAME
|
|||||||
from alias.agent.utils.constants import MODEL_MAX_RETRIES
|
from alias.agent.utils.constants import MODEL_MAX_RETRIES
|
||||||
|
|
||||||
|
|
||||||
def alias_agent_post_reply_hook(
|
|
||||||
self: "AliasAgentBase",
|
|
||||||
kwargs: dict[str, Any], # pylint: disable=unused-argument
|
|
||||||
output: Any,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
This is a monkey patch to ensure that when the agent is interrupted in
|
|
||||||
a tool call, the control returns to user
|
|
||||||
"""
|
|
||||||
if (
|
|
||||||
self.tool_call_interrupt_return
|
|
||||||
and isinstance(output, Msg)
|
|
||||||
and output.metadata
|
|
||||||
and output.metadata.get("is_interrupted", False)
|
|
||||||
):
|
|
||||||
raise asyncio.CancelledError()
|
|
||||||
|
|
||||||
|
|
||||||
class AliasAgentBase(ReActAgent):
|
class AliasAgentBase(ReActAgent):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -53,7 +35,6 @@ class AliasAgentBase(ReActAgent):
|
|||||||
state_saving_dir: Optional[str] = None,
|
state_saving_dir: Optional[str] = None,
|
||||||
sys_prompt: Optional[str] = None,
|
sys_prompt: Optional[str] = None,
|
||||||
max_iters: int = 10,
|
max_iters: int = 10,
|
||||||
tool_call_interrupt_return: bool = True,
|
|
||||||
long_term_memory: Optional[LongTermMemoryBase] = None,
|
long_term_memory: Optional[LongTermMemoryBase] = None,
|
||||||
long_term_memory_mode: Literal[
|
long_term_memory_mode: Literal[
|
||||||
"agent_control",
|
"agent_control",
|
||||||
@@ -77,14 +58,7 @@ class AliasAgentBase(ReActAgent):
|
|||||||
self.message_sending_mapping = {}
|
self.message_sending_mapping = {}
|
||||||
self.state_saving_dir = state_saving_dir
|
self.state_saving_dir = state_saving_dir
|
||||||
self.agent_stop_function_names = [self.finish_function_name]
|
self.agent_stop_function_names = [self.finish_function_name]
|
||||||
self.tool_call_interrupt_return = tool_call_interrupt_return
|
|
||||||
|
|
||||||
# interrupted if the
|
|
||||||
self.register_instance_hook(
|
|
||||||
"post_reply",
|
|
||||||
"alias_agent_post_reply_hook",
|
|
||||||
alias_agent_post_reply_hook,
|
|
||||||
)
|
|
||||||
# for message output to backend
|
# for message output to backend
|
||||||
self.register_instance_hook(
|
self.register_instance_hook(
|
||||||
"post_print",
|
"post_print",
|
||||||
@@ -92,7 +66,16 @@ class AliasAgentBase(ReActAgent):
|
|||||||
alias_post_print_hook,
|
alias_post_print_hook,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _reasoning(self):
|
# register finish_function_name
|
||||||
|
if self.finish_function_name not in self.toolkit.tools:
|
||||||
|
self.toolkit.register_tool_function(
|
||||||
|
getattr(self, self.finish_function_name),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _reasoning(
|
||||||
|
self,
|
||||||
|
tool_choice: Literal["auto", "none", "required"] | None = None,
|
||||||
|
):
|
||||||
"""Override _reasoning to add retry logic."""
|
"""Override _reasoning to add retry logic."""
|
||||||
|
|
||||||
# Call the parent class's _reasoning method directly to
|
# Call the parent class's _reasoning method directly to
|
||||||
@@ -109,7 +92,8 @@ class AliasAgentBase(ReActAgent):
|
|||||||
if hasattr(original_method, "__wrapped__"):
|
if hasattr(original_method, "__wrapped__"):
|
||||||
# This is the wrapped version, get the original
|
# This is the wrapped version, get the original
|
||||||
original_method = original_method.__wrapped__
|
original_method = original_method.__wrapped__
|
||||||
return await original_method(self)
|
|
||||||
|
return await original_method(self, tool_choice=tool_choice)
|
||||||
|
|
||||||
for i in range(MODEL_MAX_RETRIES - 1):
|
for i in range(MODEL_MAX_RETRIES - 1):
|
||||||
try:
|
try:
|
||||||
@@ -132,21 +116,18 @@ class AliasAgentBase(ReActAgent):
|
|||||||
# final attempt
|
# final attempt
|
||||||
await call_parent_reasoning()
|
await call_parent_reasoning()
|
||||||
|
|
||||||
async def _acting(self, tool_call: ToolUseBlock) -> Msg | None:
|
async def _acting(self, tool_call: ToolUseBlock) -> dict | None:
|
||||||
"""Perform the acting process.
|
"""Perform the acting process, and return the structured output if
|
||||||
|
it's generated and verified in the finish function call.
|
||||||
TODO: (part 2)
|
|
||||||
this is just a monkey patch for AS when not support interruption
|
|
||||||
during tool call; can be remove when AS framework updated
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tool_call (`ToolUseBlock`):
|
tool_call (`ToolUseBlock`):
|
||||||
The tool use block to be executed.
|
The tool use block to be executed.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
`Union[Msg, None]`:
|
`Union[dict, None]`:
|
||||||
Return a message to the user if the `_finish_function` is
|
Return the structured output if it's verified in the finish
|
||||||
called, otherwise return `None`.
|
function call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tool_res_msg = Msg(
|
tool_res_msg = Msg(
|
||||||
@@ -165,7 +146,6 @@ class AliasAgentBase(ReActAgent):
|
|||||||
# Execute the tool call
|
# Execute the tool call
|
||||||
tool_res = await self.toolkit.call_tool_function(tool_call)
|
tool_res = await self.toolkit.call_tool_function(tool_call)
|
||||||
|
|
||||||
response_msg = None
|
|
||||||
# Async generator handling
|
# Async generator handling
|
||||||
async for chunk in tool_res:
|
async for chunk in tool_res:
|
||||||
# Turn into a tool result block
|
# Turn into a tool result block
|
||||||
@@ -191,28 +171,26 @@ class AliasAgentBase(ReActAgent):
|
|||||||
tool_call["name"] != self.finish_function_name
|
tool_call["name"] != self.finish_function_name
|
||||||
or (
|
or (
|
||||||
tool_call["name"] == self.finish_function_name
|
tool_call["name"] == self.finish_function_name
|
||||||
|
and chunk.metadata
|
||||||
and not chunk.metadata.get("success")
|
and not chunk.metadata.get("success")
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
await self.print(tool_res_msg, chunk.is_last)
|
await self.print(tool_res_msg, chunk.is_last)
|
||||||
|
|
||||||
# Return message if generate_response is called successfully
|
# Return message if generate_response is called successfully
|
||||||
if tool_call[
|
if (
|
||||||
"name"
|
tool_call["name"] in self.agent_stop_function_names
|
||||||
] in self.agent_stop_function_names and chunk.metadata.get(
|
and chunk.metadata
|
||||||
|
and chunk.metadata.get(
|
||||||
"success",
|
"success",
|
||||||
True,
|
True,
|
||||||
|
)
|
||||||
):
|
):
|
||||||
response_msg = chunk.metadata.get("response_msg")
|
return chunk.metadata.get("structured_output")
|
||||||
elif chunk.is_interrupted:
|
elif chunk.is_interrupted:
|
||||||
# TODO: monkey patch happens here
|
raise asyncio.CancelledError
|
||||||
response_msg = tool_res_msg
|
|
||||||
if response_msg.metadata is None:
|
|
||||||
response_msg.metadata = {"is_interrupted": True}
|
|
||||||
else:
|
|
||||||
response_msg.metadata["is_interrupted"] = True
|
|
||||||
|
|
||||||
return response_msg
|
return None
|
||||||
finally:
|
finally:
|
||||||
# Record the tool result message in the memory
|
# Record the tool result message in the memory
|
||||||
await self.memory.add(tool_res_msg)
|
await self.memory.add(tool_res_msg)
|
||||||
@@ -228,16 +206,16 @@ class AliasAgentBase(ReActAgent):
|
|||||||
"""
|
"""
|
||||||
response_msg = Msg(
|
response_msg = Msg(
|
||||||
self.name,
|
self.name,
|
||||||
content=[
|
"I noticed that you have interrupted me. What can I "
|
||||||
TextBlock(
|
"do for you?",
|
||||||
type="text",
|
"assistant",
|
||||||
text="I got interrupted by the user. "
|
metadata={
|
||||||
"Pivot to handle the user's new request.",
|
# Expose this field to indicate the interruption
|
||||||
),
|
"_is_interrupted": True,
|
||||||
],
|
},
|
||||||
role="assistant",
|
|
||||||
metadata={},
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await self.print(response_msg, True)
|
||||||
await self.memory.add(response_msg)
|
await self.memory.add(response_msg)
|
||||||
|
|
||||||
# update and save agent states
|
# update and save agent states
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import os
|
|||||||
import json
|
import json
|
||||||
import inspect
|
import inspect
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import Type, Optional, Any
|
from typing import Type, Optional, Any, Literal
|
||||||
import asyncio
|
import asyncio
|
||||||
import copy
|
import copy
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
@@ -104,6 +104,10 @@ with open(
|
|||||||
_BROWSER_AGENT_SUMMARIZE_TASK_PROMPT = f.read()
|
_BROWSER_AGENT_SUMMARIZE_TASK_PROMPT = f.read()
|
||||||
|
|
||||||
|
|
||||||
|
class EmptyModel(BaseModel):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def browser_pre_reply_hook(
|
async def browser_pre_reply_hook(
|
||||||
self,
|
self,
|
||||||
kwargs: dict[str, Any],
|
kwargs: dict[str, Any],
|
||||||
@@ -150,6 +154,7 @@ async def browser_post_acting_hook(
|
|||||||
] = self._filter_execution_text(return_json["text"])
|
] = self._filter_execution_text(return_json["text"])
|
||||||
if tool_call["name"] != self.finish_function_name or (
|
if tool_call["name"] != self.finish_function_name or (
|
||||||
tool_call["name"] == self.finish_function_name
|
tool_call["name"] == self.finish_function_name
|
||||||
|
and tool_res_msg.metadata
|
||||||
and not tool_res_msg.metadata.get("success")
|
and not tool_res_msg.metadata.get("success")
|
||||||
):
|
):
|
||||||
await self.print(tool_res_msg)
|
await self.print(tool_res_msg)
|
||||||
@@ -343,6 +348,7 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
or "gpt-5" in self.model.model_name
|
or "gpt-5" in self.model.model_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# pylint: disable=R0912,R0915
|
||||||
async def reply(
|
async def reply(
|
||||||
self,
|
self,
|
||||||
msg: Msg | list[Msg] | None = None,
|
msg: Msg | list[Msg] | None = None,
|
||||||
@@ -370,20 +376,38 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
else ""
|
else ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if structured_model is None:
|
||||||
|
structured_model = EmptyModel
|
||||||
|
|
||||||
|
tool_choice: Literal["auto", "none", "required"] | None = None
|
||||||
|
|
||||||
self._required_structured_model = structured_model
|
self._required_structured_model = structured_model
|
||||||
# Record structured output model if provided
|
# Record structured output model if provided
|
||||||
if structured_model:
|
if structured_model:
|
||||||
|
# Register generate_response tool only when structured output
|
||||||
|
# is required
|
||||||
|
if self.finish_function_name not in self.toolkit.tools:
|
||||||
|
self.toolkit.register_tool_function(
|
||||||
|
getattr(self, self.finish_function_name),
|
||||||
|
)
|
||||||
|
|
||||||
self.toolkit.set_extended_model(
|
self.toolkit.set_extended_model(
|
||||||
self.finish_function_name,
|
self.finish_function_name,
|
||||||
structured_model,
|
structured_model,
|
||||||
)
|
)
|
||||||
|
tool_choice = "required"
|
||||||
|
else:
|
||||||
|
# Remove generate_response tool if no structured output is required
|
||||||
|
self.toolkit.remove_tool_function(self.finish_function_name)
|
||||||
|
|
||||||
# The reasoning-acting loop
|
# The reasoning-acting loop
|
||||||
|
structured_output = None
|
||||||
reply_msg = None
|
reply_msg = None
|
||||||
for iter_n in range(self.max_iters):
|
for iter_n in range(self.max_iters):
|
||||||
self.iter_n = iter_n + 1
|
self.iter_n = iter_n + 1
|
||||||
await self._summarize_mem()
|
await self._summarize_mem()
|
||||||
|
|
||||||
msg_reasoning = await self._pure_reasoning()
|
msg_reasoning = await self._pure_reasoning(tool_choice)
|
||||||
tool_calls = msg_reasoning.get_content_blocks("tool_use")
|
tool_calls = msg_reasoning.get_content_blocks("tool_use")
|
||||||
if tool_calls and tool_calls[0]["name"] == "browser_snapshot":
|
if tool_calls and tool_calls[0]["name"] == "browser_snapshot":
|
||||||
msg_reasoning = await self._reasoning_with_observation()
|
msg_reasoning = await self._reasoning_with_observation()
|
||||||
@@ -397,27 +421,69 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
|
|
||||||
# Parallel tool calls or not
|
# Parallel tool calls or not
|
||||||
if self.parallel_tool_calls:
|
if self.parallel_tool_calls:
|
||||||
acting_responses = await asyncio.gather(*futures)
|
structured_outputs = await asyncio.gather(*futures)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Sequential tool calls
|
# Sequential tool calls
|
||||||
acting_responses = [await _ for _ in futures]
|
structured_outputs = [await _ for _ in futures]
|
||||||
|
|
||||||
# Find the first non-None replying message from the acting
|
# -------------- Check for exit condition --------------
|
||||||
for acting_msg in acting_responses:
|
# If structured output is still not satisfied
|
||||||
reply_msg = reply_msg or acting_msg
|
if self._required_structured_model:
|
||||||
|
# Remove None results
|
||||||
|
structured_outputs = [_ for _ in structured_outputs if _]
|
||||||
|
|
||||||
if reply_msg:
|
msg_hint = None
|
||||||
|
# If the acting step generates structured outputs
|
||||||
|
if structured_outputs:
|
||||||
|
# Cache the structured output data
|
||||||
|
structured_output = structured_outputs[-1]
|
||||||
|
|
||||||
|
reply_msg = Msg(
|
||||||
|
self.name,
|
||||||
|
structured_output.get("subtask_progress_summary", ""),
|
||||||
|
"assistant",
|
||||||
|
metadata=structured_output,
|
||||||
|
)
|
||||||
break
|
break
|
||||||
# When the maximum iterations are reached
|
|
||||||
if not reply_msg:
|
|
||||||
reply_msg = await self._summarizing()
|
|
||||||
|
|
||||||
|
if not msg_reasoning.has_content_blocks("tool_use"):
|
||||||
|
# If structured output is required but no tool call is
|
||||||
|
# made, remind the llm to go on the task
|
||||||
|
msg_hint = Msg(
|
||||||
|
"user",
|
||||||
|
"<system-hint>Structured output is "
|
||||||
|
f"required, go on to finish your task or call "
|
||||||
|
f"'{self.finish_function_name}' to generate the "
|
||||||
|
f"required structured output.</system-hint>",
|
||||||
|
"user",
|
||||||
|
)
|
||||||
|
await self._reasoning_hint_msgs.add(msg_hint)
|
||||||
|
# Require tool call in the next reasoning step
|
||||||
|
tool_choice = "required"
|
||||||
|
|
||||||
|
if msg_hint and self.print_hint_msg:
|
||||||
|
await self.print(msg_hint)
|
||||||
|
|
||||||
|
elif not msg_reasoning.has_content_blocks("tool_use"):
|
||||||
|
# Exit the loop when no structured output is required (or
|
||||||
|
# already satisfied) and only text response is generated
|
||||||
|
msg_reasoning.metadata = structured_output
|
||||||
|
reply_msg = msg_reasoning
|
||||||
|
break
|
||||||
|
|
||||||
|
# When the maximum iterations are reached
|
||||||
|
# and no reply message is generated
|
||||||
|
if reply_msg is None:
|
||||||
|
reply_msg = await self._summarizing()
|
||||||
|
reply_msg.metadata = structured_output
|
||||||
await self.memory.add(reply_msg)
|
await self.memory.add(reply_msg)
|
||||||
|
|
||||||
return reply_msg
|
return reply_msg
|
||||||
|
|
||||||
async def _pure_reasoning(
|
async def _pure_reasoning(
|
||||||
self,
|
self,
|
||||||
|
tool_choice: Literal["auto", "none", "required"] | None = None,
|
||||||
) -> Msg:
|
) -> Msg:
|
||||||
msg = Msg(
|
msg = Msg(
|
||||||
"user",
|
"user",
|
||||||
@@ -433,12 +499,18 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
Msg("system", self.sys_prompt, "system"),
|
Msg("system", self.sys_prompt, "system"),
|
||||||
*await self.memory.get_memory(),
|
*await self.memory.get_memory(),
|
||||||
msg,
|
msg,
|
||||||
|
# The hint messages to guide the agent's behavior, maybe empty
|
||||||
|
*await self._reasoning_hint_msgs.get_memory(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Clear the hint messages after use
|
||||||
|
await self._reasoning_hint_msgs.clear()
|
||||||
|
|
||||||
res = await self.model(
|
res = await self.model(
|
||||||
prompt,
|
prompt,
|
||||||
tools=self.no_screenshot_tool_list,
|
tools=self.no_screenshot_tool_list,
|
||||||
|
tool_choice=tool_choice,
|
||||||
)
|
)
|
||||||
# handle output from the model
|
# handle output from the model
|
||||||
interrupted_by_user = False
|
interrupted_by_user = False
|
||||||
@@ -1260,15 +1332,6 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
subtask_progress_summary=summary_text,
|
subtask_progress_summary=summary_text,
|
||||||
generated_files={},
|
generated_files={},
|
||||||
)
|
)
|
||||||
|
|
||||||
response_msg = Msg(
|
|
||||||
self.name,
|
|
||||||
content=[
|
|
||||||
TextBlock(type="text", text=summary_text),
|
|
||||||
],
|
|
||||||
role="assistant",
|
|
||||||
metadata=structure_response.model_dump(),
|
|
||||||
)
|
|
||||||
return ToolResponse(
|
return ToolResponse(
|
||||||
content=[
|
content=[
|
||||||
TextBlock(
|
TextBlock(
|
||||||
@@ -1278,7 +1341,7 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
],
|
],
|
||||||
metadata={
|
metadata={
|
||||||
"success": True,
|
"success": True,
|
||||||
"response_msg": response_msg,
|
"structured_output": structure_response.model_dump(),
|
||||||
},
|
},
|
||||||
is_last=True,
|
is_last=True,
|
||||||
)
|
)
|
||||||
@@ -1290,7 +1353,7 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
text=f"Here is a summary of current status:\n{summary_text}\nPlease continue.\n Following steps \n {finish_status}",
|
text=f"Here is a summary of current status:\n{summary_text}\nPlease continue.\n Following steps \n {finish_status}",
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
metadata={"success": False, "response_msg": None},
|
metadata={"success": False, "structured_output": None},
|
||||||
is_last=True,
|
is_last=True,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -1310,8 +1373,8 @@ class BrowserAgent(AliasAgentBase):
|
|||||||
sys_prompt = (
|
sys_prompt = (
|
||||||
"You are an expert in task validation. "
|
"You are an expert in task validation. "
|
||||||
"Your job is to determine if the agent has completed its task"
|
"Your job is to determine if the agent has completed its task"
|
||||||
" based on the provided summary. If finished, strictly reply "
|
" based on the provided summary. If the summary is `NO_ANSWER`, this task is not over. If finished, strictly reply "
|
||||||
'"BROWSER_AGENT_TASK_FINISHED", otherwise return the remaining '
|
'"BROWSER_AGENT_TASK_FINISHED" and your reason, otherwise return the remaining '
|
||||||
"tasks or next steps."
|
"tasks or next steps."
|
||||||
)
|
)
|
||||||
# Extract user question from memory
|
# Extract user question from memory
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ import asyncio
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from typing import List, Dict, Optional, Any, Type, cast
|
from typing import List, Dict, Optional, Any, Type, cast, Literal
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import shortuuid
|
|
||||||
from agentscope.formatter import FormatterBase
|
from agentscope.formatter import FormatterBase
|
||||||
from agentscope.memory import MemoryBase
|
from agentscope.memory import MemoryBase
|
||||||
from agentscope.message import Msg, TextBlock, ToolUseBlock, ToolResultBlock
|
from agentscope.message import Msg, TextBlock, ToolUseBlock, ToolResultBlock
|
||||||
@@ -15,7 +14,7 @@ from agentscope.model import ChatModelBase
|
|||||||
from agentscope.tool import ToolResponse
|
from agentscope.tool import ToolResponse
|
||||||
from agentscope.tracing import trace_reply
|
from agentscope.tracing import trace_reply
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pydantic import BaseModel, ValidationError
|
from pydantic import BaseModel, ValidationError, Field
|
||||||
from tenacity import retry, stop_after_attempt, wait_fixed
|
from tenacity import retry, stop_after_attempt, wait_fixed
|
||||||
|
|
||||||
from alias.agent.agents import AliasAgentBase
|
from alias.agent.agents import AliasAgentBase
|
||||||
@@ -37,6 +36,13 @@ from .ds_agent_utils import (
|
|||||||
from .ds_agent_utils.ds_config import PROMPT_DS_BASE_PATH
|
from .ds_agent_utils.ds_config import PROMPT_DS_BASE_PATH
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultStructuredResponse(BaseModel):
|
||||||
|
response: str = Field(
|
||||||
|
description="Just a placeholder. "
|
||||||
|
"Enter any character to trigger report generation",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DataScienceAgent(AliasAgentBase):
|
class DataScienceAgent(AliasAgentBase):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -194,27 +200,140 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
"pre_reply",
|
"pre_reply",
|
||||||
"files_filter_pre_reply_hook",
|
"files_filter_pre_reply_hook",
|
||||||
)
|
)
|
||||||
return await super().reply(msg, structured_model)
|
|
||||||
|
if structured_model is None:
|
||||||
|
structured_model = DefaultStructuredResponse
|
||||||
|
|
||||||
|
# Record the input message(s) in the memory
|
||||||
|
await self.memory.add(msg)
|
||||||
|
|
||||||
|
# -------------- Retrieval process --------------
|
||||||
|
# Retrieve relevant records from the long-term memory if activated
|
||||||
|
await self._retrieve_from_long_term_memory(msg)
|
||||||
|
# Retrieve relevant documents from the knowledge base(s) if any
|
||||||
|
await self._retrieve_from_knowledge(msg)
|
||||||
|
|
||||||
|
# Control if LLM generates tool calls in each reasoning step
|
||||||
|
tool_choice: Literal["auto", "none", "required"] | None = None
|
||||||
|
|
||||||
|
# -------------- Structured output management --------------
|
||||||
|
self._required_structured_model = structured_model
|
||||||
|
|
||||||
|
# Register generate_response tool only when structured output
|
||||||
|
# is required
|
||||||
|
if self.finish_function_name not in self.toolkit.tools:
|
||||||
|
self.toolkit.register_tool_function(
|
||||||
|
getattr(self, self.finish_function_name),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set the structured output model
|
||||||
|
self.toolkit.set_extended_model(
|
||||||
|
self.finish_function_name,
|
||||||
|
structured_model,
|
||||||
|
)
|
||||||
|
tool_choice = "required"
|
||||||
|
|
||||||
|
# -------------- The reasoning-acting loop --------------
|
||||||
|
# Cache the structured output generated in the finish function call
|
||||||
|
structured_output = None
|
||||||
|
reply_msg = None
|
||||||
|
for _ in range(self.max_iters):
|
||||||
|
# -------------- The reasoning process --------------
|
||||||
|
msg_reasoning = await self._reasoning(tool_choice)
|
||||||
|
|
||||||
|
# -------------- The acting process --------------
|
||||||
|
futures = [
|
||||||
|
self._acting(tool_call)
|
||||||
|
for tool_call in msg_reasoning.get_content_blocks(
|
||||||
|
"tool_use",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
# Parallel tool calls or not
|
||||||
|
if self.parallel_tool_calls:
|
||||||
|
structured_outputs = await asyncio.gather(*futures)
|
||||||
|
else:
|
||||||
|
# Sequential tool calls
|
||||||
|
structured_outputs = [await _ for _ in futures]
|
||||||
|
|
||||||
|
# -------------- Check for exit condition --------------
|
||||||
|
# Remove None results
|
||||||
|
structured_outputs = [_ for _ in structured_outputs if _]
|
||||||
|
|
||||||
|
msg_hint = None
|
||||||
|
# If the acting step generates structured outputs
|
||||||
|
if structured_outputs:
|
||||||
|
# Cache the structured output data
|
||||||
|
structured_output = structured_outputs[-1]
|
||||||
|
|
||||||
|
reply_msg = Msg(
|
||||||
|
self.name,
|
||||||
|
structured_output.get("response"),
|
||||||
|
"assistant",
|
||||||
|
metadata=structured_output,
|
||||||
|
)
|
||||||
|
break
|
||||||
|
|
||||||
|
if not msg_reasoning.has_content_blocks("tool_use"):
|
||||||
|
# If structured output is required but no tool call is
|
||||||
|
# made, remind the llm to go on the task
|
||||||
|
msg_hint = Msg(
|
||||||
|
"user",
|
||||||
|
"<system-hint>Structured output is "
|
||||||
|
f"required, go on to finish your task or call "
|
||||||
|
f"'{self.finish_function_name}' to generate the "
|
||||||
|
f"required structured output.</system-hint>",
|
||||||
|
"user",
|
||||||
|
)
|
||||||
|
await self._reasoning_hint_msgs.add(msg_hint)
|
||||||
|
|
||||||
|
if msg_hint and self.print_hint_msg:
|
||||||
|
await self.print(msg_hint)
|
||||||
|
|
||||||
|
# When the maximum iterations are reached
|
||||||
|
# and no reply message is generated
|
||||||
|
if reply_msg is None:
|
||||||
|
reply_msg = await self._summarizing()
|
||||||
|
reply_msg.metadata = structured_output
|
||||||
|
await self.memory.add(reply_msg)
|
||||||
|
|
||||||
|
# Post-process the memory, long-term memory
|
||||||
|
if self._static_control:
|
||||||
|
await self.long_term_memory.record(
|
||||||
|
[
|
||||||
|
*([*msg] if isinstance(msg, list) else [msg]),
|
||||||
|
*await self.memory.get_memory(),
|
||||||
|
reply_msg,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
return reply_msg
|
||||||
|
|
||||||
@retry(stop=stop_after_attempt(10), wait=wait_fixed(5), reraise=True)
|
@retry(stop=stop_after_attempt(10), wait=wait_fixed(5), reraise=True)
|
||||||
async def _reasoning(
|
async def _reasoning(
|
||||||
self,
|
self,
|
||||||
|
tool_choice: str = "required",
|
||||||
) -> Msg:
|
) -> Msg:
|
||||||
"""Perform the reasoning process."""
|
"""Perform the reasoning process."""
|
||||||
prompt = await self.formatter.format(
|
prompt = await self.formatter.format(
|
||||||
msgs=[
|
msgs=[
|
||||||
Msg("system", self.sys_prompt, "system"),
|
Msg("system", self.sys_prompt, "system"),
|
||||||
*await self.memory.get_memory(),
|
*await self.memory.get_memory(),
|
||||||
|
# The hint messages to guide the agent's behavior, maybe empty
|
||||||
|
*await self._reasoning_hint_msgs.get_memory(),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Clear the hint messages after use
|
||||||
|
await self._reasoning_hint_msgs.clear()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = await self.model(
|
res = await self.model(
|
||||||
prompt,
|
prompt,
|
||||||
tools=self.toolkit.get_json_schemas(),
|
tools=self.toolkit.get_json_schemas(),
|
||||||
|
tool_choice=tool_choice,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(str(e))
|
logger.debug("Error while calling model in _reasoning: {}", e)
|
||||||
|
|
||||||
# handle output from the model
|
# handle output from the model
|
||||||
interrupted_by_user = False
|
interrupted_by_user = False
|
||||||
@@ -238,18 +357,6 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
raise e from None
|
raise e from None
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if msg and not msg.has_content_blocks("tool_use"):
|
|
||||||
# Turn plain text response into a tool call of the finish
|
|
||||||
# function
|
|
||||||
msg.content = [
|
|
||||||
ToolUseBlock(
|
|
||||||
id=shortuuid.uuid(),
|
|
||||||
type="tool_use",
|
|
||||||
name=self.think_function_name,
|
|
||||||
input={"response": msg.get_text_content()},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
# None will be ignored by the memory
|
# None will be ignored by the memory
|
||||||
await self.memory.add(msg)
|
await self.memory.add(msg)
|
||||||
|
|
||||||
@@ -279,17 +386,10 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
# pylint: disable=invalid-overridden-method, unused-argument
|
# pylint: disable=invalid-overridden-method, unused-argument
|
||||||
async def generate_response(
|
async def generate_response(
|
||||||
self,
|
self,
|
||||||
response: str,
|
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> ToolResponse:
|
) -> ToolResponse:
|
||||||
"""Call this function when you have either completed the task
|
"""
|
||||||
or cannot continue due to insurmountable reasons.
|
Generate required structured output by this function and return it
|
||||||
Provide in the `response` argument any information you believe
|
|
||||||
the user needs to be informed of.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
response (`str`):
|
|
||||||
Your response to the user.
|
|
||||||
"""
|
"""
|
||||||
memory = await self.memory.get_memory()
|
memory = await self.memory.get_memory()
|
||||||
memory_log = "\n\n".join(
|
memory_log = "\n\n".join(
|
||||||
@@ -350,20 +450,15 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
f"{self.detailed_report_path}."
|
f"{self.detailed_report_path}."
|
||||||
)
|
)
|
||||||
|
|
||||||
response_msg = Msg(
|
kwargs["response"] = response
|
||||||
self.name,
|
structured_output = {}
|
||||||
response,
|
|
||||||
"assistant",
|
|
||||||
)
|
|
||||||
|
|
||||||
await self.print(response_msg, True)
|
|
||||||
|
|
||||||
# Prepare structured output
|
# Prepare structured output
|
||||||
if self._required_structured_model:
|
if self._required_structured_model:
|
||||||
try:
|
try:
|
||||||
# Use the metadata field of the message to store the
|
# Use the metadata field of the message to store the
|
||||||
# structured output
|
# structured output
|
||||||
response_msg.metadata = (
|
structured_output = (
|
||||||
self._required_structured_model.model_validate(
|
self._required_structured_model.model_validate(
|
||||||
kwargs,
|
kwargs,
|
||||||
).model_dump()
|
).model_dump()
|
||||||
@@ -379,10 +474,18 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
],
|
],
|
||||||
metadata={
|
metadata={
|
||||||
"success": False,
|
"success": False,
|
||||||
"response_msg": None,
|
"structured_output": {},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
await self.print(
|
||||||
|
Msg(
|
||||||
|
name=self.name,
|
||||||
|
content=response,
|
||||||
|
role="assistant",
|
||||||
|
),
|
||||||
|
True,
|
||||||
|
)
|
||||||
return ToolResponse(
|
return ToolResponse(
|
||||||
content=[
|
content=[
|
||||||
TextBlock(
|
TextBlock(
|
||||||
@@ -392,7 +495,7 @@ class DataScienceAgent(AliasAgentBase):
|
|||||||
],
|
],
|
||||||
metadata={
|
metadata={
|
||||||
"success": True,
|
"success": True,
|
||||||
"response_msg": response_msg,
|
"structured_output": structured_output,
|
||||||
},
|
},
|
||||||
is_last=True,
|
is_last=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ class DeepResearchAgent(AliasAgentBase):
|
|||||||
x,
|
x,
|
||||||
x.get("task_type", "general"),
|
x.get("task_type", "general"),
|
||||||
)
|
)
|
||||||
|
if x
|
||||||
|
else None
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
self.node_level_report = node_level_report
|
self.node_level_report = node_level_report
|
||||||
|
|||||||
@@ -245,12 +245,19 @@ class MetaPlanner(AliasAgentBase):
|
|||||||
long_term_memory.tool_memory_retrieve,
|
long_term_memory.tool_memory_retrieve,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# register finish_function_name
|
||||||
|
if not self.toolkit.tools.get(self.finish_function_name):
|
||||||
|
self.toolkit.register_tool_function(
|
||||||
|
self.finish_function_name,
|
||||||
|
)
|
||||||
|
|
||||||
|
response_func = self.toolkit.tools.get(self.finish_function_name)
|
||||||
|
|
||||||
# adjust ReActAgent parameters
|
# adjust ReActAgent parameters
|
||||||
if enable_clarification:
|
if enable_clarification:
|
||||||
self._required_structured_model = (
|
self._required_structured_model = (
|
||||||
MetaPlannerResponseWithClarification
|
MetaPlannerResponseWithClarification
|
||||||
)
|
)
|
||||||
response_func = self.toolkit.tools.get(self.finish_function_name)
|
|
||||||
response_func.json_schema["function"][
|
response_func.json_schema["function"][
|
||||||
"description"
|
"description"
|
||||||
] = response_func.json_schema["function"].get(
|
] = response_func.json_schema["function"].get(
|
||||||
@@ -265,7 +272,6 @@ class MetaPlanner(AliasAgentBase):
|
|||||||
self._required_structured_model = (
|
self._required_structured_model = (
|
||||||
MetaPlannerResponseNoClarification
|
MetaPlannerResponseNoClarification
|
||||||
)
|
)
|
||||||
response_func = self.toolkit.tools.get(self.finish_function_name)
|
|
||||||
response_func.json_schema["function"][
|
response_func.json_schema["function"][
|
||||||
"description"
|
"description"
|
||||||
] = response_func.json_schema["function"].get(
|
] = response_func.json_schema["function"].get(
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# pylint: disable=C2801, W0611, W0212
|
# pylint: disable=C2801, W0611, W0212
|
||||||
from typing import Optional, Any
|
from typing import Optional, Any, Callable
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
from agentscope.model import ChatModelBase
|
from agentscope.model import ChatModelBase
|
||||||
from agentscope.formatter import FormatterBase
|
from agentscope.formatter import FormatterBase
|
||||||
from agentscope.memory import MemoryBase
|
from agentscope.memory import MemoryBase
|
||||||
from agentscope.tool import ToolResponse
|
|
||||||
from agentscope.message import (
|
|
||||||
Msg,
|
|
||||||
TextBlock,
|
|
||||||
)
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
from alias.agent.agents import AliasAgentBase
|
from alias.agent.agents import AliasAgentBase
|
||||||
@@ -50,21 +46,22 @@ class ReActWorker(AliasAgentBase):
|
|||||||
state_saving_dir=state_saving_dir,
|
state_saving_dir=state_saving_dir,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self._required_structured_model = WorkerResponse
|
||||||
|
self.reply: Callable = partial(
|
||||||
|
self.reply,
|
||||||
|
structured_model=self._required_structured_model,
|
||||||
|
)
|
||||||
|
|
||||||
self.max_iters: int = max(self.max_iters, WORKER_MAX_ITER)
|
self.max_iters: int = max(self.max_iters, WORKER_MAX_ITER)
|
||||||
|
|
||||||
def generate_response(
|
def generate_response(
|
||||||
self,
|
self,
|
||||||
response: str = "",
|
**kwargs,
|
||||||
task_done: bool = True,
|
): # pylint: disable=useless-parent-delegation
|
||||||
subtask_progress_summary: str = "",
|
|
||||||
generated_files: dict[str, str] = None,
|
|
||||||
) -> ToolResponse:
|
|
||||||
"""
|
"""
|
||||||
Generate a response summarizing the execution progress of the
|
Generate a response summarizing the execution progress of the
|
||||||
given subtask.
|
given subtask.
|
||||||
Args:
|
Args:
|
||||||
response (str):
|
|
||||||
The response text (compatible with AgentScope finish function).
|
|
||||||
task_done (bool):
|
task_done (bool):
|
||||||
REQUIRED! Whether the subtask was done or not.
|
REQUIRED! Whether the subtask was done or not.
|
||||||
subtask_progress_summary (str):
|
subtask_progress_summary (str):
|
||||||
@@ -76,37 +73,4 @@ class ReActWorker(AliasAgentBase):
|
|||||||
paths of generated files (e.g. '/FULL/PATH/OF/FILE_1.md') and
|
paths of generated files (e.g. '/FULL/PATH/OF/FILE_1.md') and
|
||||||
the values are short descriptions about the generated files.
|
the values are short descriptions about the generated files.
|
||||||
"""
|
"""
|
||||||
if generated_files is None:
|
return super().generate_response(**kwargs)
|
||||||
generated_files = {}
|
|
||||||
|
|
||||||
# If only response is provided,
|
|
||||||
# use it as subtask_progress_summary
|
|
||||||
if not subtask_progress_summary and response:
|
|
||||||
subtask_progress_summary = response
|
|
||||||
|
|
||||||
structure_response = WorkerResponse(
|
|
||||||
task_done=task_done,
|
|
||||||
subtask_progress_summary=subtask_progress_summary,
|
|
||||||
generated_files=generated_files,
|
|
||||||
)
|
|
||||||
response_msg = Msg(
|
|
||||||
self.name,
|
|
||||||
content=[
|
|
||||||
TextBlock(type="text", text=subtask_progress_summary),
|
|
||||||
],
|
|
||||||
role="assistant",
|
|
||||||
metadata=structure_response.model_dump(),
|
|
||||||
)
|
|
||||||
return ToolResponse(
|
|
||||||
content=[
|
|
||||||
TextBlock(
|
|
||||||
type="text",
|
|
||||||
text="Successfully generated response.",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
metadata={
|
|
||||||
"success": True,
|
|
||||||
"response_msg": response_msg,
|
|
||||||
},
|
|
||||||
is_last=True,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ async def save_post_reasoning_state(
|
|||||||
async def save_post_action_state(
|
async def save_post_action_state(
|
||||||
self: AliasAgentBase,
|
self: AliasAgentBase,
|
||||||
action_input: dict[str, Any], # pylint: disable=W0613
|
action_input: dict[str, Any], # pylint: disable=W0613
|
||||||
tool_output: Optional[Msg], # pylint: disable=W0613
|
tool_output: Optional[dict], # pylint: disable=W0613
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Hook func for save state after action step"""
|
"""Hook func for save state after action step"""
|
||||||
await _update_and_save_state_with_session(self)
|
await _update_and_save_state_with_session(self)
|
||||||
@@ -115,23 +115,23 @@ async def save_post_action_state(
|
|||||||
async def generate_response_post_action_hook(
|
async def generate_response_post_action_hook(
|
||||||
self: AliasAgentBase,
|
self: AliasAgentBase,
|
||||||
action_input: dict[str, Any], # pylint: disable=W0613
|
action_input: dict[str, Any], # pylint: disable=W0613
|
||||||
tool_output: Optional[Msg], # pylint: disable=W0613
|
tool_output: Optional[dict], # pylint: disable=W0613
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Hook func for printing clarification"""
|
"""Hook func for printing clarification"""
|
||||||
if not (hasattr(self, "session_service") and self.session_service):
|
if not (hasattr(self, "session_service") and self.session_service):
|
||||||
return
|
return
|
||||||
|
|
||||||
if isinstance(tool_output, Msg):
|
if isinstance(tool_output, dict):
|
||||||
if tool_output.metadata and tool_output.metadata.get(
|
if tool_output.get(
|
||||||
"require_clarification",
|
"require_clarification",
|
||||||
False,
|
False,
|
||||||
):
|
):
|
||||||
clarification_dict = {
|
clarification_dict = {
|
||||||
"clarification_question": tool_output.metadata.get(
|
"clarification_question": tool_output.get(
|
||||||
"clarification_question",
|
"clarification_question",
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
"clarification_options": tool_output.metadata.get(
|
"clarification_options": tool_output.get(
|
||||||
"clarification_options",
|
"clarification_options",
|
||||||
"",
|
"",
|
||||||
),
|
),
|
||||||
@@ -144,7 +144,7 @@ async def generate_response_post_action_hook(
|
|||||||
indent=4,
|
indent=4,
|
||||||
),
|
),
|
||||||
role="assistant",
|
role="assistant",
|
||||||
metadata=tool_output.metadata,
|
metadata=tool_output,
|
||||||
)
|
)
|
||||||
await self.print(msg, last=True)
|
await self.print(msg, last=True)
|
||||||
|
|
||||||
|
|||||||
@@ -76,14 +76,15 @@ class WorkerResponse(BaseModel):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
subtask_progress_summary: str = Field(
|
subtask_progress_summary: str = Field(
|
||||||
...,
|
default="",
|
||||||
description=WORKER_PROGRESS_SUMMARY,
|
description=WORKER_PROGRESS_SUMMARY,
|
||||||
)
|
)
|
||||||
generated_files: dict = Field(
|
generated_files: dict = Field(
|
||||||
...,
|
default=dict,
|
||||||
description=WORKER_FILE_COLLECTION_INSTRUCTION,
|
description=WORKER_FILE_COLLECTION_INSTRUCTION,
|
||||||
)
|
)
|
||||||
task_done: bool = Field(
|
task_done: bool = Field(
|
||||||
...,
|
default=True,
|
||||||
description="Whether task is done or it require addition effort",
|
description="Whether the task is done or "
|
||||||
|
"it requires additional effort",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ from .utils import (
|
|||||||
)
|
)
|
||||||
from .ds_toolkit import add_ds_specific_tool
|
from .ds_toolkit import add_ds_specific_tool
|
||||||
from .prompt_selector import LLMPromptSelector
|
from .prompt_selector import LLMPromptSelector
|
||||||
from .agent_hook import files_filter_pre_reply_hook
|
from .agent_hook import (
|
||||||
|
files_filter_pre_reply_hook,
|
||||||
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"ReportGenerator",
|
"ReportGenerator",
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ async def _planner_save_plan_with_session(
|
|||||||
async def planner_save_post_action_state(
|
async def planner_save_post_action_state(
|
||||||
self: MetaPlanner,
|
self: MetaPlanner,
|
||||||
action_input: dict[str, Any], # pylint: disable=W0613
|
action_input: dict[str, Any], # pylint: disable=W0613
|
||||||
tool_output: Optional[Msg], # pylint: disable=W0613
|
tool_output: Optional[dict], # pylint: disable=W0613
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Hook func for save state after action step"""
|
"""Hook func for save state after action step"""
|
||||||
await _update_and_save_state_with_session(self)
|
await _update_and_save_state_with_session(self)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ from alias.server.api.v1.file import router as file_router
|
|||||||
from alias.server.api.v1.inner import router as inner_router
|
from alias.server.api.v1.inner import router as inner_router
|
||||||
from alias.server.api.v1.share import router as share_router
|
from alias.server.api.v1.share import router as share_router
|
||||||
from alias.server.api.v1.user import router as user_router
|
from alias.server.api.v1.user import router as user_router
|
||||||
|
from alias.server.api.v1.monitor import router as monitor_router
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
router.include_router(user_router)
|
router.include_router(user_router)
|
||||||
@@ -19,3 +20,4 @@ router.include_router(chat_router)
|
|||||||
router.include_router(file_router)
|
router.include_router(file_router)
|
||||||
router.include_router(inner_router)
|
router.include_router(inner_router)
|
||||||
router.include_router(share_router)
|
router.include_router(share_router)
|
||||||
|
router.include_router(monitor_router)
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ class ConversationService(BaseService[Conversation]):
|
|||||||
base_url=settings.SANDBOX_URL,
|
base_url=settings.SANDBOX_URL,
|
||||||
bearer_token=settings.SANDBOX_BEARER_TOKEN,
|
bearer_token=settings.SANDBOX_BEARER_TOKEN,
|
||||||
)
|
)
|
||||||
|
sandbox.__enter__()
|
||||||
|
|
||||||
conversation_data = Conversation(
|
conversation_data = Conversation(
|
||||||
user_id=user_id,
|
user_id=user_id,
|
||||||
|
|||||||
Reference in New Issue
Block a user