From 3527cc9777f161f793ab7de3edaa11d26091685f Mon Sep 17 00:00:00 2001 From: thug0bin Date: Thu, 5 Mar 2026 20:38:46 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20PAAI=20=EC=95=BD=ED=92=88=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20Enrichment=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - enrich_medications() 함수 추가 - CD_SUNG: 성분 정보 (복합제 포함) - CD_MC: 분류(PRINT_TYPE), 상호작용(INTERACTION), 금기(CONTRA) - 프롬프트에 성분/분류 정보 포함 - AI가 성분 기반으로 정확한 판단 가능 --- backend/pmr_api.py | 122 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 2 deletions(-) diff --git a/backend/pmr_api.py b/backend/pmr_api.py index fc3e8ec..a9ed7f9 100644 --- a/backend/pmr_api.py +++ b/backend/pmr_api.py @@ -53,6 +53,104 @@ def warmup_db_connection(): warmup_db_connection() +def enrich_medications(medications: list) -> list: + """ + 약품 목록에 성분/분류/상호작용/금기 정보 추가 (PAAI용) + + CD_SUNG: 성분 정보 + CD_MC: 분류(PRINT_TYPE), 상호작용(INTERACTION), 금기(CONTRA) + """ + if not medications: + return medications + + try: + conn = get_mssql_connection('PM_DRUG') + cursor = conn.cursor() + + # DrugCode 목록 추출 + drug_codes = [m.get('code') or m.get('medication_code') for m in medications if m.get('code') or m.get('medication_code')] + + if not drug_codes: + conn.close() + return medications + + # 1. CD_MC에서 분류/상호작용/금기 조회 + placeholders = ','.join(['?' for _ in drug_codes]) + cursor.execute(f""" + SELECT + DRUGCODE, + PRINT_TYPE, + INTERACTION, + CONTRA + FROM CD_MC + WHERE DRUGCODE IN ({placeholders}) + """, drug_codes) + + mc_info = {} + for row in cursor.fetchall(): + mc_info[row.DRUGCODE] = { + 'print_type': row.PRINT_TYPE or '', + 'interaction': (row.INTERACTION or '')[:500], # 너무 길면 자르기 + 'contra': (row.CONTRA or '')[:300] + } + + # 2. CD_GOODS에서 SUNG_CODE 조회 + cursor.execute(f""" + SELECT DrugCode, SUNG_CODE + FROM CD_GOODS + WHERE DrugCode IN ({placeholders}) AND SUNG_CODE IS NOT NULL + """, drug_codes) + + sung_codes = {} + for row in cursor.fetchall(): + if row.SUNG_CODE: + sung_codes[row.DrugCode] = row.SUNG_CODE + + # 3. CD_SUNG에서 성분 정보 조회 + components_by_drug = {} + if sung_codes: + unique_sung_codes = list(set(sung_codes.values())) + placeholders2 = ','.join(['?' for _ in unique_sung_codes]) + cursor.execute(f""" + SELECT SUNG_CODE, SUNG_HNM + FROM CD_SUNG + WHERE SUNG_CODE IN ({placeholders2}) + """, unique_sung_codes) + + # SUNG_CODE별 성분 목록 + sung_components = {} + for row in cursor.fetchall(): + if row.SUNG_CODE not in sung_components: + sung_components[row.SUNG_CODE] = [] + sung_components[row.SUNG_CODE].append(row.SUNG_HNM) + + # DrugCode별로 매핑 + for drug_code, sung_code in sung_codes.items(): + components_by_drug[drug_code] = sung_components.get(sung_code, []) + + conn.close() + + # 4. medications에 정보 추가 + for med in medications: + code = med.get('code') or med.get('medication_code') + if code: + # MC 정보 + if code in mc_info: + med['print_type'] = mc_info[code]['print_type'] + med['interaction_info'] = mc_info[code]['interaction'] + med['contra_info'] = mc_info[code]['contra'] + + # 성분 정보 + if code in components_by_drug: + med['components'] = components_by_drug[code] + + return medications + + except Exception as e: + logging.error(f"[PAAI] Medication enrichment 오류: {e}") + return medications + + # ───────────────────────────────────────────────────────────── # 조제관리 페이지 # ───────────────────────────────────────────────────────────── @@ -1022,6 +1120,9 @@ def paai_analyze(): previous_medications = data.get('previous_medications', []) otc_history = data.get('otc_history', {}) + # ✅ 약품 정보 Enrichment (성분/분류/상호작용/금기) + current_medications = enrich_medications(current_medications) + # 처방 변화 분석 prescription_changes = analyze_prescription_changes( current_medications, previous_medications @@ -1200,10 +1301,27 @@ def build_paai_prompt( if disease_info.get('code_2'): diseases.append(f"[{disease_info['code_2']}] {disease_info.get('name_2', '')}") - # 현재 처방 + # 현재 처방 (성분 정보 포함) med_lines = [] for med in current_medications: - line = f"- {med.get('name', '?')}: {med.get('dosage', 0)}정 × {med.get('frequency', 0)}회 × {med.get('days', 0)}일" + name = med.get('name', '?') + dosage = med.get('dosage', 0) + freq = med.get('frequency', 0) + days = med.get('days', 0) + + line = f"- {name}: {dosage}정 × {freq}회 × {days}일" + + # 분류 정보 + if med.get('print_type'): + line += f"\n └ 분류: {med['print_type']}" + + # 성분 정보 + if med.get('components'): + components_str = ', '.join(med['components'][:3]) # 최대 3개 + if len(med['components']) > 3: + components_str += f" 외 {len(med['components'])-3}개" + line += f"\n └ 성분: {components_str}" + med_lines.append(line) # 처방 변화