-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathllm.py
275 lines (233 loc) · 8.51 KB
/
llm.py
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
import json
import os
from typing import List, Optional
import ell
import tqdm
from dotenv import load_dotenv
from pydantic import BaseModel
from sqlalchemy import create_engine
from sqlmodel import Field, Session, SQLModel, select
load_dotenv()
DB_URL = os.getenv("DB_URL")
engine = create_engine(DB_URL)
# ell.init(store="./log")
class SpecificQuestion(BaseModel):
category: str = Field(
description='The `category` can be the following values: "Chief complaint", "Medical history", "Family history", "Allergy", "Surgical history", "Lifestyle", "Medication", and "Review of system'
)
keyword: str = Field(description="Keyword for the question.")
question: str = Field(description="The actual question in Korean.")
class ListOfQuestions(BaseModel):
questions: List[SpecificQuestion]
class Question(BaseModel):
question_kor: str
groupCodeId: str
categoryId: str
isAppropriate: bool = Field(default=False)
isAIGenerated: bool = Field(default=False)
class Category(BaseModel):
id: str = Field(default=None)
name_kor: str = Field(default=None)
name_eng: str = Field(default=None)
class GroupCode(BaseModel):
id: str = Field(default=None)
code: str = Field(default=None)
name: str = Field(default=None)
kor_name: str = Field(default=None)
eng_name: str = Field(default=None)
department: str = Field(default=None)
prompt = f"""
I want to create a disease specific patient survey question for history and physical examination.
The disease data I have has the following schema.
```json
{str(GroupCode.model_json_schema())}
```
Here is an example of the data.
```json
[
{{
"id": "2735303c-fbe5-4f30-8761-39b4b752b34b",
"code": "A19",
"name": "A19",
"kor_name": "좁쌀결핵",
"eng_name": "Miliary tuberculosis",
"department": "UNASSIGNED"
}},
{{
"id": "9e7aa9cf-78a0-40e8-981d-ebe8427d5218",
"code": "A18",
"name": "A18",
"kor_name": "기타 기관의 결핵",
"eng_name": "Tuberculosis of other organs",
"department": "UNASSIGNED"
}},
{{
"id": "ba30d79b-0d7c-4395-ab84-b082ede9862a",
"code": "A18.4",
"name": "A18.4",
"kor_name": "피부 및 피하조직의 결핵",
"eng_name": "Tuberculosis of skin and subcutaneous tissue",
"department": "UNASSIGNED"
}}
]
```
You will be receiving a data from the `groupCode`. You need to create a list of questions that should be asked to the patient based on the diagnosis. The questions should be in Korean. Here is an example of the input and the output. The `category` can be the following values: "Chief complaints", "Past medical history", "Family history", "Allergy", "Past surgical history", "Lifestyle", "Medication", and "Review of system".
```input
{{
"id": "e72f8df4-7134-4f2c-921c-51b37edfd247",
"code": "C19-C20",
"name": "C19-C20",
"kor_name": "직장구불결장접합부의 악성 신생물, 직장의 악성 신생물",
"eng_name": "Malignant neoplasm of rectosigmoid junction, Malignant neoplasm of rectum",
"department": "UNASSIGNED"
}}
```
```output
[
{{
"category": "Past medical history",
"keyword": "colonoscopy",
"question": "대장내시경 검사를 해보셨나요?"
}},
{{
"category": "Past medical history",
"keyword": "colonoscopy",
"question": "대장내시경 검사를 해보셨나요?"
}},
{{
"category": "Review of system",
"keyword": "Stool caliber change",
"question": "대변 굵기 변화"
}},
{{
"category": "Review of system",
"keyword": "Anal pain",
"question": "항문 통증"
}},
{{
"category": "Review of system",
"keyword": "Pruritis ani",
"question": "항문 가려움"
}},
{{
"category": "Review of system",
"keyword": "Tenesmus",
"question": "후중감(항문이나 직장에 무언가 남아있는 것 같은 불편한 느낌)"
}},
{{
"category": "Review of system",
"keyword": "Discharge(soiling)",
"question": "대변이 묻어나오는 증상"
}},
{{
"category": "Review of system",
"keyword": "Prolapsed anal mass",
"question": "항문 종괴 돌출"
}},
{{
"category": "Review of system",
"keyword": "Urinary incontinence",
"question": "요실금"
}},
{{
"category": "Review of system",
"keyword": "Fecal incontinence",
"question": "변실금"
}}
]
```
Avoid common questions that should be asked for every patient regardless of the diagnosis. For example, "Do you have any allergies?" or "Do you have any family history of diseases?" are not relevant to the diagnosis of "직장의 제자리암종". Here are some list of common questions that should be avoided.
Colonoscopy 대장내시경 검사를 해보셨나요?
Colonoscopy 마지막 대장내시경은 언제하셨나요?
Colonoscopy 마지막 대장내시경의 결과는 어땠나요?
Stool caliber change 대변 굵기 변화
Anal pain 항문 통증
Pruritis ani 항문 가려움
Tenesmus 후중감(항문이나 직장에 무언가 남아있는 것 같은 불편한 느낌)
Discharge(soiling) 대변이 묻어나오는 증상
Prolapsed anal mass 항문 종괴 돌출
Urinary incontinence 요실금
Fecal incontinence 변실금
Chief complaint 병원에 방문하게된 가장 큰 이유가 무엇인가요?
Duration 해당 증상은 언제부터 시작되었나요?
Hypertension 고혈압을 진단 받은 적이 있나요?
Diabetes mellitus 당뇨를 진단 받은 적이 있나요?
Hepatitis 간염을 진단 받은 적이 있나요?
Pulmonary tuberculosis 결핵을 진단 받은 적이 있나요?
Cerebrovascular accident(CVA) 뇌졸중을 진단 받은 적이 있나요?
Cardiovascular disease 심혈관 질환을 진단 받은 적이 있나요?
Others 이외에 의료진에게 알려주고 싶은 질환이 있나요?
Surgical history 수술을 받은 적이 있나요?
Surgical history 어떤 수술을 받으셨나요?
Surgical history 수술 받은 이유가 무엇인가요?
Surgical history 언제 수술을 받으셨나요?
Drug allergy 약물 알레르기가 있나요?
Food allergy 음식 알레르기가 있나요?
Current Medication 현재 복용 중이신 약이 있나요?
Past Medication(1year) 최근 1년간 처방받은 약을 알려주세요.
Family history 가족 병력이 있나요?
Family history 가족 병력에 대해 자세히 알려주세요.
Alcohol 음주를 하시나요?
Alcohol 1주일에 몇 회 하시나요?
Alcohol 어떤 종류의 술을 얼마만큼 마시는지 알려주세요.
Smoking 흡연을 하시나요?
Weight 체중이 어떻게 되시나요?
Weight change 최근 체중의 변화가 있었나요?
General weakness 전신 쇠약감
Easy fatigue 쉽게 피로해짐
Fever 열이 남
Chill 몸이 참
Headache 두통
Dizziness 어지러움
Insomnia 불면증
Cough 기침
Sputum 가래
Dyspnea 숨이 참
DOE 운동 시 숨이 참
Chest pain 가슴 통증
Palpitation 두근거림
Hemoptysis 객혈
Hematemesis 토혈
Anorexia 무기력증
Nausea 멀미
Vomiting 구토
Constipation 변비
Diarrhea 설사
Abdominal pain 복통
Abdominal discomfort 복부 불편감
Hematochezia 혈변
Melena 흑색변
Dysuria 소변 시 통증
Oliguria 소변량 감소
Hematuria 혈뇨
Poor oral intake 식욕부진
Others 기타 증상
"""
@ell.complex(model="gpt-4o-mini", response_format=ListOfQuestions)
def generate_question(diagnosis_code_str: str) -> ListOfQuestions:
return [ell.system(prompt), ell.user(diagnosis_code_str)]
def get_categories() -> List[Category]:
import requests
url = "https://vexam.rnd.zarathu.com/api/rest/v1/question/category"
payload = {}
headers = {"x-api-key": "zCVwmOBR1pMY/Iva+xZndQr2PQ+RLSm+V8t221nGjMw="}
response = requests.request("GET", url, headers=headers, data=payload)
data = json.loads(response.text)
output = []
for d in data["data"]:
output.append(Category(**d))
return output
def get_group_codes() -> List[GroupCode]:
import requests
url = "https://vexam.rnd.zarathu.com/api/rest/v1/groupCode"
payload = {}
headers = {"x-api-key": "zCVwmOBR1pMY/Iva+xZndQr2PQ+RLSm+V8t221nGjMw="}
response = requests.request("GET", url, headers=headers, data=payload)
data = json.loads(response.text)
output = []
for d in data["data"]:
output.append(GroupCode(**d))
return output
if __name__ == "__main__":
print(get_group_codes())
print(get_categories())