Buckets:
| <meta charset="utf-8" /><meta name="hf:doc:metadata" content="{"title":"Response Parsing","local":"response-parsing","sections":[{"title":"Streaming response parsing","local":"streaming-response-parsing","sections":[],"depth":2},{"title":"Streaming events","local":"streaming-events","sections":[],"depth":2},{"title":"Advanced: Writing a response template","local":"advanced-writing-a-response-template","sections":[],"depth":2},{"title":"Advanced: Field API Reference","local":"advanced-field-api-reference","sections":[{"title":"Parsing the content of a field","local":"parsing-the-content-of-a-field","sections":[{"title":"Basic types","local":"basic-types","sections":[],"depth":4},{"title":"json","local":"json","sections":[],"depth":4},{"title":"xml-inline","local":"xml-inline","sections":[],"depth":4},{"title":"kv-lines","local":"kv-lines","sections":[],"depth":4}],"depth":3},{"title":"Transform","local":"transform","sections":[],"depth":3}],"depth":2},{"title":"Framework developers: Regex portability","local":"framework-developers-regex-portability","sections":[],"depth":2}],"depth":1}"/> | |
| <link href="/docs/transformers/main/en/_app/immutable/entry/start.K656vW6L.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/CEvZpVEF.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/BZU-fJBn.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/entry/app.BCfcLogB.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/CvHU6tKs.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/cwP4npO5.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/BRRD8tqb.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/DsnmJJEf.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/nodes/0.CstLl4Rh.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/B3Wd0hfR.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/nodes/15.BpQFum1S.js" rel="modulepreload"> | |
| <link href="/docs/transformers/main/en/_app/immutable/chunks/CDJi-eW2.js" rel="modulepreload"> | |
| <!--1gi18nc--><meta name="hf:doc:metadata" content="{"title":"Response Parsing","local":"response-parsing","sections":[{"title":"Streaming response parsing","local":"streaming-response-parsing","sections":[],"depth":2},{"title":"Streaming events","local":"streaming-events","sections":[],"depth":2},{"title":"Advanced: Writing a response template","local":"advanced-writing-a-response-template","sections":[],"depth":2},{"title":"Advanced: Field API Reference","local":"advanced-field-api-reference","sections":[{"title":"Parsing the content of a field","local":"parsing-the-content-of-a-field","sections":[{"title":"Basic types","local":"basic-types","sections":[],"depth":4},{"title":"json","local":"json","sections":[],"depth":4},{"title":"xml-inline","local":"xml-inline","sections":[],"depth":4},{"title":"kv-lines","local":"kv-lines","sections":[],"depth":4}],"depth":3},{"title":"Transform","local":"transform","sections":[],"depth":3}],"depth":2},{"title":"Framework developers: Regex portability","local":"framework-developers-regex-portability","sections":[],"depth":2}],"depth":1}"/><!----> | |
| <link href="/docs/transformers/main/en/_app/immutable/assets/0.tn0RQdqM.css" rel="modulepreload"> <!--[--><!--[0--><!--[--><!--[0--><!--[--><p></p> <div class="items-center shrink-0 min-w-[100px] max-sm:min-w-[50px] justify-end ml-auto flex" style="float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"><div class="inline-flex rounded-md max-sm:rounded-sm"><button class="inline-flex items-center gap-1 h-7 max-sm:h-7 px-2 max-sm:px-1.5 text-sm font-medium text-gray-800 border border-r-0 rounded-l-md max-sm:rounded-l-sm border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-live="polite"><span class="inline-flex items-center justify-center rounded-md p-0.5 max-sm:p-0 hover:text-gray-800 dark:hover:text-gray-200"><svg class="sm:size-3.5 size-3" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----></span> <span>Copy page</span></button> <button class="inline-flex items-center justify-center w-6 max-sm:w-5 h-7 max-sm:h-7 disabled:pointer-events-none text-sm text-gray-500 hover:text-gray-700 dark:hover:text-white rounded-r-md max-sm:rounded-r-sm border border-l transition border-gray-200 bg-white hover:shadow-inner dark:border-gray-850 dark:bg-gray-950 dark:text-gray-200 dark:hover:bg-gray-800" aria-haspopup="menu" aria-expanded="false" aria-label="Open copy menu"><svg class="transition-transform text-gray-400 overflow-visible sm:size-3.5 size-3 rotate-0" width="1em" height="1em" viewBox="0 0 12 7" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L6 6L11 1" stroke="currentColor"></path></svg><!----></button></div> <!--[-1--><!--]--></div><!----> <!--[0--><h1 class="relative group"><a id="response-parsing" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#response-parsing"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Response Parsing</span></h1><!--]--><!----> <p>It is increasingly common for chat models to generate structured outputs, rather than just a single reply string. For example, | |
| a <a href="https://huggingface.co/reasoning-course" rel="nofollow">reasoning model</a> might emit a chain of thought containing its reasoning trace, | |
| while a <a href="./chat_extras">tool calling</a> model might emit function names and arguments.</p> <p>The problem with structured outputs, though, is that LLMs outputs are not inherently structured. LLM APIs usually | |
| accept and return message dicts, with keys like <code>role</code> and <code>content</code> and <code>thinking</code>, but internally, LLMs actually | |
| just continue a single sequence of tokens. We use a glue layer to connect the user-facing API to the actual token | |
| stream of the model. To turn inputs into a token stream, we use <a href="./chat_templating"><code>chat_templates</code></a>, which are covered in other | |
| documents. This document is about the other half of that glue layer: <strong>Response templates</strong>, the system for turning the | |
| generated tokens output by the model back into a structured response dict.</p> <p>In many ways, response templates perform the inverse operation to chat templates. With chat templates, you feed in | |
| a list of messages, and you get tokens ready to input to the model. With response templates, you feed in the raw | |
| model output tokens, and you get a structured message. Like chat templates, response | |
| templates allow users to ignore the messy details of what specific formats and control tokens a model expects, | |
| and use a universal API of message dicts that works with any model.</p> <p>The best way to understand response templates is to see them in action. The main entry point is the <a href="/docs/transformers/pr_40546/en/internal/tokenization_utils#transformers.PreTrainedTokenizerBase.parse_response">parse_response()</a> method, which accepts either a single sequence or a batch:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-keyword">from</span> transformers <span class="hljs-keyword">import</span> AutoModelForCausalLM, AutoTokenizer | |
| checkpoint = <span class="hljs-string">"HuggingFaceTB/SmolLM3-3B"</span> | |
| tokenizer = AutoTokenizer.from_pretrained(checkpoint) | |
| model = AutoModelForCausalLM.from_pretrained(checkpoint, dtype=<span class="hljs-string">"auto"</span>, device_map=<span class="hljs-string">"auto"</span>) | |
| messages = [{<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"Summarize the end of the Cold War, very briefly."</span>}] | |
| input_ids = tokenizer.apply_chat_template(messages, add_generation_prompt=<span class="hljs-literal">True</span>, return_tensors=<span class="hljs-string">"pt"</span>)[<span class="hljs-string">"input_ids"</span>].to(model.device) | |
| outputs = model.generate(input_ids, max_new_tokens=<span class="hljs-number">1024</span>)[<span class="hljs-number">0</span>, input_ids.shape[<span class="hljs-number">1</span>]:] | |
| out_text = tokenizer.decode(outputs) | |
| <span class="hljs-built_in">print</span>(tokenizer.parse_response(out_text, prefix=input_ids[<span class="hljs-number">0</span>])) | |
| <span class="hljs-comment"># Outputs a structured dict: {"role": "assistant", "thinking": "...", "content": "..."}</span><!----></pre></div><!----> <p>When a tokenizer has a <code>response_template</code>, the <code>parse_response</code> method will cleanly turn an output message into a | |
| structured dict, ready to append to the chat. Note that we need to pass the <code>prefix</code> (the prompt tokens) to this method as well. This is because many chat templates start | |
| messages or open thinking blocks before letting the model begin its response, and so our parser needs to see the | |
| prompt to understand the message. All of the prefix before the final turn is discarded; we only parse one message | |
| at a time. We just need the prefix to ensure we’re seeing the entire final message, and not miss any prefilled | |
| fields!</p> <p>Because a missing prefix can silently mis-parse a prefilled message, <code>prefix</code> is required when parsing with a | |
| new-style <code>response_template</code>: omitting it raises an error. In the rare case where you are sure the generation | |
| already contains the complete message and no prefix context is needed, pass <code>prefix=""</code> (or an empty list of | |
| token ids) to opt out explicitly.</p> <p>If the tokenizer has no response template set, <code>parse_response</code> will raise an error. We’re working on adding | |
| templates to more models as quickly as we can!</p> <!--[1--><h2 class="relative group"><a id="streaming-response-parsing" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#streaming-response-parsing"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Streaming response parsing</span></h2><!--]--><!----> <p>In the above example, we parse the model response all at once after generation has finished. Often, though, we may | |
| want to parse partial messages as they are generated, especially in user-facing apps where we don’t just want to | |
| display a static page for a minute or two until the model is finished.</p> <p>When you want streaming parsing, call <code>tokenizer.get_response_parser()</code>, which returns a <code>ResponseParser</code>. | |
| As with <code>parse_response</code>, pass the chat prompt as <code>prefix=</code> so the parser knows about any parts of the message that | |
| were prefilled by the chat template. The returned object is a | |
| stateful parser that you can feed text into as the model generates it:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->parser = tokenizer.get_response_parser(prefix=input_ids[<span class="hljs-number">0</span>]) | |
| <span class="hljs-keyword">for</span> event <span class="hljs-keyword">in</span> parser.initial_events: | |
| render(event) <span class="hljs-comment"># Display the partial message to the user however you want to</span> | |
| <span class="hljs-keyword">for</span> chunk <span class="hljs-keyword">in</span> model_output: | |
| <span class="hljs-keyword">for</span> event <span class="hljs-keyword">in</span> parser.feed(chunk): | |
| render(event) | |
| message, final_events = parser.finalize() | |
| <span class="hljs-keyword">for</span> event <span class="hljs-keyword">in</span> final_events: | |
| render(event)<!----></pre></div><!----> <p>The parser will emit <strong>events</strong> as text from the generation process is fed in. This indicates which region is currently being generated. When | |
| the region is complete, it will be emitted in a separate event with the fully parsed content. At the end of generation, | |
| the <code>finalize()</code> method flushes any remaining text and emits any final events, as well as the complete message dict.</p> <p>Note that although <code>parse_response</code> can accept batches, streamed parsing is always single-sequence: each <code>ResponseParser</code> tracks the state of one generation. | |
| If you want to stream multiple generations at once, create one <code>ResponseParser</code> per sequence.</p> <!--[1--><h2 class="relative group"><a id="streaming-events" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#streaming-events"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Streaming events</span></h2><!--]--><!----> <p>Each streamed parsing event is a dict with a <code>type</code> key. There are three kinds:</p> <table><thead><tr><th>Type</th><th>Description</th><th>Contents</th></tr></thead><tbody><tr><td><code>region_open</code></td><td>Indicates that the model has started a new region, such as <code>content</code> or <code>thinking</code>.</td><td><code>field</code> (str): the field name.</td></tr><tr><td><code>region_chunk</code></td><td>A chunk of text for the current region.</td><td><code>field</code> (str): the field name. <code>text</code> (str): the new chunk. <code>dirty</code> (bool): <code>True</code> if the chunk is raw text that needs parsing.</td></tr><tr><td><code>region_close</code></td><td>Indicates that a region has finished, and that key is now finalized.</td><td><code>field</code> (str): the field name. <code>value</code> (any): the fully parsed value for the region</td></tr></tbody></table> <p><code>region_chunk</code> events are emitted for every region as bytes arrive, so a streaming UI can render progress | |
| even for structured regions. For text-like regions (<code>text</code>, <code>int</code>, <code>float</code>, <code>bool</code>) chunks are flagged <code>dirty=False</code>: each chunk is already part of the final value (modulo trailing whitespace stripped at | |
| close). For structured regions, like JSON-format tool calls, chunks are flagged <code>dirty=True</code>. This means | |
| text is the raw, un-parsed body; it’s safe to display incrementally, but the <em>parsed</em> value (a dict, | |
| list, etc.) only arrives in the matching <code>region_close</code> event. Either way, the finalized value of a | |
| region is always carried by <code>region_close</code>, so consumers that don’t care about intermediate rendering | |
| can simply ignore <code>region_chunk</code> events.</p> <p>If the chat <code>prefix</code> wrote anything into the message (e.g. the template opened a thinking block, or an | |
| assistant prefill started a response before handing off to the model), the parser exposes those events as <code>parser.initial_events</code>, a list you can replay into your renderer before feeding any model output. Regions | |
| that were opened <em>and</em> closed inside the prefix produce a full <code>region_open</code> / <code>region_chunk</code> / <code>region_close</code> sequence and their parsed value lands in the output dict, exactly as if the model itself had written them.</p> <p>A typical event stream might look like this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_open"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"thinking"</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_chunk"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"thinking"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">"I should "</span>, <span class="hljs-string">"dirty"</span>: <span class="hljs-literal">False</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_chunk"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"thinking"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">"greet the user"</span>, <span class="hljs-string">"dirty"</span>: <span class="hljs-literal">False</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_close"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"thinking"</span>, <span class="hljs-string">"value"</span>: <span class="hljs-string">"I should greet the user"</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_open"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"tool_calls"</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_chunk"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"tool_calls"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">'{"name": "greet_user", '</span>, <span class="hljs-string">"dirty"</span>: <span class="hljs-literal">True</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_chunk"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"tool_calls"</span>, <span class="hljs-string">"text"</span>: <span class="hljs-string">'"arguments": {"greeting": "Hi!"}}'</span>, <span class="hljs-string">"dirty"</span>: <span class="hljs-literal">True</span>} | |
| {<span class="hljs-string">"type"</span>: <span class="hljs-string">"region_close"</span>, <span class="hljs-string">"field"</span>: <span class="hljs-string">"tool_calls"</span>, <span class="hljs-string">"value"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: {<span class="hljs-string">"name"</span>: <span class="hljs-string">"greet_user"</span>, <span class="hljs-string">"arguments"</span>: {<span class="hljs-string">"greeting"</span>: <span class="hljs-string">"Hi!"</span>}}}}<!----></pre></div><!----> <p>Note how <code>thinking</code> is emitted with <code>dirty=False</code>, because fields like <code>thinking</code> and <code>content</code> are usually just raw | |
| text. This means you can treat the chunks as valid “partial output”. However, <code>tool_calls</code> is flagged as <code>dirty</code> because | |
| the raw text needs significant cleanup - tool calls often need to be parsed as JSON or another format and then | |
| restructured to generate the final tool call dict. As a result, the final output for these regions often looks very, | |
| very different from the raw text. This final parsing will only happen when <code>region_close</code> is reached. It’s | |
| up to you what you want to do with the <code>dirty</code> chunks until then - you can display them as-is to show the user the | |
| “raw” output, or you can simply wait until you have something clean to display.</p> <p>This concludes most of what you need to know to use response templates. The rest of this document is focused on | |
| the internals of the parsing system and how to write response templates. This is mostly relevant for developers | |
| and model authors. Most people can safely stop here!</p> <!--[1--><h2 class="relative group"><a id="advanced-writing-a-response-template" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#advanced-writing-a-response-template"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Advanced: Writing a response template</span></h2><!--]--><!----> <p>The best way to understand how to write a response template is to pick a concrete example. Here’s what a raw | |
| reply from <code>SmolLM</code> might look like:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-txt "><!----><think> | |
| I should greet the user | |
| </think> | |
| <tool_call>{"name": "greet_user", "arguments": {"greeting": "Hi!"}}</tool_call><!----></pre></div><!----> <p>When we parse this output in the standard message dict format, it should look like this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-json "><!----><span class="hljs-punctuation">{</span> | |
| <span class="hljs-attr">"role"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"assistant"</span><span class="hljs-punctuation">,</span> | |
| <span class="hljs-attr">"thinking"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"I should greet the user"</span><span class="hljs-punctuation">,</span> | |
| <span class="hljs-attr">"tool_calls"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span> | |
| <span class="hljs-punctuation">{</span><span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"function"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"function"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"greet_user"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"arguments"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"greeting"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Hi!"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span> | |
| <span class="hljs-punctuation">]</span> | |
| <span class="hljs-punctuation">}</span><!----></pre></div><!----> <p>And here’s the template that parses it. Don’t be intimidated - a lot of it is fairly self-explanatory!</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->{ | |
| <span class="hljs-string">"defaults"</span>: {<span class="hljs-string">"role"</span>: <span class="hljs-string">"assistant"</span>}, | |
| <span class="hljs-string">"start_anchor"</span>: <span class="hljs-string">"<|im_start|>assistant\n"</span>, | |
| <span class="hljs-string">"fields"</span>: { | |
| <span class="hljs-string">"thinking"</span>: {<span class="hljs-string">"open"</span>: <span class="hljs-string">"<think>"</span>, <span class="hljs-string">"close"</span>: <span class="hljs-string">"</think>"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"text"</span>}, | |
| <span class="hljs-string">"tool_calls"</span>: { | |
| <span class="hljs-string">"open"</span>: <span class="hljs-string">"<tool_call>"</span>, | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"</tool_call>"</span>, | |
| <span class="hljs-string">"repeats"</span>: <span class="hljs-literal">True</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"json"</span>, | |
| <span class="hljs-string">"transform"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: <span class="hljs-string">"{content}"</span>}, | |
| }, | |
| <span class="hljs-string">"content"</span>: { | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"<|im_end|>"</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"text"</span>, | |
| }, | |
| }, | |
| }<!----></pre></div><!----> <p>Essentially, the template defines <strong>fields</strong> and <strong>delimiters</strong>. Each field corresponds to a key in the | |
| output dict. Fields also include information for parsing the text inside their delimiters. There’s one subtlety: The <code>content</code> field has no <code>open</code>, because in SmolLM (and several other models), it’s not marked by a special token. Instead, <code>content</code> is stored in the space after the other regions, but before the end of the sequence. In our template, we | |
| represent this as an <strong>implicit / leftover</strong> field that picks up any text not claimed by another region.</p> <p>In addition to <code>fields</code>, the template supports two top-level keys:</p> <ul><li><code>defaults</code> (optional) — A dict of values pre-populated in the output (e.g. <code>{"role": "assistant"}</code>). Keys here are | |
| always retained in the parsed output, even if no field wrote to them; other keys are dropped when their field | |
| captured nothing.</li> <li><code>start_anchor</code> (str) / <code>start_anchor_pattern</code> (str regex) — Marks where the current assistant message | |
| begins inside a chat prompt. When you pass <code>prefix=</code> to <code>parse_response</code> or <code>get_response_parser</code>, the parser | |
| right-truncates the prefix past the <strong>last</strong> occurrence of this anchor before processing it, so earlier turns in | |
| a multi-turn conversation don’t pollute the current message’s state. The anchor is applied only to the <code>prefix</code>, | |
| never to the response/generation you parse — some formats legitimately re-emit it mid-message (gpt-oss harmony | |
| output opens every channel with <code><|start|>assistant</code>), so stripping the response past the anchor would drop the | |
| model’s own reasoning and tool calls. This is why the generation alone is never enough to guard against history | |
| bleed: pass the prompt as <code>prefix=</code>. For ChatML-style models the anchor is typically <code>"<|im_start|>assistant\n"</code>. | |
| Exactly one of <code>start_anchor</code> or <code>start_anchor_pattern</code> must be set.</li></ul> <p>For example, given this multi-turn prefix (note the <strong>two</strong> assistant turns):</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-txt "><!----><|im_start|>user | |
| Hi<|im_end|> | |
| <|im_start|>assistant | |
| Hello!<|im_end|> | |
| <|im_start|>user | |
| Again?<|im_end|> | |
| <|im_start|>assistant<!----></pre></div><!----> <p>the parser truncates everything up to the <strong>last</strong> <code><|im_start|>assistant\n</code>, discarding the earlier <code>"Hello!"</code> turn. The rule is that <em>everything but the final assistant turn is always dropped.</em></p> <p>As with chat templates, response templates are stored as tokenizer attributes and saved with the tokenizer. Unlike | |
| chat templates, we save them inside <code>tokenizer_config.json</code> and not as a separate file, because their format fits | |
| naturally in JSON, unlike a chat template Jinja script.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->tokenizer.response_template = template | |
| tokenizer.save_pretrained(...) <span class="hljs-comment"># Written as a key in tokenizer_config.json</span><!----></pre></div><!----> <!--[1--><h2 class="relative group"><a id="advanced-field-api-reference" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#advanced-field-api-reference"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Advanced: Field API Reference</span></h2><!--]--><!----> <p>Each field supports several keys. We can divide these into two types. First, there are the keys that define how the field should be captured:</p> <table><thead><tr><th>Key</th><th>Type</th><th>Purpose</th></tr></thead><tbody><tr><td><code>open</code></td><td>str or list[str]</td><td>Literal string that opens this region. A list of strings means “match any of these”.</td></tr><tr><td><code>open_pattern</code></td><td>str (regex)</td><td>Regex alternative to <code>open</code>. Named groups become capture variables available to <code>transform</code>.</td></tr><tr><td><code>close</code></td><td>str or list[str]</td><td>Literal string (or list of strings) that closes this region. Omit to run to end-of-stream.</td></tr><tr><td><code>close_pattern</code></td><td>str (regex)</td><td>Regex alternative to <code>close</code>. Named groups become capture variables available to <code>transform</code>.</td></tr><tr><td><code>repeats</code></td><td>bool</td><td>If true, the field is a list and each match appends. Default <code>false</code>.</td></tr><tr><td><code>optional</code></td><td>bool</td><td>If false and the region never matches, we raise an error. Default <code>true</code>.</td></tr></tbody></table> <p>A field should have <strong>either</strong> <code>open</code> or <code>open_pattern</code>, but not both, and the same is true for <code>close</code> and <code>close_pattern</code>.</p> <p>A field may omit <code>close</code>/<code>close_pattern</code> entirely, in which case the region stays open until the end of the | |
| generated text. This is useful for a final field that runs to the end of the message.</p> <p>A field with <strong>neither</strong> <code>open</code> nor <code>open_pattern</code> is the <strong>implicit</strong> field: it’s active whenever no explicit | |
| region is open, so it captures leftover text. At most one field can be implicit. This is most often used when <code>content</code> does not have special token tags, it’s just written as plaintext after the other fields.</p> <p>In addition to opening and closing delimiters, you can also specify <code>repeats</code>, which indicates that the field is a list | |
| and the delimiters can match multiple times. This is most common for parallel tool calling, when a model emits | |
| multiple tool calls simultaneously:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">'<tool_call>{"name": "a", ...}</tool_call><tool_call>{"name": "b", ...}</tool_call>'</span> | |
| <span class="hljs-comment"># Returns `"tool_calls": [{... "a" ...}, {... "b" ...}]` in a template with repeats: true</span><!----></pre></div><!----> <p>Finally, you can specify <code>optional: false</code> for fields that must be present. If such a field is missing, | |
| we raise an error instead of just returning a message dict without it.</p> <p>The end of generation will close and finalize any open regions, even if their closing delimiter was not seen.</p> <!--[2--><h3 class="relative group"><a id="parsing-the-content-of-a-field" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#parsing-the-content-of-a-field"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Parsing the content of a field</span></h3><!--]--><!----> <p>Once we define how to capture a field, we also need to specify how to parse the raw text inside that capture. There are four | |
| keys that control this:</p> <table><thead><tr><th>Key</th><th>Type</th><th>Purpose</th></tr></thead><tbody><tr><td><code>content</code></td><td>str</td><td>The content type inside this region. Defaults to <code>"text"</code>. Each type has its own parser.</td></tr><tr><td><code>content_args</code></td><td>dict</td><td>Arguments to be passed to the content parser for this region.</td></tr><tr><td><code>transform</code></td><td>dict/list</td><td>Optional post-parse template that reshapes the parsed body (see <strong>Transform</strong>).</td></tr><tr><td><code>transform_each</code></td><td>bool</td><td>If true, the parsed content must be a list and <code>transform</code> is applied per-element.</td></tr></tbody></table> <p>The first (and most important) key is <code>content</code>. This indicates the content type | |
| of the field, which determines the parser that will be used to convert the raw text captured in the field to the final output. <code>content_args</code> are used to configure the parser, and allow us to support various format quirks without needing custom code. | |
| We’ll take a look at each type of parser and its arguments in turn.</p> <!--[3--><h4 class="relative group"><a id="basic-types" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#basic-types"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Basic types</span></h4><!--]--><!----> <p><code>text</code>, <code>int</code>, <code>float</code> and <code>bool</code> are the basic types. These content types all just strip whitespace and then do a simple | |
| type conversion if required. They do not have any <code>content_args</code>, except for <code>text</code> which supports the arg <code>strip</code>, | |
| which strips whitespace from the start and end of the captured text, and defaults to <code>true</code>.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->field = {<span class="hljs-string">"count"</span>: {<span class="hljs-string">"open"</span>: <span class="hljs-string">"<n>"</span>, <span class="hljs-string">"close"</span>: <span class="hljs-string">"</n>"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"int"</span>}} | |
| <span class="hljs-built_in">input</span> = <span class="hljs-string">"<n> 42 </n>"</span> | |
| <span class="hljs-comment"># Returns: {"count": 42}</span><!----></pre></div><!----> <!--[3--><h4 class="relative group"><a id="json" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#json"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>json</span></h4><!--]--><!----> <p>The <code>json</code> parser parses the captured text as JSON. It’s the workhorse for tool-call arguments and | |
| anything else with nested structure. It accepts a handful of optional <code>content_args</code> to handle the | |
| various ways models mangle JSON in the wild:</p> <ul><li><code>unquoted_keys</code> (bool, default <code>false</code>): Enable when key names are raw rather than quoted | |
| (e.g. <code>{name: "foo"}</code>). Useful for models that emit Javascript-style | |
| object literals rather than strict JSON.</li> <li><code>string_delims</code> (list of <code>[open, close]</code> pairs, optional): for models that wrap string | |
| values in custom delimiters instead of <code>"..."</code>. Each pair gives an opening and closing marker.</li> <li><code>allow_non_json</code> (bool, default <code>false</code>): if parsing fails, return the stripped raw text instead | |
| of raising. Useful as a fallback for fields where the model <em>usually</em> emits JSON but occasionally | |
| drops to plain text.</li></ul> <p><code>unquoted_keys</code> and <code>string_delims</code> both exist to handle models that emit non-standard, | |
| almost-but-not-quite-JSON output, so you should only need them for a handful of models.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->field = {<span class="hljs-string">"args"</span>: {<span class="hljs-string">"open"</span>: <span class="hljs-string">"<args>"</span>, <span class="hljs-string">"close"</span>: <span class="hljs-string">"</args>"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"json"</span>, <span class="hljs-string">"content_args"</span>: {<span class="hljs-string">"unquoted_keys"</span>: <span class="hljs-literal">True</span>}}} | |
| <span class="hljs-built_in">input</span> = <span class="hljs-string">'<args>{city: "London"}</args>'</span> | |
| <span class="hljs-comment"># Returns: {"args": {"city": "London"}}</span><!----></pre></div><!----> <!--[3--><h4 class="relative group"><a id="xml-inline" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#xml-inline"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>xml-inline</span></h4><!--]--><!----> <p>The <code>xml-inline</code> parser is for regions made up of a flat sequence of XML-ish tags, where each tag | |
| becomes one entry in a dict. It’s most often used inside a <code>tool_calls</code> field for models that emit | |
| each argument as its own tag rather than as a JSON blob:</p> <ul><li><code>tag_pattern</code> (str, <strong>required</strong>): regex matching a single tag. Must contain named groups <code>key</code> (the resulting dict key) and <code>value</code> (the raw text that becomes the dict value).</li> <li><code>value_parser</code> (dict, optional): nested content parser applied to each captured <code>value</code>. A dict | |
| with <code>name</code> (the parser, e.g. <code>"json"</code>, <code>"int"</code>) and optional <code>args</code> (its <code>content_args</code>). If | |
| omitted, values stay as raw strings.</li> <li><code>merge_duplicates</code> (bool, default <code>false</code>): when the same key appears multiple times, collect the | |
| values into a list instead of letting later matches overwrite earlier ones.</li></ul> <p>For example, Qwen3 emits each tool-call argument as its own <code><parameter></code> tag, and we parse it | |
| like this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">"tool_calls"</span>: { | |
| <span class="hljs-string">"open_pattern"</span>: <span class="hljs-string">r"<tool_call>\s*<function=(?P<name>\w+)>"</span>, | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"</tool_call>"</span>, | |
| <span class="hljs-string">"repeats"</span>: <span class="hljs-literal">True</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"xml-inline"</span>, | |
| <span class="hljs-string">"content_args"</span>: { | |
| <span class="hljs-string">"tag_pattern"</span>: <span class="hljs-string">r"<parameter=(?P<key>\w+)>\s*(?P<value>.*?)\s*</parameter>"</span>, | |
| <span class="hljs-string">"value_parser"</span>: {<span class="hljs-string">"name"</span>: <span class="hljs-string">"json"</span>, <span class="hljs-string">"args"</span>: {<span class="hljs-string">"allow_non_json"</span>: <span class="hljs-literal">True</span>}}, | |
| }, | |
| <span class="hljs-string">"transform"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: {<span class="hljs-string">"name"</span>: <span class="hljs-string">"{name}"</span>, <span class="hljs-string">"arguments"</span>: <span class="hljs-string">"{content}"</span>}}, | |
| }<!----></pre></div><!----> <p>Note the nested <code>value_parser</code>: each parameter value is itself run through the <code>json</code> parser (with <code>allow_non_json</code> so plain strings still pass through). Feeding the <code>tool_calls</code> field above this input:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-built_in">input</span> = <span class="hljs-string">"<tool_call><function=get_weather><parameter=city>London</parameter><parameter=units>celsius</parameter></function></tool_call>"</span> | |
| <span class="hljs-comment"># Returns: {"tool_calls": [{"type": "function", "function": {"name": "get_weather", "arguments": {"city": "London", "units": "celsius"}}}]}</span><!----></pre></div><!----> <!--[3--><h4 class="relative group"><a id="kv-lines" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#kv-lines"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>kv-lines</span></h4><!--]--><!----> <p>The <code>kv-lines</code> parser handles line-delimited <code>key: value</code> pairs (think YAML-ish metadata or <code>.env</code> files). Each line becomes one entry in the resulting dict. All arguments are optional:</p> <ul><li><code>line_sep</code> (str, default <code>"\n"</code>): separator between pairs.</li> <li><code>kv_sep</code> (str, default <code>":"</code>): separator between a key and its value inside a single line. Only | |
| the first occurrence is used as the split point, so values may themselves contain the separator.</li> <li><code>strip</code> (bool, default <code>true</code>): strip surrounding whitespace from each key and value.</li> <li><code>value_parser</code> (dict, optional): nested content parser applied to each value, in the same <code>{"name": ..., "args": ...}</code> format as for <code>xml-inline</code>. If omitted, values stay as raw strings.</li></ul> <p>Lines that are empty or do not contain <code>kv_sep</code> are silently skipped, so stray blank lines in the | |
| captured region are tolerated.</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!---->field = {<span class="hljs-string">"metadata"</span>: {<span class="hljs-string">"open"</span>: <span class="hljs-string">"<meta>"</span>, <span class="hljs-string">"close"</span>: <span class="hljs-string">"</meta>"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"kv-lines"</span>}} | |
| <span class="hljs-built_in">input</span> = <span class="hljs-string">"<meta>name: alice\nage: 30</meta>"</span> | |
| <span class="hljs-comment"># Returns: {"metadata": {"name": "alice", "age": "30"}}</span><!----></pre></div><!----> <p>Note <code>age</code> keeps <code>"30"</code> as a string; add a <code>value_parser</code> of <code>{"name": "int"}</code> to parse it to <code>30</code>.</p> <!--[2--><h3 class="relative group"><a id="transform" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#transform"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Transform</span></h3><!--]--><!----> <p>For most fields, the <code>transform</code> key is unnecessary. It’s used when the parsed body needs to be reshaped into the final | |
| output, or when information from the delimiters has to be merged into the result. It most commonly appears in <code>tool_calls</code> fields, as these often have complex structure.</p> <p><code>transform</code> is a <strong>template</strong>: a dict (or list) that describes the output shape, where any string of the | |
| form <code>"{name}"</code> is replaced with the corresponding value. Values can be accessed from <code>content</code> (the parsed | |
| body of this region) and any named groups captured by <code>open_pattern</code> / <code>close_pattern</code>. A very common use-case is to wrap a tool | |
| call dict in an outer dict with a <code>function</code> key, as these are part of our standard tool call format:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">"tool_calls"</span>: { | |
| <span class="hljs-string">"open"</span>: <span class="hljs-string">"<tool_call>"</span>, | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"</tool_call>"</span>, | |
| <span class="hljs-string">"repeats"</span>: <span class="hljs-literal">True</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"json"</span>, | |
| <span class="hljs-string">"transform"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: <span class="hljs-string">"{content}"</span>}, | |
| },<!----></pre></div><!----> <p>So this raw output:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-txt "><!----><tool_call>{"name": "greet_user", "arguments": {"greeting": "Hi!"}}</tool_call><!----></pre></div><!----> <p>becomes (note <code>repeats: True</code> makes <code>tool_calls</code> a list):</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-json "><!----><span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span><span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"function"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"function"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"greet_user"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"arguments"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"greeting"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Hi!"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><!----></pre></div><!----> <p>A whole-string placeholder like <code>"{content}"</code> returns the looked-up value with its type preserved — so above, the | |
| parsed JSON dict slots in directly as the value of <code>function</code>. A placeholder must be the entire string: mixing | |
| text and placeholders (<code>"abc {name} def"</code>) is not permitted. They’re not f-strings!</p> <p><code>transform</code> is quite versatile, which becomes necessary when the model output has a wildly different format | |
| to our standard API. GPT-OSS is a good example - it embeds the function name in the channel header rather than in | |
| the JSON body, so we have to capture it with a named group in <code>open_pattern</code> and merge it with <code>content</code> inside the | |
| transform. All named groups in <code>open_pattern</code> and <code>close_pattern</code> become available as variables alongside <code>content</code>:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">"tool_calls"</span>: { | |
| <span class="hljs-string">"open_pattern"</span>: <span class="hljs-string">r"<\|channel\|>commentary to=functions\.(?P<name>\w+).*?<\|message\|>"</span>, | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"<|call|>"</span>, | |
| <span class="hljs-string">"repeats"</span>: <span class="hljs-literal">True</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"json"</span>, | |
| <span class="hljs-string">"transform"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: {<span class="hljs-string">"name"</span>: <span class="hljs-string">"{name}"</span>, <span class="hljs-string">"arguments"</span>: <span class="hljs-string">"{content}"</span>}}, | |
| },<!----></pre></div><!----> <p>The function name lives in the channel header, not the JSON body, so this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-txt "><!----><|channel|>commentary to=functions.get_current_weather <|constrain|>json<|message|>{"location": "San Francisco, CA"}<|call|><!----></pre></div><!----> <p>becomes:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-json "><!----><span class="hljs-punctuation">[</span><span class="hljs-punctuation">{</span><span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"function"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"function"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"get_current_weather"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"arguments"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"location"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"San Francisco, CA"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">]</span><!----></pre></div><!----> <p>Sometimes a field’s parsed content is <em>itself</em> a list of records and you want to reshape each one. The Cohere | |
| template is a good example: It emits all tool calls inside a single JSON array, so we set <code>transform_each: True</code> to | |
| apply the transform per element. Each array element’s keys are unpacked into the template scope, so <code>"{tool_name}"</code> looks up <code>tool_name</code> in the current element:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-python "><!----><span class="hljs-string">"tool_calls"</span>: { | |
| <span class="hljs-string">"open"</span>: <span class="hljs-string">"<|START_ACTION|>"</span>, | |
| <span class="hljs-string">"close"</span>: <span class="hljs-string">"<|END_ACTION|>"</span>, | |
| <span class="hljs-string">"content"</span>: <span class="hljs-string">"json"</span>, | |
| <span class="hljs-string">"transform_each"</span>: <span class="hljs-literal">True</span>, | |
| <span class="hljs-string">"transform"</span>: {<span class="hljs-string">"type"</span>: <span class="hljs-string">"function"</span>, <span class="hljs-string">"function"</span>: {<span class="hljs-string">"name"</span>: <span class="hljs-string">"{tool_name}"</span>, <span class="hljs-string">"arguments"</span>: <span class="hljs-string">"{parameters}"</span>}}, | |
| },<!----></pre></div><!----> <p>This will convert an output like this:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-json "><!----><span class="hljs-punctuation">[</span> | |
| <span class="hljs-punctuation">{</span><span class="hljs-attr">"tool_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"greet_user"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"parameters"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"greeting"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Hi!"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> | |
| <span class="hljs-punctuation">{</span><span class="hljs-attr">"tool_name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"search"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"parameters"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"query"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"weather tomorrow"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span> | |
| <span class="hljs-punctuation">]</span><!----></pre></div><!----> <p>Into an output like this, which fits our standard API:</p> <div class="code-block relative "><div class="absolute top-2.5 right-4"><button class="inline-flex items-center relative text-sm focus:text-green-500 cursor-pointer focus:outline-none transition duration-200 ease-in-out opacity-0 mx-0.5 text-gray-600 " title="code excerpt" type="button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M28,10V28H10V10H28m0-2H10a2,2,0,0,0-2,2V28a2,2,0,0,0,2,2H28a2,2,0,0,0,2-2V10a2,2,0,0,0-2-2Z" transform="translate(0)"></path><path d="M4,18H2V4A2,2,0,0,1,4,2H18V4H4Z" transform="translate(0)"></path><rect fill="none" width="32" height="32"></rect></svg><!----> <div class=" absolute pointer-events-none transition-opacity bg-black text-white py-1 px-2 leading-tight rounded font-normal shadow left-1/2 top-full transform -translate-x-1/2 translate-y-2 opacity-0 "><div class="absolute bottom-full left-1/2 transform -translate-x-1/2 w-0 h-0 border-black border-4 border-t-0" style="border-left-color: transparent; border-right-color: transparent;"></div> Copied</div><!----></button><!----></div> <pre class="language-json "><!----><span class="hljs-punctuation">[</span> | |
| <span class="hljs-punctuation">{</span><span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"function"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"function"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"greet_user"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"arguments"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"greeting"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"Hi!"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span> | |
| <span class="hljs-punctuation">{</span><span class="hljs-attr">"type"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"function"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"function"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"name"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"search"</span><span class="hljs-punctuation">,</span> <span class="hljs-attr">"arguments"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><span class="hljs-attr">"query"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"weather tomorrow"</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span> | |
| <span class="hljs-punctuation">]</span><!----></pre></div><!----> <p>The <code>transform_each</code> flag is only needed when <code>content</code> is already a list; for the more common case where each | |
| match contributes one element (and <code>repeats: True</code> accumulates them), then the transform will apply to each element | |
| by default.</p> <!--[1--><h2 class="relative group"><a id="framework-developers-regex-portability" class="header-link block pr-1.5 text-lg no-hover:hidden with-hover:absolute with-hover:p-1.5 with-hover:opacity-0 with-hover:group-hover:opacity-100 with-hover:right-full" href="#framework-developers-regex-portability"><span><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path d="M167.594 88.393a8.001 8.001 0 0 1 0 11.314l-67.882 67.882a8 8 0 1 1-11.314-11.315l67.882-67.881a8.003 8.003 0 0 1 11.314 0zm-28.287 84.86l-28.284 28.284a40 40 0 0 1-56.567-56.567l28.284-28.284a8 8 0 0 0-11.315-11.315l-28.284 28.284a56 56 0 0 0 79.196 79.197l28.285-28.285a8 8 0 1 0-11.315-11.314zM212.852 43.14a56.002 56.002 0 0 0-79.196 0l-28.284 28.284a8 8 0 1 0 11.314 11.314l28.284-28.284a40 40 0 0 1 56.568 56.567l-28.285 28.285a8 8 0 0 0 11.315 11.314l28.284-28.284a56.065 56.065 0 0 0 0-79.196z" fill="currentColor"></path></svg><!----></span></a> <span>Framework developers: Regex portability</span></h2><!--]--><!----> <p><code>open_pattern</code>, <code>close_pattern</code>, and <code>start_anchor_pattern</code> are regex strings. For most users, and even for most | |
| model authors, this shouldn’t be a problem, but if you are a developer writing an implementation of response parsing | |
| in another language, you should be aware of our implementation details. This section is dedicated to everyone | |
| who had to implement an entire Jinja parser to get non-Python chat templating to work - we hope that if you | |
| follow the simple guidelines below, then response templates should be much less painful:</p> <ul><li>We use Python’s <a href="https://pypi.org/project/regex/" rel="nofollow"><code>regex</code></a> module for all regexes used in chat parsing. | |
| Since all Python3 strings are unicode, <strong>all of our regex matches are unicode-aware</strong>. This particularly affects | |
| common characters like <code>\w</code>. Make sure you set the relevant unicode flags in your engine.</li> <li>We compile all regexes with <code>re.DOTALL</code> enabled and <code>re.MULTILINE</code> disabled, so <code>.</code> matches <code>\n</code> but <code>^</code> and <code>$</code> only match the start/end of the whole input, not line breaks.</li> <li>We use <code>(?P<name>...)</code> syntax for named groups. Other regex implementations have very different named capture group | |
| syntax, so you may need to search for this pattern in regexes and rewrite it to match your local implementation.</li> <li>We use partial regex matching to decide when we can emit data. This is necessary because the end of a region may consist of multiple tokens, | |
| and we don’t want to emit that end-of-region delimiter, so we hold tokens back until we’re sure that they’re inside the region and not part of the boundary. | |
| This means that whenever a region end regex has a partial match, we hold back data until the regex either matches or fails. If your regex engine | |
| doesn’t support partial matching, you can still implement response templates, but you may need to find another solution to this issue. One simple | |
| approach is just to hold back these regions / emit them as <code>dirty</code> until you definitively see the ending delimiter.</li> <li>Your regex engine may (rarely) not support lookarounds like <code>(?!...)</code>. Although these aren’t commonly used in response | |
| templates, they can appear and we do support them! You might need to either throw an error in those cases, or manually | |
| extract the lookarounds and enforce them in your code when the regex engine finds a possible match.</li> <li>Other advanced features like backreferences, atomic groups, possessive quantifiers, recursion and so on are generally | |
| not used in response templates. We’ll try to dissuade model authors from using them, so you can hopefully safely | |
| ignore them.</li></ul> <a class="!text-gray-400 !no-underline text-sm flex items-center not-prose mt-4" href="https://github.com/huggingface/transformers/blob/main/docs/source/en/chat_response_parsing.md" target="_blank"><svg class="mr-1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="currentColor" focusable="false" role="img" width="1em" height="1em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 32 32"><path d="M31,16l-7,7l-1.41-1.41L28.17,16l-5.58-5.59L24,9l7,7z"></path><path d="M1,16l7-7l1.41,1.41L3.83,16l5.58,5.59L8,23l-7-7z"></path><path d="M12.419,25.484L17.639,6.552l1.932,0.518L14.351,26.002z"></path></svg><!----> <span><span class="underline">Update</span> on GitHub</span></a><!----> <p></p><!--]--><!----><!--]--><!--]--><!--]--> <!--[-1--><!--]--><!--]--> | |
| <script> | |
| { | |
| __sveltekit_1p95juf = { | |
| base: "/docs/transformers/main/en", | |
| assets: "/docs/transformers/main/en" | |
| }; | |
| const element = document.currentScript.parentElement; | |
| Promise.all([ | |
| import("/docs/transformers/main/en/_app/immutable/entry/start.K656vW6L.js"), | |
| import("/docs/transformers/main/en/_app/immutable/entry/app.BCfcLogB.js") | |
| ]).then(([kit, app]) => { | |
| kit.start(app, element, { | |
| node_ids: [0, 15], | |
| data: [null,null], | |
| form: null, | |
| error: null | |
| }); | |
| }); | |
| } | |
| </script> | |
Xet Storage Details
- Size:
- 97.4 kB
- Xet hash:
- a4085e5ac550a4a0cc86317285c8bf97bf7e55f31dcde224aa504896d9b557e3
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.