From ebb70866018fc6eb3e979262e2b93a3ad51a3ecb Mon Sep 17 00:00:00 2001 From: Jesse_Chen Date: Tue, 1 Sep 2026 15:27:52 +0000 Subject: [PATCH] docs(voice): add agent output humanity task brief MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 咨询 prompt 九成禁令无 persona、Level 2 模板把温度压到审计表之后、 校正 agent 限一句话且用户可见文案全是工程腔硬编码——三源修复: voice 置顶、直接回应开场、承接放宽 2-4 句、文案集中重写加防回归词表。 Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0155nFCgCHtoA7jhSDGmZmMu --- TASK-agent-voice-20260901.md | 82 ++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 TASK-agent-voice-20260901.md diff --git a/TASK-agent-voice-20260901.md b/TASK-agent-voice-20260901.md new file mode 100644 index 00000000..a45c3d6b --- /dev/null +++ b/TASK-agent-voice-20260901.md @@ -0,0 +1,82 @@ +# 任务书 · Agent 输出人味修复:语气是产品的一部分,不是正确性的牺牲品(2026-09-01) + +基线:`origin/staging` @ `ff97de5e`。 + +## 0. 问题定性 + +用户反馈:Agent 输出"没有人味"。经排查这是**结构性**的,三个来源,全部在产品侧,均可在不动任何真实性红线的前提下修复: + +1. **咨询系统提示配比失衡**(`mastra/index.ts` + `mastra/product-voice.ts`):约 60 条指令里 ~90% 是禁令与合同(Never/Do not/Treat as final),语气指引只有三句零星短语,无 persona、无共情原则、无正面语料示例。模型被挤成审计报告腔。 +2. **Level 2 模板把温度压到最后**(`product-voice.ts`):本命问题强制以"## 统一参数与原始结构"的度数表开场,"## 现代生活"在技法审计表之后垫底。用户问"我婚姻怎么样",第一眼是岁差和上升度数。 +3. **校正 agent 限一句话 + 硬编码文案无语气**(`mastra/agentic-rectification.ts` 指令"每轮正文只输出一句确认或承接";`method-followup.ts` / `answer-choice.ts` / `rectification-decision.ts` / route.ts 里的服务端直出字符串):用户在校正里读到的话大半是修 BUG-456/D-1 那几轮为正确性手写的字符串,公文腔("按同一规则计入当前区分题")、审讯腔("有没有记得住时间的收入变化、大笔支出或欠债?")、法务腔边界句每轮重复;答完 5 题把 30 分钟缩到 7 分钟,没有任何进度反馈。 + +**关键边界**:skill 10.0.14 文本只要求"正文只做承接与解释",并未限制一句话——"一句"是产品 prompt 自加的。问题槽服务端唯一所有、正文不得出题/复述题干、candidate/accepted/confirmed 语言边界、不得宣称唯一分钟:这些红线全部保留,本任务只改**语气与节奏**。 + +## 1. 硬红线 + +1. **真实性与合同边界一字不放宽**:技法审计表仍在正文文末;不得虚构;`REPRESENTATIVE_MINUTE_DISCLAIMER` 的**语义**必须保留(措辞可重写、频率可调,但交付轮必须完整出现一次"不是已确认的唯一出生分钟"语义);answer_policy / precise-timing 守卫不动。 +2. **问题槽归属不动**:服务端 focus 仍是唯一问题源;正文仍不得提问、复述、改写题干;选择卡仍由结构化槽位承载。放宽的只是承接正文的**长度与温度**(一句 → 2-4 句,可含进度感),不是职能。 +3. **不改 skill 包**(10.0.14 文本已兼容本任务;如发现某条硬编码文案被 skill 逐字锁定,先报告再动)。 +4. **禁止空洞暖场**:人味 ≠ 客套话轰炸。不得加"亲爱的""感谢你的信任"式填充;不得每轮重复问候;不得用 emoji。人味的定义见 §voice 原则。 +5. 既有测试断言若逐字锁定旧文案,允许同步更新断言文本,但**断言的语义约束**(如"必须含不可分区间语义""不得出现唯一分钟措辞")必须保留并改为语义级匹配;在 PR 里逐条列出改动的文案断言。 +6. `cd frontend && ./node_modules/.bin/tsc --noEmit` 通过(不要用 `npx tsc`);`rectification-*` / `consultation-*` / `consult-*` / `chat-*` 测试 fail=0。 + +## 2. Voice 原则(写进代码库作为持久参照) + +新建 `frontend/docs/VOICE.md`(或 `frontend/src/lib/voice-guide.ts` 中的文档常量),至少包含: + +- **人设**:一位懂行、可靠、说人话的占星师朋友——不是客服,不是法务,不是表单。 +- **五条原则**:先回应人再展开方法;说进度("我们已经把范围从 30 分钟缩到 7 分钟了");解释为什么问(一句就够);同一约束换着说(边界句不逐字复读);口语化但不轻佻。 +- **好/坏对照各 ≥5 组**,取材自真实文案(见 §任务 C 清单)。 + +## 任务 0(门控)· 快照当前腔调,先立对照 + +把事故 case `f83d9b42` 的完整 assistant 输出串(route 直出 + 硬编码文案)按当前代码复排一份存入 PR 描述,作为"改前"样本。改后用同一形状复排"改后"样本。这是本任务书唯一的"红→绿":主观质量靠对照呈现,不靠断言。 + +## 任务 A(P0)· 咨询 prompt 重构:voice 置顶,禁令收纳 + +`mastra/index.ts` / `mastra/product-voice.ts`: + +1. `productConversationVoice` 开头新增 voice 段(人设 + 五原则 + 2 组好/坏对照),放在所有合同条款**之前**。 +2. Level 2 骨架**顺序不动**,但明确允许并要求:在 `## 统一参数与原始结构` 之前写一段 3-6 句、无标题的**直接回应**——先用人话回答用户问的事(方向性结论 + 一句共情/背景承接),再进入骨架。相应更新 "Do not shorten…" 措辞为"骨架不可省略,但必须以直接回应开场"。 +3. 禁令清单归并去重(内容不变,压缩语言密度),把散落的三句语气指令并入 voice 段。 +4. `generalJyotishInstructions` / onboarding 指令同样加 voice 段。 + +## 任务 B(P0)· 校正 agent 松绑到"2-4 句自然承接" + +`mastra/agentic-rectification.ts`: + +- "每轮正文只输出一句确认或承接" → "每轮正文 2-4 句:确认收到什么、(可选)一句为什么有用或当前进度、自然过渡到界面上的下一步。不提问、不复述题干、不预告选项。" +- 新增进度感指引:当 dossier 显示候选区间较开场收窄时,允许且鼓励用一句自然语言说出(数字来自服务端投影,不得自算)。 +- 加 2 组好/坏对照(如 坏:"好的,记下了。" 好:"2016 年 9 月上大学,记下了——这类有明确月份的节点对校正特别有用。")。 + +## 任务 C(P1)· 硬编码文案人味重写(集中 + 逐条) + +先把散落的用户可见字符串集中到一个 copy 模块(如 `lib/rectification-agentic/v9/user-copy.ts`),再逐条重写。**清单**(行号是线索,按符号定位;语义约束在括号里,必须保留): + +| 现文案 | 位置 | 问题 | 方向 | +|---|---|---|---| +| "请先说一件你记得大概时间的人生经历,比如升学、入职、搬家、结婚或生病;只记得年份也可以。" | `method-followup.ts` GENERIC_COLLECT_QUESTION | 公文枚举 | "从你最容易想起来的开始就好——比如哪年上的大学、哪年换的工作,记得大概年份就行。" | +| "有没有记得住时间的收入变化、大笔支出或欠债?" 等 USER_COLLECT_QUESTION 表 | `method-followup.ts` | 审讯式 | 每条加一层自然引子,去掉罗列感 | +| "请点选下面的选项作答。点选和一句话回答会按同一规则计入当前区分题。" | route.ts | 内部规则外漏 | "直接点下面的选项就行,打字回答也一样算数。" | +| "我没能确定这句话是否在回答当前问题。请点选下面的选项,或换一种说法。" | route.ts | 生硬 | "我不太确定这句是不是在回答上面的问题——点个选项,或者换个说法都行。" | +| "当前可信区间是 X–Y,代表分钟 Z。代表分钟只是代表性候选,不是已确认的唯一出生分钟。" | `rectification-decision.ts` nonConvergingRangeNarration | 法务腔+每轮复读 | 交付轮完整版带进度感("从最初的 30 分钟缩到了 X–Y 这 7 分钟");中间轮允许省略边界句或用短版(语义约束:交付/采用轮必须含完整边界语义) | +| "…可以从下面的时间里选一个采用。" | `answer-choice.ts` | 生硬 | 与上一条合并重写 | +| "当前问题已更新,请刷新后重新作答。" | route.ts | 机器腔 | 口语化 | +| "接下来请点选下面这一问。" 类占位 | turn-exit/答题链 | 占位残留 | 确认 Task C(上轮)已替换为真实题干后删除死文案 | +| `UNVERIFIED_BIRTH_TIME_NOTICE` 等咨询侧 notice | `consultation-birth-time-mode.ts` | 与 TASK-consultation-birth-accuracy 的任务 D 协同,避免双改冲突 | 以该任务书为准,本轮跳过 | + +重写要求:每条在 PR 里"旧 → 新 → 保留的语义约束"三栏列出。 + +## 任务 D(P2)· 防回归 + +- copy 模块导出集中后,加一条"机器腔词表"测试:用户可见文案不得包含 "按同一规则计入"、"请刷新后重新作答"、"当前状态为" 等词条(词表放测试文件,≥8 条,含本次清理的全部旧词)。 +- 交付/采用轮边界语义测试改为语义级:断言包含"不是已确认的唯一出生分钟"或等义白名单短语之一,而非逐字全句。 + +## 验收标准 + +1. 任务 0 的改前/改后对照(事故 case 形状全程文案 + 一次婚姻主题咨询的开场三段)贴 PR。 +2. `tsc --noEmit` exit 0;四组前端测试 fail=0;改动的文案断言逐条三栏说明。 +3. 红线 1/2 的证明:交付轮输出仍含边界语义;正文仍不含题干(现有 server-focus/question-ownership 测试全绿)。 +4. `VOICE.md` 落库;机器腔词表测试落库。 +5. 未在真实环境验证的部分如实注明。