fix(middleware): 修复 RuntimeConfigMiddleware 的工具override 导致的其余中间件失效的问题(还需要进一步排查 subagents 的 model 是否有问题)
This commit is contained in:
parent
812bb95f8d
commit
57d6df79bf
@ -114,6 +114,16 @@ class ReporterContext(BaseContext):
|
|||||||
|
|
||||||
中间件位于 `src/agents/common/middlewares`,包含上下文感知提示词、模型选择、动态工具加载以及附件注入等实现。如果需要编写新的中间件,请遵循 LangChain 官方文档中对 `AgentMiddleware`、`ModelRequest`、`ModelResponse` 等接口的定义,完成后在该目录的 `__init__.py` 暴露入口,主智能体即可在 `middleware` 列表中引用。
|
中间件位于 `src/agents/common/middlewares`,包含上下文感知提示词、模型选择、动态工具加载以及附件注入等实现。如果需要编写新的中间件,请遵循 LangChain 官方文档中对 `AgentMiddleware`、`ModelRequest`、`ModelResponse` 等接口的定义,完成后在该目录的 `__init__.py` 暴露入口,主智能体即可在 `middleware` 列表中引用。
|
||||||
|
|
||||||
|
#### RuntimeConfigMiddleware
|
||||||
|
|
||||||
|
`RuntimeConfigMiddleware`([runtime_config_middleware.py](https://github.com/xerrors/Yuxi-Know/blob/main/src/agents/common/middlewares/runtime_config_middleware.py))是系统默认的核心中间件之一,负责在每次模型调用前自动注入运行时配置:
|
||||||
|
|
||||||
|
1. **自动注入当前时间**:在 system prompt 开头追加当前时间,格式为 `当前时间:YYYY-MM-DD HH:MM:SS`,确保 LLM 能获取准确的时间上下文。
|
||||||
|
2. **动态加载工具**:根据 `context.tools`、`context.knowledges`、`context.mcps` 自动组装可用工具列表。
|
||||||
|
3. **模型选择**:根据 `context.model` 加载对应模型配置。
|
||||||
|
|
||||||
|
如需自定义时间注入逻辑或禁用该行为,可继承该中间件并覆盖 `awrap_model_call` 方法。
|
||||||
|
|
||||||
#### 文件上传中间件
|
#### 文件上传中间件
|
||||||
|
|
||||||
文件上传功能通过 `inject_attachment_context` 中间件实现(位于 `src/agents/common/middlewares/attachment_middleware.py`)。该中间件基于 LangChain 1.0 的 `AgentMiddleware` 标准实现,具有以下特点:
|
文件上传功能通过 `inject_attachment_context` 中间件实现(位于 `src/agents/common/middlewares/attachment_middleware.py`)。该中间件基于 LangChain 1.0 的 `AgentMiddleware` 标准实现,具有以下特点:
|
||||||
|
|||||||
@ -4,29 +4,15 @@ from collections.abc import Callable
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from langchain.agents.middleware import AgentMiddleware, ModelRequest, ModelResponse
|
from langchain.agents.middleware import AgentMiddleware, ModelRequest, ModelResponse
|
||||||
|
from langchain_core.messages import SystemMessage
|
||||||
|
|
||||||
from src.agents.common import load_chat_model
|
from src.agents.common import load_chat_model
|
||||||
from src.agents.common.tools import get_kb_based_tools, get_buildin_tools
|
from src.agents.common.tools import get_buildin_tools, get_kb_based_tools
|
||||||
from src.services.mcp_service import get_enabled_mcp_tools
|
from src.services.mcp_service import get_enabled_mcp_tools
|
||||||
|
from src.utils.datetime_utils import shanghai_now
|
||||||
from src.utils.logging_config import logger
|
from src.utils.logging_config import logger
|
||||||
|
|
||||||
|
|
||||||
def _is_system_message(msg: Any) -> bool:
|
|
||||||
if isinstance(msg, dict):
|
|
||||||
role = msg.get("role") or msg.get("type")
|
|
||||||
return role == "system"
|
|
||||||
msg_type = getattr(msg, "type", None) or getattr(msg, "role", None)
|
|
||||||
return msg_type == "system"
|
|
||||||
|
|
||||||
|
|
||||||
def _get_message_content(msg: Any) -> str | None:
|
|
||||||
if isinstance(msg, dict):
|
|
||||||
content = msg.get("content")
|
|
||||||
return str(content) if content is not None else None
|
|
||||||
content = getattr(msg, "content", None)
|
|
||||||
return str(content) if content is not None else None
|
|
||||||
|
|
||||||
|
|
||||||
class RuntimeConfigMiddleware(AgentMiddleware):
|
class RuntimeConfigMiddleware(AgentMiddleware):
|
||||||
"""运行时配置中间件 - 应用模型/工具/知识库/MCP/提示词配置
|
"""运行时配置中间件 - 应用模型/工具/知识库/MCP/提示词配置
|
||||||
|
|
||||||
@ -54,35 +40,26 @@ class RuntimeConfigMiddleware(AgentMiddleware):
|
|||||||
|
|
||||||
model = load_chat_model(getattr(runtime_context, "model", None))
|
model = load_chat_model(getattr(runtime_context, "model", None))
|
||||||
enabled_tools = await self.get_tools_from_context(runtime_context)
|
enabled_tools = await self.get_tools_from_context(runtime_context)
|
||||||
system_prompt = getattr(runtime_context, "system_prompt", None)
|
|
||||||
logger.debug(f"RuntimeConfigMiddleware: model={model}, "
|
|
||||||
f"tools={[t.name for t in enabled_tools]}. ")
|
|
||||||
|
|
||||||
existing_systems: list[Any] = []
|
# 合并之前中间件设置的 tools,避免覆盖
|
||||||
remaining: list[Any] = []
|
existing_tools = list(request.tools or [])
|
||||||
in_prefix = True
|
merged_tools = existing_tools + enabled_tools
|
||||||
for msg in request.messages:
|
|
||||||
if in_prefix and _is_system_message(msg):
|
|
||||||
existing_systems.append(msg)
|
|
||||||
else:
|
|
||||||
in_prefix = False
|
|
||||||
remaining.append(msg)
|
|
||||||
|
|
||||||
existing_contents = [_get_message_content(m) for m in existing_systems]
|
# 动态生成 system message,添加当前时间
|
||||||
|
cur_datetime = f"当前时间:{shanghai_now().strftime('%Y-%m-%d %H:%M:%S')} UTC"
|
||||||
|
system_prompt = getattr(runtime_context, "system_prompt", "") or ""
|
||||||
|
new_content = list(request.system_message.content_blocks) + [
|
||||||
|
{"type": "text", "text": f"{cur_datetime}\n\n{system_prompt}"}
|
||||||
|
]
|
||||||
|
new_system_message = SystemMessage(content=new_content)
|
||||||
|
|
||||||
new_systems: list[Any] = []
|
logger.debug(f"RuntimeConfigMiddleware: model={model}, tools={[t.name for t in merged_tools]}. ")
|
||||||
if system_prompt:
|
|
||||||
try:
|
|
||||||
idx = existing_contents.index(system_prompt)
|
|
||||||
except ValueError:
|
|
||||||
new_systems.append({"role": "system", "content": system_prompt})
|
|
||||||
else:
|
|
||||||
new_systems.append(existing_systems.pop(idx))
|
|
||||||
existing_contents.pop(idx)
|
|
||||||
|
|
||||||
messages = [*new_systems, *existing_systems, *remaining]
|
request = request.override(
|
||||||
|
model=model,
|
||||||
request = request.override(model=model, tools=enabled_tools, messages=messages)
|
tools=merged_tools,
|
||||||
|
system_message=new_system_message
|
||||||
|
)
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
async def get_tools_from_context(self, context) -> list:
|
async def get_tools_from_context(self, context) -> list:
|
||||||
|
|||||||
@ -5,10 +5,8 @@ from deepagents.middleware.patch_tool_calls import PatchToolCallsMiddleware
|
|||||||
from deepagents.middleware.subagents import SubAgentMiddleware
|
from deepagents.middleware.subagents import SubAgentMiddleware
|
||||||
from langchain.agents import create_agent
|
from langchain.agents import create_agent
|
||||||
from langchain.agents.middleware import (
|
from langchain.agents.middleware import (
|
||||||
ModelRequest,
|
|
||||||
SummarizationMiddleware,
|
SummarizationMiddleware,
|
||||||
TodoListMiddleware,
|
TodoListMiddleware,
|
||||||
dynamic_prompt,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
from src.agents.common import BaseAgent, load_chat_model
|
from src.agents.common import BaseAgent, load_chat_model
|
||||||
@ -17,7 +15,6 @@ from src.agents.common.tools import get_tavily_search
|
|||||||
from src.services.mcp_service import get_tools_from_all_servers
|
from src.services.mcp_service import get_tools_from_all_servers
|
||||||
|
|
||||||
from .context import DeepContext
|
from .context import DeepContext
|
||||||
from .prompts import DEEP_PROMPT
|
|
||||||
|
|
||||||
|
|
||||||
def _get_research_sub_agent(search_tools: list) -> dict:
|
def _get_research_sub_agent(search_tools: list) -> dict:
|
||||||
@ -57,12 +54,6 @@ critique_sub_agent = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dynamic_prompt
|
|
||||||
def context_aware_prompt(request: ModelRequest) -> str:
|
|
||||||
"""从 runtime context 动态生成系统提示词"""
|
|
||||||
return DEEP_PROMPT + "\n\n\n" + request.runtime.context.system_prompt
|
|
||||||
|
|
||||||
|
|
||||||
class DeepAgent(BaseAgent):
|
class DeepAgent(BaseAgent):
|
||||||
name = "深度分析智能体"
|
name = "深度分析智能体"
|
||||||
description = "具备规划、深度分析和子智能体协作能力的智能体,可以处理复杂的多步骤任务"
|
description = "具备规划、深度分析和子智能体协作能力的智能体,可以处理复杂的多步骤任务"
|
||||||
@ -111,7 +102,6 @@ class DeepAgent(BaseAgent):
|
|||||||
model=model,
|
model=model,
|
||||||
system_prompt=context.system_prompt,
|
system_prompt=context.system_prompt,
|
||||||
middleware=[
|
middleware=[
|
||||||
context_aware_prompt, # 动态系统提示词
|
|
||||||
inject_attachment_context, # 附件上下文注入
|
inject_attachment_context, # 附件上下文注入
|
||||||
RuntimeConfigMiddleware(extra_tools=all_mcp_tools),
|
RuntimeConfigMiddleware(extra_tools=all_mcp_tools),
|
||||||
TodoListMiddleware(),
|
TodoListMiddleware(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user