Files
Hy-Memory/docs/scene_coding_usage.md
T
e089d4b800 fix(coding): default-off search chain_block (diff) injection (#128)
Medium/heavy coding users pay large prompt tokens for the version-evolution
diff block; make MEMORY_CODING_CHAIN_BLOCK_ENABLED opt-in (default false).
Write-side observe is unchanged; HCM_BLOCK_OFF remains an advanced kill switch.

Co-authored-by: alvinfei <alvinfei@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-21 14:46:23 +08:00

10 KiB
Raw Blame History

Working 与 Coding 场景

Hy Memory 的公开 scene 参数支持三个值:

scene 用途 存储与检索路径
"chat" 闲聊、个人事实、一般问答 通用 memory pipeline
"working" 文档、办公、研究、财经、内容创作和电脑操作等生产力任务 working 双层 memory
"coding" 编码、调试、测试、构建、API/SDK、脚本、SQL 等软件工程任务 coding 双层 memory,并附带版本演进链

working 与 coding 复用同一套生产力 pipeline 结构和数据 schema,但使用不同的抽取规范、SQLite 文件和向量集合,数据不会混在一起。

1. 写入路由

显式指定 scene

生产力写入需要包含 tool message 或 assistant tool_calls:

from hy_memory import HyMemoryClient

client = HyMemoryClient(mode="pro")

messages = [
    {"role": "user", "content": "Fix the timeout in the search client."},
    {
        "role": "assistant",
        "content": "",
        "tool_calls": [
            {
                "id": "call_1",
                "type": "function",
                "function": {
                    "name": "apply_patch",
                    "arguments": '{"path":"src/search.py"}'
                },
            }
        ],
    },
    {
        "role": "tool",
        "tool_call_id": "call_1",
        "name": "apply_patch",
        "content": "Patch applied successfully",
    },
]

result = client.add(
    messages,
    scene="coding",
    user_id="user_123",
    workspace_id="github.com/example/service",
    branch="fix/search-timeout",
)

公开行为:

  • scene="chat":跳过 scene judge;tool 轨迹会被移除后进入 chat pipeline。
  • scene="working":跳过 scene judge,进入 working pipeline。
  • scene="coding":跳过 scene judge,进入 coding pipeline,并尝试记录版本演进链。
  • 显式 working/coding 但输入没有 tool/tool_calls:当前实现会回退 chat pipeline。
  • 非法 scene 会抛出 ValueError。

不指定 scene

scene=None 时:

  • 输入没有 tool/tool_calls:直接进入 chat pipeline,不调用 scene judge LLM。
  • 输入包含 tool/tool_calls:使用 user query 与工具名的有界摘要进行一次 chat / working / coding 三分类。
  • judge 失败或输出无法解析:回退 chat。
  • 判定为 chat 后,tool 轨迹会被移除再进入 chat pipeline。

分类边界:

  • coding:代码或开发产物是工作对象或实现媒介,包括源码、脚本、SQL、notebook、测试、构建、编译/运行错误、API/SDK 和代码评审。
  • working:存在明确生产力操作或交付物,但代码不是核心工作媒介,例如文档、PPT、表格、翻译、财经/业务分析、研究报告、邮件日程、项目管理、设计、文件整理、软件安装和设备操作。
  • chat:闲聊、个人信息、建议和一般事实问答。仅使用 search/browser 工具不会自动变成 working。

2. 搜索路由

显式传 scene 会直接选择对应检索路径,不调用 judge/rewrite LLM:

result = client.search(
    "Which timeout implementation was finally kept?",
    scene="coding",
    user_ids=["user_123"],
    workspace_id="github.com/example/service",
    branch="fix/search-timeout",
    limit=5,
)

默认与 agentic 行为:

调用方式 当前行为
search(query="...", search_mode="default") 固定走 chat/normal light search,零 LLM
search(queries=[...], search_mode="default") Coding 开启时分类并 rewrite;仅 Query Rewrite 开启时只 rewrite/time;两者关闭时零 LLM
search(query="...", search_mode="agentic") LLM 三分类、query rewrite 和时间范围解析
search(queries=[...], search_mode="agentic") 同上,前置 query 作为上下文
任意模式显式传 scene scene 优先,零 judge/rewrite LLM

search_mode="agentic" 使用有界 query 视图,单 query 与多 query 都会走 judge/rewrite。search_mode="default" 的单 query 保证不调用该 LLM。

default 多-query 超过 MEMORY_QUERY_REWRITE_MAX_CHARS 时不改写;Coding 开启时仍做有界 场景分类,关闭时直接使用最后一条 query。

若 coding 功能被 MEMORY_CODING_ENABLED=false 关闭,生产力搜索会安全回退 chat/normal 检索。

3. Extractor 输入窗口

working/coding extractor 将输入分成:

  • LAST 5 USER TURNS:之前 write 的历史,只用于指代消解和上下文,不重复抽取。
  • NEW MESSAGES:本次 add() 传入的全部消息,全部作为抽取主体,不受 last-5 裁剪。

当前压缩规则:

  • tool result 默认最大 2048 bytes,保留头尾并省略中段;由 MEMORY_CODING_TOOL_RESULT_MAX_BYTES 配置。
  • 单条 assistant 文本超过 6000 字符时,默认保留前 3000 和后 3000 字符。
  • 历史按 user-turn 窗口裁剪;一个 user-turn 包含该 user 消息以及下一条 user 消息前的 assistant/tool 消息。
  • MEMORY_EXTRACT_HISTORY_TURNS 控制 store 回读多少历史,默认 5;当前 extractor 最终最多注入最近 5 个 user-turn,因此大于 5 的配置不会扩大 prompt 中的历史窗口。

例如本次写入包含 10 个 user-turn 时,10 个 turn 都进入 NEW MESSAGES;历史区另外最多提供最近 5 个 user-turn。

working/coding 的 Extractor、经验 Reconcile、事实 Reconcile 与跨 session 进展总结均有 中英文模板。路由优先检查本次新输入前 10 个有效语言字符;Extractor 只看本次 NEW user messages,不使用历史或 tool result 决定语言。中文开头后接大量代码、路径或错误信息时仍走 中文模板;英文开头后面偶尔出现中文术语时保持英文模板。

4. 返回结构

working/coding 写入返回双层结果:

{
    "success": True,
    "scene": "productivity",
    "request_id": "...",
    "ops": [...],
    "ops_summary": {...},
    "experience_ids": [...],
    "fact_ops": [...],
    "fact_ops_summary": {...},
    "fact_ids": [...],
    "memory_id": "..." or None,
    "elapsed_ms": 123.4,
}

scene="coding" 还会返回 chain_rounds。出于历史兼容,该字段当前统计本次识别并处理 的 diff hunk 数,而不保证等于最终合并后的唯一演进 round 数。0 表示没有识别到可记录 的代码修改,不代表双层 memory 写入失败。

working/coding 搜索返回:

{
    "request_id": "...",
    "scene": "productivity",
    "facts": [...],
    "experiences": [...],
    "elapsed_ms": 123.4,
}

limit 分别限制 facts 与 experiences,因此两层最多各返回 limit 条。

scene="coding" 额外返回 chain_block 和 chain_used 字段(键始终存在;默认内容为空):

  • 注入 diff / 版本演进块需显式开启 MEMORY_CODING_CHAIN_BLOCK_ENABLED=true (或 CodingConfig.chain_block_enabled=True)。默认关闭,以节约 prompt token。
  • 开启后,chain_block 是与已召回 fact 对齐的版本演进上下文;无法挂链时为 ""。
  • chain_used 是已经进入 chain block 的 facts 下标。
  • SDK 不会从 facts 删除这些条目。调用方若要拼成“chain block + 剩余 facts”,需自行按 chain_used 过滤。

5. 存储与作用域

默认本地文件:

<coding db directory>/
├── coding_memory.db          # working 经验/事实 metadata
├── coding_memory_cv.db       # coding 经验/事实 metadata
├── coding_memory_trace.db    # working/coding 共用的历史消息
└── hy_code_chain/
    └── hy_code.db            # coding 版本演进链

向量集合:

变体 经验层 事实层
working {base}_coding_keys {base}_working_facts
coding {base}_coding_keys_cv {base}_working_facts_cv

同一个 client 可以交替使用 working 与 coding;实现会按变体分别缓存 writer/store。

workspace_id 与 branch 用于生产力 memory 的作用域:

  • 不传 workspace_id:不按 workspace 过滤。
  • 传 workspace_id:精确匹配该 workspace。
  • branch 只有在同时传 workspace_id 时生效。
  • branch 过滤会保留 branch IS NULL 的历史数据,避免未记录分支的通用经验被误删。

建议写入和搜索使用相同的规范化 workspace_id。版本链的 owner 由 user_id 与 workspace_id 共同构成,避免不同用户或仓库的 patch 串链。

6. Coding 版本演进链

版本演进链由 hy_memory/coding/chain_store.py 实现。它不调用 LLM 或 embedding,而是从以下来源识别修改:

  • 设置 MEMORY_CODING_CHAIN_REPO_ROOT 后,从本地 Git 工作区或变更中读取 diff。
  • 从工具轨迹中识别带 path、old、new 的确定性替换动作。

无法可靠解析的编辑形式会被跳过。链层是 best-effort:记录失败不会阻断 working/coding 的双层 memory 写入或检索。

7. 配置

变量 默认值 作用
MEMORY_CODING_ENABLED true 启用 working/coding pipeline
MEMORY_CODING_DB_PATH {DATA_DIR}/data/coding_memory.db working 基础 SQLite 路径;coding/trace 路径由此派生
MEMORY_CODING_TOOL_RESULT_MAX_BYTES 2048 单条 tool result 的字节上限
MEMORY_CODING_VERBATIM_FALLBACK_ENABLED false 模型无结果时是否保存原文 fact;默认关闭,避免 assistant/tool trace 直接展示
MEMORY_CODING_CHAIN_BLOCK_ENABLED false search 是否注入版本演进链块(chain_block / diff);默认关闭(opt-in)
MEMORY_EXTRACT_HISTORY_TURNS 5 回读的历史 user-turn 数;当前 prompt 最终最多使用 5
MEMORY_CODING_CHAIN_REPO_ROOT 空 coding 版本链读取本地 Git diff 的仓库路径

HCM_* 变量属于版本链的高级调优项,不是稳定的公共配置契约;普通接入不应依赖其默认值。 其中 HCM_BLOCK_OFF=1 可在已开启 MEMORY_CODING_CHAIN_BLOCK_ENABLED 时做消融(完全不出块)。

8. 定向验证

python -m pytest -q \
  tests/coding/test_write_scene_routing.py \
  tests/coding/test_search_scene_routing.py \
  tests/coding/test_scene_coding_variant.py \
  tests/coding/test_scene_coding_search.py \
  tests/coding/test_coding_pipeline_log.py