Syllabus Lesson 120 of 239 · Prompt Engineering for AI Engineers
Prompt Engineering for AI Engineers

Roles & System Prompts

A modern chat model does not see one blob of text. It sees a list of messages, each tagged with a role. The roles that matter: system sets the rules and persona once at the top, user is what a person typed, and assistant is what the model said back. Getting these right is the difference between a model that behaves and one that wanders.

A real call to a chat API looks like this (shown only to make the shape concrete, you will NOT call any API in this exercise):

messages = [
    {"role": "system", "content": "You are a terse support bot."},
    {"role": "user", "content": "my order is late"},
]
# response = client.messages.create(model=..., messages=messages)

If your tutor is on, an on-device model could even answer it for you. But none of that is what you are graded on. You are graded on the part you actually engineer: assembling the message list correctly and refusing to assemble a broken one.

Build chat_prompt(system, turns) that renders a transcript as a single string:

  • The first line is the system prompt: [system] <system text>.
  • Then every turn in turns (a list of (role, content) tuples) renders in order as [role] content.
  • End with a trailing open [assistant] line, the cue for the model to speak next.
  • If any turn has a role other than user or assistant, raise ValueError. The system role is set once via the first argument, never as a turn.

So chat_prompt("Be brief.", [("user", "hi")]) gives:

[system] Be brief.
[user] hi
[assistant]

That role check is not busywork. Letting a caller smuggle in a fake system turn mid-conversation is a real way prompts get hijacked. Validate the input and fail loudly. Press Run to grade.

Your turn

Write chat_prompt(system, turns) that returns a transcript string. Line 1 is [system] <system>. Each (role, content) in turns renders in order as [role] content. End with a trailing open [assistant] line. Raise ValueError if any turn role is not user or assistant. With no turns the output is exactly "[system] <system>\n[assistant]".

Spotted a problem in this lesson? Report it

Code · runs in your browser
Output