Files
context-gatekeeper/README.md

138 lines
4.2 KiB
Markdown
Raw 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.
# 上下文门控器 (Context Gatekeeper)
**论文:** https://gitea.ephron.ren/elaina/context-gatekeeper/src/branch/main/paper.md
轻量级上下文选择器,在同一会话中自动从历史对话里选出最小且相关的片段,减少话题污染和控制上下文长度。
## 特性
- 🚀 **纯 Python**,无需向量化模型依赖(无 embedding、reranker、分类器
- 💻 **轻量运行**2 核 2G 环境可流畅运行
- 🔍 **话题门控**,通过锚点 overlap + new_ratio 判断继续/切换,含指代词强制继承
- 📦 **稀疏召回**BM25/IDF-overlap 评分,用户侧权重高于助手侧
- 🎯 **最小覆盖**,基于 IDF 加权集合覆盖的贪心选择
- ⚙️ **稳定约束区**,持久化用户偏好(语言/风格/禁用项)
## 核心流程
```
用户查询 q
① 锚点提取(中文 2/3-gram、英文单词、代码标识符、版本号、引号短语
② 话题门控overlap > 0.45 → 继续overlap < 0.20 且 new_ratio > 0.70 → 切换;
有指代词 → 强制继续;中间地带默认继续)
③ 稀疏召回top-20BM25/IDF-overlap + exact match + 新鲜度奖励)
④ 最小覆盖选择gain = ΣIDF(t) / cost^α,贪心选择达到 85% 覆盖停止)
```
## 安装
```bash
pip install -e .
```
## 快速开始
```python
from src.gatekeeper import ContextGatekeeper
# 初始化token 预算 4000
gate = ContextGatekeeper(token_budget=4000)
# 添加多轮对话
gate.add_turn("如何设计一个 Redis 分布式锁?",
"分布式锁需要满足互斥性、死锁避免、性能要求。常用 Redisson 实现。")
gate.add_turn("锁的 TTL 设置多少合适?",
"TTL 取决于业务操作耗时,建议 3-5 倍 buffer同时要续期机制。")
# 为当前查询选择上下文
selected = gate.select("锁的 TTL 设置多少合适?")
for item in selected:
print(f"轮次 {item['turn_id']}: {item['user']}")
print(f"助手: {item['assistant']}\n")
# 构建完整 prompt可直接发给 LLM
prompt = gate.build_prompt("锁的 TTL 设置多少合适?")
print(prompt)
```
## 项目结构
```
context-gatekeeper/
├── src/
│ ├── anchor.py # 锚点提取2/3-gram + IDF
│ ├── block.py # Block 数据结构
│ ├── topic_gate.py # 话题门控overlap + new_ratio + 指代词)
│ ├── sparse.py # 稀疏召回BM25/IDF + exact + recency
│ ├── selector.py # 最小覆盖选择IDF加权贪心
│ └── gatekeeper.py # 主模块(组合各子模块)
├── tests/
│ ├── test_gatekeeper.py # 单元测试9/9
│ └── test_full_evaluation.py # 完整评测
├── evaluation_results.json # 评测结果
├── paper.md # 技术论文
├── SPEC.md # 规格文档
└── README.md
```
## 运行测试
```bash
# 单元测试
pytest tests/test_gatekeeper.py -v
# 完整评测20轮对话
pytest tests/test_full_evaluation.py -v
```
## 算法细节
### 话题门控判断
```python
overlap = Σ IDF(t) for t A(q)A(T) / Σ IDF(t) for t A(q)
new_ratio = Σ IDF(t) for t A(q)\A(T) / Σ IDF(t) for t A(q)
if overlap > 0.45: continue
elif overlap < 0.20 and new_ratio > 0.70: switch
elif has_deictic: continue # 指代词强制继承
else: continue # 中间地带默认继续
```
### 稀疏召回评分
```
score = 1.5·lex(u_b,q) + 0.7·lex(a_b,q) + 1.0·exact(b,q) + 0.2·recency(b)
```
### 最小覆盖 gain
```
gain(b|S) = Σ IDF(t) for t ∈ cov(b)\covered(S) / cost(b)^α, α=0.8
```
## 局限性与适用场景
**局限性:**
- 稀疏检索在语义相似但词形不同时召回率有限
- 中文锚点无停用词过滤,高频无意义词可能干扰 IDF
- Token 估算为粗略估算字符数×1.5),与实际有 2-3 倍误差
**适用场景:**
- 资源受限的生产环境(边缘设备、私有部署)
- 对延迟敏感的实时对话
- 中等复杂度对话10-50轮
**不适用:**
- 需要精确语义匹配的场景(建议用向量检索)
- 极长对话(>100轮IDF 全量更新有偏)
## License
MIT