pi-think-anchor 1.0.11 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +56 -25
- package/README.md +53 -22
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
> Requires pi >= 0.74 · Node >= 20 · MIT · no runtime dependencies
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## What it solves
|
|
6
|
+
|
|
7
|
+
In long sessions thinking drifts: repeated probing, hesitation, self-restatement, fewer sentences that actually advance. This extension reads a word-frequency fingerprint from thinking, decides whether you are focused / mixed / reactive, and pulls back in graded steps — only when needed.
|
|
6
8
|
|
|
7
9
|
## Features
|
|
8
10
|
|
|
9
|
-
- Computes a focus/distraction
|
|
10
|
-
- L1 gentle nudge when drifting into reactive; L2 stronger intervention if it persists;
|
|
11
|
-
- Interventions are
|
|
12
|
-
-
|
|
11
|
+
- Computes a focus/distraction ratio per thinking block and classifies a band over a sliding window.
|
|
12
|
+
- L1 gentle nudge when drifting into reactive; L2 stronger intervention if it persists; silence when healthy.
|
|
13
|
+
- Interventions are trailing messages (neutral wording), never written into the system prompt.
|
|
14
|
+
- Commands `/think-anchor` (status) and `/think-anchor stats` (version / bands / actions / effectiveness / log size).
|
|
13
15
|
- Log at `~/.pi/think-anchor.jsonl` (tail-preserving truncation at 1 MiB).
|
|
14
16
|
|
|
15
17
|
## Install
|
|
@@ -21,33 +23,27 @@ pi install ./pi-think-anchor
|
|
|
21
23
|
|
|
22
24
|
## Configuration
|
|
23
25
|
|
|
24
|
-
###
|
|
26
|
+
### 1 · Config file `~/.pi/think-anchor.json`
|
|
25
27
|
|
|
26
|
-
Every key is optional;
|
|
28
|
+
Every key is optional; invalid JSON falls back to defaults.
|
|
27
29
|
|
|
28
30
|
| Key | Type | Default | Description |
|
|
29
31
|
| --- | --- | --- | --- |
|
|
30
32
|
| `enabled` | boolean | `true` | Master switch |
|
|
31
|
-
| `score.minHits` | number | `3` | Evidence gate: a turn
|
|
32
|
-
| `score.spec` | number | `1.2` | Focused threshold (alpha-smoothed ratio >= this
|
|
33
|
-
| `score.react` | number | `0.5` | Reactive threshold (ratio < this
|
|
33
|
+
| `score.minHits` | number | `3` | Evidence gate: fewer hits in a turn means no scoring and no intervention |
|
|
34
|
+
| `score.spec` | number | `1.2` | Focused threshold (alpha-smoothed ratio >= this) |
|
|
35
|
+
| `score.react` | number | `0.5` | Reactive threshold (ratio < this) |
|
|
34
36
|
| `score.alpha` | number | `1` | Alpha smoothing (pulls low-hit ratios toward 1) |
|
|
35
37
|
| `windowSize` | number | `5` | Sliding window size in messages |
|
|
36
38
|
| `weights.beta` | number | `0.4` | Weight of neutral words in the numerator |
|
|
37
39
|
| `weights.eps` | number | `0.5` | Denominator floor (avoids division by zero) |
|
|
38
40
|
| `intervention.l1CooldownMin` | number | `10` | L1 cooldown in minutes |
|
|
39
41
|
| `intervention.l2CooldownMin` | number | `15` | L2 cooldown in minutes |
|
|
40
|
-
| `intervention.maxL2` | number | `2` | Max L2
|
|
41
|
-
| `lexicon.positive` / `negative` / `neutral` | string[] | built-in Chinese lexicon | Override word lists (28 focus / 18 drift
|
|
42
|
-
| `bands` | object | — | Legacy
|
|
43
|
-
|
|
44
|
-
### Environment
|
|
45
|
-
|
|
46
|
-
| Variable | Value | Description |
|
|
47
|
-
| --- | --- | --- |
|
|
48
|
-
| `THINK_ANCHOR` | `0` | Hard off; overrides the config file |
|
|
42
|
+
| `intervention.maxL2` | number | `2` | Max L2 per session |
|
|
43
|
+
| `lexicon.positive` / `negative` / `neutral` | string[] | built-in Chinese lexicon | Override word lists (28 focus / 18 drift) |
|
|
44
|
+
| `bands` | object | — | Legacy: used when `score` is absent |
|
|
49
45
|
|
|
50
|
-
|
|
46
|
+
Example:
|
|
51
47
|
|
|
52
48
|
```json
|
|
53
49
|
{
|
|
@@ -58,19 +54,54 @@ Every key is optional; defaults below apply when omitted, and invalid JSON falls
|
|
|
58
54
|
}
|
|
59
55
|
```
|
|
60
56
|
|
|
57
|
+
### 2 · Environment
|
|
58
|
+
|
|
59
|
+
| Variable | Value | Description |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| `THINK_ANCHOR` | `0` | Hard off; overrides the config file |
|
|
62
|
+
|
|
63
|
+
### 3 · Commands
|
|
64
|
+
|
|
65
|
+
| Command | Purpose |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `/think-anchor` | Current band, hit count, drift share, last intervention result |
|
|
68
|
+
| `/think-anchor stats` | Version / band distribution / actions / effectiveness / log size |
|
|
69
|
+
|
|
70
|
+
## Where it acts (CoT path)
|
|
71
|
+
|
|
72
|
+
| Stage | Does |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `turn_end` | Reads each assistant thinking block -> word fingerprint (focus / drift / neutral) -> sliding-window aggregation -> band |
|
|
75
|
+
| Evidence gate | When **this turn** has fewer than `minHits` hits it only advances the window: no score, no intervention (avoids mistaking "long and scattered" for repeated probing) |
|
|
76
|
+
| State machine | `healthy -> warning -> critical`; after L2 is exhausted it goes silent instead of escalating forever |
|
|
77
|
+
| `session_start` | Resets state machine and band history, keeping the last 3 samples and pending (cross-session settlement) |
|
|
78
|
+
|
|
79
|
+
It only reads thinking and **never rewrites it** — unlike compression extensions, it decides whether to nudge, not how the text should look.
|
|
80
|
+
|
|
81
|
+
## Feedback path (how interventions get back to the model)
|
|
82
|
+
|
|
83
|
+
| Item | Path | Why |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| L1 / L2 intervention text | Trailing message, `deliverAs: "nextTurn"`, `display: false` | Changing content must not enter the system prompt (prefix cache); neutral wording keeps it from reading as blame |
|
|
86
|
+
| Band and reason | Intervention text carries the current ratio and hit count | The model sees the evidence, not just an order |
|
|
87
|
+
| Effectiveness `eff` | Settled three turns after an intervention, written to the log (not injected) | Judge by the actual ratio change instead of assuming it worked |
|
|
88
|
+
| No escalation when ineffective | Previous `eff >= 0` -> L2 degrades to L1 | Measured: L2 gives no gain on already-drifting sessions |
|
|
89
|
+
| Adaptive silence | >= 8 samples and < 50% improvement -> record only (`acted=muted-*`) | An ineffective intervention should stop interrupting |
|
|
90
|
+
|
|
91
|
+
Actions blocked by cooldown/limits are logged as `blocked-L*`, distinguishable from "nothing needed" (`none`).
|
|
92
|
+
|
|
61
93
|
## How it works
|
|
62
94
|
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
- Effectiveness loop: `eff` is settled three turns after an intervention; the window survives 30 minutes across sessions.
|
|
67
|
-
- Adaptive silence: with >= 8 samples and < 50% improvement it records without injecting.
|
|
95
|
+
- v2.3 criteria = per-turn evidence gate + alpha-smoothed ratio (alpha=1; react < 0.5 / mixed < 1.2 / spec >= 1.2).
|
|
96
|
+
- Calibrated by replay: react 18.3% -> 9.7% over scorable turns; alpha pulls low-hit ratios toward 1.
|
|
97
|
+
- The cross-session window survives 30 minutes so an intervention near the end of a session is not lost.
|
|
68
98
|
|
|
69
99
|
## Limitations
|
|
70
100
|
|
|
71
101
|
- Turn-level evaluation, not in-stream real time.
|
|
72
102
|
- The default lexicon is Chinese-oriented; English sessions depend on wording.
|
|
73
103
|
- Interventions are hints, not enforcement.
|
|
104
|
+
- The gate is heuristic: very short thinking or pure tool turns are usually not scored.
|
|
74
105
|
|
|
75
106
|
## License
|
|
76
107
|
|
package/README.md
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
> 适用 pi ≥ 0.74 · Node ≥ 20 · MIT · 无运行时依赖
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 它解决什么问题
|
|
6
|
+
|
|
7
|
+
长时间对话里 thinking 会慢慢「散」:反复试探、犹豫、自我复述,真正推进的句子变少。本扩展读 thinking 的词频指纹,判定当前是「专注 / 过渡 / 发散」,在发散时分级拉回——且只在需要时才出声。
|
|
6
8
|
|
|
7
9
|
## 功能
|
|
8
10
|
|
|
9
|
-
- 每段 thinking 计算专注 /
|
|
11
|
+
- 每段 thinking 计算专注 / 发散词频比率,滑动窗口聚合后判定波段。
|
|
10
12
|
- 跌入发散时 L1 温和引导;持续发散时 L2 强干预;健康时零注入。
|
|
11
13
|
- 干预走对话尾部注入(中性措辞),不写 system。
|
|
12
|
-
- 命令 `/think-anchor
|
|
14
|
+
- 命令 `/think-anchor`(状态)、`/think-anchor stats`(版本 / 波段 / 动作 / 有效率 / 日志体积)。
|
|
13
15
|
- 日志 `~/.pi/think-anchor.jsonl`(超 1 MiB 保留尾部整行)。
|
|
14
16
|
|
|
15
17
|
## 安装
|
|
@@ -21,33 +23,27 @@ pi install ./pi-think-anchor
|
|
|
21
23
|
|
|
22
24
|
## 配置
|
|
23
25
|
|
|
24
|
-
### 配置文件 `~/.pi/think-anchor.json`
|
|
26
|
+
### 1 · 配置文件 `~/.pi/think-anchor.json`
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
所有键可省略;非法 JSON 自动回退默认。
|
|
27
29
|
|
|
28
30
|
| 键 | 类型 | 默认 | 说明 |
|
|
29
31
|
| --- | --- | --- | --- |
|
|
30
32
|
| `enabled` | boolean | `true` | 总开关 |
|
|
31
|
-
| `score.minHits` | number | `3` |
|
|
33
|
+
| `score.minHits` | number | `3` | 证据门槛:单轮命中少于该值则不评分、不干预 |
|
|
32
34
|
| `score.spec` | number | `1.2` | 高专注阈值(α 平滑比率 ≥ 该值为 spec) |
|
|
33
35
|
| `score.react` | number | `0.5` | 发散阈值(比率 < 该值为 react) |
|
|
34
|
-
| `score.alpha` | number | `1` | α
|
|
36
|
+
| `score.alpha` | number | `1` | α 平滑(把低命中比率拉向 1,避免「长而散」误判) |
|
|
35
37
|
| `windowSize` | number | `5` | 滑动窗口消息数(长工具链中约 1 轮) |
|
|
36
38
|
| `weights.beta` | number | `0.4` | 中性词计入分子的权重 |
|
|
37
39
|
| `weights.eps` | number | `0.5` | 分母下限(防除零) |
|
|
38
40
|
| `intervention.l1CooldownMin` | number | `10` | L1 冷却(分钟) |
|
|
39
41
|
| `intervention.l2CooldownMin` | number | `15` | L2 冷却(分钟) |
|
|
40
|
-
| `intervention.maxL2` | number | `2` | 每会话 L2
|
|
41
|
-
| `lexicon.positive` / `negative` / `neutral` | string[] | 内置中文词表 |
|
|
42
|
+
| `intervention.maxL2` | number | `2` | 每会话 L2 上限 |
|
|
43
|
+
| `lexicon.positive` / `negative` / `neutral` | string[] | 内置中文词表 | 覆盖词表(专注 28 词 / 发散 18 词) |
|
|
42
44
|
| `bands` | object | — | 旧版兼容:无 `score` 时由 `bands.spec/react` 映射 |
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
| 变量 | 取值 | 说明 |
|
|
47
|
-
| --- | --- | --- |
|
|
48
|
-
| `THINK_ANCHOR` | `0` | 硬关闭,优先级高于配置文件 |
|
|
49
|
-
|
|
50
|
-
### 示例
|
|
46
|
+
示例:
|
|
51
47
|
|
|
52
48
|
```json
|
|
53
49
|
{
|
|
@@ -58,19 +54,54 @@ pi install ./pi-think-anchor
|
|
|
58
54
|
}
|
|
59
55
|
```
|
|
60
56
|
|
|
57
|
+
### 2 · 环境变量
|
|
58
|
+
|
|
59
|
+
| 变量 | 取值 | 说明 |
|
|
60
|
+
| --- | --- | --- |
|
|
61
|
+
| `THINK_ANCHOR` | `0` | 硬关闭,优先级高于配置文件 |
|
|
62
|
+
|
|
63
|
+
### 3 · 命令
|
|
64
|
+
|
|
65
|
+
| 命令 | 作用 |
|
|
66
|
+
| --- | --- |
|
|
67
|
+
| `/think-anchor` | 当前波段、命中量、发散占比、上次干预结果 |
|
|
68
|
+
| `/think-anchor stats` | 版本 / 波段分布 / 动作分布 / 有效率 / 日志体积 |
|
|
69
|
+
|
|
70
|
+
## 作用点(CoT / 思维链通路)
|
|
71
|
+
|
|
72
|
+
| 阶段 | 做什么 |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `turn_end` | 取每条 assistant 消息的 thinking 文本 → 词频指纹(专注 / 发散 / 中性)→ 滑窗聚合 → 判波段 |
|
|
75
|
+
| 证据门槛 | **本轮**命中 < `minHits` 时只推进窗口,不评分、不干预(避免把「长而散」当成反复试探) |
|
|
76
|
+
| 状态机 | `healthy → warning → critical`;L2 用尽后静默,不无限升级 |
|
|
77
|
+
| `session_start` | 重置状态机与波段历史,只保留最近 3 条与 pending(跨会话效果结算) |
|
|
78
|
+
|
|
79
|
+
只读 thinking,**不改写任何内容**——这一点与压缩类扩展不同:它影响的是「要不要提醒」,不是「写得对不对」。
|
|
80
|
+
|
|
81
|
+
## 回灌(反馈回到模型的通路)
|
|
82
|
+
|
|
83
|
+
| 项 | 通路 | 设计理由 |
|
|
84
|
+
| --- | --- | --- |
|
|
85
|
+
| L1 / L2 干预文本 | 对话尾部消息,`deliverAs: "nextTurn"`,`display: false` | 变化内容不能进 system(毁前缀缓存);中性措辞避免模型把提醒当指责 |
|
|
86
|
+
| 波段与理由 | 干预文本里带当前比率与命中量 | 让模型知道「依据是什么」,而不是只收到一句指令 |
|
|
87
|
+
| 效果结算 `eff` | 干预后第 3 轮结算,写入日志(不直接注入) | 用实际比率变化判断干预是否有效,而不是假定有效 |
|
|
88
|
+
| 无效不升级 | 上次 `eff >= 0`(未改善)→ 本次 L2 自动降为 L1 | 实测 L2 对已发散会话无收益,避免重复无效打断 |
|
|
89
|
+
| 自适应静默 | 样本 ≥ 8 且下降率 < 50% → 只记录不注入(`acted=muted-*`) | 长期看没效果的干预不该继续打扰 |
|
|
90
|
+
|
|
91
|
+
冷却 / 上限挡下的动作记 `blocked-L*`,与「无需动作」(`none`)在日志里可区分。
|
|
92
|
+
|
|
61
93
|
## 机制
|
|
62
94
|
|
|
63
|
-
-
|
|
64
|
-
-
|
|
65
|
-
-
|
|
66
|
-
- 效果闭环:干预后第 3 轮结算 `eff`;跨会话窗口保留 30 分钟。
|
|
67
|
-
- 自适应静默:样本 ≥ 8 且下降率 < 50% 时只记录不注入。
|
|
95
|
+
- v2.3 判据 = 单轮证据门槛 + α 平滑比率(α=1;react < 0.5 / mixed < 1.2 / spec ≥ 1.2)。
|
|
96
|
+
- 判据经回放校准:react 18.3% → 9.7%(命中 ≥3 的可评分回合);α 让低命中比率趋向 1。
|
|
97
|
+
- 跨会话窗口保留 30 分钟,避免干预落在会话末尾时丢样本。
|
|
68
98
|
|
|
69
99
|
## 限制
|
|
70
100
|
|
|
71
101
|
- 按回合评估,非流内实时。
|
|
72
102
|
- 词表默认偏中文;英文会话效果取决于用词。
|
|
73
|
-
-
|
|
103
|
+
- 干预是提示不是强制,模型可能不遵守。
|
|
104
|
+
- 门槛是启发式:极短 thinking 或纯工具轮次通常不评分。
|
|
74
105
|
|
|
75
106
|
## License
|
|
76
107
|
|