ESC
深入了解 自动分类

自动分类

robotmem 使用纯正则的 L0 引擎在写入时自动分类每条记忆。无 LLM 依赖 — 亚毫秒级执行。

管道概览

learn(insight="grip_force=12.5N works best because sensor was calibrated")
         │
         ├── classify_category()
         │   正则首次匹配 → "root_cause"(匹配了 "because")
         │
         ├── estimate_confidence()
         │   基础 0.80 + 信号 → 0.90
         │   (因果 +0.05,反引号 +0.05)
         │
         ├── extract_scope()
         │   → {scope_files: [], scope_entities: ["grip_force"]}
         │
         ├── classify_tags()
         │   多标签正则 → ["root_cause", "observation"]
         │
         └── build_context_json()
             合并用户上下文 + 来源标记

分类归类

优先级顺序

分类按严格的优先级顺序匹配 — 首次匹配即生效

高优先级 ─────────────────────────────── 低优先级

constraint → preference → worldview →
tradeoff → root_cause → decision → revert →
pattern → architecture → config →
postmortem → gotcha → self_defect →
observation_debug → observation_code → observation →
code(默认兜底)

分类规则

# 分类 触发模式 衰减 示例
1 constraint must always, never, forbidden, must not, 必须, 禁止, 不允许, 强制 受保护 "Must never exceed 15N grip force"
2 preference prefer X over Y, recommended to use, 优先使用, 推荐使用 正常 "Prefer approach from left side"
3 worldview X is better than Y, the right way, from now on, 比...好, 最佳做法 正常 "ONNX is faster than Ollama for small models"
4 tradeoff tradeoff, pros and cons, 权衡, advantage, 优缺点, vs 正常 "Speed vs accuracy: use 10Hz for real-time"
5 root_cause caused by, because, root cause, 原因, 根因, 导致, 由于 正常 "Failure caused by sensor drift"
6 decision chose, decided, instead of, 选择, 决定, 决策, 采用 正常 "Chose PID over MPC for simplicity"
7 revert reverted, rollback, undo, 回滚, 撤销 正常 "Reverted to previous PID gains"
8 pattern every time, whenever, recurring, 规律, 总是, 反复出现 正常 "Every time humidity > 80%, grip fails"
9 architecture architecture, module, pipeline, 架构, 模块, 系统设计, 分层 正常 "Memory pipeline: learn → dedup → store"
10 config configuration, env var, setting, port, 配置, 环境变量, 版本 正常 "Port 6889 for web UI"
11 postmortem postmortem, lesson learned, 教训, 复盘, 事后分析 受保护 "Lesson: always calibrate before new session"
12 gotcha gotcha, pitfall, 踩坑, 陷阱, 坑: 受保护 "Pitfall: joint limits not checked in sim"
13 self_defect AI defect, 训练偏好, 幻觉倾向, 注意力衰减, 讨好倾向 受保护 "AI overengineering tendency on simple tasks"
14 observation_debug found/noticed/discovered + error/bug/crash/timeout 正常 "Found that timeout errors spike at noon"
15 observation_code found/noticed/discovered + .py/.rs/.js/function/module 正常 "Noticed search.py returns stale results"
16 observation found that, observed, noticed, discovered, 发现, 观察到, 实测 正常 "Found that red cups require more force"
17 code (默认兜底) 正常 一般技术笔记

受保护的分类

三个分类被标记为"受保护" — 它们永远不会被合并,也永远不会时间衰减

分类 受保护原因
constraint 安全规则必须永久保留
postmortem 教训不可替代
gotcha 每个陷阱都有独特的上下文

双语匹配

所有模式同时支持英文和中文:

# constraint 模式(摘录)
r"(?:must\s+(?:always|never|not)|(?:必须|禁止|不[允准许]许|强制|绝不|一定要))"

# root_cause 模式(摘录)
r"(?:root\s*cause|caused?\s*by|because|原因|根因|导致|问题出在|之所以|是因为|由于)"

置信度估计

置信度分数表示记忆的可靠程度,基于内容丰富度信号。

公式

base = 0.80
+ 0.05 如果检测到文件路径(例如 "src/search.py")
+ 0.05 如果检测到代码引用(反引号或函数调用)
+ 0.05 如果检测到因果语言("because"、"caused by" 等)
+ 0.05 如果提供了上下文 JSON(> 20 字符)
= 上限 0.95

信号检测

信号 正则模式 示例
文件路径 \w[\w./-]*\.(py|rs|js|ts|go|md|...) src/robotmem/search.py
代码引用 反引号或 \w+() 模式 `embed_one()`
因果语言 because|caused by|原因|根因|导致 "failed because of timeout"
丰富上下文 len(context.strip()) > 20 包含参数的 JSON 上下文

置信度范围

信号数 置信度 解释
0 个信号 0.80 基础水平 — 一般观察
1 个信号 0.85 中等 — 有一定证据
2 个信号 0.90 良好 — 有充分证据
3 个信号 0.95 高 — 强力证据(上限)
4 个信号 0.95 上限为 0.95

作用域提取

作用域提取器从记忆文本中识别引用的文件、实体和模块。

文件路径检测

