Stage Category: APPLY (1-1 Transformation)Transformation: N documents → N documents (or fewer with
fail_on_error=False)When to Use
When NOT to Use
Parameters
Template Context
Templates have access to the full retriever execution context:Both uppercase and lowercase namespace formats work identically (
DOC == doc).Built-in Functions
These numeric helpers are available directly in templates — useful for clamping and rounding computed values (e.g. ranking scores):
Read tunable inputs with a default using
INPUT.get, so callers can override a
weight per request but omit it otherwise: {{ INPUT.get('recency_weight', 0.3) }}.
Template Features
Jinja2 Syntax
Useful Filters
Configuration Examples
Error Handling
Common failure causes:
- Invalid template syntax
- Template rendering errors (missing fields)
- Invalid JSON output from template
- Document missing required fields
Performance
Multi-line Templates
For complex templates, use HEREDOC syntax in the API call:Common Patterns
Drop Unused Fields
Flatten Nested Metadata
Add Query Context
Compute a custom ranking signal (recency boost + used-demotion)
json_transform is the general-purpose way to compute a custom ranking score
at query time: read the relevance score and any document fields, blend in your own
signals, emit the result as a score, then order by it with
sort_relevance. Because every weight is read
from INPUT, the same retriever is tunable per request — including an instant
off-switch — with no redeploy.
The pipeline is three stages:
used_in_ad edge. The blended score is
recency_factor is a gentle linear decay max(0, 1 − days_old / freshness_days).
The template reads each weight from INPUT with a default, so callers override only
what they want. This is the exact template that runs in production, prettified for
readability (the verbatim single-line version is in the block below):
- User metadata is read from
_internal.metadatahere (md), the path managed-pipeline documents use. If your documents carry metadata at the top level or undermetadatainstead, adjust the path to match how they were ingested. - The default idiom guards
null, not just missing.INPUT.get('recency_weight') if INPUT.get('recency_weight') is not none else 0.3falls back both when the caller omits the input and when it passes an explicitnull—INPUT.get('x', 0.3)alone would keep a client-sentnull. days_oldis a pseudo-ordinal (Y*372 + M*31 + D), monotonic and accurate to about ±1 day versus true calendar days — deliberately cheap, since exact date math isn’t needed to rank by freshness.
Verbatim single-line template (paste as the template string)
Verbatim single-line template (paste as the template string)
The production template is authored on one line (newlines are optional in Jinja).
This is byte-for-byte what ran in prod:
json_transform replaces each document with the template’s JSON output, so
emit every field you want downstream — including the score that sort_relevance
reads. Pass the template to the stage as its template string (escape it as JSON,
or use the heredoc form shown under Multi-line Templates).input_schema as optional):
Related
- Sort Relevance - Order by a score, including one computed here
- RAG Prepare - Format documents for LLM context
- LLM Enrich - Extract structured data with LLMs
- API Call - Format for external API calls

