Files
context-gatekeeper/README.md
Elaina 071f9ef418 feat: 上下文门控器初始实现
- anchor.py: 锚点提取(中文 2/3-gram、英文单词、代码标识符)
- block.py: 对话块数据结构
- topic_gate.py: 话题门控(overlap/new_ratio 判断切换)
- sparse.py: 稀疏召回(BM25/IDF-overlap + exact match 加分)
- selector.py: 最小覆盖贪心选择
- gatekeeper.py: 完整流程封装
- tests/: 单元测试 + 端到端测试(含 MiniMax API 验证)

特性:
- 纯 Python,无额外模型依赖
- 支持 2 核 2G 环境
- 话题门控 + 稀疏召回 + 最小覆盖选择
2026-04-22 01:09:35 +08:00

2.6 KiB
Raw Blame History

上下文门控器 (Context Gatekeeper)

轻量级上下文选择器,在同一会话中自动从历史对话里选出最小且相关的片段,减少话题污染和控制上下文长度。

特性

  • 🚀 纯 Python,无需额外模型依赖
  • 💻 轻量运行,支持 2 核 2G 环境
  • 🔍 话题门控,智能判断继续/切换
  • 📦 稀疏召回BM25/IDF-overlap 评分
  • 🎯 最小覆盖,贪心算法选择最优子集
  • ⚙️ 稳定约束区,持久化用户偏好

安装

pip install -e .

快速开始

from src.gatekeeper import ContextGatekeeper

# 初始化token 预算 4000
gate = ContextGatekeeper(token_budget=4000)

# 添加对话历史
gate.add_turn("Redis 锁续租为什么会脑裂", "因为 TTL 设置不合理...")
gate.add_turn("如何避免脑裂", "可以增加时钟偏移检测...")

# 为当前查询选择上下文
selected = gate.select("锁的 TTL 怎么设置")

for item in selected:
    print(f"轮次 {item['turn_id']}: {item['user']}")
    print(f"助手: {item['assistant']}\n")

# 设置稳定约束
gate.set_constraint("language", "中文")
gate.set_constraint("style", "简洁")

# 构建完整 prompt
prompt = gate.build_prompt("Redis 集群如何搭建")

核心流程

用户输入 → 锚点提取 → 话题门控 → 稀疏召回 → 最小覆盖选择 → 组装 Prompt

项目结构

context-gatekeeper/
├── src/
│   ├── __init__.py
│   ├── anchor.py       # 锚点提取
│   ├── block.py        # Block 数据结构
│   ├── topic_gate.py   # 话题门控
│   ├── sparse.py       # 稀疏召回
│   ├── selector.py     # 最小覆盖选择
│   └── gatekeeper.py   # 主模块
├── tests/
│   ├── test_gatekeeper.py  # 单元测试
│   └── test_e2e.py         # 端到端测试
├── SPEC.md             # 规格文档
├── README.md
├── .env.example
└── .gitignore

运行测试

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

# 端到端测试(需要配置 .env
cp .env.example .env
# 编辑 .env 填入你的 MiniMax API Key
pytest tests/test_e2e.py -v

算法细节

话题门控

  • overlap > 0.45:继续当前话题
  • overlap < 0.20new_ratio > 0.70:切换新话题
  • 有指代词(这个/那个/它/上面)→ 强制继续

稀疏召回评分

score = 1.5 * lex(user) + 0.7 * lex(assistant) + 1.0 * exact + 0.2 * recency

最小覆盖选择

贪心选择"单位长度收益最大"的 block直到覆盖率达到 85% 或 token 预算耗尽。