Sliding Window Keeping the System Message
Problem Statement
Keep an agent's context small by retaining only the most recent turns — but never drop the leading system message, which sets the agent's instructions.
Background
A message list starts with an optional system message (role "system") followed by alternating user/assistant turns. A sliding window keeps the last k non-system messages. If the first message is a system message it is always preserved and prepended to the kept window.
Your Task
Implement:
def sliding_window(messages, k):
- If messages[0]["role"] == "system", always keep it.
- Keep the last k of the remaining (non-system-prefix) messages, in order.
- Return the new list.
Input Format
- messages: list of {"role", "content"} dicts.
- k (int): number of recent non-system messages to keep.
Output Format
- A list of message dicts.
Sample
msgs = [{"role":"system","content":"S"},{"role":"user","content":"a"},{"role":"assistant","content":"b"},{"role":"user","content":"c"}]
print(sliding_window(msgs, 2))
Output:
[{'role': 'system', 'content': 'S'}, {'role': 'assistant', 'content': 'b'}, {'role': 'user', 'content': 'c'}]
Example:
msgs = [{"role":"system","content":"S"},{"role":"user","content":"a"},{"role":"assistant","content":"b"},{"role":"user","content":"c"}]
print(sliding_window(msgs, 2))[{'role': 'system', 'content': 'S'}, {'role': 'assistant', 'content': 'b'}, {'role': 'user', 'content': 'c'}]- Identify the leading system message: Since the first message has role
"system", it is separated and preserved as the prefixhead = [{"role":"system","content":"S"}]. - Isolate the remaining conversation turns: The non-system messages form the list
rest = [{"role":"user","content":"a"}, {"role":"assistant","content":"b"}, {"role":"user","content":"c"}], which has a length of 3. - Apply the sliding window constraint: With k=2, we need the last 2 messages from
rest. Using the slice logic, we take elements from index 3−2=1 to the end, resulting inkept = [{"role":"assistant","content":"b"}, {"role":"user","content":"c"}]. - Combine the preserved prefix with the recent window: Concatenate
headandkeptto form the final list[{"role":"system","content":"S"}, {"role":"assistant","content":"b"}, {"role":"user","content":"c"}]. - The final output is
[{'role': 'system', 'content': 'S'}, {'role': 'assistant', 'content': 'b'}, {'role': 'user', 'content': 'c'}]
Constraints:
0 <= k <= len(messages).- Only a leading system message is special; system messages elsewhere are treated normally.
- Preserve original order.
1. Background Knowledge
In Large Language Model (LLM) applications, the context window is the maximum number of tokens the model can process at once. As an agent interacts with a user over many turns, the conversation history grows, eventually exceeding this limit. To manage this, developers use a sliding window strategy: they retain only the most recent k messages, discarding older ones. This keeps the context small and relevant while preserving the immediate conversational flow.
However, a critical constraint exists: the system message (typically the first message) contains the agent's core instructions, persona, and operational rules. Dropping this message would fundamentally alter the agent's behavior. Therefore, any context management strategy must treat the system message as immutable and always present, regardless of how many turns have occurred.
This problem models that exact scenario. You are given a list of message dictionaries, each with a role ("system", "user", or "assistant") and content. Your goal is to return a new list that contains the system message (if it exists) followed by the last k non-system messages. This is a common pattern in agent frameworks like LangChain or AutoGen, where memory management is essential for long-running tasks.
2. Algorithm Approach
The approach is a straightforward list slicing operation with a conditional check.
- Identify the System Message: Check if the first element in the list has the role "system".
- Separate the Rest: Define the "conversation" part of the list as everything after the system message (or the entire list if no system message exists).
- Apply the Window: Take the last k elements from the conversation part.
- Reconstruct: If a system message was found, prepend it to the sliced conversation. Otherwise, return the sliced conversation directly.
This is not a complex algorithmic problem but rather a test of careful list manipulation and edge-case handling.
3. Step-by-Step Strategy
Continue the full explanation
You're reading the free preview. Unlock the complete walkthrough, the code editor, test runner and reference solution with Premium.
Editor locked
The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.