From e69f5a76e1e596bb4ebfac7f93bcb0151dab04f0 Mon Sep 17 00:00:00 2001 From: Paul Kompfner Date: Thu, 12 Mar 2026 15:24:17 -0400 Subject: [PATCH] Add test for trailing assistant+system ordering, improve docstring Add test exercising the step 3 ordering where stripping a trailing assistant exposes a system message that then gets converted to user. Move the reasoning about when a trailing system message can occur into the docstring. --- .../adapters/services/perplexity_adapter.py | 10 ++++++---- tests/test_get_llm_invocation_params.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/pipecat/adapters/services/perplexity_adapter.py b/src/pipecat/adapters/services/perplexity_adapter.py index 754716a19..b55696893 100644 --- a/src/pipecat/adapters/services/perplexity_adapter.py +++ b/src/pipecat/adapters/services/perplexity_adapter.py @@ -84,8 +84,11 @@ class PerplexityLLMAdapter(OpenAILLMAdapter): "assistant", remove it. OpenAI appears to silently ignore trailing assistant messages server-side, so removing them preserves equivalent behavior while satisfying Perplexity's "last message must be - user/tool" constraint. If the last message is "system" (e.g. the - context only contains system messages), convert it to "user". + user/tool" constraint. If the last message is "system", convert it + to "user". A trailing system message can only occur when the context + consists entirely of system messages (possibly followed by assistant + messages that were just removed), because step 1 converts any system + message that appears after a non-system message to "user". Args: messages: List of message dicts with "role" and "content" keys. @@ -144,8 +147,7 @@ class PerplexityLLMAdapter(OpenAILLMAdapter): while messages and messages[-1].get("role") == "assistant": messages.pop() - # If the last message is "system" (e.g. the context only contains - # system messages), convert it to "user". + # If the last message is "system", convert it to "user". if messages and messages[-1].get("role") == "system": messages[-1]["role"] = "user" diff --git a/tests/test_get_llm_invocation_params.py b/tests/test_get_llm_invocation_params.py index 6e37873d4..08710d77d 100644 --- a/tests/test_get_llm_invocation_params.py +++ b/tests/test_get_llm_invocation_params.py @@ -1152,6 +1152,25 @@ class TestPerplexityGetLLMInvocationParams(unittest.TestCase): self.assertEqual(params["messages"][1]["role"], "user") self.assertEqual(params["messages"][1]["content"], "Always be polite.") + def test_trailing_assistant_removed_then_system_converted(self): + """Test that trailing assistant is removed, exposing a system message that becomes user. + + This exercises the ordering of step 3: strip trailing assistants first, + then convert a trailing system to user. + """ + messages: list[LLMStandardMessage] = [ + {"role": "system", "content": "You are helpful."}, + {"role": "assistant", "content": "Sure thing."}, + ] + + context = LLMContext(messages=messages) + params = self.adapter.get_llm_invocation_params(context) + + # Trailing assistant removed → [system] → system converted to user → [user] + self.assertEqual(len(params["messages"]), 1) + self.assertEqual(params["messages"][0]["role"], "user") + self.assertEqual(params["messages"][0]["content"], "You are helpful.") + def test_consecutive_assistants_merged_then_trailing_removed(self): """Test that consecutive assistant messages are merged, then trailing assistant is removed.""" messages: list[LLMStandardMessage] = [