refactor(backend): 更新 agentscope 提示词系统
This commit is contained in:
@@ -1,9 +1,4 @@
|
|||||||
from core.agentscope.prompts.agent_prompt import (
|
from core.agentscope.prompts.agent_prompt import build_agent_prompt
|
||||||
ROUTER_AGENT_INSTRUCTION,
|
|
||||||
WORKER_AGENT_INSTRUCTION,
|
|
||||||
build_agent_prompt,
|
|
||||||
build_intent_user_prompt,
|
|
||||||
)
|
|
||||||
from core.agentscope.prompts.system_prompt import build_system_prompt
|
from core.agentscope.prompts.system_prompt import build_system_prompt
|
||||||
from core.agentscope.prompts.tool_prompt import build_tools_prompt
|
from core.agentscope.prompts.tool_prompt import build_tools_prompt
|
||||||
|
|
||||||
@@ -11,7 +6,4 @@ __all__ = [
|
|||||||
"build_agent_prompt",
|
"build_agent_prompt",
|
||||||
"build_system_prompt",
|
"build_system_prompt",
|
||||||
"build_tools_prompt",
|
"build_tools_prompt",
|
||||||
"ROUTER_AGENT_INSTRUCTION",
|
|
||||||
"WORKER_AGENT_INSTRUCTION",
|
|
||||||
"build_intent_user_prompt",
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
from collections.abc import Callable
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from schemas.agent.runtime_models import ResultType, RouterAgentOutput, TaskType
|
from schemas.agent.system_agent import AgentType, SystemAgentLLMConfig
|
||||||
from schemas.agent.system_agent import AgentType
|
|
||||||
|
|
||||||
|
|
||||||
def _wrap_section(section: str, content: str) -> str:
|
def _wrap_section(section: str, content: str) -> str:
|
||||||
@@ -16,117 +14,96 @@ def _wrap_section(section: str, content: str) -> str:
|
|||||||
return f"{start}\n{body}\n{end}" if body else f"{start}\n{end}"
|
return f"{start}\n{body}\n{end}" if body else f"{start}\n{end}"
|
||||||
|
|
||||||
|
|
||||||
def _enum_values(enum_cls: Any) -> str:
|
PromptRuleBuilder = Callable[[SystemAgentLLMConfig | None], list[str]]
|
||||||
return ", ".join(item.value for item in enum_cls)
|
|
||||||
|
|
||||||
|
|
||||||
def _schema_json(model: type[Any]) -> str:
|
class AgentPromptRegistry:
|
||||||
return json.dumps(
|
def __init__(self) -> None:
|
||||||
model.model_json_schema(), ensure_ascii=True, separators=(",", ":")
|
self._builders: dict[AgentType, PromptRuleBuilder] = {}
|
||||||
)
|
|
||||||
|
def register(self, *, agent_type: AgentType, builder: PromptRuleBuilder) -> None:
|
||||||
|
self._builders[agent_type] = builder
|
||||||
|
|
||||||
|
def build_rules(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
agent_type: AgentType,
|
||||||
|
llm_config: SystemAgentLLMConfig | None,
|
||||||
|
) -> list[str]:
|
||||||
|
builder = self._builders.get(agent_type)
|
||||||
|
if builder is None:
|
||||||
|
builder = self._builders[AgentType.WORKER]
|
||||||
|
return builder(llm_config)
|
||||||
|
|
||||||
|
|
||||||
ROUTER_AGENT_INSTRUCTION = """
|
def _config_rules(llm_config: SystemAgentLLMConfig | None) -> list[str]:
|
||||||
[Router Agent]
|
if llm_config is None:
|
||||||
- Read the latest user input and produce a routing contract for downstream execution.
|
return []
|
||||||
- Return exactly one RouterAgentOutput JSON object.
|
context_mode = llm_config.context_messages.mode.value
|
||||||
""".strip()
|
context_count = llm_config.context_messages.count
|
||||||
|
tool_groups = [group.value for group in llm_config.enabled_tool_groups]
|
||||||
|
|
||||||
WORKER_AGENT_INSTRUCTION = """
|
|
||||||
[Worker Agent]
|
|
||||||
- Execute or answer against the routed objective and available evidence.
|
|
||||||
- Return exactly one worker output JSON object matching the runtime-injected schema.
|
|
||||||
""".strip()
|
|
||||||
|
|
||||||
|
|
||||||
def build_intent_user_prompt(
|
|
||||||
*, user_input: str | list[dict[str, Any]]
|
|
||||||
) -> str | list[dict[str, Any]]:
|
|
||||||
instruction = "\n\n".join(
|
|
||||||
[
|
|
||||||
ROUTER_AGENT_INSTRUCTION,
|
|
||||||
"[Output Schema]",
|
|
||||||
_schema_json(RouterAgentOutput),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
if isinstance(user_input, list):
|
|
||||||
return [{"type": "text", "text": instruction}, *user_input]
|
|
||||||
return "\n\n".join([instruction, "[User Input]", user_input])
|
|
||||||
|
|
||||||
|
|
||||||
def _router_role_rules() -> list[str]:
|
|
||||||
return [
|
return [
|
||||||
"Router only: extract intent and route strategy; never answer user directly.",
|
"[Runtime Config]",
|
||||||
"Preserve intent in normalized_task_input.user_text; keep wording concise and faithful.",
|
f"- context_messages.mode={context_mode}",
|
||||||
"Fill multimodal_summary only when image/attachment changes execution decisions.",
|
f"- context_messages.count={context_count}",
|
||||||
"Return key_entities and constraints that are execution-relevant; low confidence -> omit rather than guess.",
|
f"- enabled_tool_groups={','.join(tool_groups) if tool_groups else 'default'}",
|
||||||
"Set execution_mode by complexity: onestep / tool_assisted / multistep.",
|
|
||||||
"Set result_typing.primary to the most suitable response shape; use clarification_request only when required info is missing.",
|
|
||||||
"Set ui.ui_mode and ui.ui_decision_reason based on whether structured UI improves actionability.",
|
|
||||||
f"task_typing.primary must use one TaskType enum: {_enum_values(TaskType)}.",
|
|
||||||
f"task_typing.secondary max 3 enums: {_enum_values(TaskType)}.",
|
|
||||||
f"result_typing.primary must use one ResultType enum: {_enum_values(ResultType)}.",
|
|
||||||
f"result_typing.secondary max 3 enums: {_enum_values(ResultType)}.",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _worker_role_rules() -> list[str]:
|
def _worker_rules(llm_config: SystemAgentLLMConfig | None) -> list[str]:
|
||||||
return [
|
return [
|
||||||
"Worker only: execute routed objective without changing router intent.",
|
"[Worker Agent]",
|
||||||
"Treat router output as objective/constraints contract, not as a fully-materialized tool-args payload.",
|
"- Process user context directly, identify intent, then execute or answer with available evidence.",
|
||||||
"Infer deterministic required tool arguments from contract fields, tool schema, and runtime context.",
|
"- Return exactly one agent output JSON object matching the runtime-injected schema.",
|
||||||
"Ask minimal clarification only when required arguments cannot be inferred safely.",
|
"[Responsibilities]",
|
||||||
"Ground every claim in available evidence and tool results; never fabricate execution state.",
|
"- Handle user request directly from conversation context.",
|
||||||
"Keep status/result_type/answer/key_points/suggested_actions/error internally consistent.",
|
"- Decide intent first, then choose direct answer, tool call, clarification, or refusal.",
|
||||||
|
"- Prefer a direct answer when no tool result is required.",
|
||||||
|
"- Call tools only when tool results are necessary to produce a correct answer.",
|
||||||
|
"- Infer deterministic required tool arguments from context, tool schema, and runtime signals.",
|
||||||
|
"- Ask minimal clarification only when required arguments cannot be inferred safely.",
|
||||||
|
"- If request is unsafe or disallowed, return safe refusal with actionable alternative.",
|
||||||
|
"- Ground every claim in evidence and tool outputs; never fabricate execution state.",
|
||||||
|
"[Schema Guidance]",
|
||||||
|
"- The output schema is injected at runtime; follow it exactly.",
|
||||||
|
"- Do not add fields that are not present in the injected schema.",
|
||||||
|
*_config_rules(llm_config),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def build_worker_contract_prompt(*, router_output: RouterAgentOutput) -> str:
|
def _memory_rules(llm_config: SystemAgentLLMConfig | None) -> list[str]:
|
||||||
contract_json = json.dumps(
|
return [
|
||||||
router_output.model_dump(mode="json", exclude_none=True),
|
"[Memory Agent]",
|
||||||
ensure_ascii=False,
|
"- Analyze conversation context and output structured memory-safe conclusions.",
|
||||||
separators=(",", ":"),
|
"- Return exactly one agent output JSON object matching the runtime-injected schema.",
|
||||||
)
|
"[Responsibilities]",
|
||||||
return "\n".join(
|
"- Focus on extracting durable user facts and preferences from context.",
|
||||||
[
|
"- Keep outputs concise, deterministic, and evidence-backed.",
|
||||||
"[Worker Contract]",
|
"- Do not invent facts or hidden user intent.",
|
||||||
"- Keep routed objective unchanged.",
|
"- Use tool calls only when required by explicit workflow and allowed tool groups.",
|
||||||
"- Use normalized_task_input as objective text.",
|
"[Schema Guidance]",
|
||||||
"- Use multimodal_summary/key_entities/constraints as execution evidence.",
|
"- The output schema is injected at runtime; follow it exactly.",
|
||||||
"- Infer deterministic missing required tool args from evidence + tool schema.",
|
"- Do not add fields that are not present in the injected schema.",
|
||||||
"- Ask clarification only when safe inference is impossible.",
|
*_config_rules(llm_config),
|
||||||
"[RouterAgentOutput]",
|
]
|
||||||
contract_json,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_agent_prompt(*, agent_type: AgentType) -> str:
|
AGENT_PROMPT_REGISTRY = AgentPromptRegistry()
|
||||||
|
AGENT_PROMPT_REGISTRY.register(agent_type=AgentType.WORKER, builder=_worker_rules)
|
||||||
|
AGENT_PROMPT_REGISTRY.register(agent_type=AgentType.MEMORY, builder=_memory_rules)
|
||||||
|
|
||||||
|
|
||||||
|
def build_agent_prompt(
|
||||||
|
*,
|
||||||
|
agent_type: AgentType,
|
||||||
|
llm_config: SystemAgentLLMConfig | None = None,
|
||||||
|
) -> str:
|
||||||
lines = [
|
lines = [
|
||||||
"[Agent Identity]",
|
"[Agent Identity]",
|
||||||
f"- type: {agent_type.value}",
|
f"- type: {agent_type.value}",
|
||||||
|
*AGENT_PROMPT_REGISTRY.build_rules(
|
||||||
|
agent_type=agent_type,
|
||||||
|
llm_config=llm_config,
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
if agent_type == AgentType.ROUTER:
|
|
||||||
lines.extend([ROUTER_AGENT_INSTRUCTION, "[Responsibilities]"])
|
|
||||||
lines.extend(f"- {rule}" for rule in _router_role_rules())
|
|
||||||
lines.extend(
|
|
||||||
[
|
|
||||||
"[Schema Guidance]",
|
|
||||||
"- Output target is RouterAgentOutput.",
|
|
||||||
"- Keep routing output conservative when confidence is low; ask for clarification instead of guessing hidden facts.",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
lines.extend([WORKER_AGENT_INSTRUCTION, "[Responsibilities]"])
|
|
||||||
lines.extend(f"- {rule}" for rule in _worker_role_rules())
|
|
||||||
lines.extend(
|
|
||||||
[
|
|
||||||
"[Schema Guidance]",
|
|
||||||
"- The worker output schema is injected at runtime; follow it exactly.",
|
|
||||||
"- Do not add fields that are not present in the injected schema.",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
return _wrap_section("agent", "\n".join(lines))
|
return _wrap_section("agent", "\n".join(lines))
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from core.agentscope.prompts.agent_prompt import (
|
|||||||
)
|
)
|
||||||
from core.agentscope.prompts.route_prompt import build_frontend_route_prompt
|
from core.agentscope.prompts.route_prompt import build_frontend_route_prompt
|
||||||
from core.agentscope.prompts.tool_prompt import build_tools_prompt
|
from core.agentscope.prompts.tool_prompt import build_tools_prompt
|
||||||
from schemas.agent.system_agent import AgentType
|
from schemas.agent.system_agent import AgentType, SystemAgentLLMConfig
|
||||||
from schemas.agent.forwarded_props import ClientTimeContext
|
from schemas.agent.forwarded_props import ClientTimeContext
|
||||||
from schemas.user.context import UserContext
|
from schemas.user.context import UserContext
|
||||||
|
|
||||||
@@ -202,12 +202,14 @@ def _build_route_section() -> str:
|
|||||||
def build_system_prompt(
|
def build_system_prompt(
|
||||||
*,
|
*,
|
||||||
agent_type: AgentType,
|
agent_type: AgentType,
|
||||||
|
llm_config: SystemAgentLLMConfig | None,
|
||||||
user_context: UserContext,
|
user_context: UserContext,
|
||||||
now_utc: datetime,
|
now_utc: datetime,
|
||||||
runtime_client_time: ClientTimeContext | None = None,
|
runtime_client_time: ClientTimeContext | None = None,
|
||||||
extra_context: str | None = None,
|
extra_context: str | None = None,
|
||||||
tools: Sequence[Tool | dict[str, Any]] | None = None,
|
tools: Sequence[Tool | dict[str, Any]] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
|
include_route_section = agent_type == AgentType.WORKER
|
||||||
sections: list[str | None] = [
|
sections: list[str | None] = [
|
||||||
_build_identity_section(),
|
_build_identity_section(),
|
||||||
_build_env_section(
|
_build_env_section(
|
||||||
@@ -216,10 +218,11 @@ def build_system_prompt(
|
|||||||
runtime_client_time=runtime_client_time,
|
runtime_client_time=runtime_client_time,
|
||||||
extra_context=extra_context,
|
extra_context=extra_context,
|
||||||
),
|
),
|
||||||
_build_route_section(),
|
_build_route_section() if include_route_section else None,
|
||||||
_build_safety_section(),
|
_build_safety_section(),
|
||||||
build_agent_prompt(
|
build_agent_prompt(
|
||||||
agent_type=agent_type,
|
agent_type=agent_type,
|
||||||
|
llm_config=llm_config,
|
||||||
),
|
),
|
||||||
build_tools_prompt(tools=tools) if tools else None,
|
build_tools_prompt(tools=tools) if tools else None,
|
||||||
_build_output_rules(),
|
_build_output_rules(),
|
||||||
|
|||||||
Reference in New Issue
Block a user