Files
meida_backend/tests/unit/test_agent_context.py
T
xsl 7bcbb8d40b
CI / lint / typecheck / import-linter / tests / secrets (push) Canceled after 0s
feat(agent,report): 会话持久化与画像注入、报告反馈与预约留资——PM/开发双Agent迭代1-3
- 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 验证
  画像注入与历史携带
2026-09-11 21:50:58 +08:00

68 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""上下文组装(架构 §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