# 正则匹配路径如:src/robotmem/search.py, /etc/config.yaml
_FILE_PATH_RE = re.compile(
    r"(?:^|[\s\"'`(,])(/?\w[\w./-]*\.(?:py|rs|js|ts|tsx|go|md|toml|yaml|yml|json|sql|sh|css|html))"
)

支持的扩展名:.py.rs.js.ts.tsx.go.md.toml.yaml.yml.json.sql.sh.css.html

实体检测

两种提取方法:

  1. 反引号实体`ClassName``function_name()`
  2. PascalCase 名称CogDatabaseFastEmbedEmbedder
# 反引号:`embed_one()` → "embed_one"
_BACKTICK_ENTITY_RE = re.compile(r"`(\w[\w.]*)(?:\(\))?`")

# PascalCase:CogDatabase → "CogDatabase"
_PASCAL_CASE_RE = re.compile(r"\b([A-Z][a-z]+(?:[A-Z][a-z]+)+)\b")

模块推断

模块从文件路径推断:

# "src/robotmem/ops/search.py" → 模块 "ops"
# (父目录,排除 src/lib/app/tests)

作用域输出

{
    "scope_files": ["src/robotmem/search.py"],
    "scope_entities": ["embed_one", "CogDatabase"],
    "scope_modules": ["robotmem"]
}

标签分类

标签提供多标签分类 — 单条记忆可以有多个标签。

流程

def classify_tags(text, context_json=None):
    tags = []
    # 1. 匹配所有正则模式(不只是第一个)
    for category, pattern in _CATEGORY_PATTERNS:
        if pattern.search(text):
            tags.append(category)

    # 2. 从上下文 JSON 提取 scenario_tags
    if context_json:
        ctx = json.loads(context_json)
        for tag in ctx.get("scenario_tags", []):
            if tag in VALID_TAGS:
                tags.append(tag)

    # 3. 兜底
    if not tags:
        tags.append("code")

    return tags

classify_category() 的关键区别: - classify_category()首次匹配(单标签) - classify_tags()所有匹配(多标签)

基于上下文的标签

标签也可以通过上下文 JSON 注入:

{
    "scenario_tags": ["debug", "concurrency", "pattern"]
}

这些标签在插入前会通过 VALID_TAGS 白名单(50+ 个标签)验证。

标签分类体系

标签系统使用 9 维层次化树结构,包含 50+ 个标签:

metacognition          ← reasoning, cognitive_bias, decision_framework,
│                        systems_thinking, risk_thinking, worldview, decision
│
capability             ← build, debug, design, review, explain, optimize,
│                        plan, architecture, code
│
domain                 ← cs_fundamentals, ai_ml, finance, business,
│                        cross_domain, config, observation, observation_code,
│                        observation_debug
│
technique              ← patterns, anti_patterns, recipes, language_specific,
│                        pattern
│
timing                 ← when_to_start, when_to_stop, when_to_switch
│
boundary               ← tradeoff, not_applicable, diminishing_returns,
│                        constraint
│
experience             ← war_story, postmortem, gotcha, root_cause, revert
│
self_defect            ← hallucination, sycophancy, overengineering,
│                        no_verification
│
reflection             ← accuracy_calibration, behavior_rule, blind_spot,
                         preference

维度前缀

每个标签映射到一个人类可读的维度前缀用于显示:

dimension_prefix("gotcha")       # → "[经验/踩坑]"
dimension_prefix("architecture") # → "[能力/架构设计]"
dimension_prefix("metacognition")# → "[元认知]"  (根节点)

标签存储

标签存储在 memory_tags 表中:

描述
memory_id memories.id 的外键
tag 受控词汇表中的标签
source "auto"(正则推断)或 "user"(显式设置)

主键:(memory_id, tag) — 每条记忆不会有重复标签。

标签元数据

tag_meta 表维护分类层次结构:

描述
tag 标签标识符(主键)
parent 父标签(NULL = 根维度)
display_name 人类可读名称

此表在数据库初始化时自动从 TAG_META_TREE 同步。

上下文 JSON 构建器

build_context_json() 函数将用户提供的上下文与自动元数据合并:

def build_context_json(insight, context):
    result = {"source": "learn_tool"}

    if context:
        parsed = json.loads(context)
        if isinstance(parsed, dict):
            result.update(parsed)  # 合并用户字段
        else:
            result["user_context"] = context  # 原样存储

    return json.dumps(result)

这确保每条记忆至少有一个 source 字段用于来源追踪。

路径规范化

作用域提取的文件路径会被规范化以保持一致性:

def normalize_scope_files(files, project_root=None):
    """绝对路径 → 相对路径,去重,排序"""
    # /Users/jia/project/src/foo.py → src/foo.py

这防止了同一文件因使用绝对路径和相对路径而出现重复条目。

设计原则

  1. 纯正则,无 LLM:亚毫秒级执行,确定性,无幻觉风险
  2. 首次匹配优先:分类有严格排序 — 安全约束始终优先
  3. 多标签:一条记忆可以同时是 root_causeobservation
  4. 双语:所有模式同时适用于英文和中文文本
  5. 优雅降级:未知文本默认为 code 分类,置信度 0.80
  6. 受控词汇:所有标签通过白名单验证 — 无自由标记