Class: Brute::Pipeline
- Inherits:
-
Object
- Object
- Brute::Pipeline
- Defined in:
- lib/brute/pipeline.rb
Overview
Rack-style middleware pipeline for LLM calls.
Each middleware wraps the next, forming an onion model:
Tracing → Retry → DoomLoop → Reasoning → [LLM Call] → Reasoning → DoomLoop → Retry → Tracing
The innermost “app” is the actual LLM call. Each middleware can:
- Modify the env (context, params) BEFORE the call (pre-processing)
- Modify or inspect the response AFTER the call (post-processing)
- Short-circuit (return without calling inner app)
- Retry (call inner app multiple times)
## The env hash
{
context: LLM::Context, # conversation state
provider: LLM::Provider, # the LLM provider
input: <prompt/results>, # what to pass to context.talk()
tools: [Tool, ...], # tool classes
params: {}, # extra LLM call params (reasoning config, etc.)
metadata: {}, # shared scratchpad for middleware state
callbacks: {}, # :on_content, :on_tool_call_start, :on_tool_result
}
## The response
The return value of call(env) is the LLM::Message from context.talk().
## Building a pipeline
pipeline = Brute::Pipeline.new do
use Brute::Middleware::Tracing, logger: logger
use Brute::Middleware::Retry, max_attempts: 3
use Brute::Middleware::SessionPersistence, session: session
run Brute::Middleware::LLMCall.new
end
response = pipeline.call(env)
Instance Method Summary collapse
-
#build ⇒ Object
Build the chain without calling it.
-
#call(env) ⇒ Object
Build the full middleware chain and call it.
-
#initialize(&block) ⇒ Pipeline
constructor
A new instance of Pipeline.
-
#run(app) ⇒ Object
Set the terminal app (innermost handler).
-
#use(klass, *args, **kwargs, &block) ⇒ Object
Register a middleware class.
Constructor Details
#initialize(&block) ⇒ Pipeline
Returns a new instance of Pipeline.
44 45 46 47 48 |
# File 'lib/brute/pipeline.rb', line 44 def initialize(&block) @middlewares = [] @app = nil instance_eval(&block) if block end |
Instance Method Details
#build ⇒ Object
Build the chain without calling it. Useful for inspection or caching.
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/brute/pipeline.rb', line 69 def build raise "Pipeline has no terminal app — call `run` first" unless @app @middlewares.reverse.inject(@app) do |inner, (klass, args, kwargs, block)| if block klass.new(inner, *args, **kwargs, &block) else klass.new(inner, *args, **kwargs) end end end |
#call(env) ⇒ Object
Build the full middleware chain and call it.
64 65 66 |
# File 'lib/brute/pipeline.rb', line 64 def call(env) build.call(env) end |
#run(app) ⇒ Object
Set the terminal app (innermost handler).
58 59 60 61 |
# File 'lib/brute/pipeline.rb', line 58 def run(app) @app = app self end |
#use(klass, *args, **kwargs, &block) ⇒ Object
Register a middleware class. The class must implement ‘initialize(app, *args, **kwargs)` and `call(env)`.
52 53 54 55 |
# File 'lib/brute/pipeline.rb', line 52 def use(klass, *args, **kwargs, &block) @middlewares << [klass, args, kwargs, block] self end |