Fix Gemini's answer format with system instructions and examples
When Gemini's answer format changes between runs, put the rules in a system instruction, add two or three examples with an Output: prefix, then re-run to check.
Fix an unstable answer format in three layers: system instruction, few-shot examples, prefix. The example task sorts customer messages into category | urgency | one-line summary.
[1] Start with the unstable prompt. With no format rule, nothing pins the shape of the answer, so it can differ from run to run.
Classify this customer message. Message: I was charged twice for my March invoice and nobody answers my emails.[2] Put the role and format rules in the system instruction. The docs say to pass a system_instruction parameter to configure the model's behavior; the official example is the single line "You are a cat. Your name is Neko." (docs). This is the system instruction for the task.
You are a support-ticket triage assistant.For every message, reply with exactly one line in this format:<category> | <urgency> | <one-sentence summary> Rules:- category is one of: billing, bug, account, other- urgency is one of: low, medium, high- the summary is one sentence, 15 words or fewer- output nothing else: no greeting, no explanation, no markdown[3] If rules are not enough, add examples. The same page says: "We recommend to always include few-shot examples in your prompts." Each example is an input/output pair that shows the exact format from the rules. Start with two or three.
Message: The app crashes every time I open the settings page.Output: bug | medium | App crashes when the settings page is opened. Message: Please delete my account and all my data today.Output: account | high | Customer asks for immediate account and data deletion. Message: Do you have a student discount?Output: other | low | Customer asks whether a student discount exists.[4] Keep every example identical in structure. The docs say to match XML tags, whitespace, newlines, and example splitters across all examples to avoid responses in an undesired format. Here each example is a Message: line, an Output: line, and a blank line. Do not use Answer: in just one of them.
[5] Use a prefix to start the answer. The docs describe giving an example plus a response prefix (such as Output:) and letting the model complete the pattern. Write the real input in the same shape as the examples and leave the text after the last Output: empty.
Message: I was charged twice for my March invoice and nobody answers my emails.Output:Split the request like this: send the system instruction as system_instruction, and send the three examples from step 3 followed by the last input above as the user input (input).
[6] If code has to read the answer, use a response schema instead of string rules. The docs recommend the structured output feature for complex JSON Schemas; it makes the model generate responses that adhere to a provided JSON Schema (Structured output). The docs' Recipe Extractor example sets mime_type and schema in response_format.
from google import genaifrom pydantic import BaseModel, Field class Ticket(BaseModel): category: str = Field(description="One of: billing, bug, account, other") urgency: str = Field(description="One of: low, medium, high") summary: str = Field(description="One sentence, 15 words or fewer") client = genai.Client()interaction = client.interactions.create( model=MODEL, input=prompt, response_format={ "type": "text", "mime_type": "application/json", "schema": Ticket.model_json_schema() },)ticket = Ticket.model_validate_json(interaction.output_text)[7] Run the same prompt several times to check the format holds. Assume each response was saved, one line each, to out-1.txt through out-10.txt; this finds the files that break the format.
$ grep -L -E '^(billing|bug|account|other) \| (low|medium|high) \| .+$' out-*.txt$ wc -l out-*.txtgrep -L prints only the names of files with no matching line. No output means all ten runs kept the format. Open any file that is listed, see how it differs, and fix the rule line or the examples.