Skip to main content

llm-scrub

Zero-dependency scrubbers for LLM chat output. Weak models leak backend scaffolding into the text shown to the user — JSON state-op fences, injected === … === context blocks, and English "tool preamble" meta-narration. llm-scrub strips that noise deterministically, using pure string/regex logic instead of relying on the model to obey a prompt.

  • No dependencies. Pure standard library (json, re).
  • Deterministic. No model call, no network — a plain str -> str transform.
  • Conservative. Tuned to under-strip rather than over-strip: legitimate fenced code blocks, JSON data, markdown tables, and === dividers survive.
  • Idempotent. scrub(scrub(x)) == scrub(x).

Install

pip install llm-scrub

Requires Python 3.10+.

Quickstart

from llm_scrub import scrub

raw = (
    "好,开始输出。\n\n"
    "=== 时间线检索锚点 ===\n"
    "当前时间:序章 · 站台\n\n"
    "林夕睁开眼睛,废墟在昏黄的天光下铺展开来。\n\n"
    '```json\n[{"op": "set", "path": "world.location", "value": "废墟"}]\n```\n'
    "Let me mark the anchors now."
)

print(scrub(raw))
# 林夕睁开眼睛,废墟在昏黄的天光下铺展开来。

scrub chains the three scrubbers in the canonical order. Call them individually when you only need one:

from llm_scrub import (
    strip_json_state_ops,
    strip_meta_tool_preamble,
    strip_leaked_scaffold,
)

strip_json_state_ops('战斗结束。\n```json\n{"op": "append", "path": "bag", "value": "刀"}\n```')
# '战斗结束。'

strip_meta_tool_preamble("他转身离去。\nLet me update the anchors now.")
# '他转身离去。'

strip_leaked_scaffold("她走进废墟。\n\n=== 相关原文片段 ===\n某段原文\n\n她捡起刀。")
# '她走进废墟。\n\n她捡起刀。'

API

Function Signature Removes
scrub scrub(text: str, *, extra_headers=None) -> str All three, chained in the canonical order.
strip_json_state_ops strip_json_state_ops(text: str) -> str JSON state-op fences — fenced (```json […] ), un-fenced bare [{"op":…}], and truncated/unclosed ops left by a cut-off response.
strip_meta_tool_preamble strip_meta_tool_preamble(text: str) -> str A leaked English "tool preamble" sentence at the tail (e.g. "Let me mark the anchors now.").
strip_leaked_scaffold strip_leaked_scaffold(text: str, *, extra_headers=None) -> str Whole === … === backend scaffold blocks (retrieval anchors, world-line summaries, etc.), plus a trailing "begin output" reasoning preamble.

LEAKED_SCAFFOLD_KEYS is the built-in tuple of scaffold header markers; pass your own via extra_headers to extend it.

What it strips

1. JSON state-op fences. Some pipelines let the model emit state changes as JSON. Those blocks must never reach the reader:

你推开门,走了进去。

```json
[{"op": "set", "path": "player.location", "value": "地窖"}]
```

→ 你推开门,走了进去。 — including malformed and truncated (streamed-and-cut) variants. A fenced JSON block that is not ops (a plain object or array of data) is preserved, so legitimate code examples survive.

2. Leaked tool preamble. Before a native tool call, a model may blurt one line of meta-narration meant for itself:

…晨光无声流转。The scene has progressed naturally. Let me mark the anchors that have been satisfied through our gameplay.

Only a trailing, unquoted, predominantly-English segment matching a preamble phrase is removed. A character's English dialogue inside quotes is never touched.

3. Leaked scaffold blocks. Weak models sometimes dump the backend's invisible context straight into the prose:

=== 时间线检索锚点 ===
当前时间:序章 · 站台
待确认跳跃:无

These headers are fixed strings the backend injects; normal narrative never emits them verbatim, so the whole block is removed with zero collateral damage. Extend the header list for your own backend:

scrub(text, extra_headers=("我的自定义脚手架",))

Design: under-strip, never over-strip

Every scrubber is tuned to leave the text alone when in doubt:

  • Fenced/bare JSON is only stripped when it parses and carries state-op markers (op / path / question). Other JSON is preserved.
  • A trailing English segment is only stripped when it is outside quotes and matches a known tool-preamble phrase.
  • A === … === line is only stripped when its inner text matches a known scaffold header — a === 序章 === divider or a markdown setext underline is left intact.
  • If stripping would empty the text (a whole turn of pure leakage), the original is returned rather than blanking the message.

License

MIT — see LICENSE.

Acknowledgements

Extracted from the RPG Roleplay platform (https://github.com/felixchaos/rpg-roleplay-platform).

Metadata

Release files for llm-scrub 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llm-scrub 0.1.0
File Size Uploaded Provenance Actions
llm_scrub-0.1.0.tar.gz 16.6 kB With provenance Details for llm_scrub-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for llm-scrub 0.1.0
File Interpreter ABI Platform Actions
llm_scrub-0.1.0-py3-none-any.whl Python 3 none any Details for llm_scrub-0.1.0-py3-none-any.whl

Total release size: 28.0 kB

Release files / llm_scrub-0.1.0.tar.gz

Download URL llm_scrub-0.1.0.tar.gz
Size 16.6 kB
Tags Source
SHA-256 checksum
How to use checksums
628103944b375534a68d8d6d7bb55b49433423b50e2e49f1a10366a70e65efa5
BLAKE2b-256 checksum
How to use checksums
ca04d9aedc02ed157e26140babded8b57b052c4903fd31d0b6d55a91120d4c84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Release files / llm_scrub-0.1.0-py3-none-any.whl

Download URL llm_scrub-0.1.0-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1675d1c8cbd135574390861ba377a1d9962dd984acec2d43d58d97840c9bc03e
BLAKE2b-256 checksum
How to use checksums
ef51ebc39c23d8c8d462422b3bc7e861df330462f06026119cd9ca784bde0322
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

Security for llm-scrub 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for llm_scrub-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page