import sys import os from pathlib import Path os.environ.setdefault("DATABASE_URL", "sqlite:///./storage/test_core.db") os.environ.setdefault("RUNTIME_MEMORY_BACKEND", "memory") os.environ.setdefault("LLM_MOCK_ENABLED", "true") sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from app.agents.scoring_agent import ScoringAgent from app.agents.hint_agent import HintAgent from app.agents.llm_adapter import OpenAICompatibleLLMClient from app.agents.patient_agent import PatientAgent from app.core.config import settings from app.services.runtime_memory import InMemoryRuntimeMemoryService def test_runtime_memory_lifecycle() -> None: """短期 memory:验证创建、写入、读取和释放流程。""" memory = InMemoryRuntimeMemoryService() memory.create("test-memory", "开场白") memory.add_message("test-memory", "doctor", "孩子发热几天?") assert memory.has_doctor_message("test-memory") is True assert len(memory.get_messages("test-memory")) == 2 memory.release("test-memory") assert memory.get_messages("test-memory") == [] def test_score_convert_to_five_point() -> None: """评分转换:验证百分制到五分制的结构转换。""" agent = ScoringAgent() result = agent._convert_to_five_point( { "score_type": "percentage", "total_score": 80, "dimension_scores": [{"dimension": "信息获取", "score": 20, "max_score": 25, "comment": "ok"}], } ) assert result["score_type"] == "five_point" assert result["total_score"] == 4.0 assert result["dimension_scores"][0]["max_score"] == 5 def test_public_settings() -> None: """配置输出:验证 Demo 前端可读取功能开关。""" public = settings.as_public_dict() assert "score_types" in public assert "percentage" in public["score_types"] def test_reasoning_effort_disabled_when_thinking_off() -> None: """LLM 参数构造:thinking 关闭时不发送 reasoning_effort,避免 reason 测试流式 400。""" client = OpenAICompatibleLLMClient() payload = client._build_payload( model="deepseek-v4-pro", messages=[{"role": "user", "content": "hello"}], stream=True, thinking_enabled=False, reasoning_effort="low", max_tokens=128, ) assert "reasoning_effort" not in payload def test_hint_agent_invalid_json_fallback() -> None: """新手提示:验证模型输出结构不匹配时使用稳定 fallback。""" agent = HintAgent() payload = { "case": { "chief_complaint": "发热、咳嗽4天,喘息1天", "key_exams": ["blood_routine", "chest_xray"], }, "ordered_results": [], } result = agent._normalize_output({"score_type": "percentage"}, payload) assert result["hints"] assert result["next_questions"] assert result["recommended_orders"] def test_patient_agent_config_rule_boundary() -> None: """病人配置提示:验证训练页初始化配置进入 Patient Agent 且不改变病例事实边界。""" agent = PatientAgent() rule = agent._build_patient_config_rule( { "labels": { "visit_environment": "急诊", "age_group": "儿童", "education_level": "小学及以下", "personality": "焦虑", } } ) assert "就诊环境=急诊" in rule assert "以家属代述为主" in rule assert "不能改变病例事实" in rule assert "不能编造检查检验结果" in rule if __name__ == "__main__": test_runtime_memory_lifecycle() test_score_convert_to_five_point() test_public_settings() test_reasoning_effort_disabled_when_thinking_off() test_hint_agent_invalid_json_fallback() test_patient_agent_config_rule_boundary() print("core logic tests passed")