{"id":77719,"date":"2026-03-15T12:25:53","date_gmt":"2026-03-15T12:25:53","guid":{"rendered":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/"},"modified":"2026-03-15T12:25:53","modified_gmt":"2026-03-15T12:25:53","slug":"how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic","status":"publish","type":"post","link":"https:\/\/youzum.net\/zh\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/","title":{"rendered":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic"},"content":{"rendered":"<p>In this tutorial, we build a workflow using <a href=\"http:\/\/github.com\/dottxt-ai\/outlines\"><strong>Outlines<\/strong><\/a> to generate structured and type-safe outputs from language models. We work with typed constraints like Literal, int, and bool, and design prompt templates using outlines.Template, and enforce strict schema validation with Pydantic models. We also implement robust JSON recovery and a function-calling style that generates validated arguments and executes Python functions safely. Throughout the tutorial, we focus on reliability, constraint enforcement, and production-grade structured generation.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">import os, sys, subprocess, json, textwrap, re\n\n\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\",\n                      \"outlines\", \"transformers\", \"accelerate\", \"sentencepiece\", \"pydantic\"])\n\n\nimport torch\nimport outlines\nfrom transformers import AutoTokenizer, AutoModelForCausalLM\n\n\nfrom typing import Literal, List, Union, Annotated\nfrom pydantic import BaseModel, Field\nfrom enum import Enum\n\n\nprint(\"Torch:\", torch.__version__)\nprint(\"CUDA available:\", torch.cuda.is_available())\nprint(\"Outlines:\", getattr(outlines, \"__version__\", \"unknown\"))\ndevice = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nprint(\"Using device:\", device)\n\n\nMODEL_NAME = \"HuggingFaceTB\/SmolLM2-135M-Instruct\"\n\n\ntokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)\nhf_model = AutoModelForCausalLM.from_pretrained(\n   MODEL_NAME,\n   torch_dtype=torch.float16 if device == \"cuda\" else torch.float32,\n   device_map=\"auto\" if device == \"cuda\" else None,\n)\n\n\nif device == \"cpu\":\n   hf_model = hf_model.to(device)\n\n\nmodel = outlines.from_transformers(hf_model, tokenizer)\n\n\ndef build_chat(user_text: str, system_text: str = \"You are a precise assistant. Follow instructions exactly.\") -&gt; str:\n   try:\n       msgs = [{\"role\": \"system\", \"content\": system_text}, {\"role\": \"user\", \"content\": user_text}]\n       return tokenizer.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)\n   except Exception:\n       return f\"{system_text}nnUser: {user_text}nAssistant:\"\n\n\ndef banner(title: str):\n   print(\"n\" + \"=\" * 90)\n   print(title)\n   print(\"=\" * 90)<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We install all required dependencies and initialize the Outlines pipeline with a lightweight instruct model. We configure device handling so that the system automatically switches between CPU and GPU based on availability. We also build reusable helper functions for chat formatting and clean section banners to structure the workflow.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">def extract_json_object(s: str) -&gt; str:\n   s = s.strip()\n   start = s.find(\"{\")\n   if start == -1:\n       return s\n   depth = 0\n   in_str = False\n   esc = False\n   for i in range(start, len(s)):\n       ch = s[i]\n       if in_str:\n           if esc:\n               esc = False\n           elif ch == \"\\\":\n               esc = True\n           elif ch == '\"':\n               in_str = False\n       else:\n           if ch == '\"':\n               in_str = True\n           elif ch == \"{\":\n               depth += 1\n           elif ch == \"}\":\n               depth -= 1\n               if depth == 0:\n                   return s[start:i + 1]\n   return s[start:]\n\n\ndef json_repair_minimal(bad: str) -&gt; str:\n   bad = bad.strip()\n   last = bad.rfind(\"}\")\n   if last != -1:\n       return bad[:last + 1]\n   return bad\n\n\ndef safe_validate(model_cls, raw_text: str):\n   raw = extract_json_object(raw_text)\n   try:\n       return model_cls.model_validate_json(raw)\n   except Exception:\n       raw2 = json_repair_minimal(raw)\n       return model_cls.model_validate_json(raw2)\n\n\nbanner(\"2) Typed outputs (Literal \/ int \/ bool)\")\n\n\nsentiment = model(\n   build_chat(\"Analyze the sentiment: 'This product completely changed my life!'. Return one label only.\"),\n   Literal[\"Positive\", \"Negative\", \"Neutral\"],\n   max_new_tokens=8,\n)\nprint(\"Sentiment:\", sentiment)\n\n\nbp = model(build_chat(\"What's the boiling point of water in Celsius? Return integer only.\"), int, max_new_tokens=8)\nprint(\"Boiling point (int):\", bp)\n\n\nprime = model(build_chat(\"Is 29 a prime number? Return true or false only.\"), bool, max_new_tokens=6)\nprint(\"Is prime (bool):\", prime)<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We implement robust JSON extraction and minimal repair utilities to safely recover structured outputs from imperfect generations. We then demonstrate strongly typed generation using Literal, int, and bool, ensuring the model returns values that are strictly constrained. We validate how Outlines enforces deterministic type-safe outputs directly at generation time.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">banner(\"3) Prompt templating (outlines.Template)\")\n\n\ntmpl = outlines.Template.from_string(textwrap.dedent(\"\"\"\n&lt;|system|&gt;\nYou are a strict classifier. Return ONLY one label.\n&lt;|user|&gt;\nClassify sentiment of this text:\n{{ text }}\nLabels: Positive, Negative, Neutral\n&lt;|assistant|&gt;\n\"\"\").strip())\n\n\ntemplated = model(tmpl(text=\"The food was cold but the staff were kind.\"), Literal[\"Positive\",\"Negative\",\"Neutral\"], max_new_tokens=8)\nprint(\"Template sentiment:\", templated)<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We use outlines.Template to build structured prompt templates with strict output control. We dynamically inject user input into the template while preserving role formatting and classification constraints. We demonstrate how templating improves reusability and ensures consistent, constrained responses.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">banner(\"4) Pydantic structured output (advanced constraints)\")\n\n\nclass TicketPriority(str, Enum):\n   low = \"low\"\n   medium = \"medium\"\n   high = \"high\"\n   urgent = \"urgent\"\n\n\nIPv4 = Annotated[str, Field(pattern=r\"^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)$\")]\nISODate = Annotated[str, Field(pattern=r\"^d{4}-d{2}-d{2}$\")]\n\n\nclass ServiceTicket(BaseModel):\n   priority: TicketPriority\n   category: Literal[\"billing\", \"login\", \"bug\", \"feature_request\", \"other\"]\n   requires_manager: bool\n   summary: str = Field(min_length=10, max_length=220)\n   action_items: List[str] = Field(min_length=1, max_length=6)\n\n\nclass NetworkIncident(BaseModel):\n   affected_service: Literal[\"dns\", \"vpn\", \"api\", \"website\", \"database\"]\n   severity: Literal[\"sev1\", \"sev2\", \"sev3\"]\n   public_ip: IPv4\n   start_date: ISODate\n   mitigation: List[str] = Field(min_length=2, max_length=6)\n\n\nemail = \"\"\"\nSubject: URGENT - Cannot access my account after payment\nI paid for the premium plan 3 hours ago and still can't access any features.\nI have a client presentation in an hour and need the analytics dashboard.\nPlease fix this immediately or refund my payment.\n\"\"\".strip()\n\n\nticket_text = model(\n   build_chat(\n       \"Extract a ServiceTicket from this message.n\"\n       \"Return JSON ONLY matching the ServiceTicket schema.n\"\n       \"Action items must be distinct.nnMESSAGE:n\" + email\n   ),\n   ServiceTicket,\n   max_new_tokens=240,\n)\n\n\nticket = safe_validate(ServiceTicket, ticket_text) if isinstance(ticket_text, str) else ticket_text\nprint(\"ServiceTicket JSON:n\", ticket.model_dump_json(indent=2))<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We define advanced Pydantic schemas with enums, regex constraints, field limits, and structured lists. We extract a complex ServiceTicket object from raw email text and validate it using schema-driven decoding. We also apply safe validation logic to handle edge cases and ensure robustness at production scale.<\/p>\n<div class=\"dm-code-snippet dark dm-normal-version default no-background-mobile\">\n<div class=\"control-language\">\n<div class=\"dm-buttons\">\n<div class=\"dm-buttons-left\">\n<div class=\"dm-button-snippet red-button\"><\/div>\n<div class=\"dm-button-snippet orange-button\"><\/div>\n<div class=\"dm-button-snippet green-button\"><\/div>\n<\/div>\n<div class=\"dm-buttons-right\"><a><span class=\"dm-copy-text\">Copy Code<\/span><span class=\"dm-copy-confirmed\">Copied<\/span><span class=\"dm-error-message\">Use a different Browser<\/span><\/a><\/div>\n<\/div>\n<pre class=\"no-line-numbers\"><code class=\"no-wrap language-php\">banner(\"5) Function-calling style (schema -&gt; args -&gt; call)\")\n\n\nclass AddArgs(BaseModel):\n   a: int = Field(ge=-1000, le=1000)\n   b: int = Field(ge=-1000, le=1000)\n\n\ndef add(a: int, b: int) -&gt; int:\n   return a + b\n\n\nargs_text = model(\n   build_chat(\"Return JSON ONLY with two integers a and b. Make a odd and b even.\"),\n   AddArgs,\n   max_new_tokens=80,\n)\n\n\nargs = safe_validate(AddArgs, args_text) if isinstance(args_text, str) else args_text\nprint(\"Args:\", args.model_dump())\nprint(\"add(a,b) =\", add(args.a, args.b))\n\n\nprint(\"Tip: For best speed and fewer truncations, switch Colab Runtime \u2192 GPU.\")<\/code><\/pre>\n<\/div>\n<\/div>\n<p>We implement a function-calling style workflow by generating structured arguments that conform to a defined schema. We validate the generated arguments, then safely execute a Python function with those validated inputs. We demonstrate how schema-first generation enables controlled tool invocation and reliable LLM-driven computation.<\/p>\n<p>In conclusion, we implemented a fully structured generation pipeline using Outlines with strong typing, schema validation, and controlled decoding. We demonstrated how to move from simple typed outputs to advanced Pydantic-based extraction and function-style execution patterns. We also built resilience through JSON salvage and validation mechanisms, making the system robust against imperfect model outputs. Overall, we created a practical and production-oriented framework for deterministic, safe, and schema-driven LLM applications.<\/p>\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n<p>Check out\u00a0<strong><a href=\"https:\/\/github.com\/Marktechpost\/AI-Tutorial-Codes-Included\/blob\/main\/Agentic%20AI%20Codes\/outlines_typed_structured_generation_marktechpost.py\" target=\"_blank\" rel=\"noreferrer noopener\">Full Codes here<\/a>.\u00a0<\/strong>Also,\u00a0feel free to follow us on\u00a0<strong><a href=\"https:\/\/x.com\/intent\/follow?screen_name=marktechpost\" target=\"_blank\" rel=\"noreferrer noopener\"><mark>Twitter<\/mark><\/a><\/strong>\u00a0and don\u2019t forget to join our\u00a0<strong><a href=\"https:\/\/www.reddit.com\/r\/machinelearningnews\/\" target=\"_blank\" rel=\"noreferrer noopener\">120k+ ML SubReddit<\/a><\/strong>\u00a0and Subscribe to\u00a0<strong><a href=\"https:\/\/www.aidevsignals.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">our Newsletter<\/a><\/strong>. Wait! are you on telegram?\u00a0<strong><a href=\"https:\/\/t.me\/machinelearningresearchnews\" target=\"_blank\" rel=\"noreferrer noopener\">now you can join us on telegram as well.<\/a><\/strong><\/p>\n<p>The post <a href=\"https:\/\/www.marktechpost.com\/2026\/03\/14\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\">How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic<\/a> appeared first on <a href=\"https:\/\/www.marktechpost.com\/\">MarkTechPost<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>In this tutorial, we build a workflow using Outlines to generate structured and type-safe outputs from language models. We work with typed constraints like Literal, int, and bool, and design prompt templates using outlines.Template, and enforce strict schema validation with Pydantic models. We also implement robust JSON recovery and a function-calling style that generates validated arguments and executes Python functions safely. Throughout the tutorial, we focus on reliability, constraint enforcement, and production-grade structured generation. Copy CodeCopiedUse a different Browser import os, sys, subprocess, json, textwrap, re subprocess.check_call([sys.executable, &#8220;-m&#8221;, &#8220;pip&#8221;, &#8220;install&#8221;, &#8220;-q&#8221;, &#8220;outlines&#8221;, &#8220;transformers&#8221;, &#8220;accelerate&#8221;, &#8220;sentencepiece&#8221;, &#8220;pydantic&#8221;]) import torch import outlines from transformers import AutoTokenizer, AutoModelForCausalLM from typing import Literal, List, Union, Annotated from pydantic import BaseModel, Field from enum import Enum print(&#8220;Torch:&#8221;, torch.__version__) print(&#8220;CUDA available:&#8221;, torch.cuda.is_available()) print(&#8220;Outlines:&#8221;, getattr(outlines, &#8220;__version__&#8221;, &#8220;unknown&#8221;)) device = &#8220;cuda&#8221; if torch.cuda.is_available() else &#8220;cpu&#8221; print(&#8220;Using device:&#8221;, device) MODEL_NAME = &#8220;HuggingFaceTB\/SmolLM2-135M-Instruct&#8221; tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True) hf_model = AutoModelForCausalLM.from_pretrained( MODEL_NAME, torch_dtype=torch.float16 if device == &#8220;cuda&#8221; else torch.float32, device_map=&#8221;auto&#8221; if device == &#8220;cuda&#8221; else None, ) if device == &#8220;cpu&#8221;: hf_model = hf_model.to(device) model = outlines.from_transformers(hf_model, tokenizer) def build_chat(user_text: str, system_text: str = &#8220;You are a precise assistant. Follow instructions exactly.&#8221;) -&gt; str: try: msgs = [{&#8220;role&#8221;: &#8220;system&#8221;, &#8220;content&#8221;: system_text}, {&#8220;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: user_text}] return tokenizer.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True) except Exception: return f&#8221;{system_text}nnUser: {user_text}nAssistant:&#8221; def banner(title: str): print(&#8220;n&#8221; + &#8220;=&#8221; * 90) print(title) print(&#8220;=&#8221; * 90) We install all required dependencies and initialize the Outlines pipeline with a lightweight instruct model. We configure device handling so that the system automatically switches between CPU and GPU based on availability. We also build reusable helper functions for chat formatting and clean section banners to structure the workflow. Copy CodeCopiedUse a different Browser def extract_json_object(s: str) -&gt; str: s = s.strip() start = s.find(&#8220;{&#8220;) if start == -1: return s depth = 0 in_str = False esc = False for i in range(start, len(s)): ch = s[i] if in_str: if esc: esc = False elif ch == &#8220;\\&#8221;: esc = True elif ch == &#8216;&#8221;&#8216;: in_str = False else: if ch == &#8216;&#8221;&#8216;: in_str = True elif ch == &#8220;{&#8220;: depth += 1 elif ch == &#8220;}&#8221;: depth -= 1 if depth == 0: return s[start:i + 1] return s[start:] def json_repair_minimal(bad: str) -&gt; str: bad = bad.strip() last = bad.rfind(&#8220;}&#8221;) if last != -1: return bad[:last + 1] return bad def safe_validate(model_cls, raw_text: str): raw = extract_json_object(raw_text) try: return model_cls.model_validate_json(raw) except Exception: raw2 = json_repair_minimal(raw) return model_cls.model_validate_json(raw2) banner(&#8220;2) Typed outputs (Literal \/ int \/ bool)&#8221;) sentiment = model( build_chat(&#8220;Analyze the sentiment: &#8216;This product completely changed my life!&#8217;. Return one label only.&#8221;), Literal[&#8220;Positive&#8221;, &#8220;Negative&#8221;, &#8220;Neutral&#8221;], max_new_tokens=8, ) print(&#8220;Sentiment:&#8221;, sentiment) bp = model(build_chat(&#8220;What&#8217;s the boiling point of water in Celsius? Return integer only.&#8221;), int, max_new_tokens=8) print(&#8220;Boiling point (int):&#8221;, bp) prime = model(build_chat(&#8220;Is 29 a prime number? Return true or false only.&#8221;), bool, max_new_tokens=6) print(&#8220;Is prime (bool):&#8221;, prime) We implement robust JSON extraction and minimal repair utilities to safely recover structured outputs from imperfect generations. We then demonstrate strongly typed generation using Literal, int, and bool, ensuring the model returns values that are strictly constrained. We validate how Outlines enforces deterministic type-safe outputs directly at generation time. Copy CodeCopiedUse a different Browser banner(&#8220;3) Prompt templating (outlines.Template)&#8221;) tmpl = outlines.Template.from_string(textwrap.dedent(&#8220;&#8221;&#8221; &lt;|system|&gt; You are a strict classifier. Return ONLY one label. &lt;|user|&gt; Classify sentiment of this text: {{ text }} Labels: Positive, Negative, Neutral &lt;|assistant|&gt; &#8220;&#8221;&#8221;).strip()) templated = model(tmpl(text=&#8221;The food was cold but the staff were kind.&#8221;), Literal[&#8220;Positive&#8221;,&#8221;Negative&#8221;,&#8221;Neutral&#8221;], max_new_tokens=8) print(&#8220;Template sentiment:&#8221;, templated) We use outlines.Template to build structured prompt templates with strict output control. We dynamically inject user input into the template while preserving role formatting and classification constraints. We demonstrate how templating improves reusability and ensures consistent, constrained responses. Copy CodeCopiedUse a different Browser banner(&#8220;4) Pydantic structured output (advanced constraints)&#8221;) class TicketPriority(str, Enum): low = &#8220;low&#8221; medium = &#8220;medium&#8221; high = &#8220;high&#8221; urgent = &#8220;urgent&#8221; IPv4 = Annotated[str, Field(pattern=r&#8221;^((25[0-5]|2[0-4]d|[01]?dd?).){3}(25[0-5]|2[0-4]d|[01]?dd?)$&#8221;)] ISODate = Annotated[str, Field(pattern=r&#8221;^d{4}-d{2}-d{2}$&#8221;)] class ServiceTicket(BaseModel): priority: TicketPriority category: Literal[&#8220;billing&#8221;, &#8220;login&#8221;, &#8220;bug&#8221;, &#8220;feature_request&#8221;, &#8220;other&#8221;] requires_manager: bool summary: str = Field(min_length=10, max_length=220) action_items: List[str] = Field(min_length=1, max_length=6) class NetworkIncident(BaseModel): affected_service: Literal[&#8220;dns&#8221;, &#8220;vpn&#8221;, &#8220;api&#8221;, &#8220;website&#8221;, &#8220;database&#8221;] severity: Literal[&#8220;sev1&#8221;, &#8220;sev2&#8221;, &#8220;sev3&#8221;] public_ip: IPv4 start_date: ISODate mitigation: List[str] = Field(min_length=2, max_length=6) email = &#8220;&#8221;&#8221; Subject: URGENT &#8211; Cannot access my account after payment I paid for the premium plan 3 hours ago and still can&#8217;t access any features. I have a client presentation in an hour and need the analytics dashboard. Please fix this immediately or refund my payment. &#8220;&#8221;&#8221;.strip() ticket_text = model( build_chat( &#8220;Extract a ServiceTicket from this message.n&#8221; &#8220;Return JSON ONLY matching the ServiceTicket schema.n&#8221; &#8220;Action items must be distinct.nnMESSAGE:n&#8221; + email ), ServiceTicket, max_new_tokens=240, ) ticket = safe_validate(ServiceTicket, ticket_text) if isinstance(ticket_text, str) else ticket_text print(&#8220;ServiceTicket JSON:n&#8221;, ticket.model_dump_json(indent=2)) We define advanced Pydantic schemas with enums, regex constraints, field limits, and structured lists. We extract a complex ServiceTicket object from raw email text and validate it using schema-driven decoding. We also apply safe validation logic to handle edge cases and ensure robustness at production scale. Copy CodeCopiedUse a different Browser banner(&#8220;5) Function-calling style (schema -&gt; args -&gt; call)&#8221;) class AddArgs(BaseModel): a: int = Field(ge=-1000, le=1000) b: int = Field(ge=-1000, le=1000) def add(a: int, b: int) -&gt; int: return a + b args_text = model( build_chat(&#8220;Return JSON ONLY with two integers a and b. Make a odd and b even.&#8221;), AddArgs, max_new_tokens=80, ) args = safe_validate(AddArgs, args_text) if isinstance(args_text, str) else args_text print(&#8220;Args:&#8221;, args.model_dump()) print(&#8220;add(a,b) =&#8221;, add(args.a, args.b)) print(&#8220;Tip: For best speed and fewer truncations, switch Colab Runtime \u2192 GPU.&#8221;) We implement a function-calling style workflow by generating structured arguments that conform to a defined schema. We validate the generated arguments, then safely execute a Python function with those validated inputs. We demonstrate how schema-first generation enables controlled tool invocation and reliable LLM-driven computation. In conclusion, we implemented a fully structured generation pipeline using Outlines with strong typing, schema validation, and controlled decoding. We demonstrated how to move from simple typed outputs to advanced Pydantic-based extraction and function-style execution patterns. We also built resilience through JSON salvage and validation mechanisms, making<\/p>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"pmpro_default_level":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_pvb_checkbox_block_on_post":false,"footnotes":""},"categories":[52,5,7,1],"tags":[],"class_list":["post-77719","post","type-post","status-publish","format-standard","hentry","category-ai-club","category-committee","category-news","category-uncategorized","pmpro-has-access"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v25.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum<\/title>\n<meta name=\"description\" content=\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/youzum.net\/zh\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum\" \/>\n<meta property=\"og:description\" content=\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\" \/>\n<meta property=\"og:url\" content=\"https:\/\/youzum.net\/zh\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\" \/>\n<meta property=\"og:site_name\" content=\"YouZum\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DroneAssociationTH\/\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-15T12:25:53+00:00\" \/>\n<meta name=\"author\" content=\"admin NU\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin NU\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\"},\"author\":{\"name\":\"admin NU\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c\"},\"headline\":\"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic\",\"datePublished\":\"2026-03-15T12:25:53+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\"},\"wordCount\":480,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\"},\"articleSection\":[\"AI\",\"Committee\",\"News\",\"Uncategorized\"],\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\",\"url\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\",\"name\":\"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum\",\"isPartOf\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#website\"},\"datePublished\":\"2026-03-15T12:25:53+00:00\",\"description\":\"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19\",\"breadcrumb\":{\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/youzum.net\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/yousum.gpucore.co\/#website\",\"url\":\"https:\/\/yousum.gpucore.co\/\",\"name\":\"YouSum\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/yousum.gpucore.co\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/yousum.gpucore.co\/#organization\",\"name\":\"Drone Association Thailand\",\"url\":\"https:\/\/yousum.gpucore.co\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png\",\"contentUrl\":\"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png\",\"width\":300,\"height\":300,\"caption\":\"Drone Association Thailand\"},\"image\":{\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/DroneAssociationTH\/\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c\",\"name\":\"admin NU\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/yousum.gpucore.co\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png\",\"contentUrl\":\"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png\",\"caption\":\"admin NU\"},\"url\":\"https:\/\/youzum.net\/zh\/members\/adminnu\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum","description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/youzum.net\/zh\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/","og_locale":"zh_CN","og_type":"article","og_title":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum","og_description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","og_url":"https:\/\/youzum.net\/zh\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/","og_site_name":"YouZum","article_publisher":"https:\/\/www.facebook.com\/DroneAssociationTH\/","article_published_time":"2026-03-15T12:25:53+00:00","author":"admin NU","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin NU","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"6 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#article","isPartOf":{"@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/"},"author":{"name":"admin NU","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c"},"headline":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic","datePublished":"2026-03-15T12:25:53+00:00","mainEntityOfPage":{"@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/"},"wordCount":480,"commentCount":0,"publisher":{"@id":"https:\/\/yousum.gpucore.co\/#organization"},"articleSection":["AI","Committee","News","Uncategorized"],"inLanguage":"zh-Hans","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/","url":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/","name":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic - YouZum","isPartOf":{"@id":"https:\/\/yousum.gpucore.co\/#website"},"datePublished":"2026-03-15T12:25:53+00:00","description":"\u0e01\u0e34\u0e08\u0e01\u0e23\u0e23\u0e21\u0e40\u0e01\u0e35\u0e48\u0e22\u0e27\u0e01\u0e31\u0e1a\u0e42\u0e14\u0e23\u0e19","breadcrumb":{"@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/youzum.net\/how-to-build-type-safe-schema-constrained-and-function-driven-llm-pipelines-using-outlines-and-pydantic\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/youzum.net\/"},{"@type":"ListItem","position":2,"name":"How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic"}]},{"@type":"WebSite","@id":"https:\/\/yousum.gpucore.co\/#website","url":"https:\/\/yousum.gpucore.co\/","name":"YouSum","description":"","publisher":{"@id":"https:\/\/yousum.gpucore.co\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/yousum.gpucore.co\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"zh-Hans"},{"@type":"Organization","@id":"https:\/\/yousum.gpucore.co\/#organization","name":"Drone Association Thailand","url":"https:\/\/yousum.gpucore.co\/","logo":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/","url":"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png","contentUrl":"https:\/\/youzum.net\/wp-content\/uploads\/2024\/11\/tranparent-logo.png","width":300,"height":300,"caption":"Drone Association Thailand"},"image":{"@id":"https:\/\/yousum.gpucore.co\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DroneAssociationTH\/"]},{"@type":"Person","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/97fa48242daf3908e4d9a5f26f4a059c","name":"admin NU","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/yousum.gpucore.co\/#\/schema\/person\/image\/","url":"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png","contentUrl":"https:\/\/youzum.net\/wp-content\/uploads\/avatars\/2\/1746849356-bpfull.png","caption":"admin NU"},"url":"https:\/\/youzum.net\/zh\/members\/adminnu\/"}]}},"rttpg_featured_image_url":null,"rttpg_author":{"display_name":"admin NU","author_link":"https:\/\/youzum.net\/zh\/members\/adminnu\/"},"rttpg_comment":0,"rttpg_category":"<a href=\"https:\/\/youzum.net\/zh\/category\/ai-club\/\" rel=\"category tag\">AI<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/committee\/\" rel=\"category tag\">Committee<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/news\/\" rel=\"category tag\">News<\/a> <a href=\"https:\/\/youzum.net\/zh\/category\/uncategorized\/\" rel=\"category tag\">Uncategorized<\/a>","rttpg_excerpt":"In this tutorial, we build a workflow using Outlines to generate structured and type-safe outputs from language models. We work with typed constraints like Literal, int, and bool, and design prompt templates using outlines.Template, and enforce strict schema validation with Pydantic models. We also implement robust JSON recovery and a function-calling style that generates validated&hellip;","_links":{"self":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts\/77719","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/comments?post=77719"}],"version-history":[{"count":0,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/posts\/77719\/revisions"}],"wp:attachment":[{"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/media?parent=77719"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/categories?post=77719"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/youzum.net\/zh\/wp-json\/wp\/v2\/tags?post=77719"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}