Few-Shot Examples

Ma Mahalakshmi V Updated 16 Sep 2026
20 min read ·Lesson 13 of 224

What Few-Shot Prompting Is

Few-shot prompting means showing the model a small number of worked examples of the task — input paired with the exact output you want — before giving it the real input to handle. The name contrasts with zero-shot prompting, where you only describe the task in words and give no examples at all, which is what every example in Lessons 1 and 2 of this unit has done so far.

# Zero-shot: describe the task, no examples
instructions = "Classify the tone of the message as formal, casual, or urgent."

# Few-shot: show the task being done, then ask for it again
instructions = """Classify the tone of the message as formal, casual, or urgent.

Message: "Per our conversation, please find the attached report."
Tone: formal

Message: "hey lol did you see that email"
Tone: casual

Message: "Server is down, need eyes on this NOW."
Tone: urgent"""

Both versions ask the model to do the same job. The difference is that the second version demonstrates the job three times before asking the model to do it a fourth time on new input. This works because language models are fundamentally pattern-continuation engines: shown a consistent pattern of input-output pairs, the strong statistical pull is to continue that exact pattern rather than to improvise a new one. Few-shot prompting harnesses that pull directly, rather than relying entirely on the model correctly interpreting a verbal description of what you want.

Why Examples Succeed Where Descriptions Sometimes Fail

Lesson 2 of this unit was about removing ambiguity from instructions by describing every decision point explicitly. Few-shot examples are a second, complementary way to remove ambiguity — instead of describing the boundary between categories in words, you demonstrate it with a concrete instance on each side of the boundary. This matters for exactly the cases where a verbal description is hard to write precisely but an example is easy to produce.

Take the tone classifier above. Try to write a purely verbal definition of "casual" precise enough to reliably separate it from "formal" across every message you might encounter, and you will find yourself writing paragraphs of caveats about punctuation, abbreviation, capitalisation, and word choice — and still leaving edge cases unaddressed. Show three examples instead, and the model infers the pattern of what separates the categories directly from the demonstrated instances, often more effectively than from an equivalent-length written definition, because the examples encode nuance (word choice, punctuation style, capitalisation) that would be tedious and incomplete to spell out explicitly.

This is also why few-shot examples are particularly valuable for output formatting that is easier to show than to describe. Explaining in words exactly how you want a citation formatted, or how you want a code diff annotated, or how you want a multi-field extraction laid out, is often more error-prone than simply showing one or two instances of the exact formatting and letting the model match it.

Choosing and Ordering Examples

Few-shot prompting is not simply "add examples until it works" — the choice, number, and order of examples materially affects both accuracy and consistency, and a poorly chosen set of examples can actively mislead the model.

Cover the actual category boundaries, not just easy cases. If a classifier needs to distinguish "mixed" feedback from "negative" feedback, at least one example needs to sit right at that boundary — genuinely mixed feedback that a less careful example set might have simplified into "negative." Examples that are all clear-cut, unambiguous cases teach the model your labels exist, but not where the actual dividing lines are, which is exactly where classification tends to go wrong on real traffic.

Keep the format of every example identical. If your first example writes "Tone: formal" and your third writes "tone -> formal", you have taught the model that the output format is itself somewhat flexible, which undermines the entire reason for showing examples in the first place. Formatting consistency across your examples is at least as important as the content of the examples.

Order matters, and recency has a real effect. Models tend to weight the most recent examples in a sequence somewhat more heavily than earlier ones — a form of recency bias. If your examples are not perfectly balanced across categories, placing an example of a less common but important category last, rather than first, can help counteract the ordering effect and make outputs more balanced across categories rather than mildly biased toward whatever category dominates the least-recent early examples.

Use realistic examples, not sanitised ones. An example written by you, in clean and careful prose, may not resemble the real, messy, occasionally ungrammatical input your application will actually receive. Pull real examples (with any private information removed or replaced) from your actual traffic or logs whenever possible — a few-shot set built from realistic input teaches the model to handle the actual distribution of inputs it will see, not an idealised version of the task.

How Many Examples Are Enough?

There is no fixed number that works universally — it depends on task complexity and how many distinct category boundaries or format nuances need to be demonstrated — but a few practical guidelines hold up well across most classification and extraction tasks.

