Transformer
Introduction
Overview
LLM::Transformer
is the superclass for message transformers. A transformer is bound
to a context and rewrites a single message before it is sent to the
provider. This lets you scrub sensitive data, inject context, or
otherwise modify outgoing messages without changing your prompt
code.
How it works
A transformer is a subclass of
LLM::Transformer
that implements
LLM::Transformer#call.
The method receives the message to transform and returns a
message.
You can mutate the message in place or return a new one; either way,
the returned message is what gets sent.
Configure the transformer on a context with the transformer: option,
passing a class rather than an instance. The runtime instantiates it
once per turn. Options passed through transformer_options: are
forwarded to call as keyword arguments. The transformer runs on
the most recent message in both chat completions and Responses API
turns, before the request reaches the provider:
class RedactEmails < LLM::Transformer
def call(message:)
content = message.content.to_s.gsub(/[\w.+-]+@[\w-]+\.[\w.]+/, "[EMAIL]")
LLM::Message.new(message.role, content, message.extra)
end
end
llm = LLM.deepseek(key: ENV["KEY"])
ctx = LLM::Context.new(
llm,
transformer: RedactEmails
)
ctx.talk "Contact support@example.com for help"
Why would I use it?
Transformers give you a single hook point for all outgoing messages. Common uses include redacting PII before it leaves your process, injecting a timestamp or request ID, or normalizing content for a particular provider. Because the transformer runs automatically on every turn, you never need to remember to apply the transform in your prompt code.
Notes
LLM::Transformer::Null
is the default transformer; it returns the message unchanged. The
transformer_options: hash is passed to call on every turn.
Streams can observe transformation through the
LLM::Stream#on_transform
and
LLM::Stream#on_transform_finish
callbacks, which receive the transformer instance.