CI / lint / typecheck / import-linter / tests / secrets (push) Canceled after 0s
- agent: ag_conversation/ag_message 表(迁移0007),上下文组装注入最近报告画像摘要 (report.profile.latest_profile_summary 经 apps 层闭包注入,同层不互调),历史带最近 AGENT_HISTORY_TURNS=10 轮;POST/GET /agent/conversations 与消息历史接口 - agent 修复:ChatRequest.conversation_id 改 str(雪花ID超2^53,JS Number丢精度); _build_context 挪进 reserve commit 后同一 try,异常走 refund 兜底 - report: rp_feedback(维度反馈 upsert,认同率/修正率 SQL 可算,T-P3-21 最小版—— L1 记忆未建,不回写结论)+ rp_reservation(预约留资幂等,T-P3-22,预约率口径 行数/full_report.card_view 去重曝光,门槛≥8%),迁移0008 - 测试:全量 606 passed;ruff/mypy/lint-imports 全绿;E2E 真实 deepseek-v4-flash 验证 画像注入与历史携带
68 lines
2.9 KiB
Python
68 lines
2.9 KiB
Python
"""上下文组装(架构 §7.2 步骤③)的纯逻辑测试:画像注入与历史截尾。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from packages.agent.context import (
|
||
PROFILE_SUMMARY_MAX_CHARS,
|
||
build_context_messages,
|
||
build_profile_message,
|
||
)
|
||
from packages.llm.types import Message
|
||
|
||
|
||
class TestBuildContextMessages:
|
||
def test_profile_first_then_history(self) -> None:
|
||
history = [
|
||
Message(role="user", content="第一句"),
|
||
Message(role="assistant", content="第一答"),
|
||
]
|
||
messages = build_context_messages(
|
||
profile_summary='{"dimensions":[]}', history=history, history_turns=10
|
||
)
|
||
assert len(messages) == 3
|
||
assert messages[0].role == "system"
|
||
assert '{"dimensions":[]}' in messages[0].content
|
||
assert [m.role for m in messages[1:]] == ["user", "assistant"]
|
||
assert [m.content for m in messages[1:]] == ["第一句", "第一答"]
|
||
|
||
def test_no_profile_degrades_to_history_only(self) -> None:
|
||
"""无画像用户(FR-AGT-10 降级):不注入画像消息,历史照常携带。"""
|
||
history = [Message(role="user", content="hi")]
|
||
messages = build_context_messages(profile_summary=None, history=history, history_turns=10)
|
||
assert len(messages) == 1
|
||
assert messages[0].role == "user"
|
||
|
||
def test_empty_profile_string_treated_as_absent(self) -> None:
|
||
messages = build_context_messages(profile_summary="", history=[], history_turns=10)
|
||
assert messages == []
|
||
|
||
def test_history_tail_kept_by_turns(self) -> None:
|
||
"""一轮 = user+assistant 两条;N=2 时只留最近 4 条,截头不截尾。"""
|
||
history: list[Message] = []
|
||
for i in range(5):
|
||
history.append(Message(role="user", content=f"u{i}"))
|
||
history.append(Message(role="assistant", content=f"a{i}"))
|
||
messages = build_context_messages(profile_summary=None, history=history, history_turns=2)
|
||
assert [m.content for m in messages] == ["u3", "a3", "u4", "a4"]
|
||
|
||
def test_zero_turns_drops_history(self) -> None:
|
||
history = [Message(role="user", content="u0")]
|
||
messages = build_context_messages(profile_summary=None, history=history, history_turns=0)
|
||
assert messages == []
|
||
|
||
def test_history_message_content_capped(self) -> None:
|
||
history = [Message(role="user", content="x" * 5000)]
|
||
messages = build_context_messages(profile_summary=None, history=history, history_turns=10)
|
||
assert len(messages[0].content) == 2000
|
||
|
||
|
||
class TestBuildProfileMessage:
|
||
def test_wraps_summary_as_system_message(self) -> None:
|
||
message = build_profile_message("{}")
|
||
assert message.role == "system"
|
||
assert message.content.endswith("{}")
|
||
|
||
def test_budget_constant_within_token_budget(self) -> None:
|
||
"""画像摘要预算 ≤ 500 token(README 预算表),按 ~1.6 字符/token 折算。"""
|
||
assert PROFILE_SUMMARY_MAX_CHARS <= 500 * 1.6
|