@team-harness/memory-algorithms
v0.2.0
Published
Host-independent L1/L2/L3 and Skill extraction derived from TencentDB-Agent-Memory
Downloads
679
Readme
@team-harness/memory-algorithms
从软件协作对话提取带原文证据的事实与经验候选(L1),经人工确认后,进一步整理为场景经验(L2)、画像或工作准则(L3)。也支持独立提取 Skill。
独立 TypeScript / ESM 包,要求 Node.js 22+。应用提供消息和模型驱动,负责权限、存储、审核界面与同步;算法返回候选和运行记录,不启动服务、不保存 L0、不自动发布知识。
安装与版本
本版本为 0.2.0。npm 发布状态可通过 npm view @team-harness/memory-algorithms version --registry=https://registry.npmjs.org/ 核对。
npm install @team-harness/[email protected]0.2.0 的 L1 是破坏性升级。 入口仍叫 extractL1,输入新增稳定的 streamId,返回 EvidenceNote 待审候选,不再返回可直接存为记忆的 Atom。调用方必须适配,不能只修改依赖版本。
L2/L3/Skill 的调用契约保持不变。公开的 durableMemoryStrategy 现在必须明确传入 "l2" 或 "l3"。旧 L1 的 mode、strategy、conflictRecallTopK 不再接受;旧续跑位置不能用于新版。旧数据应保留原算法版本和审核历史,不会由本包自动迁移或重新提取。
提取流程
| 接口 | 输入 | 输出 |
| --- | --- | --- |
| extractL1 | 有序消息、稳定会话标识、范围、可选续跑位置 | 待审事实与经验 EvidenceNote、证据窗口、运行记录 |
| applyEvidenceDecision | 候选、原始证据、真实用户决定 | 更新后的候选及审核记录 |
| exportReviewedLessons | 当前证据与已审核候选 | 可供 L2 使用的 Atom[],附未导出原因 |
| extractL2 | 已确认的 L1 经验、已有场景 | 场景文档候选 |
| extractL3 | 已确认的场景、已有画像 | Persona 文档候选 |
| extractSkills | 对话、已有技能读取接口 | Skill 文档及资源候选 |
L0 消息 → extractL1 → 待审事实 / 经验
↓ 人工保留或修订
已确认的经验 → L2 候选 → 审核 → L3 候选 → 审核事实可以保留供查询使用,不能自动提升为工作原则。Skill 可独立提取,不必等待 L3。
提取 L1
import { extractL1, type Message, type ModelDriver } from "@team-harness/memory-algorithms";
export async function analyze(model: ModelDriver, messages: Message[]) {
return extractL1({ model }, {
runId: "analysis-attempt-1",
scopeKey: "host-1:project-1",
streamId: "conversation-1",
messages,
limits: { maxInputChars: 120000, maxOutputTokens: 8192, timeoutMs: 180000 },
});
}每条 Message 包含稳定的 id、role、content、毫秒时间戳 timestamp,以及至少一个 { id, version } 形式的 evidence 引用。引用应能定位到应用保存的不可变 L0;可补充 hash 和 completeness。输入已裁剪时,消息标记 completeness: "truncated"。
scopeKey 是宿主明确指定的项目、团队等范围,不根据目录名猜测;streamId 是稳定会话标识,不随重试变化;runId 标识一次执行。
- 默认每批 20 条新消息,最多带入之前 5 条 user/assistant 消息,总计不超过 25 条。
maxNewMessages和maxBackgroundMessages可调整上述窗口。超过输入字符预算时,先减少背景,再减少整条新消息,保留续跑位置。- 工具消息保留在进度统计中但不送入模型。这里不发送工具输入或输出正文;必要的故障原因应由聊天正文提供。
- 单条消息本身超出预算会明确失败,不暗中裁剪。宿主可扩大预算,或提供带截断标记的输入视图。
- 每窗口最多一次模型调用,不做自动审核和修订循环。最多生成 8 条候选,提示词要求其中最多 2 条经验;模型建议不代表质量确认。
- 单条候选格式或引用错误只拒绝该候选,其他有效候选仍可保存。仅引用背景的候选被排除;跨窗口候选必须包含本批新证据。
changes[].after 是 EvidenceNote:包含 kind: "fact" | "lesson"、标题、正文、来源归属、原文引文、范围、版本及 review.status: "pending"。来源归属区分用户陈述、助手报告、计划和推断。引文匹配只是机械校验,不证明正文语义正确。
分批与失败处理
每次调用返回 status、changes、coverage、provenance,以及以下 L1 字段:
| 字段 | 含义 |
| --- | --- |
| packet | 该窗口的临时证据视图;输入校验失败时可能没有 |
| continuation | 后续窗口位置;有此字段才继续调用 |
| rejected | 逐条机械校验失败,不是语义质量判断 |
| unrepresentedSourceIds | 本批没有候选引用的 user/assistant 消息,不表示它们都值得成为经验 |
| promotion | 固定为 manual_review_required |
partial 可能表示还有消息,也可能只有个别候选被拒绝;不能仅凭 partial 无限重试。将有效待审候选、拒绝原因和续跑位置放在同一事务保存,之后使用同一份完整消息快照及 continuation 继续。范围、会话、模型、窗口设置或消息变化会使续跑位置失效。
failed / cancelled 不返回可提交候选,不推进原检查点。参数错误也可能直接抛出异常,调用层仍需捕获。completed 可以是空结果;扫描完成不代表所有重要事件都被正确总结。
provenance 包含算法版本、上游基线、模型、输入及提示词 hash、调用数和 token 用量。未提供实际用量时为 null,不要按零计费。L1 不执行语义去重或自动替换已保留记忆;相同窗口及内容的候选 ID 稳定,宿主应以 ID 幂等保存,跨窗口重复或矛盾交给审核处理。
保存 create 必须采用不存在才插入的语义。 同 ID 已存在时读取现有记录,不得 upsert 覆盖其版本、正文或人工审核状态;重跑提取返回的 pending 草稿不能覆盖已保留或归档的记录。审核修改只通过带 expectedVersion/expectedDigest 的事务应用。
人工审核与 L2 导出
import {
applyEvidenceDecision, exportReviewedLessons, extractL2, durableMemoryStrategy,
} from "@team-harness/memory-algorithms";
// result 来自 extractL1;仅在真实用户操作后执行下面的审核。
const packet = result.packet!;
const selected = result.changes[0].after!;
const reviewed = applyEvidenceDecision(packet, selected, {
actor: authenticatedReviewerId,
at: new Date().toISOString(),
expectedVersion: selected.version,
expectedDigest: selected.digest,
action: "keep",
reason: humanReviewReason,
});
await saveWithCompareAndSwap(selected.version, selected.digest, reviewed);
const { memories, excluded } = exportReviewedLessons(packet, [reviewed.note]);
const l2 = await extractL2({ model }, {
runId: "scenario-attempt-1", scopeKey: packet.scopeKey,
memories, scenes: savedReviewedScenes,
strategy: durableMemoryStrategy("l2"),
});审核操作支持 keep、edit_and_keep、archive。修订需要完整 body(kind、title、content、attribution、citations);只有 edit_and_keep 接受该字段。身份认证、原子版本比较和持久化由宿主负责,不能把审核接口交给模型自动调用。
只有证据仍匹配、同一范围、人工保留的 lesson 才能导出为 L2 输入。该导出是只读输入快照,不是新增数据库记录的指令。保留的 fact、pending、archived 或证据过期的候选会返回排除原因。L2/L3 输出也需要独立审核,Lib 不自动升级或共享。
审阅时用 prepareEvidenceReview({ scopeKey, streamId, sources }) 从权威 L0 重建 packet;sources 包含原窗口的消息和绝对索引。packet 无需成为另一份长期 L0。proposeEvidenceNote 支持人工补写遗漏候选。宿主需要保存来源引用与审阅历史,发现后续相关纠正时重新组装证据并标记旧结论待复核;Lib 不会自行检索会话后文。
每个窗口需保存 scopeKey、streamId、evidenceDigest,以及 packet.sources 全部消息的 ID、原始索引、hash、L0 引用与版本,不仅是候选引用过的消息。审核时据此读回同一批原文重建 packet;同一个证据集合的顺序改变不影响身份,但增减或修改消息会使旧审核过期。来自多个窗口的候选应按窗口分别调用 exportReviewedLessons,再合并导出的 Atom 数组供 L2 使用,不能把它们放入一个拼接 packet 强行审核。
selectEvidenceContext 按预算装配宿主指定的原始来源和已保留笔记,报告超预算、过期或未确认的内容。它不执行搜索、相关性排序或权限校验;原始历史、助手报告和人工解释都不应冒充独立执行验证。
模型驱动
所有提取接口接收 { model: ModelDriver }。包不绑定厂商 SDK:
import type { ModelDriver, ModelRequest, ModelResponse } from "@team-harness/memory-algorithms";
export const model: ModelDriver = {
id: "provider:model",
async complete(request: ModelRequest): Promise<ModelResponse> {
return callYourModelAPI(request);
},
};应用将 systemPrompt、messages、工具 JSON Schema、maxOutputTokens、signal 转换为真实 API 请求。返回 text、可选的 toolCalls、finishReason 和实际 usage。工具参数须解析成对象;工具调用 ID 在往返中保持一致。L1 接受一次 submit 工具调用或符合 schema 的 JSON 文本;L2/L3/Skill 需要完整的工具调用支持。驱动只负责一次网络请求,算法负责工具编排。
不要在驱动中无限重试。length 或 error 结束原因会使当前调用失败;取消信号应传到网络请求。
L2、L3 与 Skill
import { extractL2, extractL3, extractSkills } from "@team-harness/memory-algorithms";
const l2 = await extractL2({ model }, {
runId, scopeKey, memories: reviewedAtoms, scenes: reviewedScenes,
});
const l3 = await extractL3({ model }, {
runId, scopeKey, scenes: reviewedScenes,
persona: savedPersona, previousSceneVersions,
});
const skills = await extractSkills({ model, skills: skillReader }, {
runId, scopeKey, messages,
});首次 L2 的 scenes 为 [];首次 L3 可省略 persona。L3 提交时保存本次场景 { id, version } 列表,下次作为 previousSceneVersions 识别变化。L2/L3 可传 mode: "code" | "chat",默认 code;长期工作经验可传对应层的 durableMemoryStrategy。这些选项不适用于新版 L1。
L2/L3 返回带版本及证据的 Document 变更;Skill 返回完整文档和资源,读取端口需实现 list/search/get 并提供真实 writable 权限。保存变更前校验 readSet 和 before 版本,并在事务中应用 create/update/merge/retire。失败或取消时不提交临时写入。
L2/L3 不自动分批;宿主提供有界输入。Skill 默认保留对话前 8000 / 后 32000 字符,发生截取返回 partial 和诊断,没有自动续跑位置。另有 compressMessage、compressMessages、applyOversizeStrategy 供显式预处理。
来源与能力边界
L2/L3/Skill 及内部原算法基线来自 TencentDB-Agent-Memory。0.2 的 L1 候选与人工审核流程是本包新增策略;事实与长期结论分开的设计受 Hindsight 对照实验启发,未复制 Hindsight 源码,也未内置它的检索、consolidation 或 Reflect 引擎。
保留 bounded-analysis-v1 的宿主边界,不承诺与原服务逐行为等价。测试覆盖契约、失败处理和来源回放,不证明模型不会遗漏、误读状态或过度推导。长程事件关联、跨窗口语义去重及自动知识升级不在本版本的保证范围内。