One example per output category, at minimum, so the model has seen every possible answer at least once, not just described it in words. For a binary classification, two examples is a bare minimum; for a five-category classification, five is a reasonable floor.

Two to three examples per category is a common sweet spot for moderately nuanced tasks, giving enough coverage of the boundary cases described above without the prompt growing so long that it becomes expensive and unwieldy — remember from Unit 1 that every token in your examples is sent, and billed, on every single request.

More examples help less than you'd expect past a certain point, and can sometimes hurt. Adding a tenth example to a task that was already well-specified by five rarely improves accuracy meaningfully, and a very long few-shot block increases cost per request substantially while doing comparatively little additional work — the model has generally extracted the pattern well before example ten. If you find yourself adding many examples and still seeing inconsistent output, the more likely fix is Lesson 2's technique of tightening the verbal instruction alongside the examples, not adding still more examples.

Diminishing and sometimes negative returns from redundant examples. If several of your examples are near-duplicates of each other (three formal examples that are all polite corporate emails, say, with none showing formal-but-terse or formal-but-emotional variation), they teach the model less than three genuinely varied formal examples would, because the model is inferring the boundary of "formal" from the variation across your examples as much as from their count.

Static vs. Dynamic Few-Shot Selection

Lesson 1 of this unit drew a distinction between content that belongs in instructions (stable, applies to every request) and content that belongs in input (specific to the current request). Few-shot examples can genuinely belong in either, depending on how they're selected.

Static few-shot — the same fixed set of examples used for every request — belongs in instructions, exactly like the tone-classifier example earlier in this lesson. This is the right approach when a small, fixed set of examples adequately covers the task's category boundaries, and it has a real efficiency advantage: because instructions is a stable prefix, a static few-shot block benefits fully from prompt caching (Unit 1, Lesson 5), making the marginal cost of the examples on every subsequent request very small.

Dynamic few-shot — selecting the most relevant examples for this specific input from a larger pool, typically via embedding similarity (Unit 10 covers the mechanism in full) — belongs in input, because the selected examples change on every request by definition. This approach is worth the added complexity when your task spans a wide variety of input shapes that no single small static set can adequately represent — a general-purpose support ticket classifier handling everything from billing questions to bug reports, say, where showing five examples of a similar past ticket is more useful than five fixed generic examples that may not resemble the current one at all.

# Dynamic few-shot: examples selected per request, so they belong in input
def build_input(current_message: str, similar_examples: list[tuple[str, str]]) -> str:
    example_block = "\n\n".join(
        f'Message: "{msg}"\nTone: {tone}' for msg, tone in similar_examples
    )
    return f"{example_block}\n\nMessage: \"{current_message}\"\nTone:"

response = client.responses.create(
    model="gpt-5.6-luna",
    instructions="Classify the tone of the message as formal, casual, or urgent. Follow the pattern shown in the examples.",
    input=build_input(current_message, similar_examples),
)

Note that even in the dynamic case, the task description ("classify the tone...") still belongs in instructions as the stable part, while only the selected examples plus the new message move into input as the part that changes per request — the static/dynamic distinction applies to the examples specifically, not to the whole prompt.

Few-Shot for Format, Zero-Shot for Judgment

A useful heuristic when deciding whether a given prompt needs few-shot examples at all: examples are most valuable when the hard part of the task is matching a specific format or style, and least valuable — sometimes actively unhelpful — when the hard part is exercising judgment on a case that genuinely differs from anything you could show in advance.

For formatting-heavy tasks — extract these fields in this exact layout, write in this exact tone, follow this exact citation style — few-shot examples are close to essential, because format is precisely the kind of thing that's easy to show and hard to describe completely in words.

For judgment-heavy tasks — is this a good business decision, does this code have a subtle bug, is this argument logically sound — a fixed set of examples can sometimes narrow the model's reasoning toward the surface pattern of your examples rather than genuinely reasoning about the new case on its merits, especially if your examples happen to share superficial features (all bugs in the examples were off-by-one errors, say) that don't generalise to the actual variety of cases you'll see. For this category of task, a precise zero-shot instruction (Lesson 2's techniques) combined, where the model supports it, with a higher reasoning_effort (Lesson 4 of this unit) is often more effective than trying to demonstrate judgment through a handful of worked examples.

