mirror of
https://github.com/slhaf/Partner.git
synced 2026-05-12 08:43:02 +08:00
refactor(action): optimize prompts
This commit is contained in:
@@ -43,7 +43,7 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
|
||||
private static final String IMMEDIATE_WATCHER_CRON = "0/5 * * * * ?";
|
||||
private static final String BLOCK_SOURCE = "action_planner_pending";
|
||||
private static final String TENDENCIES_EVALUATING_BLOCK_NAME = "tendencies_in_evaluating";
|
||||
private static final String TENDENCIES_EVALUATING_BLOCK_NAME = "action_tendencies_under_evaluation";
|
||||
|
||||
private final ActionAssemblyHelper assemblyHelper = new ActionAssemblyHelper();
|
||||
|
||||
@@ -93,30 +93,28 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
buildTendenciesEvaluatingCompactBlock(tendencies, datetime),
|
||||
buildTendenciesEvaluatingAbstractBlock(tendencies, datetime),
|
||||
Set.of(ContextBlock.FocusedDomain.ACTION),
|
||||
60,
|
||||
18,
|
||||
4
|
||||
60, 18, 4
|
||||
));
|
||||
}
|
||||
|
||||
private @NotNull BlockContent buildTendenciesEvaluatingAbstractBlock(List<String> tendencies, String datetime) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName(), BlockContent.Urgency.HIGH) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName()) {
|
||||
@Override
|
||||
protected void fillXml(@NotNull Document document, @NotNull Element root) {
|
||||
appendTextElement(document, root, "datetime", datetime);
|
||||
appendTextElement(document, root, "abstract", "There are " + tendencies.size() + " related tendencies in evaluating.");
|
||||
appendTextElement(document, root, "abstract", "There are " + tendencies.size() + " candidate action tendencies under evaluation.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private @NotNull BlockContent buildTendenciesEvaluatingCompactBlock(List<String> tendencies, String datetime) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName(), BlockContent.Urgency.HIGH) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName()) {
|
||||
@Override
|
||||
protected void fillXml(@NotNull Document document, @NotNull Element root) {
|
||||
int size = tendencies.size();
|
||||
boolean num = size > 3;
|
||||
appendTextElement(document, root, "datetime", datetime);
|
||||
appendTextElement(document, root, "state", "Partner is considering whether to do these");
|
||||
appendTextElement(document, root, "state", "Candidate action tendencies are under evaluation");
|
||||
appendTextElement(document, root, "tendencies_count", size);
|
||||
appendListElement(document, root, num ? "tendencies_truncated" : "tendencies", "tendency", num ? tendencies.subList(0, 3) : tendencies);
|
||||
}
|
||||
@@ -124,10 +122,10 @@ public class ActionPlanner extends AbstractAgentModule.Running<PartnerRunningFlo
|
||||
}
|
||||
|
||||
private @NotNull BlockContent buildTendenciesEvaluatingFullBlock(List<String> tendencies) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName(), BlockContent.Urgency.HIGH) {
|
||||
return new BlockContent(TENDENCIES_EVALUATING_BLOCK_NAME, getModuleName()) {
|
||||
@Override
|
||||
protected void fillXml(@NotNull Document document, @NotNull Element root) {
|
||||
appendTextElement(document, root, "state", "Partner is considering whether to do these");
|
||||
appendTextElement(document, root, "state", "Candidate action tendencies are under evaluation");
|
||||
appendListElement(document, root, "tendencies", "tendency", tendencies);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -26,51 +26,105 @@ import java.util.concurrent.ExecutorService;
|
||||
|
||||
public class ActionEvaluator extends AbstractAgentModule.Sub<EvaluatorInput, List<EvaluatorResult>> implements ActivateModel {
|
||||
private static final String MODULE_PROMPT = """
|
||||
你负责评估单条行动倾向,并判断它是否值得进入后续行动链。
|
||||
你负责评估单条行动倾向,并判断它是否应该进入后续行动链。
|
||||
|
||||
你会收到:
|
||||
- 一条结构化上下文消息,其中可能包含当前活跃的行动相关状态、近期交流轨迹、认知相关上下文、以及当前活跃记忆切片;
|
||||
- 一组 <available_meta_actions>,表示当前可用的 MetaAction 候选;
|
||||
- 一条最新的 user message,其内容就是当前需要评估的单条 tendency。
|
||||
- 一条结构化上下文消息,其中可能包含当前活跃的 action、communication、perceive、memory、cognition 相关信息;
|
||||
- 一组 <available_meta_actions>,表示当前系统真实可用的 MetaAction 候选;
|
||||
- 一条最新 user message,其内容就是当前需要评估的单条 tendency。
|
||||
|
||||
你的任务:
|
||||
- 判断该 tendency 是否成立、是否值得推进;
|
||||
- 判断该 tendency 是否成立;
|
||||
- 判断它是否真的需要通过“行动推进”来处理,而不是直接交流回应;
|
||||
- 判断它更适合立即执行,还是先进入规划;
|
||||
- 判断是否需要先向用户确认;
|
||||
- 若可推进,则基于 available_meta_actions 生成 primaryActionChain;
|
||||
- 只有在确实可推进时,才生成 primaryActionChain;
|
||||
- 若当前 tendency 与某个待处理 pending 明确对应,且本轮已完成承接或推进,应正确填写 resolvedPending;
|
||||
- 若当前 tendency 明确包含可调度语义,再填写 scheduleData。
|
||||
- 若当前 tendency 明确包含调度语义,再填写 scheduleData。
|
||||
|
||||
评估原则:
|
||||
- 结合上下文理解当前 tendency 与近期交流、当前行动状态、活跃记忆之间的关系。
|
||||
你的核心目标:
|
||||
- 不要把“可以做点什么”误判成“应该进入行动链”;
|
||||
- 不要把“值得回应”误判成“值得行动”;
|
||||
- 不要返回“能推进但实际上没有动作链”的假阳性结果;
|
||||
- 如果用户确实提出了一个行动请求,但当前系统无法承接,也要明确评估出来,而不是伪造可执行结果。
|
||||
|
||||
基本判断原则:
|
||||
- 只有当该 tendency 需要依赖后续动作链、能力调用、系统操作、任务推进或计划安排,才考虑返回 ok=true。
|
||||
- 若当前输入更适合直接交流回应,即使它看起来“也可以通过行动补充更多信息”,通常也应返回 ok=false。
|
||||
- 若当前上下文、记忆、感知信息已经足以直接回答,则不应为了获取更多信息而发起行动。
|
||||
- “信息查询”不等于“行动请求”;只有当用户明确要求系统执行查询、访问外部资源、操作对象、推进任务或完成某项动作时,才可能成立为行动倾向。
|
||||
- 若 tendency 只是解释、分析、总结、评价、翻译、闲聊、感叹、上下文询问、系统状态询问、记忆内容询问,通常应返回 ok=false。
|
||||
- 若 tendency 只是对当前交流内容的自然延续,且通过正常回复即可完成,也应返回 ok=false。
|
||||
|
||||
与现有行动状态的关系:
|
||||
- 若 tendency 与已有正在执行、等待确认、或已明确覆盖的行动完全等价,通常不应重复建立新的行动链。
|
||||
- 若 tendency 是对已有待确认行动的确认、拒绝、补充条件、修改要求或继续推进,则应优先视为对原有行动状态的承接,而不是无关新任务。
|
||||
- 若 action 相关上下文中存在等待确认的 block,且当前 tendency 明显与其相关,则必须显式承接这一点,不要因为其已存在于上下文中而省略。
|
||||
- 只有在 tendency 明确具有可执行意义时,才返回 ok=true。
|
||||
- 若 tendency 更适合直接交流回应,或尚不足以形成行动推进,则返回 ok=false。
|
||||
- primaryActionChain 中只能使用 available_meta_actions 内出现的 action_key,不要编造不存在的动作。
|
||||
- 不要输出完整执行细节、自然语言计划正文或额外解释,只输出 EvaluatorResult 对应结构。
|
||||
- 若 tendency 是对已有 pending 的确认、拒绝、补充条件、修改要求、继续推进或取消,应优先视为对原有行动状态的承接。
|
||||
- 若 action 上下文中存在等待确认的 block,且当前 tendency 明显与其相关,则必须显式承接这一点,不要将其误判为全新无关任务。
|
||||
|
||||
关于字段:
|
||||
- ok 表示该 tendency 是否值得进入后续行动推进。
|
||||
- needConfirm 表示在真正推进前是否必须先得到用户确认。
|
||||
- type:
|
||||
- IMMEDIATE: 可直接进入即时执行链;
|
||||
- PLANNING: 需要先形成或进入规划链,再决定后续执行。
|
||||
- primaryActionChain 表示按 order 分组的候选动作链,每个元素包含:
|
||||
- order: 执行顺序
|
||||
- actionKeys: 该顺序下的 action_key 列表
|
||||
- reason 用于说明你为何做出该判断,应简洁明确。
|
||||
- description 用于概括本次行动评估结果,应能帮助后续模块快速理解该 tendency 的推进方向。
|
||||
- scheduleData 仅在该 tendency 明确包含可调度语义时填写;否则留空。
|
||||
- scheduleData.type: 一次性计划或周期性计划
|
||||
- scheduleData.content: 符合 Quartz 标准的 Cron 表达式
|
||||
- resolvedPending 仅在你能明确判断当前 tendency 已承接某个 pending block 时填写;否则留空。
|
||||
- 当 ok=false 时,type、primaryActionChain、scheduleData、resolvedPending 通常应留空或保持无效默认值,不要强行填充。
|
||||
关于可执行性:
|
||||
- 当 ok=true 时,primaryActionChain 必须非空。
|
||||
- primaryActionChain 中只能使用 <available_meta_actions> 中实际存在的 action_key。
|
||||
- 若当前系统没有任何可用 MetaAction 能承接该 tendency,则不得返回 ok=true。
|
||||
- 不允许输出“该 tendency 成立,但没有动作链”的结果。
|
||||
- “理论上值得做”不等于“当前可推进”;只有当当前系统存在真实可用的 action chain 时,才可返回 ok=true。
|
||||
|
||||
关于“做不了”的情况:
|
||||
- 若 tendency 确实对应用户明确提出的行动要求,但当前系统无法生成有效的 primaryActionChain,则应返回 ok=false。
|
||||
- 在这种情况下,reason 与 description 应明确指出:当前无法执行、无法推进、暂不支持,或缺少必要能力。
|
||||
- 这样后续交流模块才能自然向用户说明“当前做不了”,而不是假装已进入执行。
|
||||
|
||||
needConfirm 的判断:
|
||||
- 若该 tendency 代表的行动具有明显副作用、资源消耗、系统修改、外部操作、风险、持续执行或用户可能希望先确认的影响,则可设 needConfirm=true。
|
||||
- 若该 tendency 是低风险、明确、可立即推进的动作,且上下文中没有要求先确认的信号,可设 needConfirm=false。
|
||||
|
||||
type 的判断:
|
||||
- IMMEDIATE:当前可直接进入即时执行链。
|
||||
- PLANNING:需要先形成规划、拆分步骤、组织执行路径,再决定后续执行。
|
||||
- 若 ok=false,则 type 通常留空或无效默认值,不要强行填写。
|
||||
|
||||
primaryActionChain 的要求:
|
||||
- 只在 ok=true 时填写。
|
||||
- 每个元素包含:
|
||||
- order:执行顺序
|
||||
- actionKeys:该顺序下要使用的 action_key 列表
|
||||
- 不要编造不存在的 action_key。
|
||||
- 不要输出自然语言步骤说明,不要输出伪代码,只输出动作链结构。
|
||||
|
||||
scheduleData 的要求:
|
||||
- 仅当该 tendency 明确包含调度语义时填写;
|
||||
- 若用户只是泛泛表示“以后提醒我”“找时间做”,但无法稳定落到可调度语义,则不要强填;
|
||||
- scheduleData.type 表示一次性或周期性计划;
|
||||
- scheduleData.content 必须符合 Quartz 标准的 Cron 表达式。
|
||||
|
||||
resolvedPending 的要求:
|
||||
- 仅当你能明确判断当前 tendency 已承接某个 pending block 时填写;
|
||||
- 若无法明确对应,则留空;
|
||||
- 不要为了“看起来完整”而猜测填写。
|
||||
|
||||
reason 与 description 的要求:
|
||||
- reason 用于简洁说明你为何做出该判断;
|
||||
- description 用于概括这条 tendency 的处理结论,帮助后续模块快速理解;
|
||||
- 若 ok=false 且原因是“更适合直接回复”,应明确体现这一点;
|
||||
- 若 ok=false 且原因是“用户要求行动,但当前做不了”,也应明确体现这一点。
|
||||
|
||||
以下情形通常应返回 ok=false:
|
||||
- 当前输入本质上是可直接回答的问题;
|
||||
- 当前输入只是解释型、说明型、分析型、评价型、总结型请求;
|
||||
- 当前输入只是询问上下文、系统状态、记忆内容、当前可见内容;
|
||||
- 当前输入只是轻量追问、闲聊、感叹、态度表达;
|
||||
- tendency 与已有行动完全重复,且没有新的推进信息;
|
||||
- tendency 虽然像一个行动请求,但当前没有任何 available_meta_actions 能承接,无法形成有效 primaryActionChain。
|
||||
|
||||
以下情形通常才应返回 ok=true:
|
||||
- 用户明确要求系统执行某项动作、访问外部资源、操作系统对象、调用能力、推进某项任务;
|
||||
- 用户明确要求继续、修改、取消、确认某个已有待处理行动;
|
||||
- 用户明确要求调度未来动作;
|
||||
- 当前若不进入行动链,就无法真正完成该 tendency;
|
||||
- 且当前系统确实存在可用的 primaryActionChain。
|
||||
|
||||
输出要求:
|
||||
- 严格按照 EvaluatorResult 对应结构输出。
|
||||
- 不要输出结构之外的解释、注释或额外文本。
|
||||
- 不要输出结构之外的解释、注释、推理过程或额外文本。
|
||||
""";
|
||||
|
||||
@InjectCapability
|
||||
@@ -104,8 +158,9 @@ public class ActionEvaluator extends AbstractAgentModule.Sub<EvaluatorInput, Lis
|
||||
cognitionCapability.contextWorkspace().resolve(List.of(
|
||||
ContextBlock.FocusedDomain.ACTION,
|
||||
ContextBlock.FocusedDomain.COMMUNICATION,
|
||||
ContextBlock.FocusedDomain.COGNITION,
|
||||
ContextBlock.FocusedDomain.MEMORY
|
||||
ContextBlock.FocusedDomain.PERCEIVE,
|
||||
ContextBlock.FocusedDomain.MEMORY,
|
||||
ContextBlock.FocusedDomain.COGNITION
|
||||
)).encodeToMessage(),
|
||||
availableMetaActionContext(),
|
||||
new Message(Message.Character.USER, tendency)
|
||||
|
||||
@@ -17,19 +17,46 @@ import java.util.List;
|
||||
public class ActionExtractor extends AbstractAgentModule.Sub<String, Result<ExtractorResult>> implements ActivateModel {
|
||||
|
||||
private static final String MODULE_PROMPT = """
|
||||
你负责从当前输入中提取可能的行动倾向,供后续模块继续评估。
|
||||
你负责从当前输入中提取“可能值得进入后续行动评估”的行动倾向。
|
||||
|
||||
你会收到:
|
||||
- 一条结构化上下文消息,主要包含 communication 域与 action 域内容;
|
||||
- 一条结构化上下文消息,主要包含 communication 域、perceive 域与 action 域内容;
|
||||
- 一条最新输入,作为本轮重点分析对象。
|
||||
|
||||
规则:
|
||||
- communication 域主要用于理解当前会话语境、主题延续与用户意图。
|
||||
- action 域主要用于判断相关行动是否已经在执行、等待确认,或已被覆盖。
|
||||
- 只提取“可能值得进入后续评估的行动倾向”,不要输出完整行动计划、执行步骤或工具细节。
|
||||
- 若某个倾向已经明显处于执行中,且当前输入没有带来新的推进信息、修正信息或条件变化,应避免重复提出。
|
||||
你的任务:
|
||||
- 基于当前输入与上下文,提取少量、明确、值得继续进入行动评估的行动倾向;
|
||||
- 这里只提取“可能需要通过行动推进”的倾向,而不是所有可回应的意图;
|
||||
- 若当前输入更适合直接交流回应,而不需要额外行动推进,则返回空结果。
|
||||
|
||||
基本原则:
|
||||
- communication 域主要用于理解当前会话语境、话题延续、指代对象与用户真实意图。
|
||||
- perceive 域可用于理解当前系统状态、环境信息、时间信息等;若当前输入仅是在询问这些已可直接回答的信息,不应因此提取行动倾向。
|
||||
- action 域主要用于判断相关行动是否已经在执行、等待确认、或已被覆盖。
|
||||
- 只提取“可能值得进入后续评估的行动倾向”,不要输出完整行动计划、执行步骤、工具细节或命令内容。
|
||||
- 若某个倾向已经明显处于执行中,且当前输入没有带来新的推进信息、修正信息、确认信息或条件变化,应避免重复提出。
|
||||
- 若 action 域中存在等待确认的 block,且当前输入与其相关,则必须提取出对应的行动倾向;不要因为其已存在于上下文中而省略。
|
||||
- 若当前输入没有明显行动倾向,可返回空结果。
|
||||
|
||||
什么情况下应提取行动倾向:
|
||||
- 用户明确要求系统执行某个动作、调用某项能力、访问某类外部信息、操作某个对象或推进某个待办;
|
||||
- 用户要求修改、继续、取消、确认或补充某个已有待处理行动;
|
||||
- 用户明确要求系统代其完成某件事,而不是仅作解释、说明或回答;
|
||||
- 若不进入行动链,则该请求无法被真正推进或完成。
|
||||
|
||||
什么情况下不应提取行动倾向:
|
||||
- 当前输入本质上是一个可直接回答的提问;
|
||||
- 当前输入只是要求解释、分析、总结、说明、翻译、评价、闲聊或感叹;
|
||||
- 当前输入只是询问当前上下文、系统状态、已知信息、记忆内容或当前可见内容,而这些内容可直接通过交流给出;
|
||||
- 当前输入只是一般性的信息查询,但没有明确要求系统通过外部行动补充信息;
|
||||
- 当前输入只是对已有回复的轻量追问、澄清或自然延续,仍然更适合直接回应;
|
||||
- 当前输入语义模糊,仅凭“可能有东西可做”不足以进入行动评估;
|
||||
- 当前输入虽然提到某个对象或任务,但并未形成明确的行动推进意图。
|
||||
|
||||
重要限制:
|
||||
- 不要把“可以通过行动获得更多信息”当成提取理由。
|
||||
- 不要把“询问信息”自动等同于“要求去执行查询动作”。
|
||||
- 不要为了提高召回而泛化提取。
|
||||
- 如果更适合 communication 直接回答,就返回空结果。
|
||||
- 倾向应简洁明确,表达“要推进什么”,不要写成自然语言执行方案。
|
||||
|
||||
输出要求:
|
||||
- 严格按照 ExtractorResult 对应结构输出。
|
||||
@@ -44,6 +71,7 @@ public class ActionExtractor extends AbstractAgentModule.Sub<String, Result<Extr
|
||||
List<Message> messages = List.of(
|
||||
cognitionCapability.contextWorkspace().resolve(List.of(
|
||||
ContextBlock.FocusedDomain.COMMUNICATION,
|
||||
ContextBlock.FocusedDomain.PERCEIVE,
|
||||
ContextBlock.FocusedDomain.ACTION
|
||||
)).encodeToMessage(),
|
||||
new Message(Message.Character.USER, input)
|
||||
|
||||
Reference in New Issue
Block a user