fix: append trailing user message so conversation summary calls don't 400
Root cause: get_messages() returns history ending with the just-saved assistant reply, but the Anthropic Messages API rejects any request whose last message is not role=user - this failed on every single chat turn in production, silently swallowed by the existing try/except. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V57jSQPqwkGG8BuAXg59X5
This commit is contained in:
parent
246fe60ce7
commit
da48882671
|
|
@ -1086,6 +1086,7 @@ async def update_conversation_summary(conversation_id: int):
|
|||
try:
|
||||
history = await get_messages(conversation_id)
|
||||
claude_messages = [{"role": m["role"], "content": m["content"]} for m in history]
|
||||
claude_messages.append({"role": "user", "content": "Fasse das bisherige Gespraech zusammen."})
|
||||
completion = await asyncio.to_thread(
|
||||
claude_client.messages.create,
|
||||
model=CLAUDE_MODEL,
|
||||
|
|
|
|||
|
|
@ -237,6 +237,34 @@ async def test_update_conversation_summary_upserts_summary_and_embedding():
|
|||
mock_upsert.assert_called_once_with(3, "Nutzer fragte nach seinem Hund Bruno.", [0.1, 0.2])
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_conversation_summary_ends_messages_with_user_role():
|
||||
"""Regression: history always ends with the just-saved assistant reply,
|
||||
but the Anthropic Messages API rejects a request whose last message is
|
||||
not role=user (no prefill support) - a trailing user instruction must
|
||||
be appended, or this call 400s on every real conversation."""
|
||||
history = [
|
||||
{"role": "user", "content": "Wie geht es meinem Hund?", "tokens_used": None, "created_at": None},
|
||||
{"role": "assistant", "content": "Bruno geht es gut.", "tokens_used": 5, "created_at": None},
|
||||
]
|
||||
completion = MagicMock()
|
||||
text_block = MagicMock()
|
||||
text_block.type = "text"
|
||||
text_block.text = "Zusammenfassung."
|
||||
completion.content = [text_block]
|
||||
|
||||
main.claude_client = MagicMock()
|
||||
main.claude_client.messages.create.return_value = completion
|
||||
|
||||
with patch.object(main, "get_messages", new=AsyncMock(return_value=history)), patch.object(
|
||||
main, "get_embedding", new=AsyncMock(return_value=[0.1])
|
||||
), patch.object(main, "upsert_conversation_summary", new=AsyncMock()):
|
||||
await main.update_conversation_summary(conversation_id=3)
|
||||
|
||||
_, kwargs = main.claude_client.messages.create.call_args
|
||||
assert kwargs["messages"][-1]["role"] == "user"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_conversation_summary_swallows_exceptions():
|
||||
with patch.object(main, "get_messages", new=AsyncMock(side_effect=RuntimeError("DB down"))):
|
||||
|
|
|
|||
Loading…
Reference in New Issue