Files
context-gatekeeper/README.md

4.2 KiB
Raw Blame History

上下文门控器 (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% 覆盖停止)

安装

pip install -e .

快速开始

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

运行测试

# 单元测试
pytest tests/test_gatekeeper.py -v

# 完整评测20轮对话
pytest tests/test_full_evaluation.py -v

算法细节

话题门控判断

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