Initial commit
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import unittest
|
||||
|
||||
from opc.layer5_memory.history_compactor import HistoryCompactor
|
||||
|
||||
|
||||
class _OverflowLLM:
|
||||
def __init__(self) -> None:
|
||||
self.calls = 0
|
||||
|
||||
def is_context_overflow_error(self, error: Exception) -> bool:
|
||||
return "prompt too long" in str(error).lower()
|
||||
|
||||
async def simple_chat(self, prompt: str, system: str | None = None, task_type: str | None = None) -> str:
|
||||
_ = (system, task_type)
|
||||
self.calls += 1
|
||||
payload = json.loads(prompt)
|
||||
messages = list(payload.get("messages", []) or [])
|
||||
if self.calls == 1:
|
||||
raise RuntimeError("prompt too long")
|
||||
return json.dumps(
|
||||
{
|
||||
"history_summary": f"summarized {len(messages)} messages",
|
||||
"memory_summary": "## Primary Goal\n- Continue safely.",
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
|
||||
class _SingleMessageOverflowLLM:
|
||||
def __init__(self) -> None:
|
||||
self.calls = 0
|
||||
|
||||
def is_context_overflow_error(self, error: Exception) -> bool:
|
||||
return "prompt too long" in str(error).lower()
|
||||
|
||||
async def simple_chat(self, prompt: str, system: str | None = None, task_type: str | None = None) -> str:
|
||||
_ = (system, task_type)
|
||||
self.calls += 1
|
||||
if len(prompt) > 4500:
|
||||
raise RuntimeError("prompt too long")
|
||||
payload = json.loads(prompt)
|
||||
messages = list(payload.get("messages", []) or [])
|
||||
return json.dumps(
|
||||
{
|
||||
"history_summary": f"single-message summarized {len(messages)} messages",
|
||||
"memory_summary": "## Primary Goal\n- Continue safely.",
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
|
||||
|
||||
class HistoryCompactorRetryTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_simple_chat_retry_truncates_messages_after_overflow(self) -> None:
|
||||
llm = _OverflowLLM()
|
||||
compactor = HistoryCompactor(
|
||||
llm=llm,
|
||||
store=object(),
|
||||
memory_manager=object(),
|
||||
)
|
||||
result = await compactor._summarize_session(
|
||||
project_id="proj1",
|
||||
session_id="sess1",
|
||||
messages=[
|
||||
{"role": "user", "content": "a"},
|
||||
{"role": "assistant", "content": "b"},
|
||||
{"role": "user", "content": "c"},
|
||||
{"role": "assistant", "content": "d"},
|
||||
{"role": "user", "content": "e"},
|
||||
],
|
||||
existing_memory="",
|
||||
existing_summary="",
|
||||
)
|
||||
|
||||
self.assertEqual(llm.calls, 2)
|
||||
self.assertIn("summarized", result["history_summary"])
|
||||
self.assertIn("Primary Goal", result["memory_summary"])
|
||||
|
||||
async def test_simple_chat_retry_truncates_single_huge_message_content(self) -> None:
|
||||
llm = _SingleMessageOverflowLLM()
|
||||
compactor = HistoryCompactor(
|
||||
llm=llm,
|
||||
store=object(),
|
||||
memory_manager=object(),
|
||||
)
|
||||
result = await compactor._summarize_session(
|
||||
project_id="proj1",
|
||||
session_id="sess1",
|
||||
messages=[
|
||||
{"role": "assistant", "content": "x" * 5000},
|
||||
],
|
||||
existing_memory="",
|
||||
existing_summary="",
|
||||
)
|
||||
|
||||
self.assertGreaterEqual(llm.calls, 2)
|
||||
self.assertIn("single-message summarized", result["history_summary"])
|
||||
Reference in New Issue
Block a user