新增:添加Triager科室分诊智能体模块
- 实现TriageAgent智能体,支持根据现病史、既往史和主诉进行科室分诊 - 添加TriageResult响应模型,包含一级科室、二级科室、信心度和推理过程 - 创建TriagerPrompt提示词模板,包含完整的科室体系和分诊逻辑 - 支持13个一级科室和对应的二级科室精确匹配 - 通过测试验证,能够准确分诊心血管、儿科、脊柱外科等不同类型疾病 - 提供便捷接口支持仅主诉分诊和信心度评价功能 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e24b161e54
commit
f47d56051b
4
agent_system/triager/__init__.py
Normal file
4
agent_system/triager/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .agent import TriageAgent
|
||||||
|
from .response_model import TriageResult
|
||||||
|
|
||||||
|
__all__ = ["TriageAgent", "TriageResult"]
|
||||||
183
agent_system/triager/agent.py
Normal file
183
agent_system/triager/agent.py
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
from typing import Any
|
||||||
|
from agent_system.base import BaseAgent
|
||||||
|
from agent_system.triager.prompt import TriagerPrompt
|
||||||
|
from agent_system.triager.response_model import TriageResult
|
||||||
|
|
||||||
|
|
||||||
|
class TriageAgent(BaseAgent):
|
||||||
|
"""
|
||||||
|
科室分诊智能体
|
||||||
|
|
||||||
|
根据患者的现病史、既往史和主诉,分析症状特点,
|
||||||
|
推荐最适合的一级科室和二级科室。
|
||||||
|
|
||||||
|
核心功能:
|
||||||
|
1. 分析患者症状涉及的主要器官系统
|
||||||
|
2. 匹配合适的一级科室和二级科室
|
||||||
|
3. 提供分诊信心度评估
|
||||||
|
4. 给出详细的分诊推理过程
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
model_type (str): 使用的大语言模型类型,默认为 gpt-oss:latest
|
||||||
|
llm_config (dict): LLM模型配置参数
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, model_type: str = "gpt-oss:latest", llm_config: dict = None):
|
||||||
|
"""
|
||||||
|
初始化科室分诊智能体
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model_type (str): 大语言模型类型,默认使用 gpt-oss:latest
|
||||||
|
llm_config (dict): LLM模型的配置参数,如果为None则使用默认配置
|
||||||
|
"""
|
||||||
|
super().__init__(
|
||||||
|
model_type=model_type,
|
||||||
|
description="根据患者病史信息进行科室分诊",
|
||||||
|
instructions=TriagerPrompt.instructions,
|
||||||
|
response_model=TriageResult,
|
||||||
|
llm_config=llm_config or {},
|
||||||
|
structured_outputs=True,
|
||||||
|
markdown=False,
|
||||||
|
use_cache=False
|
||||||
|
)
|
||||||
|
|
||||||
|
def run(self, chief_complaint: str, hpi_content: str = "", ph_content: str = "") -> TriageResult:
|
||||||
|
"""
|
||||||
|
执行科室分诊
|
||||||
|
|
||||||
|
基于患者的主诉、现病史和既往史信息,分析症状特点,
|
||||||
|
推荐最适合的一级科室和二级科室。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chief_complaint (str): 患者主诉,描述主要症状和不适
|
||||||
|
hpi_content (str, optional): 现病史内容,详细的症状发展过程,默认为空字符串
|
||||||
|
ph_content (str, optional): 既往史内容,患者的历史疾病信息,默认为空字符串
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TriageResult: 包含分诊结果的结构化数据,包括:
|
||||||
|
- primary_department: 推荐的一级科室
|
||||||
|
- secondary_department: 推荐的二级科室
|
||||||
|
- confidence_score: 分诊信心度评分(0-1之间)
|
||||||
|
- triage_reasoning: 分诊推理过程和建议理由
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
Exception: 当LLM调用失败时,返回包含默认分诊建议的TriageResult
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 构建分诊分析提示词
|
||||||
|
prompt = self.build_prompt(chief_complaint, hpi_content, ph_content)
|
||||||
|
|
||||||
|
# 调用基类的run方法执行LLM推理
|
||||||
|
result = super().run(prompt)
|
||||||
|
|
||||||
|
# 确保返回正确的类型并进行类型转换
|
||||||
|
return self._ensure_result_type(result)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
# 当分诊分析失败时记录错误并返回默认结果
|
||||||
|
print(f"科室分诊分析失败: {str(e)}")
|
||||||
|
return self._get_fallback_result()
|
||||||
|
|
||||||
|
def build_prompt(self, chief_complaint: str, hpi_content: str = "", ph_content: str = "") -> str:
|
||||||
|
"""
|
||||||
|
构建科室分诊的提示词模板
|
||||||
|
|
||||||
|
根据主诉、现病史和既往史内容,构建精简高效的分诊提示词,
|
||||||
|
引导LLM进行专业的科室分诊分析。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chief_complaint (str): 患者主诉
|
||||||
|
hpi_content (str): 现病史内容
|
||||||
|
ph_content (str): 既往史内容
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 精简的分诊分析提示词
|
||||||
|
"""
|
||||||
|
# 确保各项内容的合理显示
|
||||||
|
hpi_display = hpi_content.strip() if hpi_content.strip() else "暂无详细现病史"
|
||||||
|
ph_display = ph_content.strip() if ph_content.strip() else "暂无既往史信息"
|
||||||
|
|
||||||
|
# 从prompt类获取示例输出格式
|
||||||
|
example_output = TriagerPrompt.get_example_output()
|
||||||
|
|
||||||
|
prompt = f"""患者就诊信息:
|
||||||
|
主诉: {chief_complaint}
|
||||||
|
现病史: {hpi_display}
|
||||||
|
既往史: {ph_display}
|
||||||
|
|
||||||
|
请根据上述患者信息,分析症状特点,推荐最适合的一级科室和二级科室。
|
||||||
|
|
||||||
|
输出格式示例:
|
||||||
|
{example_output}
|
||||||
|
|
||||||
|
请严格按照上述JSON格式输出,确保一级科室和二级科室的对应关系正确。
|
||||||
|
输出内容为:"""
|
||||||
|
|
||||||
|
return prompt
|
||||||
|
|
||||||
|
def _ensure_result_type(self, result: Any) -> TriageResult:
|
||||||
|
"""
|
||||||
|
确保返回结果为正确的类型
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result (Any): LLM返回的原始结果
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TriageResult: 转换后的结构化结果
|
||||||
|
"""
|
||||||
|
if isinstance(result, TriageResult):
|
||||||
|
return result
|
||||||
|
elif isinstance(result, dict):
|
||||||
|
return TriageResult(**result)
|
||||||
|
else:
|
||||||
|
# 如果类型不匹配,返回默认结果
|
||||||
|
return self._get_fallback_result()
|
||||||
|
|
||||||
|
def _get_fallback_result(self) -> TriageResult:
|
||||||
|
"""
|
||||||
|
生成分诊失败时的默认结果
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TriageResult: 包含默认分诊建议的结果
|
||||||
|
"""
|
||||||
|
return TriageResult(
|
||||||
|
primary_department="全科",
|
||||||
|
secondary_department="全科(二级)",
|
||||||
|
confidence_score=0.3,
|
||||||
|
triage_reasoning="由于分诊分析过程中出现异常,系统推荐全科就诊。建议患者先到全科进行初步评估,医生会根据具体情况进一步转诊到合适的专科。"
|
||||||
|
)
|
||||||
|
|
||||||
|
def triage_by_chief_complaint(self, chief_complaint: str) -> TriageResult:
|
||||||
|
"""
|
||||||
|
仅基于患者主诉进行科室分诊的便捷接口
|
||||||
|
|
||||||
|
这是一个专门针对仅有主诉信息的分诊方法,
|
||||||
|
适用于患者初次就诊、信息较少的情况。
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chief_complaint (str): 患者的主要症状主诉
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
TriageResult: 基于主诉的分诊结果
|
||||||
|
"""
|
||||||
|
return self.run(chief_complaint=chief_complaint, hpi_content="", ph_content="")
|
||||||
|
|
||||||
|
def get_department_confidence(self, result: TriageResult) -> str:
|
||||||
|
"""
|
||||||
|
获取分诊信心度的描述性评价
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result (TriageResult): 分诊结果
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 信心度的描述性评价
|
||||||
|
"""
|
||||||
|
confidence = result.confidence_score
|
||||||
|
if confidence >= 0.8:
|
||||||
|
return "高度确信"
|
||||||
|
elif confidence >= 0.6:
|
||||||
|
return "较为确信"
|
||||||
|
elif confidence >= 0.4:
|
||||||
|
return "一般确信"
|
||||||
|
else:
|
||||||
|
return "建议进一步评估"
|
||||||
82
agent_system/triager/prompt.py
Normal file
82
agent_system/triager/prompt.py
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
from agent_system.base import BasePrompt
|
||||||
|
|
||||||
|
|
||||||
|
class TriagerPrompt(BasePrompt):
|
||||||
|
"""
|
||||||
|
科室分诊智能体的提示词模板
|
||||||
|
|
||||||
|
定义了分诊智能体的角色、任务目标和执行指令,
|
||||||
|
确保智能体能够根据患者的病史信息准确推荐就诊科室。
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 智能体角色和目标描述
|
||||||
|
description = (
|
||||||
|
"你是一名专业的医院分诊医师,擅长根据患者的现病史、既往史和主诉,"
|
||||||
|
"准确判断患者应该就诊的科室。你的主要任务是分析患者的症状特点和疾病表现,"
|
||||||
|
"结合医学专业知识,为患者推荐最合适的一级科室和二级科室。"
|
||||||
|
"你的分诊建议将直接影响患者的就医效率和诊疗质量。"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 执行指令和注意事项
|
||||||
|
instructions = [
|
||||||
|
"## 核心分诊任务",
|
||||||
|
"1. **症状系统分析**: 根据患者主诉和现病史,准确识别疾病涉及的主要器官系统",
|
||||||
|
"2. **科室匹配判断**: 结合症状特点,选择最适合的一级科室和对应的二级科室",
|
||||||
|
"3. **专业度评估**: 基于病情复杂程度和专业要求,确定最合适的专科科室",
|
||||||
|
"4. **信心度评价**: 对分诊决策的确信程度进行量化评估",
|
||||||
|
"",
|
||||||
|
"## 科室结构体系",
|
||||||
|
"### 一级科室列表:",
|
||||||
|
"内科、外科、儿科、妇产科、皮肤性病科、口腔科、眼科、肿瘤科、耳鼻咽喉科、康复科、精神科、全科、体检科",
|
||||||
|
"",
|
||||||
|
"### 二级科室详细对应关系:",
|
||||||
|
"- **内科**: 传染科, 免疫科, 内分泌科, 呼吸内科, 心血管内科, 感染科, 普通内科, 消化内科, 神经内科, 结核病科, 肝病科, 肾脏内科, 血液科, 过敏反应科, 风湿科",
|
||||||
|
"- **外科**: 乳腺外科, 关节骨科, 创伤骨科, 外伤科, 心胸外科, 心脏外科, 手外科, 整形科, 普外科, 泌尿外科, 烧伤科, 神经外科, 肛肠外科, 肝胆外科, 胃肠外科, 胰腺外科, 胸外科, 脊柱外科, 血管外科, 骨科",
|
||||||
|
"- **儿科**: 儿科综合, 小儿免疫科, 小儿内科, 小儿呼吸科, 小儿外科, 小儿感染科, 小儿泌尿科, 小儿神经内科, 小儿骨科, 新生儿科",
|
||||||
|
"- **妇产科**: 妇产科综合, 妇科, 妇科内分泌, 妇科肿瘤, 普通产科, 计划生育科, 高危产科",
|
||||||
|
"- **皮肤性病科**: 皮肤性病科综合, 皮肤科",
|
||||||
|
"- **口腔科**: 口腔修复科, 口腔科综合, 牙体牙髓科, 种植科, 颌面外科",
|
||||||
|
"- **眼科**: 白内障, 眼眶及肿瘤, 眼科综合, 青光眼",
|
||||||
|
"- **肿瘤科**: 放疗科, 肿瘤内科, 肿瘤外科, 肿瘤妇科, 肿瘤综合科",
|
||||||
|
"- **耳鼻咽喉科**: 耳鼻咽喉科(二级)",
|
||||||
|
"- **康复科**: 康复科(二级)",
|
||||||
|
"- **精神科**: 精神科(二级)",
|
||||||
|
"- **全科**: 全科(二级)",
|
||||||
|
"- **体检科**: 体检科(二级)",
|
||||||
|
"",
|
||||||
|
"## 分诊决策原则",
|
||||||
|
"1. **主诉优先**: 以患者的主要症状和主诉为首要分诊依据",
|
||||||
|
"2. **系统归属**: 根据症状涉及的主要器官系统选择对应科室",
|
||||||
|
"3. **专业程度**: 考虑病情的复杂程度和所需专业技术水平",
|
||||||
|
"4. **紧急程度**: 对于急症患者,优先推荐能快速处理的科室",
|
||||||
|
"5. **年龄特异性**: 特别关注儿童患者,优先考虑儿科",
|
||||||
|
"",
|
||||||
|
"## 输出要求和质量标准",
|
||||||
|
"1. **科室匹配**: 一级科室和二级科室必须严格对应上述科室体系",
|
||||||
|
"2. **推理清晰**: 分诊推理过程必须逻辑清楚,有理有据",
|
||||||
|
"3. **信心度合理**: 信心度评分应反映分诊决策的确信程度",
|
||||||
|
"4. **格式规范**: 严格按照 TriageResult 的 JSON 结构输出",
|
||||||
|
"",
|
||||||
|
"## 示例输出格式(JSON)",
|
||||||
|
"{",
|
||||||
|
" \"primary_department\": \"内科\",",
|
||||||
|
" \"secondary_department\": \"心血管内科\",",
|
||||||
|
" \"confidence_score\": 0.85,",
|
||||||
|
" \"triage_reasoning\": \"患者主诉胸闷、胸痛,伴有呼吸困难,症状提示心血管系统疾病。结合既往高血压病史,考虑冠心病可能性较大,建议心血管内科就诊进行进一步检查和治疗。\"",
|
||||||
|
"}"
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_example_output() -> str:
|
||||||
|
"""
|
||||||
|
获取示例输出格式,用于指导 LLM 生成符合要求的结构化输出
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: JSON 格式的示例输出
|
||||||
|
"""
|
||||||
|
return """{
|
||||||
|
"primary_department": "推荐的一级科室(必须从科室列表中选择)",
|
||||||
|
"secondary_department": "推荐的二级科室(必须是一级科室的下属科室)",
|
||||||
|
"confidence_score": 0.85,
|
||||||
|
"triage_reasoning": "详细的分诊推理过程,包括症状分析、科室选择依据和建议理由"
|
||||||
|
}"""
|
||||||
34
agent_system/triager/response_model.py
Normal file
34
agent_system/triager/response_model.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from typing import Literal
|
||||||
|
from pydantic import Field
|
||||||
|
from agent_system.base import BaseResponseModel
|
||||||
|
|
||||||
|
|
||||||
|
class TriageResult(BaseResponseModel):
|
||||||
|
"""
|
||||||
|
科室分诊结果模型
|
||||||
|
"""
|
||||||
|
primary_department: Literal[
|
||||||
|
"内科", "外科", "儿科", "妇产科", "皮肤性病科",
|
||||||
|
"口腔科", "眼科", "肿瘤科", "耳鼻咽喉科", "康复科",
|
||||||
|
"精神科", "全科", "体检科"
|
||||||
|
] = Field(
|
||||||
|
...,
|
||||||
|
description="一级科室,必须从指定的科室列表中选择"
|
||||||
|
)
|
||||||
|
|
||||||
|
secondary_department: str = Field(
|
||||||
|
...,
|
||||||
|
description="二级科室,必须是一级科室的下属科室"
|
||||||
|
)
|
||||||
|
|
||||||
|
confidence_score: float = Field(
|
||||||
|
...,
|
||||||
|
ge=0.0,
|
||||||
|
le=1.0,
|
||||||
|
description="分诊信心度评分(0-1之间)"
|
||||||
|
)
|
||||||
|
|
||||||
|
triage_reasoning: str = Field(
|
||||||
|
...,
|
||||||
|
description="分诊推理过程,解释为什么推荐该科室"
|
||||||
|
)
|
||||||
Loading…
x
Reference in New Issue
Block a user