DyingWallet/dsh-pet-configurable-llm

dsh-pet-configurable-llm

为 dsh-pet 提供的可配置 LLM 接入层:OpenAI 兼容 API,把桌宠对话接到专用 DSH 会话,复用 AGENTS.md 人格与 memories/ 长期记忆,并注入召回与回顾。 Configurable OpenAI-compatible LLM bridge for dsh-pet: routes pet chats into a dedicated DSH session, reusing AGENTS.md persona and memories/ long-term memory with recall + review injection.

미분류desktop-petdsh-petllm

dsh-pet-configurable-llm —— 桌宠的「LLM」接入层

项目名:dsh-pet-configurable-llm(可配置的 dsh-pet LLM 接入层)。
DSH 里的 provider ID 是 pet-llm(2026-10-25 从 pet-brain 改名;旧 ID 不再使用,
升级时要把 profile 的 llm-pi-ai 和 dsh-pet 的 chatModel / whisperModel 一起改)。
代码标识符统一用 LLM/agent 的说法(DshAgent、createPetLlmServer、PET_LLM_*);
只有旧补丁标记 petBrainReplyPriority / .bak-petbrain 保留旧拼写,因为要认出已经
打过补丁的文件(见 src/patch-dsh-pet.mjs)。

把 dsh-pet 的对话/碎碎念接到同一个工作区里的专用 DSH 会话,让桌宠复用工作区的 AGENTS.md 人格、memories/ 长期记忆和同一个模型账户;它自己的 memory.json 不再参与生成。

桌宠 UI ──POST /chat──▶ dsh-pet host ──ctx.llm──▶ DSH 自定义 provider「pet-llm」
                                                   │
                                            本服务(OpenAI 兼容 /v1)
                                                   │
                                    专用 DSH 会话(workspace=D:\deepseek_workspace)
                                    preset=pet-chat(只读工具)
                                    └─ AGENTS.md + memories/ + 记忆卡

它解决什么

  • 不是“把模型换成 DeepSeek”——桌宠本来就用当前 DSH 模型;这里换的是会话身份:

同一个工作区、同一份 AGENTS.md、同一份 memories/,以及一条能在 DSH 里打开审计的会话。

  • 桌宠的 memory.json 不进入上下文(chatMemoryRounds: 0);真正的记忆是

memories/ + 那条 DSH 会话。

  • 桌宠只是“嘴和身体”:气泡、动画、工作状态仍由 dsh-pet 管;模型会话在 DSH 里。

前置

  • Windows,DSH 桌面版 0.2.1-rc.2(见下节;其它版本未验证)。
  • Node.js ≥ 22.12。本机 PATH 没有 node 时,用 DSH 自带的:

D:\Software\dsh\resources\runtime\primary-runtime\dependencies\node\bin\node.exe

  • qq-agent-presets 插件(pet-chat preset 复用它提供的只读工具守卫)。
  • 本服务依赖 ..\qq-bridge\src\dsh-client.js(Cookie 铸造、端口发现、session RPC),

所以 qq-bridge 目录要保留在同级。

DSH 版本支持

已验证 `0.2.1-rc.2` 与 `0.2.1-rc.3`(rc.3 实测:--check 通过、session/prompt 等 RPC 形态未变)。其它版本未验证,升级后请先自检:

node src\index.mjs --check

为什么绑得这么紧——本服务吃的是 DSH 的未公开 RPC 形态,不是稳定协议:

依赖点 · 在 0.2.1-rc.2 的形态 session/prompt · 必须带 requestId;mode: 'queue' session/selectModel · 选完模型后 reasoningEffort 由 DSH 决定 session/projections · 队列/权限/token 用量都从这里读 agentPresets.list · preset 存在才能建会话(pet-chat) commands.execute · /permission read-only 走这条 turn/end 的 reason · {kind: completed\ · aborted · error\ · blocked};`blocked` 没有 message

升级 DSH 后如果桌宠开始报错或只回降级文案,先看 logs/pet-llm.log 里的 reason: blocked 见 memories/50-knowledge/2026-10-24-pet-blocked-session.md,error 才是网络/进程问题。

