from typing import Dict from agent_system.base import BaseAgent from agent_system.monitor.prompt import MonitorPrompt from agent_system.monitor.response_model import MonitorResult class Monitor(BaseAgent): """ Monitor智能体 根据具体任务提供专门的评分标准,实现分诊阶段和病史收集阶段的精准评估 """ def __init__(self, model_type: str = "gpt-oss:latest", llm_config: dict = {}): super().__init__( model_type=model_type, description=MonitorPrompt.description, instructions=MonitorPrompt.instructions, response_model=MonitorResult, llm_config=llm_config, structured_outputs=True, markdown=False, use_cache=False ) def run(self, hpi_content: str, ph_content: str, chief_complaint: str, task_name: str = None, task_description: str = None, triage_result: dict = None) -> MonitorResult: """ 监控病史质量 Args: hpi_content: 现病史内容 ph_content: 既往史内容 chief_complaint: 主诉 task_name: 任务名称(可选,用于针对性评估) task_description: 任务描述(可选,用于针对性评估) triage_result: 分诊结果(可选,仅在分诊阶段使用) Returns: MonitorResult: 包含完成度评分和评分理由 """ if task_name and task_description: prompt = self._build_task_specific_prompt(task_name, task_description, hpi_content, ph_content, chief_complaint, triage_result) else: prompt = self.build_prompt(hpi_content, ph_content, chief_complaint, triage_result) # 调用LLM进行评估 result = super().run(prompt) # 确保返回正确的类型 if isinstance(result, MonitorResult): return result elif isinstance(result, dict): return MonitorResult(**result) else: return MonitorResult( completion_score=0.0, reason="监控评估失败:无法解析LLM响应" ) def build_prompt(self, hpi_content: str, ph_content: str, chief_complaint: str, triage_result: dict = None) -> str: """ 构建整体病史质量评估的提示语 Args: hpi_content: 现病史内容 ph_content: 既往史内容 chief_complaint: 主诉 triage_result: 分诊结果(可选) Returns: str: 构建好的提示语 """ task_name = "整体病史质量评估" task_description = "综合评估现病史、既往史和主诉的信息完整性" return self._build_task_specific_prompt( task_name, task_description, hpi_content, ph_content, chief_complaint, triage_result ) def _build_task_specific_prompt(self, task_name: str, task_description: str, hpi_content: str, ph_content: str, chief_complaint: str, triage_result: dict = None) -> str: """ 构建针对特定任务的评估提示语,每个子任务有专门的评分标准 Args: task_name: 任务名称 task_description: 任务描述 hpi_content: 现病史内容 ph_content: 既往史内容 chief_complaint: 主诉 triage_result: 分诊结果(可选) Returns: str: 构建好的任务特定评估提示语 """ # 获取任务特定的评分标准 scoring_criteria = self._get_task_scoring_criteria(task_name, triage_result) # 构建分诊信息(仅在分诊阶段使用) triage_info = "" if task_name in ["一级科室判定", "二级科室判定"] and triage_result: primary_dept = triage_result.get("primary_department", "") secondary_dept = triage_result.get("secondary_department", "") triage_info = f""" **分诊结果参考**: 一级科室:{primary_dept} 二级科室:{secondary_dept} **评估重点**: 基于上述分诊结果,评估当前病史信息对科室选择的支持程度。""" prompt = f"""请对以下病史信息进行质量监控和评估: **评估目标任务**: 任务名称:{task_name} 任务描述:{task_description} {triage_info} **当前病史信息**: 主诉:{chief_complaint} **现病史**: {hpi_content} **既往史**: {ph_content} **评估要求**: 1. **专门针对任务"{task_name}"进行评估** 2. 根据任务描述"{task_description}",判断当前病史信息在这个方面的完整性 3. 重点关注与该任务相关的信息是否充分收集 4. 基于临床实际价值进行评估,否定性回答(如"无""未发生""不记得")具有同等重要的临床意义 5. 考虑记忆限制的合理性,对时间久远或非关键细节接受模糊回答 6. 避免过度询问,当患者明确表示无相关情况时不应继续追问 7. 给出该任务的完成度评分(0.0-1.0范围) 8. 详细说明评分理由,解释信息缺失是否影响诊疗决策 {scoring_criteria} **临床考量要点**: - 否定性回答(如"无既往病史""无过敏史")是重要的临床信息 - 对于时间久远的事件记不清属正常现象 - 非关键性细节(如具体药物商品名)的模糊回答不影响评分 - 重点关注与当前病情密切相关的信息 **输出格式**: 严格按照以下JSON格式输出: {{ "completion_score": 浮点数(0.0-1.0), "reason": "详细评分理由,需具体说明:1)哪些信息具有临床价值(包括否定性回答);2)哪些缺失或模糊是可接受的;3)哪些缺陷可能影响诊疗决策" }} 请基于上述要求进行客观评估。""" return prompt def _get_task_scoring_criteria(self, task_name: str, triage_result: dict = None) -> str: """ 获取每个子任务专门的评分标准 Args: task_name: 任务名称 triage_result: 分诊结果(用于分诊阶段) Returns: str: 该任务的专门评分标准 """ # 分诊阶段评分标准 if task_name == "一级科室判定": return """**一级科室分类评分标准**: - 0.9-1.0:症状明确指向某一级科室,病史信息充分支持科室选择 - 0.8-0.9:症状与科室匹配度较高,病史信息基本完整,接受"可能属于某科室"等模糊判断 - 0.65-0.79:科室选择基本合理,但信息支持度一般,询问不够全面 - 0.5-0.65:科室选择勉强合理,病史信息明显不足,缺少关键信息 - 0.0-0.5:科室选择不合理或与症状描述不符,未进行基本分诊判断""" elif task_name == "二级科室判定": return """**二级科室分类评分标准**: - 0.9-1.0:在一级科室基础上,症状明确指向具体二级科室,信息充分 - 0.8-0.9:二级科室选择合理,症状支持度高,信息较完整,接受"可能属于某二级科室"等模糊判断 - 0.65-0.79:二级科室选择基本合理,但信息支持度有限,询问不够全面 - 0.5-0.65:二级科室选择存疑,信息支持不足,缺少关键分诊信息 - 0.0-0.5:二级科室选择不合理或与症状不符,未进行基本二级分诊判断""" # 现病史阶段评分标准 elif task_name == "发病情况": return """**发病情况评估标准**(重要:否定性诱因回答同样有效): - 0.85-1.0:发病时间和方式已询问,接受"突然起病""逐渐加重""无明确诱因"等回答,包括"无明显诱因""记不清具体时间"等回答视为完整 - 0.7-0.85:发病时间或方式已询问,但部分细节询问不够明确 - 0.6-0.69:发病基本情况已获取,但询问不够全面 - 0.5-0.59:缺少发病时间和方式的询问 - 0.0-0.49:发病情况询问严重缺失,未进行基本询问 **重要原则**: - "无明显诱因""记不清具体发病时间"等回答视为有效临床信息 - 对久远事件的时间模糊回答不影响高分评价 - 重点关注发病模式是否符合当前疾病特征""" elif task_name == "主要症状特征": return """**主要症状特征评估标准**(重要:否定性症状描述同样有效): - 0.85-1.0:主要症状特征已询问,接受"疼痛程度记不清""无特殊缓解方法"等回答,包括"记不清具体部位""无明显缓解因素"等回答视为完整 - 0.7-0.85:症状基本特征已获取,但部分特征询问不够明确 - 0.6-0.69:症状特征询问已进行,但不够全面 - 0.5-0.59:缺少症状关键特征的询问 - 0.0-0.49:症状特征询问严重缺失,未进行基本询问 **重要原则**: - "记不清具体部位""无法描述疼痛性质""无明显缓解因素"等回答视为有效临床信息 - 对症状细节记忆模糊的回答给予理解,不影响高分评价 - 重点关注症状是否符合当前疾病特征,而非描述的精确程度""" elif task_name == "病情发展与演变": return """**病情发展与演变评估标准**(重要:时间模糊但趋势清晰同样有效): - 0.9-1.0:病情演变过程按时间顺序描述,变化趋势清晰,"逐渐加重""时好时坏"等描述视为完整 - 0.8-0.89:病情发展趋势明确,接受"记不清具体时间""大概几周前开始加重"等模糊时间描述 - 0.7-0.79:病情变化基本脉络清晰,但部分时间点或变化细节略有缺失 - 0.6-0.69:病情发展大致过程可辨,时间顺序不够精确但趋势明确 - 0.5-0.59:病情变化描述不够系统,缺乏清晰的时间概念 - 0.0-0.49:病情发展信息严重缺失,无法了解疾病演变过程 **重要原则**: - "记不清具体时间""大概几个月前"等时间模糊回答视为有效临床信息 - "逐渐加重""突然恶化""时轻时重"等趋势描述具有重要临床价值 - 对久远事件具体时间记不清属正常现象,不影响高分评价 - 重点关注病情变化趋势和规律,而非时间节点的精确性 - 慢性病程中的波动情况(如"反复发作""间歇性加重")视为重要信息""" elif task_name == "伴随症状": return """**伴随症状评估标准**(重要:"无伴随症状"同样具有临床价值): - 0.9-1.0:伴随症状已询问,包括"无其他不适""无相关症状"等否定性回答视为完整 - 0.8-0.89:主要伴随症状已询问,接受"记不清是否有其他症状""好像没有其他不适"等回答 - 0.7-0.79:伴随症状基本询问已进行,但部分相关症状询问不够明确 - 0.6-0.69:伴随症状询问已进行,但不够全面 - 0.5-0.59:缺少伴随症状的询问 - 0.0-0.49:伴随症状询问严重缺失,未进行基本询问 **重要原则**: - "无其他症状""无伴随不适""未发现其他异常"等否定性回答视为有效完整信息 - "记不清是否有其他症状""不太确定"等模糊回答给予理解,不影响高分评价 - 重点关注与主要疾病相关的典型伴随症状,而非所有可能的症状 - 系统性疾病相关的全身症状(如发热、乏力等)询问视为重要内容""" elif task_name == "诊疗经过": return """**诊疗经过评估标准**(重要:"未就诊""未治疗"同样具有临床价值): - 0.9-1.0:诊疗过程已询问,包括"未就诊""未治疗""自行缓解"等否定性回答视为完整 - 0.8-0.89:诊疗经过已询问,接受"记不清具体药物""治疗效果一般"等模糊描述 - 0.7-0.79:诊疗基本信息已获取,但部分检查或治疗细节略有缺失 - 0.6-0.69:诊疗经过基本具备,但效果描述或具体措施不够详细 - 0.5-0.59:诊疗经过信息不完整,缺乏关键诊疗信息 - 0.0-0.49:诊疗经过严重缺失,未进行基本询问 **重要原则**: - "未就诊""未治疗""未用药"等否定性回答视为有效完整信息 - "记不清药名""记不清检查项目"等记忆模糊回答给予理解 - 重点关注诊疗措施与当前病情的相关性,而非详细的治疗记录 - 自行用药、民间疗法等信息的收集视为有价值的临床信息""" elif task_name == "一般情况": return """**一般情况评估标准**(重要:否定性回答具有同等临床价值): - 0.85-1.0:精神状态、睡眠、食欲、大小便、体重已询问,无论肯定或否定回答均视为完整 - 0.7-0.85:已询问主要生活状况,接受"无异常""正常""记不清"等回答,基本满足诊疗需求 - 0.6-0.69:基本生活状况信息已获取,但询问不够全面 - 0.5-0.59:缺少部分重要生活状况的询问 - 0.0-0.49:关键生活状况信息严重缺失,未进行基本询问 **重要原则**: - "精神状态正常""睡眠尚可""食欲正常""大小便正常""体重无明显变化"等否定性回答视为有效信息 - 对记不清具体时间或细节的回答给予理解,不影响高分评价 - 重点关注是否存在影响诊疗的异常情况,而非描述的详细程度""" # 既往史阶段评分标准 elif task_name == "疾病史": return """**疾病史评估标准**: - 0.9-1.0:既往疾病史已询问,包括"无慢性疾病史""否认高血压糖尿病"等否定性回答视为完整有效 - 0.8-0.89:主要疾病史已询问,接受"既往体健""无重大疾病"等回答,满足诊疗需求 - 0.7-0.79:基本疾病史信息已获取,但部分重要疾病询问不够明确 - 0.6-0.69:疾病史基本询问已进行,但不够全面 - 0.5-0.59:缺少部分重要疾病史的询问 - 0.0-0.49:疾病史询问严重缺失,未进行基本询问 **重要原则**: - "既往体健""无慢性疾病史""否认传染病史"等否定性回答视为有效完整信息 - 对记不清具体疾病名称或时间的回答给予理解 - 重点关注是否存在影响当前诊疗的重要既往疾病,而非病史的详细程度""" elif task_name == "预防接种史": return """**预防接种史评估标准**: - 0.9-1.0:疫苗接种史已询问,包括"疫苗接种随当地""无特殊疫苗接种史"等否定性回答视为完整 - 0.8-0.89:疫苗接种史已询问,接受"按常规接种""无特殊要求"等回答,满足诊疗需求 - 0.7-0.79:疫苗接种史基本询问已进行,但部分重要疫苗询问不够明确 - 0.6-0.69:疫苗接种史询问已进行,但不够全面 - 0.5-0.59:缺少疫苗接种史的询问 - 0.0-0.49:疫苗接种史询问严重缺失,未进行基本询问 **重要原则**: - "预防接种随当地""按常规接种""无特殊疫苗接种史"等回答视为有效完整信息 - 对记不清具体疫苗名称或接种时间的回答给予理解 - 重点关注是否存在影响当前诊疗的特殊疫苗接种情况""" elif task_name == "手术外伤史": return """**手术外伤史评估标准**: - 0.9-1.0:手术外伤史已询问,包括"无手术史""无重大外伤史""否认手术外伤史"等否定性回答视为完整 - 0.8-0.89:手术外伤史已询问,接受"无相关手术""无重大外伤"等回答,满足诊疗需求 - 0.7-0.79:手术外伤史已询问,但回答不够明确 - 0.6-0.69:手术外伤史询问已进行,但不够全面 - 0.5-0.59:缺少手术外伤史的询问 - 0.0-0.49:手术外伤史询问严重缺失,未进行基本询问 **重要原则**: - "无手术史""无外伤史""否认手术外伤史"等否定性回答视为有效完整信息 - 对记不清具体手术时间或细节的回答给予理解 - 重点关注是否存在影响当前诊疗的手术外伤史""" elif task_name == "输血史": return """**输血史评估标准**: - 0.9-1.0:输血史已询问,包括"无输血史""否认输血史""无相关输血"等否定性回答视为完整 - 0.8-0.89:输血史已询问,接受"无输血需求""未接受过输血"等回答,满足诊疗需求 - 0.7-0.79:输血史已询问,但回答不够明确 - 0.6-0.69:输血史询问已进行,但不够全面 - 0.5-0.59:缺少输血史的询问 - 0.0-0.49:输血史询问严重缺失,未进行基本询问 **重要原则**: - "无输血史""否认输血史""未接受过输血"等否定性回答视为有效完整信息 - 对记不清具体输血时间或细节的回答给予理解 - 重点关注是否存在影响当前诊疗的输血史""" elif task_name == "过敏史": return """**过敏史评估标准**: - 0.9-1.0:过敏史已询问,包括"无过敏史""否认过敏史""无药物食物过敏"等否定性回答视为完整 - 0.8-0.89:过敏史已询问,接受"无过敏""未发现过敏"等回答,满足诊疗需求 - 0.7-0.79:过敏史基本询问已进行,但不够明确 - 0.6-0.69:过敏史询问已进行,但不够全面 - 0.5-0.59:缺少过敏史的询问 - 0.0-0.49:过敏史询问严重缺失,未进行基本询问 **重要原则**: - "无过敏史""否认过敏史""无药物过敏"等否定性回答视为有效完整信息 - 对记不清具体过敏源或反应的回答给予理解 - 重点关注是否存在影响当前诊疗的过敏史""" else: # 默认评分标准 return """**通用评分标准**(病史阶段专用,强调否定性回答价值): - 0.9-1.0:相关病史信息已询问,包括"无异常""未发生""记不清"等否定性回答视为完整有效 - 0.8-0.89:重要病史信息已询问,接受"无相关""正常""无特殊"等回答,满足诊疗需求 - 0.7-0.79:关键病史信息已询问,但部分询问不够明确 - 0.6-0.69:基本病史信息已获取,但询问不够全面 - 0.5-0.59:缺少重要病史信息的询问 - 0.0-0.49:病史询问严重缺失,未进行基本询问 **重要原则**: - 所有否定性回答("无""未发生""否认""正常")均视为有效完整的临床信息 - 对时间久远或非关键细节的记忆模糊回答给予充分理解 - 重点关注是否存在影响诊疗的异常情况,而非信息描述的详细程度""",