Treat prompts as code: parameterised templates, idempotent runs, version-controlled and unit-tested.
Saving your best recipe as a template so you do not guess ingredients every time.
template = "Translate to {language}. Preserve markdown.\n\n{text}"
tests = [{'language':'French','text':'good morning','expect':'bonjour'}, ...]
Prompts are code: each production prompt deserves a git hash, owner, parameter set, expected output examples and a regression suite. Tools like promptfoo, dspy and LangSmith add a layer of eval. The benefit: a prompt change goes through review and rollback like any other code.
template = "Translate to {language}. Preserve markdown.\n\n{text}"
def render(language, text):
return template.format(language=language, text=text)
print(render(language='French', text='good morning'))
str.format or jinja-style templating keeps prompts testable and editable.
def call_translate(language, text, model='gpt-4o-mini'):
return openai.chat.completions.create(
model=model,
messages=[{'role':'system','content': f'Translate to {language}.'},
{'role':'user', 'content': text}]).choices[0].message.content
Pinning model plus prompt is the simplest versioned contract.
tests = [
{'language':'French','text':'good morning','expect':'bonjour'},
{'language':'Spanish','text':'good morning','expect':'buenos'},
]
for t in tests:
out = call_translate(t['language'], t['text'])
assert t['expect'] in out.lower()
Fixture-set assertions catch regressions before they ship to production.
Hardcoding prompt strings in business logic — a tone tweak needs a code deploy. Always store prompts in a registry or template file with a version.
Every production prompt gets: a template file, parameter schema, version, owner, model id and fixture-based regression test.