Files
group_xinghuo_jinrong/tests/test_visitor_faq.py
T
zhanghongyu_0626 9d4d4aaa6d feat(chat): Enhance session management with new API endpoints and filtering options
- Added `status` query parameter to `list_sessions_api` for filtering sessions by their status (active/closed).
- Introduced `close_all_sessions_api` endpoint to allow users to close all active sessions for the current actor.
- Updated `SessionRepository` to support status filtering in session listing and implemented logic for closing active sessions.
- Improved Redis connection settings for better performance and reliability.

This update enhances the chat functionality by providing more control over session management, improving user experience and system efficiency.
2026-09-10 22:30:07 +08:00

94 lines
3.2 KiB
Python

"""游客 FAQ:开户类问题意图与 Redis/LLM 降级。"""
from __future__ import annotations
import app.service.visitor_service as vs
from app.model.schemas import AuthContext
from app.service.visitor_service import (
VisitorState,
generate,
intent_classify,
run_visitor_chat,
)
def _base_state(message: str) -> VisitorState:
return {
"session_id": "sess-faq",
"trace_id": "tr-faq",
"message": message,
"intent": "",
"chitchat_memory": [],
"consult_memory": [],
"rag_context": "",
"rag_sources": [],
"reply": "",
"has_disclaimer": False,
"transfer_to_human": False,
}
def test_open_account_intent_uses_faq_keyword_without_llm(monkeypatch):
"""LLM 不可用时,开户类问题仍应走 faq 分支(不依赖 DeepSeek 分类)。"""
monkeypatch.setattr(vs, "_build_llm", lambda: (_ for _ in ()).throw(RuntimeError("no llm")))
out = intent_classify(_base_state("开户需要哪些资料"))
assert out["intent"] == "faq"
def test_generate_uses_rag_when_llm_fails(monkeypatch):
"""有 RAG 上下文但 LLM 失败时,用知识片段降级回复,而非整段 fallback。"""
monkeypatch.setattr(vs, "_build_llm", lambda: (_ for _ in ()).throw(RuntimeError("no llm")))
monkeypatch.setattr(
vs.VisitorMemoryService,
"as_prompt_text",
lambda self, sid, kind: (_ for _ in ()).throw(ConnectionError("redis down")),
)
state = _base_state("开户需要哪些资料")
state["intent"] = "faq"
state["rag_context"] = (
"[来源: faq-open-account | 片段 1]\n"
"开户需要有效身份证件、本人银行卡,并完成实名认证与风险测评问卷。"
)
out = generate(state)
assert "身份证" in out["reply"]
assert "银行卡" in out["reply"]
assert "暂时无法回答" not in out["reply"]
def test_run_visitor_open_account_with_mocks(monkeypatch):
"""端到端:mock RAG + 降级生成,应回答开户材料要点。"""
class _FakeRag:
def retrieve(self, intent, query, top_k=5):
return (
"[来源: faq-open-account | 片段 1]\n"
"开户需要有效身份证件、本人银行卡,并完成实名认证与风险测评问卷。",
[{"source_doc": "faq-open-account"}],
)
monkeypatch.setattr(vs, "VisitorRagService", _FakeRag)
monkeypatch.setattr(vs, "_build_llm", lambda: (_ for _ in ()).throw(RuntimeError("no llm")))
monkeypatch.setattr(vs.VisitorMemoryService, "recall", lambda self, sid, kind: [])
monkeypatch.setattr(
vs.VisitorMemoryService,
"as_prompt_text",
lambda self, sid, kind: "",
)
monkeypatch.setattr(vs.VisitorMemoryService, "append", lambda self, *a, **k: None)
ctx = AuthContext(
sub="visitor",
token_type="visitor",
roles=[],
actor_id="visitor",
agent_type="visitor",
trace_id="t",
jti="jti-faq",
)
reply, _, intent, transfer = run_visitor_chat(ctx, "开户需要哪些资料", "e2e-faq")
assert intent == "faq"
assert not transfer
assert "身份证" in reply