安装(三步)

1. 安装 pet-chat preset

# 先 dry-run,确认目标与备份路径
powershell -ExecutionPolicy Bypass -File scripts\apply-preset.ps1
# 确认后写入 profile patch
powershell -ExecutionPolicy Bypass -File scripts\apply-preset.ps1 -Apply

然后重启 DSH 桌面版(插件/preset 变更必须重启)。重启后:

# 本机 PATH 没有 node 时用这个包装(会自动找 DSH 自带 Node)
powershell -ExecutionPolicy Bypass -File scripts\check.ps1
# 或直接:
& 'D:\Software\dsh\resources\runtime\primary-runtime\dependencies\node\bin\node.exe' src\index.mjs --check

--check 会生成 state/token.txt(即使 presetReady 还是 false,也可以先拿 token)。 presetReady 必须是 true。回滚:

powershell -ExecutionPolicy Bypass -File scripts\rollback-preset.ps1
# 或从备份恢复
powershell -ExecutionPolicy Bypass -File scripts\rollback-preset.ps1 -Restore

2. 在 DSH 里添加自定义 provider

DSH 设置 → 模型 → 添加自定义提供方(或直接写 settings.yaml 的 llm-pi-ai):

字段 · 值 Provider ID · pet-llm 显示名称 · 桌宠 基础 URL · http://127.0.0.1:8790/v1 API 协议 · openai-completions 凭据 / API Key · state/token.txt 里的那串(首次启动生成) 模型 · id xi,名称 桌宠 超时 · 55000 ms(低于桌宠 /chat 的 60s)

settings.yaml 等价写法(按你机器上的 DSH 版本字段为准):

llm-pi-ai:
  providers:
    pet-llm:
      displayName: 桌宠
      api: openai-completions
      baseURL: http://127.0.0.1:8790/v1
      apiKeyEnv: PET_LLM_KEY   # 或在 UI 里保存凭据
      timeoutMs: 55000
      compat:
        supportsDeveloperRole: false
        maxTokensField: max_tokens
      models:
        - id: xi
          name: 桌宠
不要把 pet-llm 设成 DSH 的默认模型:那会让本服务里的 DSH 会话再调回本服务,
形成自我递归。它只给桌宠的 chatModel 用。
建议把该路由的重试调低(retryPolicy.maxRetries: 0 或 1):DSH 超时后自动重试会
对同一条会话再发一次 prompt,产生重复的 agent turn。

3. 配置桌宠

编辑 $DSH_HOME\dsh-pet\main-config.jsonc(或设置页)把全局默认改成:

{
  "chatModel": { "provider": "pet-llm", "model": "xi" },
  "whisperModel": { "provider": "pet-llm", "model": "xi" },
  "chatMemoryRounds": 0,
  "pets": [
    {
      "id": "main",
      "whisperEnabled": false
      // …其余字段保持原样
    }
  ]
}
  • chatMemoryRounds: 0:桌宠的 memory.json 不再进上下文。
  • whisperEnabled: false:关掉每 300 秒自动碎碎念(否则每 5 分钟烧一个 agent turn)。

手动右键「碎碎念」//chat 空参数仍可用,走同一个 LLM 会话。

  • 如果设置页的下拉框暂时看不到 pet-llm/xi,直接改 main-config.jsonc 也能生效

(配置校验只要求 provider/model 都非空)。

启动与验证

# 启动(前台;建议用计划任务/隐藏窗口在登录时启动)
& 'D:\Software\dsh\resources\runtime\primary-runtime\dependencies\node\bin\node.exe' src\index.mjs

# 另开一个终端:
curl http://127.0.0.1:8790/health
& 'D:\...\node.exe' tools\pet.mjs state
& 'D:\...\node.exe' tools\pet.mjs chat "在吗"

验“里面是不是我”

  1. 长期记忆:问桌宠「QQ 桥接的启动链有哪几段?」它应能说出

