diff --git a/CHANGELOG.md b/CHANGELOG.md index 475f11d3..c70d05d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # 印度占星 Skill 更新日志 +## 2026-10-29 — 咨询回答快约三分之一 + +- 咨询里写回答那一步,模型的思考量默认改为「低」:对比测试里思考量少约一半,一轮回答从约 34 秒降到约 22 秒,回答质量逐份并排读过没有变差(issue #134,产品选 A)。 +- 只影响写回答那一步;排盘、查资料那几步不变。 +- 需要退回时,在服务器设 `CONSULT_ANSWER_REASONING_EFFORT=off` 即恢复原来的请求。 + ## 2026-10-28 — 切换人物时看得出是谁的盘 - 「当前星盘」按钮上写名字、出生日期时间和城市;名单每行写关系和出生时间、城市。 diff --git a/docs/tasks/README.md b/docs/tasks/README.md index 3a980050..6cdbceaa 100644 --- a/docs/tasks/README.md +++ b/docs/tasks/README.md @@ -546,3 +546,4 @@ | `TASK-home-crash-saved-people-20261027.md` | `PROGRESS-home-crash-saved-people-20261027.md` | **#115 首页崩溃**:存过别人的账户一进首页就「页面出错了」——人物列表的资料缺两个字段,启程引导一读就报错;入口补齐默认值(BUG-1464) | 待验收 | `codex/home-crash-saved-people-20261027` | | `TASK-upstream-sync9-20261028.md` | `PROGRESS-upstream-sync9-20261028.md` | **第 1 次打回(快速门 1 败:Darakaraka 旧测试锁错值,见 `TASK-upstream-sync9-fix-20261028.md`)** · **#141 上游同步第九轮**:甲批九项已做完并推 `codex/upstream-sync9-20261028`;校正 20 条和 900 条与上一份回放逐条相同;乙批仍等 #137 | 待验收 | `codex/upstream-sync9-20261028` | | `TASK-upstream-sync9b-20261028.md` | `PROGRESS-upstream-sync9b-20261028.md` | **第 1 次打回(冻结契约排除清单删了第八轮两条,见 `TASK-upstream-sync9b-fix-20261028.md`)** · **#159 上游同步第九轮乙批(产品选 A)**:Sarpa Drekkana 补成五段、第 22 号 Drekkana 改为 D3 第 8 宫;改冻结文件 `varga.py`,校正 20 + 900 与上一份逐条相同后按 ERR-110 重新冻结。Narayana 小运强度口径(B2)不做,另问产品 | 待验收 | `codex/upstream-sync9b-20261028` | +| — | — | **#134 咨询答题默认低思考量(产品选 A)**:`CONSULT_ANSWER_REASONING_EFFORT` 不设时默认 `low`,设 `off` 恢复原请求体(Claude 直接执行) | 已推 staging | `codex/answer-effort-default-20261029` | diff --git a/docs/testing/answer-effort-default-20261029.md b/docs/testing/answer-effort-default-20261029.md new file mode 100644 index 00000000..1555318b --- /dev/null +++ b/docs/testing/answer-effort-default-20261029.md @@ -0,0 +1,7 @@ +# 真机走查 · 咨询回答默认低思考量(issue #134) + +| # | 操作 | 应该看到 | +| --- | --- | --- | +| 1 | 用一张星盘问一个具体问题(如「今年事业怎么样」) | 回答正常出来,比以前快一截(以前常要半分钟以上) | +| 2 | 连问两三个追问 | 每轮都正常回答,引用的宫位、大运和以前一样具体 | +| 3 | 问一个时间段(如「明年上半年」) | 照常出时段分析,没有空答或中途断掉 | diff --git a/frontend/src/mastra/consultation-tools.ts b/frontend/src/mastra/consultation-tools.ts index 6613c877..965a0dcf 100644 --- a/frontend/src/mastra/consultation-tools.ts +++ b/frontend/src/mastra/consultation-tools.ts @@ -177,22 +177,26 @@ export const MAX_EVIDENCE_LOOKUPS_PER_TURN = 3; export const CONSULTATION_WINDOW_CALC_TOOL_ID = "run-jyotish-window-consultation"; /** - * Answer-step reasoning effort. Unset or blank keeps today's request body. - * An illegal value warns once and is treated as unset. + * Answer-step reasoning effort. Unset or blank means "low" (issue #134: the + * A/B halved reasoning tokens and cut answer time ~37% with no quality loss). + * "off" sends no reasoning_effort, i.e. the pre-#134 request body. + * An illegal value warns once and is treated as "off". */ const CONSULT_ANSWER_REASONING_EFFORTS = ["low", "medium", "high", "max"] as const; +export const CONSULT_ANSWER_REASONING_EFFORT_DEFAULT: ProviderReasoningEffort = "low"; let consultAnswerReasoningEffortWarned = false; export function consultAnswerReasoningEffort(): ProviderReasoningEffort | undefined { const raw = process.env.CONSULT_ANSWER_REASONING_EFFORT; - if (raw === undefined || raw.trim() === "") return undefined; + if (raw === undefined || raw.trim() === "") return CONSULT_ANSWER_REASONING_EFFORT_DEFAULT; const value = raw.trim(); + if (value === "off") return undefined; if ((CONSULT_ANSWER_REASONING_EFFORTS as readonly string[]).includes(value)) { return value as ProviderReasoningEffort; } if (!consultAnswerReasoningEffortWarned) { consultAnswerReasoningEffortWarned = true; - console.warn(`CONSULT_ANSWER_REASONING_EFFORT=${value} is not low, medium, high, or max; leaving reasoning effort unset.`); + console.warn(`CONSULT_ANSWER_REASONING_EFFORT=${value} is not off, low, medium, high, or max; leaving reasoning effort unset.`); } return undefined; } diff --git a/frontend/tests/answer-effort-switch-20261013.test.ts b/frontend/tests/answer-effort-switch-20261013.test.ts index 20589d37..d8ab7f66 100644 --- a/frontend/tests/answer-effort-switch-20261013.test.ts +++ b/frontend/tests/answer-effort-switch-20261013.test.ts @@ -51,9 +51,12 @@ test("an illegal effort warns once and stays unset", () => { } }); -test("unset effort keeps the pre-change request bodies", async () => { +// 原值: 不设环境变量时请求体与改动前逐字节相同 +// 新值: 设成 "off" 时请求体与改动前逐字节相同;不设时默认 "low"(见下一条) +// 原因: issue #134 产品选 A,答题步默认低思考量;"off" 是一行回退 +test("off keeps the pre-change request bodies", async () => { const previous = process.env.CONSULT_ANSWER_REASONING_EFFORT; - delete process.env.CONSULT_ANSWER_REASONING_EFFORT; + process.env.CONSULT_ANSWER_REASONING_EFFORT = "off"; try { const natal = await captureStreamBodies({ settings: consultationGenerationSettings(MODEL), @@ -76,6 +79,43 @@ test("unset effort keeps the pre-change request bodies", async () => { } }); +test("unset or blank effort defaults to low", () => { + const previous = process.env.CONSULT_ANSWER_REASONING_EFFORT; + try { + delete process.env.CONSULT_ANSWER_REASONING_EFFORT; + assert.equal(consultAnswerReasoningEffort(), "low"); + process.env.CONSULT_ANSWER_REASONING_EFFORT = " "; + assert.equal(consultAnswerReasoningEffort(), "low"); + process.env.CONSULT_ANSWER_REASONING_EFFORT = "off"; + assert.equal(consultAnswerReasoningEffort(), undefined); + } finally { + if (previous === undefined) delete process.env.CONSULT_ANSWER_REASONING_EFFORT; + else process.env.CONSULT_ANSWER_REASONING_EFFORT = previous; + } +}); + +test("unset effort puts low on the answer step only", async () => { + const previous = process.env.CONSULT_ANSWER_REASONING_EFFORT; + delete process.env.CONSULT_ANSWER_REASONING_EFFORT; + try { + const natal = await captureStreamBodies({ + settings: consultationGenerationSettings(MODEL), + prepareStep: (input) => consultationNatalPrepareStep({ + stepNumber: input.stepNumber, + answerReady: input.stepNumber >= 1, + model: MODEL, + }), + steps: 2, + }) as Record[]; + assert.deepEqual(natal[0], fixture.natal[0]); + assert.equal(natal[1]?.reasoning_effort, "low"); + assert.deepEqual(withoutEffort(natal[1]), fixture.natal[1]); + } finally { + if (previous === undefined) delete process.env.CONSULT_ANSWER_REASONING_EFFORT; + else process.env.CONSULT_ANSWER_REASONING_EFFORT = previous; + } +}); + test("low effort is only on the answer step", async () => { const previous = process.env.CONSULT_ANSWER_REASONING_EFFORT; process.env.CONSULT_ANSWER_REASONING_EFFORT = "low";