Negative and Near-Miss Examples

Every example shown so far has been a positive example — an input paired with the correct output. There is a second, less commonly used technique worth understanding: showing the model an input that looks like it belongs to one category but is deliberately labeled with the correct, less obvious answer, specifically to correct a mistake the model would otherwise make by surface-level pattern matching.

Consider a support-ticket urgency classifier. A message reading "This is absolutely critical, please respond ASAP!!!" looks urgent by its choice of words and punctuation alone. But if that particular phrasing, in your actual data, tends to come from a small number of users who mark everything as critical regardless of actual severity, a purely surface-level classifier will over-predict "urgent" for that user's traffic. A near-miss example makes the boundary explicit:

instructions = """Classify the message as low, medium, or high urgency, based on the
actual technical impact described, not the emotional intensity of the wording.

Message: "This is absolutely critical, please respond ASAP!!! My dashboard widget is the wrong color."
Urgency: low

Message: "Hey, whenever you get a chance — production database is returning errors for all users."
Urgency: high

Message: "URGENT URGENT please help my export button is missing a tooltip"
Urgency: low"""

Both "low" examples use urgent-sounding language attached to a low-impact issue, and the "high" example uses calm language attached to a severe issue. This is a stronger training signal than three examples that simply pair urgent language with "high" and calm language with "low," because it directly demonstrates the distinction the classifier actually needs to make — impact, not tone — rather than leaving the model free to fall back on the surface correlation between emotional language and urgency that its pretraining data likely reinforces.

Near-miss examples are most useful precisely when you have observed the model making a specific, describable mistake in practice. Rather than guessing at what might confuse the model in advance, this technique works best as a repair — after production output review or evaluation (Unit 13 covers this systematically) surfaces a real error pattern, add one example that demonstrates the boundary the model is currently missing. Adding near-miss examples speculatively, before you've observed an actual failure mode, risks manufacturing examples for problems that don't occur in your real traffic, which wastes both prompt tokens and design effort without clear benefit.

Few-Shot Examples Alongside Structured Output Schemas

Unit 6 introduces text.format for enforcing a strict output schema — a JSON structure the API guarantees the model's output will conform to, independent of prompting. It's worth previewing the relationship between few-shot examples and schema enforcement now, because it resolves a question that comes up naturally once you know both techniques exist: if a schema already guarantees the shape of the output, do few-shot examples still add value?

They do, but for a different reason than in the unstructured case. A schema enforces which fields exist and their types — it guarantees you'll get a string where you asked for a string, and an array where you asked for an array. It says nothing about content quality within those constraints: whether a "summary" field is actually concise and accurate, whether a "category" field picks the label that best fits a genuinely ambiguous case, whether extracted values are normalized consistently (e.g., dates as 2026-09-13 rather than sometimes September 13, 2026). Few-shot examples continue to do useful work at this level even when a schema is enforcing the surrounding structure:

response = client.responses.create(
    model="gpt-5.6-luna",
    instructions="""Extract the invoice fields into the given schema.

Example:
Input: "Invoice #4471, dated March 3rd 2026, due net-30, total $1,240.00 from Acme Supplies."
Output: {"invoice_number": "4471", "date": "2026-03-03", "due_date": "2026-04-02", "total": 1240.00, "vendor": "Acme Supplies"}""",
    input=invoice_text,
    text={"format": {"type": "json_schema", "name": "invoice", "schema": INVOICE_SCHEMA, "strict": True}},
)

The schema guarantees the response is valid JSON with exactly these fields and types; the example teaches the specific normalization choice — ISO date format, net-30 converted into an actual due date, total as a bare number without a currency symbol — that the schema alone cannot express. This is a case where zero-shot-plus-schema handles the shape problem and few-shot handles the content convention problem, and combining both is more reliable than either alone.

A Full Worked Example: From Zero-Shot Failure to Few-Shot Fix

To see the technique's practical value end to end, consider a task that on the surface looks like simple extraction: pulling structured line items out of free-text purchase requests submitted by employees to a procurement system.

Iteration 1 — zero-shot.

response = client.responses.create(
    model="gpt-5.6-luna",
    instructions="Extract the item name, quantity, and unit price from the purchase request. Return one line per item.",
    input="Need 3 standing desks at around $450 each, and a dozen HDMI cables, maybe $12 a piece.",
)

A plausible zero-shot output:

Standing desks - 3 - $450
HDMI cables - 12 - $12

This looks reasonable at first glance, but it's already inconsistent in a way that will break any downstream parser: item names aren't capitalized consistently with the source ("HDMI cables" vs. "Standing desks" — arbitrary casing decisions the model made on its own), quantities and prices use different separator characters depending on the model's momentary choice ("3" then "-" then "$450" — no fixed field delimiter), and "a dozen" was correctly converted to "12" but nothing in the instructions actually told the model to normalize quantity phrases at all — it happened to get this one right, which is not the same as it reliably getting every phrasing right.

Iteration 2 — few-shot with explicit normalization rules.

instructions = """Extract purchase request line items. For each item, output exactly:
name|quantity|unit_price

Normalize quantities to plain integers (convert phrases like "a dozen" to 12, "a pair" to 2).
Normalize prices to a plain number with two decimal places, no currency symbol.
Use title case for item names.

Example:
Input: "Grab 2 boxes of pens, about $4 each, and a dozen legal pads at $3.50."
Output:
Pens|2|4.00
Legal Pads|12|3.50"""

response = client.responses.create(
    model="gpt-5.6-luna",
    instructions=instructions,
    input="Need 3 standing desks at around $450 each, and a dozen HDMI cables, maybe $12 a piece.",
)

Expected output now:

Standing Desks|3|450.00
Hdmi Cables|12|12.00

This version is dramatically more reliable for a downstream parser: the pipe delimiter is unambiguous, the price format is fixed at two decimals, and the quantity-phrase normalization ("a dozen" → 12) is demonstrated rather than left to chance. Notice this is a case where the example is doing work that a purely verbal instruction struggles to fully specify — you could write out a rule for every possible quantity phrase ("a dozen" means 12, "a pair" means 2, "a few" means...), but one example combined with the general rule "normalize quantities to plain integers" communicates the pattern of normalization far more compactly and completely than an exhaustive verbal enumeration ever could. (One rough edge remains: "Hdmi Cables" is technically wrong title-casing for an acronym — a mistake worth catching in testing and fixing either with a second example that includes an acronym, or by adding an explicit instruction about preserving existing capitalization for acronyms.)

Comparison: Zero-Shot, Static Few-Shot, and Dynamic Few-Shot

AspectZero-shotStatic few-shotDynamic few-shot
Where it livesinstructions onlyinstructions (stable block)input (selected per request)
Best suited forJudgment-heavy tasks; simple, well-defined formatsFormatting-heavy tasks with a small, stable set of category boundariesTasks spanning a wide, varied input distribution
Token cost per requestLowestFixed, moderateVariable, and does not benefit from caching
Prompt caching benefitFull (entire instructions is stable)Full (example block is part of the stable prefix)None (selected examples change every request)
Setup complexityLowest — just write the instructionLow — write and test the fixed examplesHigher — requires an example pool, embedding retrieval (Unit 10), and selection logic
Failure mode if misusedAmbiguous edge cases handled inconsistentlyOverfits to the fixed examples' incidental surface featuresRetrieval picks unhelpful or misleading "similar" examples

This table is a starting point for a design decision, not a strict ranking — many production prompts in practice combine a zero-shot instruction for the general rule with a small static few-shot block for the trickiest boundary cases, without ever needing the added complexity of dynamic selection at all.

Few-Shot Examples Across a Chained Conversation

Lesson 1 of this unit established that instructions are not automatically carried forward when you chain calls with previous_response_id — each call's instructions field applies only to that call. This has a direct, easily overlooked consequence for few-shot examples specifically: if your few-shot block lives in instructions, and you chain a follow-up call without re-supplying that same instructions value, the model no longer has your examples in context for the follow-up turn, even though it "remembers" the earlier conversation's input and output content through the chain.

first = client.responses.create(
    model="gpt-5.6-luna",
    instructions=FEW_SHOT_TONE_INSTRUCTIONS,  # contains the three tone examples
    input="Message: \"per our conversation, following up on the report\"\nTone:",
)

