Skip to main content
Laravel, thinking fast.
Chapter 16 · Long Content

Prompt With Names, Not Codes

Julian Beaujardin

/**
 * Full English names for the supported target languages. Prompting with a
 * name instead of a bare ISO code makes the model translate reliably.
 */
private const LANGUAGE_NAMES = [
    'en' => 'English',
    'es' => 'Spanish',
    'de' => 'German',
    'it' => 'Italian',
    'pt' => 'Portuguese',
];

Your API takes es; the prompt should say Spanish. A two-letter code is ambiguous and under-specified in a way a name is not, and the difference shows up in output quality.

The general rule: your internal identifiers are not prompt material. Enum cases, foreign keys, status codes — translate them into words before they reach the model. It reasons about language, and you should give it some.

Note also that this map is the same whitelist the endpoint validates against, from Chapter 5. The set of allowed languages and the set of known names are one list. Two lists would drift, and the drift would be a validated language with no name — which prompts with an ISO code and quietly degrades.

When the Browser Has to Call Directly

Long work runs into an infrastructure limit that has nothing to do with the model: intermediaries have their own timeouts, and one you do not control may be shorter than the work takes.

We hit this with a CDN in front of the application, whose first-byte timeout was shorter than a full-site translation. Every architecturally tidy option — proxy it, queue it and poll — either hit the same limit or was disproportionate for something a user triggers occasionally and waits for.

The answer was to let the browser call an endpoint that begins responding immediately, bypassing the intermediary that was timing out.

Which is not a violation of Chapter 5, and the distinction is worth restating: the browser calls your endpoint, which authenticates, meters, and composes the prompt. The credential never leaves the server. What moved was the transport, not the decisions.

Know which of your limits are yours. A timeout you did not set and cannot change is a constraint on the architecture, and pretending otherwise produces a design that fails in production and works everywhere else.

Clear What Goes Stale Afterwards

Long content lands somewhere — a file, a config, a cache — and the layer that reads it may not notice.

Our worst instance: a translation was written correctly to disk, and the process serving the site kept reading a cached copy of the old version. The editor showed stale content, the user "fixed" it, and saving clobbered the good translation with the old one. Correct write, correct file, wrong thing served — and a data-loss bug that looked like a translation bug.

Enumerate what caches the thing you just wrote, and invalidate all of it in the same operation. Bytecode caches, config caches, static page caches, CDN edges. The write is not finished until every reader can see it.

What This Chapter Argued

  • Chunk on structure, never on character offsets. Each chunk should be a complete sub-document.
  • Budget instructions plus input plus expansion, and leave slack — a too-large chunk truncates, and truncation looks like success.
  • Fail the whole operation if any chunk fails. Partial results that look complete get shipped.
  • Prompt with names, not internal identifiers. Keep the whitelist and the name map as one list.
  • Some limits are not yours. An intermediary's timeout is a constraint on the design.
  • Moving transport is not moving decisions. The browser may call your endpoint; the credential and the prompt stay server-side.
  • Invalidate every cache of what you just wrote, in the same operation.