Skip to main content
Lesson 2 of 20 · Production, Evals, and Optimization

End-to-end optimization: from prompt to network

Lesson 2 of 20 Updated November 3, 2026 Advanced
On this page
  1. Optimization is a system, not a parameter
  2. Optimize the prompt
  3. Optimize API parameters
  4. Optimize the network
  5. Optimize post-processing
  6. Key takeaways

Lesson updated November 3, 2026 based on OpenAI documentation: temperature and top_p are only accepted with a reasoning effort of none, whereas GPT-5.6 models reason by default (medium). Calls that set these parameters must therefore specify reasoning={"effort": "none"} (Responses API) or reasoning_effort="none" (Chat Completions). Sources: Using GPT-6 · GPT-5.6 Terra.

Optimization is a system, not a parameter

Reducing latency and costs for an LLM application isn’t just about picking a faster model. It’s a chain of optimizations stretching from the prompt to network configuration, and the weakest link dictates performance for the rest. A team that halves its system prompt size but leaves its server opening a new TLS connection for every request will lose in network overhead what it saved in tokens.

The order in which you tackle these levers matters. Start with the prompt because it impacts both cost and latency without requiring infrastructure changes. Next come API parameters, then network configuration, and finally how your application consumes the response. This lesson guides you through each lever in that order.

Optimize the prompt

Every input token costs time and money, and most production prompts carry baggage from their prototyping phase: instructions added one by one, each rephrasing the previous one. Your first reflex should be to rewrite the prompt densely, removing address forms and repetitions without touching the actual constraints transmitted to the model.

# ❌ Verbose prompt
prompt_long = """
You are an expert financial analysis assistant. You must always
respond in a professional and structured manner. You must use
numerical data when possible. You must avoid unnecessary jargon.
You must be concise but complete.
Analyze the following quarterly report: ...
"""

# ✅ Optimized prompt (same result, fewer tokens)
prompt_court = """Role: Senior financial analyst.
Constraints: Structured, numerical, concise.
Task: Analyze this quarterly report: ..."""

Both versions transmit exactly the same five constraints; the second does so without the five “You must” phrases that add nothing for the model. On a service processing ten thousand reports a day, this thirty-second rewrite pays for itself daily.

Choose the right model for the task

The second lever relies on the fact that not every call requires the same model. Routing a field extraction task to a high-reasoning model means paying for capacity the task doesn’t use and waiting longer for an identical result.

Task typeRecommended modelReason
Classification / extractiongpt-5.6-lunaFast, economical
Complex reasoninggpt-5.6-terra with medium reasoningBest quality/cost ratio
Critical tasksgpt-5.6-sol with high reasoningHighest quality, slower
High volumegpt-5.6-luna via Batch API-50% cost

In practice, codify this choice in a routing function rather than leaving it to developers’ discretion; otherwise, the default model always wins out:

import openai

client = openai.OpenAI()

def route_model(task: str, complexity: str) -> str:
    """Selects the optimal model based on the task."""
    if complexity == "low":
        return "gpt-5.6-luna"
    elif task in ("reasoning", "math", "code"):
        return "gpt-5.6-terra"
    elif complexity == "critical":
        return "gpt-5.6-sol"
    return "gpt-5.6-terra"

def optimized_call(prompt: str, task: str, complexity: str) -> str:
    model = route_model(task, complexity)
    response = client.responses.create(
        model=model,
        input=prompt,
    )
    return response.output_text

Optimize API parameters

A response that’s too long wastes generation time no one will read. Always specify max_output_tokens: this is a hard limit that protects both your bill and your interface, preventing a poorly phrased prompt from spiraling into a two-thousand-word digression.

response = client.responses.create(
    model="gpt-5.6-terra",
    reasoning={"effort": "none"},  # temperature requires effort none
    input="Summarize this text in one sentence.",
    max_output_tokens=100,  # Hard limit
    temperature=0.0,         # Deterministic = faster
)

Sampling parameters work in the same direction. Setting temperature=0 makes responses deterministic and slightly faster, which is exactly what you want for extraction or classification tasks where creativity is a source of variance, not an asset. Reducing top_p to 0.1 restricts the search space and speeds up generation; reserve this setting for tasks where only one phrasing is acceptable, and keep default values where response richness is part of the product.

Optimize the network

Packet travel costs add up on every call, yet they remain invisible in your application metrics. The OpenAI API is primarily hosted on the US East Coast: placing your application server in the same region as the endpoint can yield a potential gain of 50 to 150 milliseconds in network latency. For a conversational application, this is a significant fraction of Time to First Token (TTFT).

The second gain comes from connection reuse. Without a pool, every request replays the TLS handshake, adding several round trips before any useful data flows. Configuring an HTTP client once and for all solves this:

import httpx

# Client with persistent connection pool
client_http = httpx.Client(
    base_url="https://api.openai.com/v1",
    timeout=60.0,
    limits=httpx.Limits(
        max_connections=20,
        max_keepalive_connections=10,
    ),
)

Optimize post-processing

The last link is often the one people forget: an application that receives a streaming response but waits until the end to display it cancels out all the benefits of streaming. Process the response on the fly rather than after full reception.

async def progressive_processing(prompt: str):
    """Processes each chunk as soon as it arrives."""
    stream = client.responses.create(
        model="gpt-5.6-terra",
        input=prompt,
        stream=True,
    )

    buffer = ""
    for event in stream:
        if event.type == "response.output_text.delta":
            buffer += event.delta
            # Process by complete sentence
            if buffer.endswith((".", "!", "?")):
                yield buffer.strip()
                buffer = ""

Splitting by complete sentence is a deliberate compromise: emitting every token produces a jittery display, while waiting for the entire paragraph recreates the feeling of waiting. The sentence is the unit readers naturally consume. Reuse this pattern whenever your interface needs to display, read aloud, or stream what the model produces.

Key takeaways

  • Optimize the prompt first: fewer tokens = less latency and cost
  • Route to the right model based on task complexity
  • Limit max_output_tokens and use temperature=0 when possible
  • Reuse HTTP connections and process responses via streaming