Skip to content

Feedback classifier leaks raw LLM completion (think tags, special tokens) into persisted feedback rationale #2336

Description

@hxyinan

Summary

Feedback classification responses can leak the raw LLM completion — including closing <think> tags and DeepSeek special tokens — into the persisted feedback rationale. The existing thinking-disable only covers capture.summarize; every other op (e.g. feedback.classify) can receive thinking-enabled model output, and nothing strips think-tags from message.content before it is stored.

This is related to #2308 (the op parameter was dropped at the LLM boundary): even with op correctly propagated, thinking is only disabled for capture.summarize.

Reproduction / evidence

Two feedback rows stored on 2026-09-02 in our deployment contain a rationale that is clearly a raw model completion, not classified output:

rationale: "</think>\n<|end▁of▁sentence|>\n<|end▁of▁session|>\n\n---\n\n[Writing Rule]..."
polarity: negative

Code path (v2.0.17)

  1. dist/core/feedback/llm-classifier.jsclassifyByLlm() calls llm.complete(..., { op: "feedback.classify" })
  2. dist/core/llm/providers/openai.js only disables thinking for one op:
if (opts.op === "capture.summarize") {
    body.thinking = { type: "disabled" };
}
  1. For thinking-enabled models served through gateways that keep <think> blocks inside message.content, the raw completion (with </think>, <|end▁of▁sentence|>, …) flows back unmodified.
  2. dist/core/experience/feedback-builder.js then persists feedback.rationale (and raw verifier text) verbatim into the store — polluted text becomes retrieval-visible memory.

Suggested fix

Either (ideally both):

  1. Sanitize at the provider choke point: strip <think>…</think> blocks, orphan closing </think> fragments, and DeepSeek special tokens (<|begin▁of▁sentence|>, <|end▁of▁sentence|>, <|end▁of▁session|>) from choice.message.content before returning from the provider — one place, fixes all ops.
  2. Extend thinking-disable to deterministic/analytical ops (feedback.classify, l3.abstraction, verifier, retrieval filter), not just capture.summarize.

Environment

  • memos-local plugin 2.0.17 (npm memtensor-memos-local-plugin-2.0.17)
  • Adapter: Hermes (adapters/hermes/memos_provider)
  • Windows 11, Node v24, LLM provider openai_compatible (deepseek-family model)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

ai:taskDispatched to AI coding agent | 已派发给 AI 编码任务ai:testingAI agent is running tests | AI 正在运行测试area:pluginOpenClaw & Hermesstatus:in-progressSomeone or AI is working on it | 人工或 AI 正在处理types:bugSomething isn't working | 功能异常

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions