• About Us
  • Disclaimer
  • Contact Us
  • Privacy Policy
Wednesday, July 29, 2026
mGrowTech
No Result
View All Result
  • Technology And Software
    • Account Based Marketing
    • Channel Marketing
    • Marketing Automation
      • Al, Analytics and Automation
      • Ad Management
  • Digital Marketing
    • Social Media Management
    • Google Marketing
  • Direct Marketing
    • Brand Management
    • Marketing Attribution and Consulting
  • Mobile Marketing
  • Event Management
  • PR Solutions
  • Technology And Software
    • Account Based Marketing
    • Channel Marketing
    • Marketing Automation
      • Al, Analytics and Automation
      • Ad Management
  • Digital Marketing
    • Social Media Management
    • Google Marketing
  • Direct Marketing
    • Brand Management
    • Marketing Attribution and Consulting
  • Mobile Marketing
  • Event Management
  • PR Solutions
No Result
View All Result
mGrowTech
No Result
View All Result
Home Al, Analytics and Automation

How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic

Josh by Josh
March 15, 2026
in Al, Analytics and Automation
0
How to Build Type-Safe, Schema-Constrained, and Function-Driven LLM Pipelines Using Outlines and Pydantic


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.

import os, sys, subprocess, json, textwrap, re


subprocess.check_call([sys.executable, "-m", "pip", "install", "-q",
                      "outlines", "transformers", "accelerate", "sentencepiece", "pydantic"])


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("Torch:", torch.__version__)
print("CUDA available:", torch.cuda.is_available())
print("Outlines:", getattr(outlines, "__version__", "unknown"))
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using device:", device)


MODEL_NAME = "HuggingFaceTB/SmolLM2-135M-Instruct"


tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, use_fast=True)
hf_model = AutoModelForCausalLM.from_pretrained(
   MODEL_NAME,
   torch_dtype=torch.float16 if device == "cuda" else torch.float32,
   device_map="auto" if device == "cuda" else None,
)


if device == "cpu":
   hf_model = hf_model.to(device)


model = outlines.from_transformers(hf_model, tokenizer)


def build_chat(user_text: str, system_text: str = "You are a precise assistant. Follow instructions exactly.") -> str:
   try:
       msgs = [{"role": "system", "content": system_text}, {"role": "user", "content": user_text}]
       return tokenizer.apply_chat_template(msgs, tokenize=False, add_generation_prompt=True)
   except Exception:
       return f"{system_text}\n\nUser: {user_text}\nAssistant:"


