Files
context-gatekeeper/SPEC.md
2026-04-22 01:12:03 +08:00

143 lines
3.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 上下文门控器 - SPEC.md
## 1. 项目概述
**项目名称:** context-gatekeeper
**功能:** 轻量级上下文选择器,在同一会话中自动从历史对话里选出最小且相关的片段,减少话题污染和控制上下文长度。
**约束:** 纯 Python无额外模型依赖2 核 2G 可运行。
---
## 2. 核心架构
### 四步流程
```
用户输入 → 锚点提取 → 话题门控 → 稀疏召回 → 最小覆盖选择 → 组装 Prompt
```
### 数据结构
```python
Block:
- user_text: str # 用户消息
- assistant_text: str # 助手回复
- tokens_user: int # 用户消息 token 数(估算)
- tokens_assistant: int # 助手消息 token 数(估算)
- anchors: list[str] # 锚点列表2-gram/3-gram
- turn_id: int # 对话轮次
```
---
## 3. 功能模块
### 3.1 锚点提取 (Anchor Extraction)
- 中文: 2-gram / 3-gram 连续字符串
- 英文: 单词
- 代码标识符、版本号、引号短语、反引号内代码
- 计算 IDF 权重,高频通用词自动降权
### 3.2 话题门控 (Topic Gate)
输入: 当前 query 锚点集合 + 活跃话题锚点集合
输出: `continue` | `switch`
规则:
- `overlap > 0.45`: 继续当前话题
- `overlap < 0.20``new_ratio > 0.70`: 切换新话题
- 有指代词(这个/那个/它/上面/刚才/继续/展开)→ 强暗示继续
### 3.3 稀疏召回 (Sparse Retrieval)
评分函数:
```
score(block, query) = 1.5 * lex(user_text, query)
+ 0.7 * lex(assistant_text, query)
+ 1.0 * exact_match(query, block)
+ 0.2 * recency
```
- `lex`: BM25/IDF overlap简单实现
- `exact_match`: 英文术语、代码标识符、数字版本号、引号短语完整命中加分
- `recency`: 弱先验,仅做微调
候选集: top 20 blocks
### 3.4 最小覆盖选择 (Minimum Coverage Selection)
贪心算法:
```
每步选"单位长度收益最大"的 block:
gain = covered_anchor_idf / cost^alpha
停止条件:
- 覆盖率达到 85% (η=0.85)
- 或达到 token 预算上限
```
### 3.5 句级裁剪 (Intra-Block Trimming)
选中 block 后,进一步裁剪:
- 保留覆盖了 query anchors 的句子
- 保留 exact match 的句子
- 连带保留对应用户问题句
### 3.6 常量区 (Stable Constraints)
维护一个小的稳定约束区:
- 用户显式声明的长期偏好
- 输出语言、风格、禁用项
不是记忆系统,只是一个固定 KV。
---
## 4. 对外接口
```python
class ContextGatekeeper:
def __init__(self, token_budget: int = 4000)
def add_turn(self, user_text: str, assistant_text: str) -> None
"""添加一轮对话到历史"""
def select(self, query: str) -> list[dict]:
"""为当前 query 选择上下文 blocks"""
# 返回: [{"user": ..., "assistant": ..., "turn_id": ...}, ...]
def set_constraint(self, key: str, value: str) -> None
"""设置稳定约束"""
def get_constraints(self) -> dict:
"""获取当前所有约束"""
```
---
## 5. 测试验证
使用 MiniMax API 做一个端到端对话测试:
- 模拟多轮对话(至少 3 轮,其中包含话题切换)
- 验证:
1. 同一话题内,后续问题能召回前面对话
2. 切换话题后,旧话题内容不会被召回
3. 有指代词时,强制继承最近 1-2 个 block
4. token 预算控制正常
.env 文件格式:
```
MINIMAX_API_KEY=你的key
```
---
## 6. 验收标准
- [ ] 纯 Python无第三方模型依赖
- [ ] 可在 2 核 2G 环境运行
- [ ] 单元测试覆盖核心模块
- [ ] 端到端对话测试通过
- [ ] .env 正确 gitignore
- [ ] 代码上传 Gitea 仓库