refactor: update agentscope[full] to 1.0.11 (#92)

This commit is contained in:
MeiXin Chen
2026-01-09 17:03:35 +08:00
committed by GitHub
parent fe4b7f53b0
commit 72991cdddb
15 changed files with 312 additions and 190 deletions

View File

@@ -288,7 +288,7 @@ The backend server will:
- Create the initial superuser account (if not exists)
- 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
@@ -361,7 +361,7 @@ Once both servers are running:
- **Frontend UI**: Open `http://localhost:5173` in your browser
- **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)
- **Health Check**: `http://localhost:8000/api/v1/monitor/health`
- **Health Check**: `http://localhost:8000/api/v1/health`
#### Default Login Credentials

View File

@@ -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/api/v1/monitor/health` 来验证服务器是否正在运行。
通过访问 `http://localhost:8000/api/v1/health` 来验证服务器是否正在运行。
#### 启动前端
@@ -362,7 +362,7 @@ bash script/start_memory_service.sh
- **前端 UI**:在浏览器中打开 `http://localhost:5173`
- **后端 API**:可在 `http://localhost:8000` 访问
- **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`
#### 默认登录凭据

View File

@@ -31,7 +31,7 @@ dependencies = [
"elasticsearch>=9.0.0",
"jinja2>=3.1.6",
"bcrypt==4.0.1",
"agentscope[full]==1.0.7",
"agentscope[full]==1.0.11",
"tenacity>=8.5.0",
"apscheduler>=3.11.0",
"chardet>=5.2.0",
@@ -42,7 +42,7 @@ dependencies = [
"alembic>=1.16.1",
"openpyxl>=3.1.5",
"sentry-sdk[fastapi]===2.30.0",
"agentscope-runtime==0.2.0",
"agentscope-runtime>=1.0.0",
"aiosqlite>=0.21.0",
"asyncpg>=0.30.0",
"itsdangerous>=2.2.0"

View File

@@ -11,7 +11,7 @@ from agentscope.agent import ReActAgent
from agentscope.model import ChatModelBase
from agentscope.formatter import FormatterBase
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.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
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):
def __init__(
self,
@@ -53,7 +35,6 @@ class AliasAgentBase(ReActAgent):
state_saving_dir: Optional[str] = None,
sys_prompt: Optional[str] = None,
max_iters: int = 10,
tool_call_interrupt_return: bool = True,
long_term_memory: Optional[LongTermMemoryBase] = None,
long_term_memory_mode: Literal[
"agent_control",
@@ -77,14 +58,7 @@ class AliasAgentBase(ReActAgent):
self.message_sending_mapping = {}
self.state_saving_dir = state_saving_dir
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
self.register_instance_hook(
"post_print",
@@ -92,7 +66,16 @@ class AliasAgentBase(ReActAgent):
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."""
# Call the parent class's _reasoning method directly to
@@ -109,7 +92,8 @@ class AliasAgentBase(ReActAgent):
if hasattr(original_method, "__wrapped__"):
# This is the wrapped version, get the original
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):
try:
@@ -132,21 +116,18 @@ class AliasAgentBase(ReActAgent):
# final attempt
await call_parent_reasoning()
async def _acting(self, tool_call: ToolUseBlock) -> Msg | None:
"""Perform the acting process.
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
async def _acting(self, tool_call: ToolUseBlock) -> dict | None:
"""Perform the acting process, and return the structured output if
it's generated and verified in the finish function call.
Args:
tool_call (`ToolUseBlock`):
The tool use block to be executed.
Returns:
`Union[Msg, None]`:
Return a message to the user if the `_finish_function` is
called, otherwise return `None`.
`Union[dict, None]`:
Return the structured output if it's verified in the finish
function call.
"""
tool_res_msg = Msg(
@@ -165,7 +146,6 @@ class AliasAgentBase(ReActAgent):
# Execute the tool call
tool_res = await self.toolkit.call_tool_function(tool_call)
response_msg = None
# Async generator handling
async for chunk in tool_res:
# Turn into a tool result block
@@ -191,28 +171,26 @@ class AliasAgentBase(ReActAgent):
tool_call["name"] != self.finish_function_name
or (
tool_call["name"] == self.finish_function_name
and chunk.metadata
and not chunk.metadata.get("success")
)
):
await self.print(tool_res_msg, chunk.is_last)
# Return message if generate_response is called successfully
if tool_call[
"name"
] in self.agent_stop_function_names and chunk.metadata.get(
"success",
True,
if (
tool_call["name"] in self.agent_stop_function_names
and chunk.metadata
and chunk.metadata.get(
"success",
True,
)
):
response_msg = chunk.metadata.get("response_msg")
return chunk.metadata.get("structured_output")
elif chunk.is_interrupted:
# TODO: monkey patch happens here
response_msg = tool_res_msg
if response_msg.metadata is None:
response_msg.metadata = {"is_interrupted": True}
else:
response_msg.metadata["is_interrupted"] = True
raise asyncio.CancelledError
return response_msg
return None
finally:
# Record the tool result message in the memory
await self.memory.add(tool_res_msg)
@@ -228,16 +206,16 @@ class AliasAgentBase(ReActAgent):
"""
response_msg = Msg(
self.name,
content=[
TextBlock(
type="text",
text="I got interrupted by the user. "
"Pivot to handle the user's new request.",
),
],
role="assistant",
metadata={},
"I noticed that you have interrupted me. What can I "
"do for you?",
"assistant",
metadata={
# Expose this field to indicate the interruption
"_is_interrupted": True,
},
)
await self.print(response_msg, True)
await self.memory.add(response_msg)
# update and save agent states

View File

@@ -10,7 +10,7 @@ import os
import json
import inspect
from functools import wraps
from typing import Type, Optional, Any
from typing import Type, Optional, Any, Literal
import asyncio
import copy
from loguru import logger
@@ -104,6 +104,10 @@ with open(
_BROWSER_AGENT_SUMMARIZE_TASK_PROMPT = f.read()
class EmptyModel(BaseModel):
pass
async def browser_pre_reply_hook(
self,
kwargs: dict[str, Any],
@@ -150,6 +154,7 @@ async def browser_post_acting_hook(
] = self._filter_execution_text(return_json["text"])
if tool_call["name"] != self.finish_function_name or (
tool_call["name"] == self.finish_function_name
and tool_res_msg.metadata
and not tool_res_msg.metadata.get("success")
):
await self.print(tool_res_msg)
@@ -343,6 +348,7 @@ class BrowserAgent(AliasAgentBase):
or "gpt-5" in self.model.model_name
)
# pylint: disable=R0912,R0915
async def reply(
self,
msg: Msg | list[Msg] | None = None,
@@ -370,20 +376,38 @@ class BrowserAgent(AliasAgentBase):
else ""
)
if structured_model is None:
structured_model = EmptyModel
tool_choice: Literal["auto", "none", "required"] | None = None
self._required_structured_model = structured_model
# Record structured output model if provided
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.finish_function_name,
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
structured_output = None
reply_msg = None
for iter_n in range(self.max_iters):
self.iter_n = iter_n + 1
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")
if tool_calls and tool_calls[0]["name"] == "browser_snapshot":
msg_reasoning = await self._reasoning_with_observation()
@@ -397,27 +421,69 @@ class BrowserAgent(AliasAgentBase):
# Parallel tool calls or not
if self.parallel_tool_calls:
acting_responses = await asyncio.gather(*futures)
structured_outputs = await asyncio.gather(*futures)
else:
# 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
for acting_msg in acting_responses:
reply_msg = reply_msg or acting_msg
# -------------- Check for exit condition --------------
# If structured output is still not satisfied
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
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
if not reply_msg:
reply_msg = await self._summarizing()
await self.memory.add(reply_msg)
# 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)
return reply_msg
async def _pure_reasoning(
self,
tool_choice: Literal["auto", "none", "required"] | None = None,
) -> Msg:
msg = Msg(
"user",
@@ -433,12 +499,18 @@ class BrowserAgent(AliasAgentBase):
Msg("system", self.sys_prompt, "system"),
*await self.memory.get_memory(),
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(
prompt,
tools=self.no_screenshot_tool_list,
tool_choice=tool_choice,
)
# handle output from the model
interrupted_by_user = False
@@ -1260,15 +1332,6 @@ class BrowserAgent(AliasAgentBase):
subtask_progress_summary=summary_text,
generated_files={},
)
response_msg = Msg(
self.name,
content=[
TextBlock(type="text", text=summary_text),
],
role="assistant",
metadata=structure_response.model_dump(),
)
return ToolResponse(
content=[
TextBlock(
@@ -1278,7 +1341,7 @@ class BrowserAgent(AliasAgentBase):
],
metadata={
"success": True,
"response_msg": response_msg,
"structured_output": structure_response.model_dump(),
},
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}",
),
],
metadata={"success": False, "response_msg": None},
metadata={"success": False, "structured_output": None},
is_last=True,
)
except Exception as e:
@@ -1310,8 +1373,8 @@ class BrowserAgent(AliasAgentBase):
sys_prompt = (
"You are an expert in task validation. "
"Your job is to determine if the agent has completed its task"
" based on the provided summary. If finished, strictly reply "
'"BROWSER_AGENT_TASK_FINISHED", otherwise return the remaining '
" based on the provided summary. If the summary is `NO_ANSWER`, this task is not over. If finished, strictly reply "
'"BROWSER_AGENT_TASK_FINISHED" and your reason, otherwise return the remaining '
"tasks or next steps."
)
# Extract user question from memory

View File

@@ -4,10 +4,9 @@ import asyncio
import json
import os
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 shortuuid
from agentscope.formatter import FormatterBase
from agentscope.memory import MemoryBase
from agentscope.message import Msg, TextBlock, ToolUseBlock, ToolResultBlock
@@ -15,7 +14,7 @@ from agentscope.model import ChatModelBase
from agentscope.tool import ToolResponse
from agentscope.tracing import trace_reply
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 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
class DefaultStructuredResponse(BaseModel):
response: str = Field(
description="Just a placeholder. "
"Enter any character to trigger report generation",
)
class DataScienceAgent(AliasAgentBase):
def __init__(
self,
@@ -194,27 +200,140 @@ class DataScienceAgent(AliasAgentBase):
"pre_reply",
"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)
async def _reasoning(
self,
tool_choice: str = "required",
) -> Msg:
"""Perform the reasoning process."""
prompt = await self.formatter.format(
msgs=[
Msg("system", self.sys_prompt, "system"),
*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:
res = await self.model(
prompt,
tools=self.toolkit.get_json_schemas(),
tool_choice=tool_choice,
)
except Exception as e:
print(str(e))
logger.debug("Error while calling model in _reasoning: {}", e)
# handle output from the model
interrupted_by_user = False
@@ -238,18 +357,6 @@ class DataScienceAgent(AliasAgentBase):
raise e from None
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
await self.memory.add(msg)
@@ -279,17 +386,10 @@ class DataScienceAgent(AliasAgentBase):
# pylint: disable=invalid-overridden-method, unused-argument
async def generate_response(
self,
response: str,
**kwargs: Any,
) -> ToolResponse:
"""Call this function when you have either completed the task
or cannot continue due to insurmountable reasons.
Provide in the `response` argument any information you believe
the user needs to be informed of.
Args:
response (`str`):
Your response to the user.
"""
Generate required structured output by this function and return it
"""
memory = await self.memory.get_memory()
memory_log = "\n\n".join(
@@ -350,20 +450,15 @@ class DataScienceAgent(AliasAgentBase):
f"{self.detailed_report_path}."
)
response_msg = Msg(
self.name,
response,
"assistant",
)
await self.print(response_msg, True)
kwargs["response"] = response
structured_output = {}
# Prepare structured output
if self._required_structured_model:
try:
# Use the metadata field of the message to store the
# structured output
response_msg.metadata = (
structured_output = (
self._required_structured_model.model_validate(
kwargs,
).model_dump()
@@ -379,10 +474,18 @@ class DataScienceAgent(AliasAgentBase):
],
metadata={
"success": False,
"response_msg": None,
"structured_output": {},
},
)
await self.print(
Msg(
name=self.name,
content=response,
role="assistant",
),
True,
)
return ToolResponse(
content=[
TextBlock(
@@ -392,7 +495,7 @@ class DataScienceAgent(AliasAgentBase):
],
metadata={
"success": True,
"response_msg": response_msg,
"structured_output": structured_output,
},
is_last=True,
)

View File

@@ -107,6 +107,8 @@ class DeepResearchAgent(AliasAgentBase):
x,
x.get("task_type", "general"),
)
if x
else None
),
)
self.node_level_report = node_level_report

View File

@@ -245,12 +245,19 @@ class MetaPlanner(AliasAgentBase):
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
if enable_clarification:
self._required_structured_model = (
MetaPlannerResponseWithClarification
)
response_func = self.toolkit.tools.get(self.finish_function_name)
response_func.json_schema["function"][
"description"
] = response_func.json_schema["function"].get(
@@ -265,7 +272,6 @@ class MetaPlanner(AliasAgentBase):
self._required_structured_model = (
MetaPlannerResponseNoClarification
)
response_func = self.toolkit.tools.get(self.finish_function_name)
response_func.json_schema["function"][
"description"
] = response_func.json_schema["function"].get(

View File

@@ -1,15 +1,11 @@
# -*- coding: utf-8 -*-
# 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.formatter import FormatterBase
from agentscope.memory import MemoryBase
from agentscope.tool import ToolResponse
from agentscope.message import (
Msg,
TextBlock,
)
from dotenv import load_dotenv
from alias.agent.agents import AliasAgentBase
@@ -50,21 +46,22 @@ class ReActWorker(AliasAgentBase):
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)
def generate_response(
self,
response: str = "",
task_done: bool = True,
subtask_progress_summary: str = "",
generated_files: dict[str, str] = None,
) -> ToolResponse:
**kwargs,
): # pylint: disable=useless-parent-delegation
"""
Generate a response summarizing the execution progress of the
given subtask.
Args:
response (str):
The response text (compatible with AgentScope finish function).
task_done (bool):
REQUIRED! Whether the subtask was done or not.
subtask_progress_summary (str):
@@ -76,37 +73,4 @@ class ReActWorker(AliasAgentBase):
paths of generated files (e.g. '/FULL/PATH/OF/FILE_1.md') and
the values are short descriptions about the generated files.
"""
if generated_files is None:
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,
)
return super().generate_response(**kwargs)

View File

@@ -106,7 +106,7 @@ async def save_post_reasoning_state(
async def save_post_action_state(
self: AliasAgentBase,
action_input: dict[str, Any], # pylint: disable=W0613
tool_output: Optional[Msg], # pylint: disable=W0613
tool_output: Optional[dict], # pylint: disable=W0613
) -> None:
"""Hook func for save state after action step"""
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(
self: AliasAgentBase,
action_input: dict[str, Any], # pylint: disable=W0613
tool_output: Optional[Msg], # pylint: disable=W0613
tool_output: Optional[dict], # pylint: disable=W0613
) -> None:
"""Hook func for printing clarification"""
if not (hasattr(self, "session_service") and self.session_service):
return
if isinstance(tool_output, Msg):
if tool_output.metadata and tool_output.metadata.get(
if isinstance(tool_output, dict):
if tool_output.get(
"require_clarification",
False,
):
clarification_dict = {
"clarification_question": tool_output.metadata.get(
"clarification_question": tool_output.get(
"clarification_question",
"",
),
"clarification_options": tool_output.metadata.get(
"clarification_options": tool_output.get(
"clarification_options",
"",
),
@@ -144,7 +144,7 @@ async def generate_response_post_action_hook(
indent=4,
),
role="assistant",
metadata=tool_output.metadata,
metadata=tool_output,
)
await self.print(msg, last=True)

View File

@@ -76,14 +76,15 @@ class WorkerResponse(BaseModel):
"""
subtask_progress_summary: str = Field(
...,
default="",
description=WORKER_PROGRESS_SUMMARY,
)
generated_files: dict = Field(
...,
default=dict,
description=WORKER_FILE_COLLECTION_INSTRUCTION,
)
task_done: bool = Field(
...,
description="Whether task is done or it require addition effort",
default=True,
description="Whether the task is done or "
"it requires additional effort",
)

View File

@@ -9,7 +9,9 @@ from .utils import (
)
from .ds_toolkit import add_ds_specific_tool
from .prompt_selector import LLMPromptSelector
from .agent_hook import files_filter_pre_reply_hook
from .agent_hook import (
files_filter_pre_reply_hook,
)
__all__ = [
"ReportGenerator",

View File

@@ -128,7 +128,7 @@ async def _planner_save_plan_with_session(
async def planner_save_post_action_state(
self: MetaPlanner,
action_input: dict[str, Any], # pylint: disable=W0613
tool_output: Optional[Msg], # pylint: disable=W0613
tool_output: Optional[dict], # pylint: disable=W0613
) -> None:
"""Hook func for save state after action step"""
await _update_and_save_state_with_session(self)

View File

@@ -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.share import router as share_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.include_router(user_router)
@@ -19,3 +20,4 @@ router.include_router(chat_router)
router.include_router(file_router)
router.include_router(inner_router)
router.include_router(share_router)
router.include_router(monitor_router)

View File

@@ -80,6 +80,7 @@ class ConversationService(BaseService[Conversation]):
base_url=settings.SANDBOX_URL,
bearer_token=settings.SANDBOX_BEARER_TOKEN,
)
sandbox.__enter__()
conversation_data = Conversation(
user_id=user_id,