def banner(title: str):
   print("\n" + "=" * 90)
   print(title)
   print("=" * 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.

READ ALSO

Prompt Engineering vs Loop Engineering vs Graph Engineering: What Changes at Each Layer

5 Architectural Patterns for Persistent Memory and State in AI Agents

def extract_json_object(s: str) -> str:
   s = s.strip()
   start = s.find("{")
   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 == "\\":
               esc = True
           elif ch == '"':
               in_str = False
       else:
           if ch == '"':
               in_str = True
           elif ch == "{":
               depth += 1
           elif ch == "}":
               depth -= 1
               if depth == 0:
                   return s[start:i + 1]
   return s[start:]


def json_repair_minimal(bad: str) -> str:
   bad = bad.strip()
   last = bad.rfind("}")
   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("2) Typed outputs (Literal / int / bool)")


sentiment = model(
   build_chat("Analyze the sentiment: 'This product completely changed my life!'. Return one label only."),
   Literal["Positive", "Negative", "Neutral"],
   max_new_tokens=8,
)
print("Sentiment:", sentiment)


bp = model(build_chat("What's the boiling point of water in Celsius? Return integer only."), int, max_new_tokens=8)
print("Boiling point (int):", bp)


prime = model(build_chat("Is 29 a prime number? Return true or false only."), bool, max_new_tokens=6)
print("Is prime (bool):", 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.

banner("3) Prompt templating (outlines.Template)")


tmpl = outlines.Template.from_string(textwrap.dedent("""
<|system|>
You are a strict classifier. Return ONLY one label.
<|user|>
Classify sentiment of this text:
{{ text }}
Labels: Positive, Negative, Neutral
<|assistant|>
""").strip())


templated = model(tmpl(text="The food was cold but the staff were kind."), Literal["Positive","Negative","Neutral"], max_new_tokens=8)
print("Template sentiment:", 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.

banner("4) Pydantic structured output (advanced constraints)")


class TicketPriority(str, Enum):
   low = "low"
   medium = "medium"
   high = "high"
   urgent = "urgent"


IPv4 = Annotated[str, Field(pattern=r"^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$")]
ISODate = Annotated[str, Field(pattern=r"^\d{4}-\d{2}-\d{2}$")]


class ServiceTicket(BaseModel):
   priority: TicketPriority
   category: Literal["billing", "login", "bug", "feature_request", "other"]
   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["dns", "vpn", "api", "website", "database"]
   severity: Literal["sev1", "sev2", "sev3"]
   public_ip: IPv4
   start_date: ISODate
   mitigation: List[str] = Field(min_length=2, max_length=6)


email = """
Subject: URGENT - Cannot access my account after payment
I paid for the premium plan 3 hours ago and still can'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.
""".strip()


ticket_text = model(
   build_chat(
       "Extract a ServiceTicket from this message.\n"
       "Return JSON ONLY matching the ServiceTicket schema.\n"
       "Action items must be distinct.\n\nMESSAGE:\n" + email
   ),
   ServiceTicket,
   max_new_tokens=240,
)


ticket = safe_validate(ServiceTicket, ticket_text) if isinstance(ticket_text, str) else ticket_text
print("ServiceTicket JSON:\n", 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.

banner("5) Function-calling style (schema -> args -> call)")


class AddArgs(BaseModel):
   a: int = Field(ge=-1000, le=1000)
   b: int = Field(ge=-1000, le=1000)


def add(a: int, b: int) -> int:
   return a + b


args_text = model(
   build_chat("Return JSON ONLY with two integers a and b. Make a odd and b even."),
   AddArgs,
   max_new_tokens=80,
)


args = safe_validate(AddArgs, args_text) if isinstance(args_text, str) else args_text
print("Args:", args.model_dump())
print("add(a,b) =", add(args.a, args.b))


print("Tip: For best speed and fewer truncations, switch Colab Runtime → GPU.")

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 the system robust against imperfect model outputs. Overall, we created a practical and production-oriented framework for deterministic, safe, and schema-driven LLM applications.


Check out Full Codes here. Also, feel free to follow us on Twitter and don’t forget to join our 120k+ ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.




Source_link

Related Posts

Prompt Engineering vs Loop Engineering vs Graph Engineering: What Changes at Each Layer
Al, Analytics and Automation

Prompt Engineering vs Loop Engineering vs Graph Engineering: What Changes at Each Layer

July 29, 2026
Al, Analytics and Automation

5 Architectural Patterns for Persistent Memory and State in AI Agents

July 29, 2026
A Practical Guide to Bone Tissue Labeling and Annotation
Al, Analytics and Automation

A Practical Guide to Bone Tissue Labeling and Annotation

July 29, 2026
OpenAI and Anthropic Back Employee Call to Pace AI Progress – Unite.AI
Al, Analytics and Automation

OpenAI and Anthropic Back Employee Call to Pace AI Progress – Unite.AI

July 29, 2026
Building Non-Interactive Agentic Coding Workflows with Moonshot AI’s Kimi CLI, JSONL Streaming, Testing, and Session Memory
Al, Analytics and Automation

Building Non-Interactive Agentic Coding Workflows with Moonshot AI’s Kimi CLI, JSONL Streaming, Testing, and Session Memory

July 29, 2026
Microsoft AI Releases MAI-Cyber-1-Flash: A 5B-Active-Parameter Cyber Model That Pushes MDASH to 95.95% on CyberGym
Al, Analytics and Automation

Microsoft AI Releases MAI-Cyber-1-Flash: A 5B-Active-Parameter Cyber Model That Pushes MDASH to 95.95% on CyberGym

July 28, 2026
Next Post
ByteDance has reportedly suspended the global rollout of its new AI video generator

ByteDance has reportedly suspended the global rollout of its new AI video generator

POPULAR NEWS

Trump ends trade talks with Canada over a digital services tax

Trump ends trade talks with Canada over a digital services tax

June 28, 2025
15 Trending Songs on TikTok in 2025 (+ How to Use Them)

15 Trending Songs on TikTok in 2025 (+ How to Use Them)

June 18, 2025
Communication Effectiveness Skills For Business Leaders

Communication Effectiveness Skills For Business Leaders

June 10, 2025
App Development Cost in Singapore: Pricing Breakdown & Insights

App Development Cost in Singapore: Pricing Breakdown & Insights

June 22, 2025
Comparing the Top 7 Large Language Models LLMs/Systems for Coding in 2025

Comparing the Top 7 Large Language Models LLMs/Systems for Coding in 2025

November 4, 2025

EDITOR'S PICK

Does the Printed Case for Support Still Matter?

Does the Printed Case for Support Still Matter?

July 11, 2026
Abstract or die: Why AI enterprises can't afford rigid vector stacks

Abstract or die: Why AI enterprises can't afford rigid vector stacks

October 19, 2025
Grow a Garden Gnome Merchant Shop

Grow a Garden Gnome Merchant Shop

June 29, 2025

How to Get More From One Blog Post: Multi-URL Pin Strategy

October 3, 2025

About

We bring you the best Premium WordPress Themes that perfect for news, magazine, personal blog, etc. Check our landing page for details.

Follow us

Categories

  • Account Based Marketing
  • Ad Management
  • Al, Analytics and Automation
  • Brand Management
  • Channel Marketing
  • Digital Marketing
  • Direct Marketing
  • Event Management
  • Google Marketing
  • Marketing Attribution and Consulting
  • Marketing Automation
  • Mobile Marketing
  • PR Solutions
  • Social Media Management
  • Technology And Software
  • Uncategorized

Recent Posts

  • Prompt Engineering vs Loop Engineering vs Graph Engineering: What Changes at Each Layer
  • Moburst’s Mobile Marketing Roundup #33
  • The Scoop: Cracker Barrel’s CEO won the battle but lost the war
  • Nimble claims its new, domain-specialized Web Search Agents cut token costs in half while boosting retrieval accuracy
  • About Us
  • Disclaimer
  • Contact Us
  • Privacy Policy
No Result
View All Result
  • Technology And Software
    • Account Based Marketing
    • Channel Marketing
    • Marketing Automation
      • Al, Analytics and Automation
      • Ad Management
  • Digital Marketing
    • Social Media Management
    • Google Marketing
  • Direct Marketing
    • Brand Management
    • Marketing Attribution and Consulting
  • Mobile Marketing
  • Event Management
  • PR Solutions