Files
ZNJJ-api-server/test/agent/test_history_window.py
T
Eric Wang b8008da959 feat(config): configurable conversation history window (B3)
FastGPT maintains full history server-side; LangGraph truncated the
injected history at a hardcoded 50 messages, so long conversations
behaved differently across backends.

- Config.AGENT_HISTORY_MESSAGES (env): max messages injected into the
  model prompt (recent N, both roles counted); default 50 unchanged;
  larger values support long conversations; 0 = no truncation, matching
  FastGPT's full-history semantics. Only the injected window is
  affected - dialogue stays fully persisted in the checkpoint.
- validate(): rejects negative values; 0 and positive accepted
- conversation_history reads the config (import-time class attribute,
  monkeypatched in tests); explicit None-check keeps 0 falsy-safe
- .env.example documents the knob

Verified: 225 unit tests (6 new history-window tests)
2026-10-22 23:01:40 +08:00

63 lines
2.2 KiB
Python

"""对话历史窗口配置测试(B3):env 可调最大注入条数,0 = 不截断。
对照 FastGPT:服务端全量维护历史、客户端只发单条消息;
LangGraph 侧历史注入曾硬编码截断 50 条,超长会话两端行为不对称。
现由 Config.AGENT_HISTORY_MESSAGES 控制(默认 50 不变)。
"""
import pytest
from src.agent.collect import conversation_history
from src.core.config import Config
def _dialogue(n: int) -> dict:
return {"dialogue": [
{"role": "user", "content": f"第{i}条"} for i in range(n)
]}
def test_default_window_keeps_last_50(monkeypatch):
"""缺省 50:与工作流 chatNode history 配置一致(现状不变)。"""
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 50)
history = conversation_history(_dialogue(60))
assert len(history) == 50
assert history[0]["content"] == "第10条"
def test_large_window_supports_long_dialogues(monkeypatch):
"""调大窗口:长对话注入更多历史(B3 目标)。"""
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 500)
history = conversation_history(_dialogue(120))
assert len(history) == 120
def test_zero_window_disables_truncation(monkeypatch):
"""0 = 不截断:对齐 FastGPT 全量历史语义。"""
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 0)
history = conversation_history(_dialogue(300))
assert len(history) == 300
assert history[0]["content"] == "第0条"
def test_history_does_not_mutate_state(monkeypatch):
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 2)
state = _dialogue(10)
conversation_history(state)
assert len(state["dialogue"]) == 10 # 原文不动,截断只发生在拷贝
def test_validate_rejects_negative_window(monkeypatch):
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", -1)
with pytest.raises(ValueError, match="AGENT_HISTORY_MESSAGES"):
Config.validate()
def test_validate_accepts_zero_and_positive(monkeypatch):
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 0)
monkeypatch.setattr(Config, "AGENT_BACKEND", "langgraph")
monkeypatch.setattr(Config, "LLM_PROVIDER", "fake")
Config.validate()
monkeypatch.setattr(Config, "AGENT_HISTORY_MESSAGES", 10)
Config.validate()