自动分类
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
实体检测
两种提取方法:
- 反引号实体:
`ClassName`、`function_name()` - PascalCase 名称:
CogDatabase、FastEmbedEmbedder
# 反引号:`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
这防止了同一文件因使用绝对路径和相对路径而出现重复条目。
设计原则
- 纯正则,无 LLM:亚毫秒级执行,确定性,无幻觉风险
- 首次匹配优先:分类有严格排序 — 安全约束始终优先
- 多标签:一条记忆可以同时是
root_cause和observation - 双语:所有模式同时适用于英文和中文文本
- 优雅降级:未知文本默认为
code分类,置信度 0.80 - 受控词汇:所有标签通过白名单验证 — 无自由标记