Spectre.Reply.Sanitizer behaviour (Spectre v0.3.3)

Copy Markdown View Source

Strips Spectre control tokens from model output before it becomes a user-visible reply.

Prompts teach the model Spectre's routing and planning markup — <al>, <intent>, <reply> wrappers, INTENT:/AL: control lines — and models also emit reasoning wrappers (<think>, HTML comments). None of that may reach the user, and without a core scrubber every host rewrites the same cleanup. This sanitizer is the runtime default wherever LLM text becomes reply_text; pass sanitize_reply: false to opt out. An action planner may perform its own cleanup first, but its visible reply still crosses this structural boundary unless sanitization is explicitly disabled.

Host-specific cleanup (localized model preambles, channel formatting) stays in the host. It can be supplied through :reply_sanitizer as a module, or {module, options}, implementing this module's callbacks. The configured sanitizer is an additive layer: Spectre removes its own control tokens first, then invokes the extension. This keeps the core security boundary in place while allowing a package such as Pulse to own model-specific cleanup.

Streaming extensions must implement all three streaming callbacks as well as sanitize/2. They receive only text already accepted by the core incremental sanitizer. A sanitizer may suppress text but must not synthesize or expand it. Its provisional output must also be monotonic with sanitize/2: concatenated deltas must not contain text that the terminal callback would remove.

Summary

Functions

Removes Spectre control tokens and reasoning wrappers, then trims.

Types

stream_state()

@type stream_state() :: term()

Callbacks

finish_stream(stream_state)

(optional)
@callback finish_stream(stream_state()) :: {:ok, String.t()} | {:error, term()}

init_stream(keyword)

(optional)
@callback init_stream(keyword()) :: {:ok, stream_state()} | {:error, term()}

sanitize(t, keyword)

@callback sanitize(
  String.t(),
  keyword()
) :: String.t()

sanitize_chunk(t, stream_state)

(optional)
@callback sanitize_chunk(String.t(), stream_state()) ::
  {:ok, String.t(), stream_state()} | {:error, term()}

Functions

sanitize(text, opts \\ [])

@spec sanitize(
  String.t(),
  keyword()
) :: String.t()

Removes Spectre control tokens and reasoning wrappers, then trims.

iex> Spectre.Reply.Sanitizer.sanitize("<think>hmm</think>Hello <al>a1</al>there")
"Hello there"

Honors sanitize_reply: false in opts by returning the text trimmed but otherwise untouched. :reply_sanitizer accepts a callback module or {module, options} for additional cleanup after Spectre's built-in pass.