# Wrong: omitting instructions means the few-shot examples are gone for this turn
second = client.responses.create(
    model="gpt-5.6-luna",
    previous_response_id=first.id,
    input="Message: \"omg thanks so much!!\"\nTone:",
)

# Right: re-supply the same instructions (cheap, due to prompt caching on the stable prefix)
second = client.responses.create(
    model="gpt-5.6-luna",
    instructions=FEW_SHOT_TONE_INSTRUCTIONS,
    previous_response_id=first.id,
    input="Message: \"omg thanks so much!!\"\nTone:",
)

The fix is simple once you know the rule — re-pass the same instructions value on every chained call in the conversation — and because that value is an identical stable string, prompt caching (Unit 1, Lesson 5) means the repeated cost of re-sending it is small. The mistake is easy to make precisely because the first call's behavior looks correct, and the failure only shows up several turns later when classification quality silently degrades, which is why it's worth testing a multi-turn conversation's later turns specifically, not just its first response, whenever few-shot examples live in instructions.

Measuring the Cost of a Few-Shot Block

Because few-shot examples add real, billable tokens, it's worth actually measuring the cost rather than assuming it's negligible, especially before deciding between a static block (cached) and a dynamic one (not cached).

def estimate_fewshot_cost(examples_tokens: int, requests_per_day: int,
                            input_price_per_million: float, cached_price_per_million: float,
                            cache_hit_rate: float = 0.0) -> float:
    """Rough daily cost, in dollars, of sending a fixed few-shot block on every request."""
    effective_price = (
        cached_price_per_million * cache_hit_rate
        + input_price_per_million * (1 - cache_hit_rate)
    )
    return (examples_tokens * requests_per_day * effective_price) / 1_000_000

# Static few-shot: cached after the first request, using gpt-5.6-luna pricing
static_cost = estimate_fewshot_cost(
    examples_tokens=650, requests_per_day=50_000,
    input_price_per_million=0.20, cached_price_per_million=0.02, cache_hit_rate=0.9,
)

# Dynamic few-shot: different examples selected per request, so no cache benefit
dynamic_cost = estimate_fewshot_cost(
    examples_tokens=650, requests_per_day=50_000,
    input_price_per_million=0.20, cached_price_per_million=0.02, cache_hit_rate=0.0,
)

print(f"Static (mostly cached):  ${static_cost:.2f}/day")
print(f"Dynamic (never cached):  ${dynamic_cost:.2f}/day")

At 50,000 requests a day and a 650-token example block, a static block with a 90% cache hit rate costs roughly $0.65 a day, while the same block sent uncached every time costs roughly $6.50 a day — a tenfold difference driven entirely by whether the examples are stable enough to sit in a cached prefix. This is the concrete version of the caching argument made earlier in this lesson: at meaningful request volume, the decision between static and dynamic few-shot is not just an accuracy trade-off, it's a cost decision worth actually running numbers on rather than guessing at, particularly once a prompt is heading toward production traffic rather than staying at prototype scale.

Common Mistakes

Inconsistent formatting across examples. Covered above — even small inconsistencies (a colon versus an arrow, a trailing period on some outputs but not others) teach the model that the format itself is negotiable, which is precisely the opposite of what few-shot prompting is meant to establish.

Examples that don't cover the actual boundary cases. All-easy examples fail to teach the model where your categories actually diverge, which is exactly where real input tends to be hardest to classify.

Too many examples, driving up cost with little accuracy benefit. Past roughly two to three well-chosen examples per category, additional examples usually add cost without proportional benefit; audit a bloated few-shot block for redundancy before assuming more will help.

Using few-shot to compensate for a vague instruction, instead of alongside a precise one. Examples and precise verbal instructions reinforce each other; examples alone, with no instruction stating the categories and rules explicitly, leave the model to infer the entire task purely from pattern-matching, which is less reliable than combining both.

Forgetting that few-shot examples are billed tokens on every request. A five-example, 800-token few-shot block sent on every single classification call adds real cost at scale; weigh that against the accuracy gain, and consider whether Unit 6's structured outputs or a smaller, more targeted example set can achieve the same reliability more cheaply.

Best Practices

Match your examples' format exactly to the format you want back, down to punctuation and capitalisation — the model will match what it sees, not what you meant.