start-stack.ps1 / SnowLuma / hook / 桥接(来自 50-knowledge/,不在记忆卡里, 必须真的用 read/grep 查)。

  1. 身份暗号:问「暗号是什么?」它应回答 海盐柠檬 0423

(来自 memories/.meta/identity-canary.md;答不出=没读到记忆)。

  1. 清空它自己的记忆:备份并清空 $DSH_HOME\dsh-pet\memory.json,再问上面任意一题。

答对 = 没有依赖桌宠自己的 memory。

  1. 审计:在 DSH 会话列表里打开「桌宠 LLM」,能看到这轮对话与工具调用。

记忆卡

  • 服务启动时生成 memories/.meta/pet-memory-card.md,内容 = profile / preferences /

index / 最近 2 篇日志 / 项目 / 近期决策 / 相关的人 / 00-inbox/live-context.md。

  • 第一条消息把它作为“启动卡”注入;之后同一会话不再重复注入。
  • 定时刷新(默认 10 分钟)与会话重置后重新注入;也可 POST /admin/memory/refresh。
  • 需要细节时,pet-chat 的只读工具会去读 memories/index.md 指向的原文件。
这张卡是长期记忆。主会话里刚发生的事不走这张卡,走每轮召回时并取的「live」块
(见下节「记忆服务」):最近的短期 chat 直接拼进 prompt,不必等写进 memories/。
记忆卡每 10 分钟刷新一次;live 块每轮都是新的。

dsh-pet 气泡优先级自愈

dsh-pet 的气泡位只有一个,回合结束时「工作状态」气泡(“任务完成啦”等)会优先占位,盖住刚到的回复。

本服务启动时会自动给已安装的 dsh-pet 打补丁(src/patch-dsh-pet.mjs),网页和桌面 helper 两套渲染栈都改:

  • 网页 lib/client.js:两个工作状态分支加 && !(whisperBubbleOn && whisperText);
  • 桌面 runtime/electron-helper/sprite.js:bubble slot 改成 whisperOn ? 'whisper' : workTerminal && workOn ? 'work' : ...;
  • 幂等(petLlmReplyPriority 标记,同时认旧标记 petBrainReplyPriority),首次修改前各自备份

.bak-petllm(旧的 .bak-petbrain 也认);

  • dsh-pet 升级后下次启动自动重打;匹配不到只记 warning。

生效:网页刷新即可;桌面 helper 需要重启 DSH(helper 进程启动时才读 sprite.js)。

记忆服务(memd)

除记忆卡之外,本服务还接 memory-hub(memd):

  • src/memory.mjs:每轮 POST /v1/recall(scene=pet)把相关记忆拼在 prompt 最前;同时 POST /v1/ingest 上报用户消息与回复(短期层,50 条/批,失败静默)。
  • 令牌在 state/memory.token(surface pet,scopes main/qq:owner/pet,无 work:read)。
  • 可见范围:owner 的 main/qq:owner + shared;不含工作/财务、群、第三人私聊。
  • 配置段:
"memoryService": {
  "endpoint": "http://127.0.0.1:8787",
  "tokenFile": "D:/deepseek_workspace/dsh-pet-configurable-llm/state/memory.token",
  "scene": "pet",
  "recallK": 3,
  "recallMaxChars": 800,
  "live": { "k": 6, "minutes": 30, "scenes": ["main"], "maxChars": 400 },
  "timeoutMs": 800,
  "ingest": true
}
  • live = 「对方那边刚刚在聊的」:每轮带 live 参数调 /v1/recall,把指定场景最近

minutes 分钟的短期 chat 拼在长期记忆之前(是现状,不是回忆)。"live": false 关闭。 可见性仍由 memd 的 SQL 决定:pet 令牌看得到 owner 的 main chat,看不到 sensitive、 看不到群和别人的私聊。主会话消息由 dsh-memory 插件上报,所以这条链路是自动的。

  • memd 不在线时静默降级:没有记忆块,但桌宠照常回复。
  • 验证:node test/run-all.mjs(含「召回块进 prompt、用户与回复都入库」用例)。