-
Notifications
You must be signed in to change notification settings - Fork 28
Expand file tree
/
Copy pathcoding_agent.py
More file actions
128 lines (111 loc) · 3.76 KB
/
Copy pathcoding_agent.py
File metadata and controls
128 lines (111 loc) · 3.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""
Coding Agent — ICD-10 automatic coding and DRGs grouping.
Responsibilities:
- Map diagnoses to ICD-10-CM codes with high precision
- Determine DRGs grouping based on principal diagnosis + procedures
- Provide coding confidence scores and rationale
- Cross-validate codes against diagnosis descriptions
"""
from __future__ import annotations
import json
import structlog
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from ..config.settings import get_settings
logger = structlog.get_logger(__name__)
CODING_SYSTEM_PROMPT = """You are a certified medical coding specialist (CCS) with expertise in ICD-10-CM and DRGs grouping. Given diagnosis information and treatment details, assign accurate medical codes.
Return a JSON object:
{
"primary_icd10": {
"code": "exact ICD-10-CM code (e.g., J18.1)",
"description": "official code description",
"confidence": 0.92,
"category": "category name"
},
"secondary_icd10_codes": [
{
"code": "ICD-10 code",
"description": "description",
"confidence": 0.85,
"category": "category"
}
],
"drg_group": {
"drg_code": "DRG number (e.g., 193)",
"description": "DRG description",
"weight": 1.2,
"mean_los": 4.5
},
"coding_notes": "rationale for code selection",
"coding_confidence": 0.90
}
Rules:
- Use the most specific ICD-10-CM code available (4th-7th character level).
- Primary code should match the principal diagnosis.
- Include comorbidity and complication codes as secondary.
- DRGs weight and mean length of stay should be realistic estimates.
- Confidence reflects how certain the code assignment is.
- Return ONLY valid JSON, no markdown fences."""
def coding_agent(state) -> dict:
"""
LangGraph node: Assign ICD-10 codes and DRGs grouping.
Reads: state.diagnosis, state.treatment_plan
Writes: state.coding_result, state.current_agent
"""
logger.info("coding_agent.start")
diagnosis = state.diagnosis
treatment = state.treatment_plan
if not diagnosis:
return {
"coding_result": None,
"current_agent": "coding",
"errors": state.errors + ["No diagnosis available for coding"],
}
settings = get_settings()
llm = ChatOpenAI(
model=settings.openai_model,
api_key=settings.openai_api_key,
temperature=0.1,
)
context = json.dumps(
{"diagnosis": diagnosis, "treatment_plan": treatment},
indent=2,
ensure_ascii=False,
)
messages = [
SystemMessage(content=CODING_SYSTEM_PROMPT),
HumanMessage(
content=(
f"Clinical data for coding:\n\n{context}\n\n"
"Assign ICD-10 codes and DRGs group."
)
),
]
try:
response = llm.invoke(messages)
content = response.content.strip()
if content.startswith("```"):
content = content.split("\n", 1)[1].rsplit("```", 1)[0].strip()
coding_data = json.loads(content)
logger.info(
"coding_agent.success",
primary_code=coding_data.get("primary_icd10", {}).get("code"),
)
return {
"coding_result": coding_data,
"current_agent": "coding",
}
except json.JSONDecodeError as e:
logger.error("coding_agent.json_error", error=str(e))
return {
"coding_result": None,
"current_agent": "coding",
"errors": state.errors + [f"Coding JSON parse error: {e}"],
}
except Exception as e:
logger.error("coding_agent.error", error=str(e))
return {
"coding_result": None,
"current_agent": "coding",
"errors": state.errors + [f"Coding error: {e}"],
}