Sync primary diagnosis from discharge table
This commit is contained in:
@@ -146,9 +146,6 @@ FIELD_GROUPS: list[dict[str, Any]] = [
|
|||||||
"fields": [
|
"fields": [
|
||||||
("outpatient_diagnosis", "门急诊诊断", "text", None),
|
("outpatient_diagnosis", "门急诊诊断", "text", None),
|
||||||
("outpatient_diagnosis_code", "门急诊诊断编码", "text", None),
|
("outpatient_diagnosis_code", "门急诊诊断编码", "text", None),
|
||||||
("primary_diagnosis", "主要诊断", "text", None),
|
|
||||||
("primary_diagnosis_code", "主要诊断编码", "text", None),
|
|
||||||
("primary_admission_condition", "主要诊断入院病情", "text", None),
|
|
||||||
("discharge_diagnoses", "出院诊断", "json", None),
|
("discharge_diagnoses", "出院诊断", "json", None),
|
||||||
("injury_poisoning_external_cause", "损伤中毒外部原因", "text", None),
|
("injury_poisoning_external_cause", "损伤中毒外部原因", "text", None),
|
||||||
("injury_poisoning_code", "损伤中毒疾病编码", "text", None),
|
("injury_poisoning_code", "损伤中毒疾病编码", "text", None),
|
||||||
@@ -385,9 +382,6 @@ AI_REDACT_PATTERNS = (
|
|||||||
AI_UPLOAD_FIELDS = [
|
AI_UPLOAD_FIELDS = [
|
||||||
"outpatient_diagnosis",
|
"outpatient_diagnosis",
|
||||||
"outpatient_diagnosis_code",
|
"outpatient_diagnosis_code",
|
||||||
"primary_diagnosis",
|
|
||||||
"primary_diagnosis_code",
|
|
||||||
"primary_admission_condition",
|
|
||||||
"discharge_diagnoses",
|
"discharge_diagnoses",
|
||||||
"operations",
|
"operations",
|
||||||
"pathology_diagnosis",
|
"pathology_diagnosis",
|
||||||
@@ -1808,6 +1802,35 @@ def json_changed_fields(field: str, old_value: Any, new_value: Any) -> list[dict
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main_diagnosis_row_index(rows: list[Any]) -> int:
|
||||||
|
for index, row in enumerate(rows):
|
||||||
|
if isinstance(row, dict) and str(row.get("诊断类别") or "").strip() == "主要诊断":
|
||||||
|
return index
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def main_diagnosis_from_discharge_diagnoses(value: Any) -> dict[str, str]:
|
||||||
|
rows = value if isinstance(value, list) else []
|
||||||
|
if not rows:
|
||||||
|
return {"primary_diagnosis": "", "primary_diagnosis_code": "", "primary_admission_condition": ""}
|
||||||
|
index = main_diagnosis_row_index(rows)
|
||||||
|
row = rows[index] if index < len(rows) and isinstance(rows[index], dict) else {}
|
||||||
|
return {
|
||||||
|
"primary_diagnosis": str(row.get("出院诊断") or row.get("诊断名称") or "").strip(),
|
||||||
|
"primary_diagnosis_code": str(row.get("疾病编码") or row.get("诊断编码") or "").strip(),
|
||||||
|
"primary_admission_condition": str(row.get("入院病情") or "").strip(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def sync_primary_diagnosis_updates(updates: dict[str, Any], before: dict[str, Any]) -> None:
|
||||||
|
if "discharge_diagnoses" not in updates:
|
||||||
|
return
|
||||||
|
derived = main_diagnosis_from_discharge_diagnoses(updates.get("discharge_diagnoses"))
|
||||||
|
for field, value in derived.items():
|
||||||
|
if comparable(before.get(field)) != comparable(value):
|
||||||
|
updates[field] = value
|
||||||
|
|
||||||
|
|
||||||
def build_record_updates(
|
def build_record_updates(
|
||||||
record_id: int,
|
record_id: int,
|
||||||
fields: dict[str, Any],
|
fields: dict[str, Any],
|
||||||
@@ -1838,6 +1861,8 @@ def build_record_updates(
|
|||||||
if "inpatient_no" in updates and not str(updates["inpatient_no"] or "").strip():
|
if "inpatient_no" in updates and not str(updates["inpatient_no"] or "").strip():
|
||||||
raise HTTPException(status_code=400, detail="患者号不能为空")
|
raise HTTPException(status_code=400, detail="患者号不能为空")
|
||||||
|
|
||||||
|
sync_primary_diagnosis_updates(updates, before)
|
||||||
|
|
||||||
manual_note = manual_note.strip()
|
manual_note = manual_note.strip()
|
||||||
if manual_note:
|
if manual_note:
|
||||||
current = before.get("review_notes") or []
|
current = before.get("review_notes") or []
|
||||||
@@ -2343,7 +2368,7 @@ def build_ai_prompt(record: dict[str, Any], pdf_context: dict[str, Any], privacy
|
|||||||
5. 只有仍需要复核或纠正的问题,classification 返回 "problem",并写入 remaining_issues。
|
5. 只有仍需要复核或纠正的问题,classification 返回 "problem",并写入 remaining_issues。
|
||||||
6. 如果手术表格中能看到“手术及操作编码”列但对应单元格为空,写“编码栏可见但为空白”,不要写“编码区域未在首页显示”;单元格本来为空且无需补录时不要因此判为 problem。
|
6. 如果手术表格中能看到“手术及操作编码”列但对应单元格为空,写“编码栏可见但为空白”,不要写“编码区域未在首页显示”;单元格本来为空且无需补录时不要因此判为 problem。
|
||||||
7. 手术操作名称可能因为换行被结构化解析截断;如果 PDF定位文本或局部截图中显示完整多行名称,请把完整名称放入 suggested_updates。
|
7. 手术操作名称可能因为换行被结构化解析截断;如果 PDF定位文本或局部截图中显示完整多行名称,请把完整名称放入 suggested_updates。
|
||||||
8. 门急诊诊断编码只能用于 outpatient_diagnosis_code;不要把门急诊诊断编码复制到 primary_diagnosis_code 或 discharge_diagnoses[].疾病编码,除非出院诊断表格对应“疾病编码”单元格本身清楚显示该编码。
|
8. 门急诊诊断编码只能用于 outpatient_diagnosis_code;主要诊断请修正 discharge_diagnoses 中“诊断类别=主要诊断”的行,不要把门急诊诊断编码复制到 discharge_diagnoses[].疾病编码,除非出院诊断表格对应“疾病编码”单元格本身清楚显示该编码。
|
||||||
9. remaining_issues 只写当前文档复核人应该特别注意的内容;不要写如何修改,不要重复 suggested_updates,不要写“无需补录/无需处理/首页原貌”这类已判定无问题的说明。
|
9. remaining_issues 只写当前文档复核人应该特别注意的内容;不要写如何修改,不要重复 suggested_updates,不要写“无需补录/无需处理/首页原貌”这类已判定无问题的说明。
|
||||||
10. 不要编造 PDF 中看不见的内容,不要输出置信度。
|
10. 不要编造 PDF 中看不见的内容,不要输出置信度。
|
||||||
|
|
||||||
@@ -2353,7 +2378,7 @@ def build_ai_prompt(record: dict[str, Any], pdf_context: dict[str, Any], privacy
|
|||||||
"summary": "一句话结论,60字以内",
|
"summary": "一句话结论,60字以内",
|
||||||
"method": "AI视觉核验:PDF文本定位+局部截图,对照复核定位和结构化字段",
|
"method": "AI视觉核验:PDF文本定位+局部截图,对照复核定位和结构化字段",
|
||||||
"suggested_updates": [
|
"suggested_updates": [
|
||||||
{{"field": "字段名或路径,例如 primary_diagnosis_code 或 operations[0].麻醉方式", "value": "PDF中应写入的值", "reason": "20字以内"}}
|
{{"field": "字段名或路径,例如 discharge_diagnoses[0].疾病编码 或 operations[0].麻醉方式", "value": "PDF中应写入的值", "reason": "20字以内"}}
|
||||||
],
|
],
|
||||||
"remaining_issues": ["AI觉得有必要复核的内容,最多3条;无则返回空数组"],
|
"remaining_issues": ["AI觉得有必要复核的内容,最多3条;无则返回空数组"],
|
||||||
"evidence": [
|
"evidence": [
|
||||||
@@ -2660,8 +2685,22 @@ def ai_outpatient_code_leak(path: tuple[str, int | None, str | None], value: Any
|
|||||||
return bool(target_is_diagnosis_code)
|
return bool(target_is_diagnosis_code)
|
||||||
|
|
||||||
|
|
||||||
|
PRIMARY_DIAGNOSIS_AI_TARGETS = {
|
||||||
|
"primary_diagnosis": "出院诊断",
|
||||||
|
"主要诊断": "出院诊断",
|
||||||
|
"主要诊断名称": "出院诊断",
|
||||||
|
"primary_diagnosis_code": "疾病编码",
|
||||||
|
"主要诊断编码": "疾病编码",
|
||||||
|
"primary_admission_condition": "入院病情",
|
||||||
|
"主要诊断入院病情": "入院病情",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def ai_update_path(field_text: str, item: dict[str, Any]) -> tuple[str, int | None, str | None] | None:
|
def ai_update_path(field_text: str, item: dict[str, Any]) -> tuple[str, int | None, str | None] | None:
|
||||||
text = str(field_text or "").strip()
|
text = str(field_text or "").strip()
|
||||||
|
for keyword, column in sorted(PRIMARY_DIAGNOSIS_AI_TARGETS.items(), key=lambda entry: len(entry[0]), reverse=True):
|
||||||
|
if keyword in text:
|
||||||
|
return ("discharge_diagnoses", -1, column)
|
||||||
if text in EDITABLE_FIELDS:
|
if text in EDITABLE_FIELDS:
|
||||||
return (text, None, None)
|
return (text, None, None)
|
||||||
for name, meta in FIELD_META.items():
|
for name, meta in FIELD_META.items():
|
||||||
@@ -2726,6 +2765,10 @@ def ai_suggested_updates(result: dict[str, Any], before: dict[str, Any]) -> tupl
|
|||||||
continue
|
continue
|
||||||
rows = old_value if isinstance(old_value, list) else []
|
rows = old_value if isinstance(old_value, list) else []
|
||||||
rows = [dict(row) if isinstance(row, dict) else {} for row in rows]
|
rows = [dict(row) if isinstance(row, dict) else {} for row in rows]
|
||||||
|
if index == -1 and field == "discharge_diagnoses":
|
||||||
|
if not rows:
|
||||||
|
rows = [{"诊断类别": "主要诊断", "出院诊断": "", "疾病编码": "", "入院病情": ""}]
|
||||||
|
index = main_diagnosis_row_index(rows)
|
||||||
if index < 0 or index >= len(rows):
|
if index < 0 or index >= len(rows):
|
||||||
continue
|
continue
|
||||||
compare_old = rows[index].get(key)
|
compare_old = rows[index].get(key)
|
||||||
@@ -2750,6 +2793,7 @@ def ai_suggested_updates(result: dict[str, Any], before: dict[str, Any]) -> tupl
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sync_primary_diagnosis_updates(updates, before)
|
||||||
return updates, changed_fields
|
return updates, changed_fields
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,9 +68,7 @@ const FIELD_KEYWORDS = {
|
|||||||
discharge_dept: ["出院科别", "科室"],
|
discharge_dept: ["出院科别", "科室"],
|
||||||
hospital_days: ["住院天数"],
|
hospital_days: ["住院天数"],
|
||||||
major_department: ["大科室"],
|
major_department: ["大科室"],
|
||||||
primary_diagnosis: ["主要诊断"],
|
discharge_diagnoses: ["出院诊断", "主要诊断", "主要诊断编码", "主要诊断入院病情", "其他诊断", "诊断编码", "入院病情"],
|
||||||
primary_diagnosis_code: ["主要诊断编码", "疾病编码"],
|
|
||||||
discharge_diagnoses: ["出院诊断", "其他诊断", "诊断编码", "入院病情"],
|
|
||||||
operations: ["手术", "操作", "麻醉", "切口"],
|
operations: ["手术", "操作", "麻醉", "切口"],
|
||||||
total_cost: ["总费用"],
|
total_cost: ["总费用"],
|
||||||
self_pay_amount: ["自付"],
|
self_pay_amount: ["自付"],
|
||||||
|
|||||||
Reference in New Issue
Block a user