Include at least one example near each category boundary, not only clear-cut cases, so the model learns where your categories actually diverge.

Prefer real, messy examples from actual data over clean, hand-written ones, since real input is what the model will actually face in production.

Keep static few-shot blocks in instructions to benefit from prompt caching; move to dynamically selected examples in input only when task diversity genuinely requires it.

Re-evaluate your few-shot set whenever you change models. A set of examples tuned against one model's particular tendencies may transfer imperfectly to another, especially across a model family change rather than a minor version bump — treat few-shot examples as part of the same testing discipline Lesson 2 recommended for verbal instructions.

0 Comments

Reviewed before they appear

No comments yet.

OpenAI SDK
Introduction to the OpenAI SDK Setting Up Python Creating an API Key Your First Call — client.responses.create() and response.output_text Understanding Billing, Credits, and What a Request Costs Why Responses Replaced Chat Completions Anatomy of a Request: model, input, and instructions Anatomy of a Response: The Typed output Array, Not Just Text Roles: User, Assistant, and Developer/System Choosing a Model, and Reading the Models Page Instead of Memorizing Names Instructions vs. Input Writing Prompts That Get Consistent Results Few-Shot Examples Reasoning Models and the reasoning Parameter Debugging a Prompt That Misbehaves Why Streaming Matters for User Experience stream=True and Iterating Over Events Handling the Event Types You Actually Care About Background Mode for Long-Running Jobs Project — Add Live Streaming to Your Chatbot The Problem With Parsing Free Text JSON Schema and Strict Mode Pydantic Models With the SDK's Parse Helpers Handling Refusals and Validation Failures Project — A Resume-to-JSON Extractor Working With input_image input_file, PDFs, and the Files API Image Generation Speech-to-Text and Text-to-Speech Project: A PDF Question-Answering Script What Function Calling Is Defining a Tool Schema The Full Loop Multiple Tools Errors, Timeouts, and Untrusted Arguments Project: A Weather Assistant Web Search File Search and Vector Stores Code Interpreter Remote MCP Servers and Connectors Project: A Research Assistant What an Embedding Is, Without the Maths Generating and Storing Embeddings Similarity Search From Scratch Hosted Vector Stores vs. Rolling Your Own A Small RAG App Over a Folder of Notes Agents vs. a Single API Call — When You Need One pip install openai Giving Agents Tools Handoffs and Multi-Agent Triage Guardrails and Approvals Tracing and Observing What Your Agent Did A Multi-Agent Support Desk Error Codes and What Each One Means Retries, Timeouts, and Backoff Rate Limits and Spend Limits Prompt Caching and Cost Optimisation The Batch API for Bulk Work Async Clients and Concurrency Moderation and Safety Best Practices Designing the App Backend With FastAPI Streaming to a Simple Frontend Deploying and a Cost/Safety Checklist Why Web Search Is Useful for Current Information Using the Web Search Tool with the Responses API Configuring Search Behavior for Application Use Cases Understanding Citations and Source Attribution Where to Go Next Building a Research Assistant with Web Search Combining Web Search with Structured Outputs Handling Conflicting or Low-Quality Web Sources Reducing Unsupported Claims with Grounded Generation Testing Freshness-Sensitive AI Answers Production Considerations for Web-Grounded Applications Understanding File Search and Retrieval-Augmented Generation Creating and Organizing Vector Stores Uploading Documents for Retrieval Connecting Vector Stores to Responses API Requests Designing Document Metadata and Filtering Strategies Building a PDF Question-Answering Application Improving Retrieval Quality With Better Document Preparation Handling Missing Evidence and Retrieval Failures Combining File Search With Web Search Building a Production Knowledge-Base Assistant What the Code Interpreter Tool Is Designed For Running Python-Based Analysis Through the OpenAI SDK Uploading Datasets for Analysis Analyzing CSV and Spreadsheet Data Generating Charts and Data Summaries Handling Generated Files and Downloadable Artifacts Building a Data-Analysis Assistant Combining Code Execution with Structured Outputs Validating Generated Calculations and Results Security and Sandbox Considerations for Code Execution Understanding Multimodal Input with the OpenAI SDK Sending Images to a Model Image Analysis from URLs and Uploaded Files Extracting Text and Information from Screenshots Building an Image-Question-Answering Application Combining Image Input with Structured Output Analyzing Multiple Images in One Request Handling Image Quality and Input Limitations Designing Multimodal Prompts for Reliable Results Building a Practical Vision-Powered Python Application Understanding Speech-to-Text and Text-to-Speech Workflows Transcribing Audio with the OpenAI SDK Working with Uploaded Audio Files Handling Timestamps and Transcription Metadata Building a Meeting Transcription Workflow Generating Spoken Responses from Text Handling Long Audio and Processing Failures Combining Audio with Text and Tool Calling Building an End-to-End Python Voice Application What Embeddings Are and When to Use Them Generating Embeddings With the OpenAI API Preparing Text for Embedding Comparing Vectors With Cosine Similarity Building a Simple Semantic Search Engine in Python Storing Embeddings in a Database Metadata Filtering for Semantic Search Chunking Strategies for Better Retrieval Evaluating Semantic Search Quality Building a Document Similarity Application When Batch Processing Makes Sense Designing Large-Volume AI Processing Pipelines Using Asynchronous Python with the OpenAI SDK Running Concurrent Requests Safely Controlling Concurrency and Avoiding Rate Limits Tracking Batch Job Progress Handling Partial Failures in Bulk Workloads Retrying Failed Items Without Duplicating Successful Work Designing Resumable AI Processing Jobs Building a Production Batch-Processing Pipeline Batch Processing Makes Sense Large-Scale AI Processing Pipelines Async Python with OpenAI SDK Safe Concurrent Requests Concurrency & Rate Limits Batch Progress Tracking Partial Failure Handling Safe Retry Handling Resumable AI Jobs Production Batch Pipeline System–User Data Separation Reusable App Instructions Prompt Templates & Variables Extraction & Classification Prompts Summarization & Transformation Prompts Explicit Output Requirements Prompt Version Management Prompt Testing & Evaluation Reusable Python Prompt Library API Key Security Secure API Key Storage Secure Secret Management Prompt Injection Prevention Trusted vs. Untrusted Content Tool Argument Validation Sensitive Data Handling Secure Logging AI Action Authorization Production AI Security Checklist Why AI Applications Need Evaluation Beyond Unit Tests Unit Testing OpenAI SDK Integration Code Mocking API Responses in Python Tests Testing Structured Outputs Against Schemas Testing Tool-Calling Workflows Building a Small Evaluation Dataset Measuring Accuracy, Consistency, and Failure Rates Regression Testing Prompts and Model Changes Human Evaluation Versus Automated Evaluation Creating a Repeatable Evaluation Pipeline AI Request Monitoring Token Cost Management Usage Metrics Design Reducing Model Calls Prompt & Context Optimization Model Selection & Optimization AI Caching Strategies Interactive Latency Optimization Usage Dashboards & Budget Alerts Performance & Cost Checklist Every API Call Starts Fresh Fixing API Statelessness Server-Side Conversation Memory Limits of Response Chaining What We're Building Conversation Memory Challenges Preparing an OpenAI SDK Application for Deployment Environment-Specific Configuration for Development and Production Deploying a Python AI Service with Docker Container Health Checks and Startup Configuration Managing Secrets in Cloud Deployments Background Workers for Long-Running AI Tasks Queues and Asynchronous Job Architectures Scaling AI Workloads Horizontally Monitoring Production Incidents and Failures Production Deployment Checklist for OpenAI SDK Applications Reusable OpenAI Service Classes AI Client Dependency Injection Typed AI Responses Python Configuration Management AI Request Decorators Centralized AI Error Handling Clean SDK Abstractions Reusable OpenAI Utilities Internal AI Python Libraries SDK Integration Maintenance Production AI Chatbot Document Q&A System Web Research Assistant Customer Support Agent AI Data Analysis Assistant Image Analysis App Meeting Transcription & Summary Semantic Document Search Multi-Tool AI Agent Production OpenAI SDK App Why "It Looked Fine When I Tested It" Isn't Enough Timing Note Status Note Pre-Decision Status Note Current Availability Note
Ask about this post
AI Ask about this post

Ask questions about Few-Shot Examples and get answers drawn from it.

Signed-in readers only.