Merge pull request 'Add the working-method prompt set and demote the compose rewrite (quality P4)' (#121) from feature/agent-quality-phase04 into main
ci / vet-and-test (push) Successful in 41s
ci / vet-and-test (push) Successful in 41s
This commit was merged in pull request #121.
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
---
|
||||
id: base.method
|
||||
layer: base
|
||||
version: 1
|
||||
title: 工作方法
|
||||
description: 把任务做完的方法论:计划、换路、查 API、坚持到完成、回到材料(常驻基座)
|
||||
---
|
||||
按以下方法工作:
|
||||
|
||||
- **先计划再动手**:预计三步以上、或要产出文件的任务,开始前用 update_plan 列出步骤;每完成一步就更新状态,同一时间只有一步进行中。计划是给自己看的进度账,不是给用户看的排场。
|
||||
- **一个方法失败两次就换路**:同样的调用连续失败两次,停下来想第三条路(换工具、换参数结构、换实现方式),不要原样重试第三次。
|
||||
- **写脚本前先查 API**:调用不熟悉的库/模块前,先用 grep 查它的函数签名(`inspect.signature`/`dir`)或读 SKILL.md 的示例,确认参数形态后再写完整脚本。猜 API 是失败的最大来源。
|
||||
- **编辑粒度**:修改文件时先想清楚要改哪几处,用 multi_edit 或大块 edit 一次改完,不要一行一个 edit_file 连发十几次;改完立即验证(build/运行),验证通过再继续下一处。
|
||||
- **坚持到完成**:任务没做完不要停。收尾前检查最后一段:如果还是计划、承诺或"接下来我将",就先把承诺的事做掉。只有用户输入才能解决的阻塞才允许停下来问。
|
||||
- **结论回到材料**:写进交付物的数字、百分比、日期、人名必须能在本轮材料(附件/工具输出/会议原文)里找到出处;找不到的改成不写,或明确标注"推测"。材料里的日期基准与你理解的不一致时,以材料为准或向用户确认。
|
||||
- **终稿如实**:最后的回复先给结论,再列交付物与要点;没做完、没验证的部分如实说明,不用模糊措辞掩盖。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.edit_file
|
||||
layer: tool
|
||||
version: 1
|
||||
title: edit_file 工具描述
|
||||
description: 工作区文件精确编辑的模型侧说明文案
|
||||
---
|
||||
对工作区文件做唯一匹配替换:old 必须与文件内容逐字一致(含缩进)且在文件中唯一,不唯一时带上更多上下文行。改前必须先 read 过该文件;文件在读取后被外部修改会拒绝,重读即可。多处相关修改用 multi_edit 一次提交,不要一行一个调用连发。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.glob
|
||||
layer: tool
|
||||
version: 1
|
||||
title: glob 工具描述
|
||||
description: 文件名模式匹配的模型侧说明文案
|
||||
---
|
||||
按通配模式找文件路径(** 跨目录),用于"这类文件有哪些/在哪个目录"。找内容用 grep,不要用 glob 后逐个 cat。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.grep
|
||||
layer: tool
|
||||
version: 1
|
||||
title: grep 工具描述
|
||||
description: 工作区内容检索的模型侧说明文案
|
||||
---
|
||||
在工作区文件内容里做正则检索(支持 include 按文件名过滤、ignore_case)。用于定位章节、函数、数据点;配合 read_file 的 offset 直达相关段落,替代整文件通读。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.read_file
|
||||
layer: tool
|
||||
version: 1
|
||||
title: read_file 工具描述
|
||||
description: 工作区文件读取的模型侧说明文案
|
||||
---
|
||||
读取会话工作区内的文本文件,输出带行号(1-based)。用法:先不带 offset/limit 读前 2000 行看全貌;文件大时用 offset/limit 分页,不要反复从头读。编辑前必须先读过目标文件。长输出会被截断并提示分页方式。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.run_python
|
||||
layer: tool
|
||||
version: 1
|
||||
title: run_python 工具描述
|
||||
description: Python 执行原语的模型侧说明文案
|
||||
---
|
||||
执行完整 Python 脚本(python3,工作目录=会话工作区)。适用:数据处理、生成 Excel/PPT/图片(housestyle kit)、批量操作。Word 交付物优先写 .md 源后用 run_shell 跑 `python3 -m housestyle.build`,不要在脚本里手工拼 docx。报错先读退出码与 traceback 定位行号再改,同一错误不要原样重跑。生成带排式的文件(xlsx/pptx)先读 `$AGENT_SKILLS_DIR/house-style/SKILL.md` 的构件表,不确定签名先 `inspect.signature`。
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
id: tool.run_shell
|
||||
layer: tool
|
||||
version: 1
|
||||
title: run_shell 工具描述
|
||||
description: bash 执行原语的模型侧说明文案
|
||||
---
|
||||
在会话工作区内执行 bash 脚本(环境最小化:PATH/HOME/LANG;AGENT_SKILLS_DIR 与 PYTHONPATH 已注入)。适用:housestyle build/lint、pip install --user、文件批操作。读文件用 read_file、找内容用 grep——不要用 cat/sed/grep 命令行代替专用工具。同一命令失败两次换方法。
|
||||
@@ -73,9 +73,9 @@ func TestResolveSystemDefaultBase(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// 默认:base 七块(identity/behavior/caution/style/tools/deliverables/quality)+ env 一块,无技能注入。
|
||||
if len(blocks) != 8 {
|
||||
t.Errorf("blocks = %d, want 8 (7 base + env)", len(blocks))
|
||||
// 默认:base 八块(identity/behavior/method/caution/style/tools/deliverables/quality)+ env 一块,无技能注入。
|
||||
if len(blocks) != 9 {
|
||||
t.Errorf("blocks = %d, want 9 (8 base + env)", len(blocks))
|
||||
}
|
||||
var envBody string
|
||||
for _, b := range blocks {
|
||||
|
||||
@@ -58,6 +58,7 @@ type directRun struct {
|
||||
closedToolTurn bool
|
||||
checklistTouched bool
|
||||
toolTurnsSince int
|
||||
nudgedPlanless bool
|
||||
progress *gates.ProgressReminder
|
||||
checks []core.CheckPart
|
||||
servedModel string
|
||||
@@ -318,9 +319,16 @@ func (l *LLMRunner) runDirect(rc RunCtx, stream agentllm.StreamFunc, model strin
|
||||
},
|
||||
}, user)
|
||||
composed := false
|
||||
if err == nil && res.Err == nil && len(st.evidence) > 0 && st.eff.GetBool("runtime.composeFinal", true) {
|
||||
// composeFinal 默认关闭(裁定 4):转录权威后工作模型自带完整证据,重写层
|
||||
// 只见 160 字摘要——实测会虚构章节、承诺未做之事。开启或异常兜底时才重写。
|
||||
composeWanted := st.eff.GetBool("runtime.composeFinal", false)
|
||||
if err == nil && res.Err == nil && len(st.evidence) > 0 && composeWanted {
|
||||
composed = st.composeFinal(stream, model, res.Notice, streamOpts)
|
||||
}
|
||||
if err == nil && res.Err == nil && !composed && res.Notice == "" && strings.TrimSpace(st.turnBody) == "" && len(st.evidence) > 0 {
|
||||
// 兜底:工作轮结束但没有任何给用户的正文(罕见),才用重写层补一段。
|
||||
composed = st.composeFinal(stream, model, "", streamOpts)
|
||||
}
|
||||
if res.Notice != "" && !composed {
|
||||
st.finalParts = append(st.finalParts, core.Part{Type: core.PartText, Text: res.Notice})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
core "agent-system-core"
|
||||
)
|
||||
|
||||
// P4:计划提醒常开——没有任何计划/待办而任务变长时,给一次可忽略的轻提醒;
|
||||
// 已有计划但停滞的旧提醒行为不变。
|
||||
func TestPlanlessNudgeFiresOnce(t *testing.T) {
|
||||
rc := &fakeRunCtx{
|
||||
ctx: context.Background(),
|
||||
prof: core.AgentProfile{Model: core.ModelRoute{Chat: "test-model"}},
|
||||
}
|
||||
quiet := textDeltaTurn("", toolCall("make_report", "{}"))
|
||||
turns := [][]interface{}{}
|
||||
_ = turns
|
||||
st := &directRun{l: &LLMRunner{}, rc: rc, eff: core.EffectiveSettings{}}
|
||||
var seen []string
|
||||
emitReminder := func(turn int) []string {
|
||||
// 模拟连续工具轮推进。
|
||||
st.closedToolTurn = true
|
||||
st.toolTurnsSince++
|
||||
return st.reminders(turn)
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
seen = append(seen, emitReminder(i)...)
|
||||
}
|
||||
if len(seen) != 1 || !strings.Contains(seen[0], "update_plan") {
|
||||
t.Fatalf("planless nudge should fire exactly once, got %v", seen)
|
||||
}
|
||||
for i := 0; i < 6; i++ {
|
||||
seen = append(seen, emitReminder(i)...)
|
||||
}
|
||||
if len(seen) != 1 {
|
||||
t.Fatalf("planless nudge must not repeat, got %v", seen)
|
||||
}
|
||||
_ = quiet
|
||||
}
|
||||
@@ -143,12 +143,22 @@ func (st *directRun) reminders(turn int) []string {
|
||||
if st.toolTurnsSince < gates.ReminderToolGap {
|
||||
return nil
|
||||
}
|
||||
todos, plans := st.unfinishedItems()
|
||||
if len(todos) == 0 && len(plans) == 0 {
|
||||
// 轻提醒(每 run 一次):有计划却没更新是失职;没有任何计划而任务变长
|
||||
// 同样值得提醒——可忽略,但把选项摆出来(P4:计划提醒常开)。
|
||||
if !st.nudgedPlanless {
|
||||
st.nudgedPlanless = true
|
||||
st.toolTurnsSince = 0
|
||||
return []string{"本次任务已连续多个工具轮没有任何计划。如果剩余工作不止一步,用 update_plan 列出步骤再继续;确实只剩简单收尾就忽略本条。"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
// N1 WP5:节流、封顶与文案走下沉的 ProgressReminder;
|
||||
// 工具轮计数留在这里(它与 directRun 的事件流耦合)。
|
||||
if st.progress == nil {
|
||||
st.progress = &gates.ProgressReminder{}
|
||||
}
|
||||
todos, plans := st.unfinishedItems()
|
||||
got := st.progress.Remind(todos, plans, time.Now())
|
||||
if got != nil {
|
||||
st.toolTurnsSince = 0
|
||||
|
||||
@@ -96,7 +96,7 @@ func Schema() []core.SettingDesc {
|
||||
{Key: "runtime.verify", Group: "runtime", Label: "终轮结果检查", Type: core.SettingBool, Default: true, Effect: core.EffectNewRun, Description: "终轮确定性检查与独立验证"},
|
||||
{Key: "runtime.llmRetries", Group: "runtime", Label: "模型重试次数", Type: core.SettingNumber, Default: 2, Effect: core.EffectNewRun, Description: "直连模型在还没有任何输出时,遇到超时、限流或服务端错误的额外重试次数。0 = 不重试。已经开始输出后不再重试"},
|
||||
{Key: "runtime.codeOrchestration", Group: "runtime", Label: "代码编排", Type: core.SettingBool, Default: false, Effect: core.EffectNewRun, Description: "允许模型用 run_tool_script 写脚本批量调用工具。默认关闭"},
|
||||
{Key: "runtime.composeFinal", Group: "runtime", Label: "终轮整理回复", Type: core.SettingBool, Default: true, Effect: core.EffectNewRun, Description: "用过工具的回合结束后,再用主模型写一段直接回答用户的最终回复"},
|
||||
{Key: "runtime.composeFinal", Group: "runtime", Label: "终轮整理回复", Type: core.SettingBool, Default: false, Effect: core.EffectNewRun, Description: "用过工具的回合结束后,再用主模型重写一段最终回复。默认关闭(裁定 4:转录权威后工作模型已看到完整证据,重写只见过 160 字摘要、实测会虚构章节与承诺未做之事);异常收尾时另有兜底"},
|
||||
{Key: "runtime.intentSemantic", Group: "runtime", Label: "意图语义裁决(慢通道)", Type: core.SettingBool, Default: false, Effect: core.EffectRestart, Description: "规则歧义时用 embedding 语义相似度裁决。需已配置 embedding 端点。默认关闭(行为与 I1 一致)"},
|
||||
{Key: "runtime.intentGenerator", Group: "runtime", Label: "意图命令生成(慢通道)", Type: core.SettingBool, Default: false, Effect: core.EffectRestart, Description: "规则与语义都未命中时用轻量模型生成意图命令(幻觉 fail-closed 回退)。默认关闭(行为与 I1 一致)"},
|
||||
{Key: "telemetry.otlpEndpoint", Group: "telemetry", Label: "OTLP 端点", Type: core.SettingString, Default: "", Effect: core.EffectRestart, Description: "OTel HTTP JSON 上报端点(如 http://localhost:4318)。空 = 不导出(默认);环境变量 OTEL_EXPORTER_OTLP_ENDPOINT 作为后备"},
|
||||
|
||||
Reference in New Issue
Block a user