README.md
README.md
Real-time repetition guard for LM Studio: the moment a local model starts looping on repeated text — in the answer, in the thinking stream, or in tool-call arguments — generation is stopped automatically. Everything generated before the loop is kept intact.
Quantized local models (especially small ones) can degenerate into loops mid-generation, repeating the same sentence in reasoning, or spam identical tool-call JSON — burning tokens and polluting the context. LM Studio ships no built-in loop breaker; this plugin adds one.
The plugin registers a Guarded Generator that wraps a locally loaded model. Every fragment is forwarded to the UI and inspected by a single Z-function detector:
The streams are guarded independently: answer text, thinking/reasoning, and tool-call arguments, two of them are toggleable.
On trigger: the underlying prediction is aborted immediately (the server stops generating), emitted fragments are preserved, the turn finishes cleanly (exactly like a user stop), and an optional one-line note is appended. Nothing is deleted. Warnings about the connection being dropped will appear in the logs. This is normal.
- |) are stripped before matching, so tables never false-positive on their decorations.Pick the guarded generator provided by this plugin in the chat model selector.
UPD: tupik/repetition-guard Replaced the detector algorithm with the reversed Z-function. Increased the period of detectable cycles. Threshold adjustment has been simplified. A simple mechanism based on the percentage of cycle repetition.
the Fork Inspired by: https://lmstudio.ai/siqyin/repetition-guard
The loop detection engine has been refactored, replacing the heuristic "window-chant" approach with a Reverse Z-Algorithm.
The loop detection engine utilizes a Reverse Z-Algorithm on a normalized text buffer.
-|).D (the loop period) and its current continuous overlap length matchLen hits the dynamic threshold, generation is immediately aborted.Instead of a fixed character cap, the threshold is computed dynamically based on the current loop distance: [\text{Calculated Threshold} = \max(16, \lfloor \text{distance} \times \text{repetitionThreshold} \rfloor)]
The multiplier value controls the level of allowed structural redundancy after the first (original) text generation:
| Setting | Default | Meaning |
|---|---|---|
| Model Key | (empty) | Local model to guard (empty = current active model) |
| Temperature | 0.8 | Passed through to the loaded model |
| Repeat Threshold | 1.0 | Dynamic multiplier of loop distance (0.5 to 4.0). Lower values trigger pre-emptively. |
| Check Interval | 1 | Runs the check every X normalized chars. 1 ensures single-character precision. |
| Max Text Length | 20000 | Size of the rolling memory window (use 25000+ for massive 10K structural cycles). |
| Guard Thinking Stream | on | Intercept loops inside the reasoning/thinking text (<think>). |
LM Studio 实时重复输出守卫:本地模型正文 / 思考流一开始"复读",立刻自动截停,已生成内容完整保留。
量化模型(尤其是小模型)长生成时容易陷入循环:wait wait wait wait …、思考里反复念同一句话、工具调用参数刷同一段 JSON——白烧 token 还占着上下文。目前 LM Studio 没有内置的"检测到循环就停"机制,本插件补上这一环。
插件注册一个 Guarded Generator,包裹本地已加载的模型,逐片段转发输出的同时用单一的 Z-函数检测器 检查:
maxTextLength 个归一化字符(去除空白和 Markdown 表格装饰 -|,并转小写)。对于更长的重复单元,触发会比单字符更早。检测同时作用于三路流:正文、思考(reasoning)、工具调用参数,可分别开关。
灵敏度说明:与仅检测尾部的旧方案不同,Z-函数会对比缓冲区开头,因此输出早期某段原样重复出现也会被判定为循环——比之前的双检测器更灵敏。
- |)在匹配前会被去除,不会因表格装饰而误判。| 项 | 默认 | 说明 |
|---|---|---|
| Model Key | (空=当前模型) | 要守护的本地模型 |
| Temperature | 0.8 | 透传给模型 |
| Repeat Threshold | 1.0 | 循环触发阈值,越小截停越早 |
| Check Interval | 1 | Z-函数检查间隔(归一化字符数) |
| Max Text Length | 20000 | 用于检查时保留的最大归一化文本长度 |
| Guard Thinking Stream | 开 | 检测思考流 |
| Guard Answer Stream | 开 | 检测正文流 |
| Notify On Stop | 开 | 截停时附提示行 |
在聊天的模型选择器里选本插件提供的 guarded 生成器即可生效。
Detection strategy inspired by dsh-repetition-guard / dsh-dupguard (DeepSeek Harness) and Qwen Code's LoopDetectionService.
MIT
Real-time repetition guard for LM Studio: the moment a local model starts looping on repeated text — in the answer, in the thinking stream, or in tool-call arguments — generation is stopped automatically. Everything generated before the loop is kept intact.
Quantized local models (especially small ones) can degenerate into loops mid-generation, repeating the same sentence in reasoning, or spam identical tool-call JSON — burning tokens and polluting the context. LM Studio ships no built-in loop breaker; this plugin adds one.
The plugin registers a Guarded Generator that wraps a locally loaded model. Every fragment is forwarded to the UI and inspected by a single Z-function detector:
The streams are guarded independently: answer text, thinking/reasoning, and tool-call arguments, two of them are toggleable.
On trigger: the underlying prediction is aborted immediately (the server stops generating), emitted fragments are preserved, the turn finishes cleanly (exactly like a user stop), and an optional one-line note is appended. Nothing is deleted. Warnings about the connection being dropped will appear in the logs. This is normal.
- |) are stripped before matching, so tables never false-positive on their decorations.Pick the guarded generator provided by this plugin in the chat model selector.
UPD: tupik/repetition-guard Replaced the detector algorithm with the reversed Z-function. Increased the period of detectable cycles. Threshold adjustment has been simplified. A simple mechanism based on the percentage of cycle repetition.
the Fork Inspired by: https://lmstudio.ai/siqyin/repetition-guard
The loop detection engine has been refactored, replacing the heuristic "window-chant" approach with a Reverse Z-Algorithm.
The loop detection engine utilizes a Reverse Z-Algorithm on a normalized text buffer.
-|).D (the loop period) and its current continuous overlap length matchLen hits the dynamic threshold, generation is immediately aborted.Instead of a fixed character cap, the threshold is computed dynamically based on the current loop distance: [\text{Calculated Threshold} = \max(16, \lfloor \text{distance} \times \text{repetitionThreshold} \rfloor)]
The multiplier value controls the level of allowed structural redundancy after the first (original) text generation:
| Setting | Default | Meaning |
|---|---|---|
| Model Key | (empty) | Local model to guard (empty = current active model) |
| Temperature | 0.8 | Passed through to the loaded model |
| Repeat Threshold | 1.0 | Dynamic multiplier of loop distance (0.5 to 4.0). Lower values trigger pre-emptively. |
| Check Interval | 1 | Runs the check every X normalized chars. 1 ensures single-character precision. |
| Max Text Length | 20000 | Size of the rolling memory window (use 25000+ for massive 10K structural cycles). |
| Guard Thinking Stream | on | Intercept loops inside the reasoning/thinking text (<think>). |
LM Studio 实时重复输出守卫:本地模型正文 / 思考流一开始"复读",立刻自动截停,已生成内容完整保留。
量化模型(尤其是小模型)长生成时容易陷入循环:wait wait wait wait …、思考里反复念同一句话、工具调用参数刷同一段 JSON——白烧 token 还占着上下文。目前 LM Studio 没有内置的"检测到循环就停"机制,本插件补上这一环。
插件注册一个 Guarded Generator,包裹本地已加载的模型,逐片段转发输出的同时用单一的 Z-函数检测器 检查:
maxTextLength 个归一化字符(去除空白和 Markdown 表格装饰 -|,并转小写)。对于更长的重复单元,触发会比单字符更早。检测同时作用于三路流:正文、思考(reasoning)、工具调用参数,可分别开关。
灵敏度说明:与仅检测尾部的旧方案不同,Z-函数会对比缓冲区开头,因此输出早期某段原样重复出现也会被判定为循环——比之前的双检测器更灵敏。
- |)在匹配前会被去除,不会因表格装饰而误判。| 项 | 默认 | 说明 |
|---|---|---|
| Model Key | (空=当前模型) | 要守护的本地模型 |
| Temperature | 0.8 | 透传给模型 |
| Repeat Threshold | 1.0 | 循环触发阈值,越小截停越早 |
| Check Interval | 1 | Z-函数检查间隔(归一化字符数) |
| Max Text Length | 20000 | 用于检查时保留的最大归一化文本长度 |
| Guard Thinking Stream | 开 | 检测思考流 |
| Guard Answer Stream | 开 | 检测正文流 |
| Notify On Stop | 开 | 截停时附提示行 |
在聊天的模型选择器里选本插件提供的 guarded 生成器即可生效。
Detection strategy inspired by dsh-repetition-guard / dsh-dupguard (DeepSeek Harness) and Qwen Code's LoopDetectionService.
MIT
| Guard Answer Stream | on | Intercept loops in the final visible output. |
| Notify On Stop | on | Append a clean system note to the chat turn on cut-off. |
checkInterval 个字符计算该缓冲区的 Z-函数:Z[i] = 整个文本与从位置 i 开始的后缀的最长公共前缀长度。max(Z) ≥ threshold − 1,则判定为循环(例如连续 10 个相同字符 → maxZ = 9)。近似重复次数为 floor(maxZ / zThreshold) + 1(zThreshold = threshold − 1)。npm install
npm run dev # development mode (hot reload)
node test/detector.test.js # run tests
npm run push # publish to LM Studio Hub
npm install
npm run dev # 开发模式(热重载)
npm run push # 发布到 LM Studio Hub
| Guard Answer Stream | on | Intercept loops in the final visible output. |
| Notify On Stop | on | Append a clean system note to the chat turn on cut-off. |
checkInterval 个字符计算该缓冲区的 Z-函数:Z[i] = 整个文本与从位置 i 开始的后缀的最长公共前缀长度。max(Z) ≥ threshold − 1,则判定为循环(例如连续 10 个相同字符 → maxZ = 9)。近似重复次数为 floor(maxZ / zThreshold) + 1(zThreshold = threshold − 1)。npm install
npm run dev # development mode (hot reload)
node test/detector.test.js # run tests
npm run push # publish to LM Studio Hub
npm install
npm run dev # 开发模式(热重载)
npm run push # 发布到 LM Studio Hub