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` 列表中引用。
|
||||
|
||||
#### 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` 标准实现,具有以下特点:
|
||||
|
||||
@ -4,29 +4,15 @@ from collections.abc import Callable
|
||||
from typing import Any
|
||||
|
||||
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.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.utils.datetime_utils import shanghai_now
|
||||
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):
|
||||
"""运行时配置中间件 - 应用模型/工具/知识库/MCP/提示词配置
|
||||
|
||||
@ -54,35 +40,26 @@ class RuntimeConfigMiddleware(AgentMiddleware):
|
||||
|
||||
model = load_chat_model(getattr(runtime_context, "model", None))
|
||||
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] = []
|
||||
remaining: list[Any] = []
|
||||
in_prefix = True
|
||||
for msg in request.messages:
|
||||
if in_prefix and _is_system_message(msg):
|
||||
existing_systems.append(msg)
|
||||
else:
|
||||
in_prefix = False
|
||||
remaining.append(msg)
|
||||
# 合并之前中间件设置的 tools,避免覆盖
|
||||
existing_tools = list(request.tools or [])
|
||||
merged_tools = existing_tools + enabled_tools
|
||||
|
||||
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] = []
|
||||
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)
|
||||
logger.debug(f"RuntimeConfigMiddleware: model={model}, tools={[t.name for t in merged_tools]}. ")
|
||||
|
||||
messages = [*new_systems, *existing_systems, *remaining]
|
||||
|
||||
request = request.override(model=model, tools=enabled_tools, messages=messages)
|
||||
request = request.override(
|
||||
model=model,
|
||||
tools=merged_tools,
|
||||
system_message=new_system_message
|
||||
)
|
||||
return await handler(request)
|
||||
|
||||
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 langchain.agents import create_agent
|
||||
from langchain.agents.middleware import (
|
||||
ModelRequest,
|
||||
SummarizationMiddleware,
|
||||
TodoListMiddleware,
|
||||
dynamic_prompt,
|
||||
)
|
||||
|
||||
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 .context import DeepContext
|
||||
from .prompts import DEEP_PROMPT
|
||||
|
||||
|
||||
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):
|
||||
name = "深度分析智能体"
|
||||
description = "具备规划、深度分析和子智能体协作能力的智能体,可以处理复杂的多步骤任务"
|
||||
@ -111,7 +102,6 @@ class DeepAgent(BaseAgent):
|
||||
model=model,
|
||||
system_prompt=context.system_prompt,
|
||||
middleware=[
|
||||
context_aware_prompt, # 动态系统提示词
|
||||
inject_attachment_context, # 附件上下文注入
|
||||
RuntimeConfigMiddleware(extra_tools=all_mcp_tools),
|
||||
TodoListMiddleware(),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user