Files
ZNJJ-api-server/test/backends/test_langgraph_backend.py
T
Eric Wang 5d68b731d4 feat(backends): wire LangGraph backend behind AGENT_BACKEND switch (assignment 2)
- src/backends/langgraph.py: LangGraphBackend implements ChatBackend;
  complete() runs one graph turn per session (thread_id=sessionId) and
  returns state-prefixed content; stream() emits the full state prefix
  before body fragments (full-answer slicing, not yet real incremental
  output - assignment 8)
- src/core/config.py: AGENT_BACKEND=fastgpt|langgraph, langgraph mode
  no longer requires FastGPT credentials at startup
- src/core/fastgpt_client.py: lifespan builds the backend by switch
- test/backends/test_langgraph_backend.py: adapter acceptance tests

Verified:
- pytest: 48 passed
- AGENT_BACKEND=langgraph uvicorn: POST /chat -> 1002;
  browser_addon -> browser_addon.1002; SSE = stage_code, text_delta,
  single done

Known limit: stream slices a complete answer; no formUpdate deltas yet
(assignment 6).
2026-10-19 14:29:31 +08:00

63 lines
2.0 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.
"""作业 2 验收测试:LangGraph 后端适配器。
通过标准(对应迁移计划作业 2):
- ``complete()`` 返回带 ``<state>1002</state>`` 前缀的 ``ChatResult``,
API 层据此解析阶段码;
- ``stream()`` 先产出含完整 state 前缀的 ``TextDelta``,再产出正文,
保证 ``stage_code`` 事件先于正文;
- 会话通过 ``thread_id = session_id`` 绑定(图 checkpoint 语义)。
注意:``src/backends/langgraph.py`` 中的 TODO 完成前,
本文件的测试会失败,属于预期状态。
"""
import pytest
from src.backends.chat import ChatInput, TextDelta
from src.backends.langgraph import LangGraphBackend
def make_input() -> ChatInput:
return ChatInput(
session_id="session-001",
text="发生了交通事故",
client_mode="direct",
)
@pytest.mark.asyncio
async def test_complete_returns_state_prefixed_result() -> None:
backend = LangGraphBackend()
result = await backend.complete(make_input())
assert result.content.startswith("<state>1002</state>")
assert "发生了交通事故" in result.content
@pytest.mark.asyncio
async def test_stream_emits_prefix_before_body() -> None:
backend = LangGraphBackend()
events = [event async for event in backend.stream(make_input())]
assert events, "stream 至少应产生一个 TextDelta"
assert all(isinstance(event, TextDelta) for event in events)
joined = "".join(event.text for event in events)
assert joined.startswith("<state>1002</state>")
assert "发生了交通事故" in joined
@pytest.mark.asyncio
async def test_sessions_are_isolated_by_thread_id() -> None:
backend = LangGraphBackend()
first = await backend.complete(make_input())
second = await backend.complete(make_input())
other = await backend.complete(
ChatInput(session_id="session-002", text="你好", client_mode="direct")
)
assert first.content != "" and second.content != ""
assert "你好" in other.content