feat: 약재 효능 태그 시스템 추가
- herb_efficacy_tags 테이블 생성 (효능 마스터) - herb_item_tags 테이블 생성 (약재-효능 다대다 관계) - 18개 기본 효능 태그 등록 (보혈, 활혈, 보기 등) - Git 사용 가이드라인 문서 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
3f4b9c816a
commit
037e307637
341
add_sample_herb_data.py
Normal file
341
add_sample_herb_data.py
Normal file
@ -0,0 +1,341 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
한약재 샘플 데이터 추가 스크립트
|
||||
주요 약재들의 확장 정보와 효능 태그를 추가합니다.
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
|
||||
def get_connection():
|
||||
"""데이터베이스 연결"""
|
||||
return sqlite3.connect('database/kdrug.db')
|
||||
|
||||
def add_herb_extended_data():
|
||||
"""약재 확장 정보 추가"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 주요 약재들의 확장 정보
|
||||
herbs_data = [
|
||||
{
|
||||
'ingredient_code': '3400H1AHM', # 인삼
|
||||
'property': '온',
|
||||
'taste': '감,미고',
|
||||
'meridian_tropism': '비,폐,심',
|
||||
'main_effects': '대보원기, 보비익폐, 생진지갈, 안신증지',
|
||||
'indications': '기허증, 비허증, 폐허증, 심기허증, 진액부족, 당뇨병',
|
||||
'contraindications': '실증, 열증, 음허화왕',
|
||||
'precautions': '복용 중 무 섭취 금지, 고혈압 환자 주의',
|
||||
'dosage_range': '3-9g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': '인삼사포닌(ginsenoside Rb1, Rg1, Rg3), 다당체, 아미노산',
|
||||
'pharmacological_effects': '면역증강, 항피로, 항산화, 혈당조절, 인지능력개선',
|
||||
'clinical_applications': '만성피로, 면역력저하, 당뇨병 보조치료, 노인성 인지저하',
|
||||
'tags': [('보기', 5), ('보양', 4), ('안신', 3), ('진통', 2)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1ADL', # 감초
|
||||
'property': '평',
|
||||
'taste': '감',
|
||||
'meridian_tropism': '비,위,폐,심',
|
||||
'main_effects': '보비익기, 청열해독, 거담지해, 완급지통, 조화제약',
|
||||
'indications': '비허증, 해수, 인후통, 소화성궤양, 경련성 통증',
|
||||
'contraindications': '습증, 수종, 고혈압',
|
||||
'precautions': '장기복용 시 부종 주의, 칼륨 감소 주의',
|
||||
'dosage_range': '2-10g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': 'glycyrrhizin, liquiritin, flavonoid, triterpenoid',
|
||||
'pharmacological_effects': '항염증, 항궤양, 간보호, 진해거담, 항알레르기',
|
||||
'clinical_applications': '위염, 위궤양, 기관지염, 약물조화, 간염',
|
||||
'tags': [('보기', 3), ('청열', 3), ('해독', 4), ('거담', 3), ('항염', 4)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1ACD', # 당귀
|
||||
'property': '온',
|
||||
'taste': '감,신',
|
||||
'meridian_tropism': '간,심,비',
|
||||
'main_effects': '보혈활혈, 조경지통, 윤장통변',
|
||||
'indications': '혈허증, 월경부조, 무월경, 변비, 타박상',
|
||||
'contraindications': '설사, 습성체질',
|
||||
'precautions': '과량 복용 시 설사 주의',
|
||||
'dosage_range': '5-15g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': 'ligustilide, n-butylidene phthalide, ferulic acid',
|
||||
'pharmacological_effects': '혈액순환개선, 항혈전, 자궁수축조절, 진정진통',
|
||||
'clinical_applications': '빈혈, 월경불순, 산후조리, 혈액순환장애',
|
||||
'tags': [('보혈', 5), ('활혈', 5), ('진통', 3)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1AGN', # 황기
|
||||
'property': '온',
|
||||
'taste': '감',
|
||||
'meridian_tropism': '비,폐',
|
||||
'main_effects': '보기승양, 고표지한, 이수소종, 탁독배농',
|
||||
'indications': '기허증, 자한, 부종, 탈항, 자궁탈수',
|
||||
'contraindications': '표실증, 음허화왕',
|
||||
'precautions': '감기 초기 금지',
|
||||
'dosage_range': '10-30g',
|
||||
'dosage_max': '60g',
|
||||
'active_compounds': 'astragaloside, polysaccharide, flavonoid',
|
||||
'pharmacological_effects': '면역조절, 항바이러스, 항산화, 신기능보호',
|
||||
'clinical_applications': '면역력저하, 만성신장염, 당뇨병, 심부전',
|
||||
'tags': [('보기', 5), ('이수', 3), ('해표', 2)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1AEW', # 작약
|
||||
'property': '량',
|
||||
'taste': '고,산',
|
||||
'meridian_tropism': '간,비',
|
||||
'main_effects': '양혈조경, 유간지통, 렴음지한',
|
||||
'indications': '혈허증, 월경부조, 간혈부족, 자한도한',
|
||||
'contraindications': '양허설사',
|
||||
'precautions': '한성약물과 병용 주의',
|
||||
'dosage_range': '6-15g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': 'paeoniflorin, albiflorin, benzoic acid',
|
||||
'pharmacological_effects': '진정진통, 항경련, 항염증, 면역조절',
|
||||
'clinical_applications': '월경통, 근육경련, 두통, 자가면역질환',
|
||||
'tags': [('보혈', 4), ('평간', 4), ('진통', 4)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1ACF', # 천궁
|
||||
'property': '온',
|
||||
'taste': '신',
|
||||
'meridian_tropism': '간,담,심포',
|
||||
'main_effects': '활혈행기, 거풍지통',
|
||||
'indications': '혈어증, 두통, 월경불순, 풍습비통',
|
||||
'contraindications': '음허화왕, 월경과다',
|
||||
'precautions': '출혈 경향 환자 주의',
|
||||
'dosage_range': '3-10g',
|
||||
'dosage_max': '15g',
|
||||
'active_compounds': 'ligustilide, senkyunolide, ferulic acid',
|
||||
'pharmacological_effects': '혈관확장, 항혈전, 진정진통, 항염증',
|
||||
'clinical_applications': '편두통, 혈관성 두통, 어혈증, 월경통',
|
||||
'tags': [('활혈', 5), ('이기', 4), ('진통', 5)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1ACG', # 지황(숙지황)
|
||||
'property': '온',
|
||||
'taste': '감',
|
||||
'meridian_tropism': '간,신',
|
||||
'main_effects': '보혈자음, 익정전수',
|
||||
'indications': '혈허증, 간신음허, 수발조백, 유정도한',
|
||||
'contraindications': '비허설사, 담습',
|
||||
'precautions': '소화불량 주의',
|
||||
'dosage_range': '10-30g',
|
||||
'dosage_max': '60g',
|
||||
'active_compounds': 'catalpol, rehmannioside, aucubin',
|
||||
'pharmacological_effects': '조혈촉진, 면역조절, 혈당강하, 신경보호',
|
||||
'clinical_applications': '빈혈, 당뇨병, 치매예방, 불임증',
|
||||
'tags': [('보혈', 5), ('보음', 5)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1AFJ', # 백출
|
||||
'property': '온',
|
||||
'taste': '고,감',
|
||||
'meridian_tropism': '비,위',
|
||||
'main_effects': '건비익기, 조습이수, 지한안태',
|
||||
'indications': '비허증, 식욕부진, 설사, 수종, 자한',
|
||||
'contraindications': '음허조갈',
|
||||
'precautions': '진액부족 시 주의',
|
||||
'dosage_range': '6-15g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': 'atractylenolide, atractylon',
|
||||
'pharmacological_effects': '위장운동촉진, 이뇨, 항염증, 항종양',
|
||||
'clinical_applications': '만성설사, 부종, 임신오조',
|
||||
'tags': [('보기', 4), ('이수', 4), ('소화', 3)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1AGM', # 복령
|
||||
'property': '평',
|
||||
'taste': '감,담',
|
||||
'meridian_tropism': '심,비,폐,신',
|
||||
'main_effects': '이수삼습, 건비안신',
|
||||
'indications': '수종, 소변불리, 비허설사, 불면, 심계',
|
||||
'contraindications': '음허진액부족',
|
||||
'precautions': '이뇨제와 병용 주의',
|
||||
'dosage_range': '10-15g',
|
||||
'dosage_max': '30g',
|
||||
'active_compounds': 'pachymic acid, polysaccharide',
|
||||
'pharmacological_effects': '이뇨, 진정, 항염증, 면역조절',
|
||||
'clinical_applications': '부종, 불면증, 만성설사',
|
||||
'tags': [('이수', 5), ('안신', 3), ('보기', 2)]
|
||||
},
|
||||
{
|
||||
'ingredient_code': '3400H1AGI', # 반하
|
||||
'property': '온',
|
||||
'taste': '신',
|
||||
'meridian_tropism': '비,위,폐',
|
||||
'main_effects': '조습화담, 강역지구, 소비산결',
|
||||
'indications': '습담, 구토, 해수담다, 현훈',
|
||||
'contraindications': '음허조해, 임신',
|
||||
'precautions': '임산부 금기, 생품 독성 주의',
|
||||
'dosage_range': '5-10g',
|
||||
'dosage_max': '15g',
|
||||
'active_compounds': 'ephedrine, β-sitosterol',
|
||||
'pharmacological_effects': '진토, 진해거담, 항종양',
|
||||
'clinical_applications': '임신오조, 기관지염, 현훈증',
|
||||
'tags': [('거담', 5), ('소화', 3)]
|
||||
}
|
||||
]
|
||||
|
||||
for herb in herbs_data:
|
||||
# herb_master_extended 업데이트
|
||||
cursor.execute("""
|
||||
UPDATE herb_master_extended
|
||||
SET property = ?,
|
||||
taste = ?,
|
||||
meridian_tropism = ?,
|
||||
main_effects = ?,
|
||||
indications = ?,
|
||||
contraindications = ?,
|
||||
precautions = ?,
|
||||
dosage_range = ?,
|
||||
dosage_max = ?,
|
||||
active_compounds = ?,
|
||||
pharmacological_effects = ?,
|
||||
clinical_applications = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE ingredient_code = ?
|
||||
""", (
|
||||
herb['property'], herb['taste'], herb['meridian_tropism'],
|
||||
herb['main_effects'], herb['indications'], herb['contraindications'],
|
||||
herb['precautions'], herb['dosage_range'], herb['dosage_max'],
|
||||
herb['active_compounds'], herb['pharmacological_effects'],
|
||||
herb['clinical_applications'], herb['ingredient_code']
|
||||
))
|
||||
|
||||
# herb_id 조회
|
||||
cursor.execute("""
|
||||
SELECT herb_id FROM herb_master_extended
|
||||
WHERE ingredient_code = ?
|
||||
""", (herb['ingredient_code'],))
|
||||
|
||||
result = cursor.fetchone()
|
||||
if result:
|
||||
herb_id = result[0]
|
||||
|
||||
# 효능 태그 매핑
|
||||
for tag_name, strength in herb.get('tags', []):
|
||||
# 태그 ID 조회
|
||||
cursor.execute("""
|
||||
SELECT tag_id FROM herb_efficacy_tags
|
||||
WHERE tag_name = ?
|
||||
""", (tag_name,))
|
||||
|
||||
tag_result = cursor.fetchone()
|
||||
if tag_result:
|
||||
tag_id = tag_result[0]
|
||||
|
||||
# 태그 매핑 추가
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO herb_item_tags
|
||||
(herb_id, tag_id, strength)
|
||||
VALUES (?, ?, ?)
|
||||
""", (herb_id, tag_id, strength))
|
||||
|
||||
print(f"✅ {herb['ingredient_code']} 데이터 추가 완료")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def add_prescription_rules():
|
||||
"""처방 배합 규칙 추가"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 몇 가지 대표적인 배합 규칙 추가
|
||||
rules = [
|
||||
# 상수(相須) - 서로 도와서 효과를 증강
|
||||
{
|
||||
'herb1': '인삼', 'herb2': '황기',
|
||||
'relationship': '상수',
|
||||
'description': '두 약재가 함께 사용되면 보기 효과가 증강됨',
|
||||
'severity': 0
|
||||
},
|
||||
{
|
||||
'herb1': '당귀', 'herb2': '천궁',
|
||||
'relationship': '상수',
|
||||
'description': '혈액순환 개선 효과가 증강됨',
|
||||
'severity': 0
|
||||
},
|
||||
# 상사(相使) - 한 약이 다른 약의 효능을 도움
|
||||
{
|
||||
'herb1': '반하', 'herb2': '생강',
|
||||
'relationship': '상사',
|
||||
'description': '생강이 반하의 독성을 감소시킴',
|
||||
'severity': 0
|
||||
},
|
||||
# 상반(相反) - 함께 사용하면 독성이나 부작용 발생
|
||||
{
|
||||
'herb1': '감초', 'herb2': '감수',
|
||||
'relationship': '상반',
|
||||
'description': '십팔반(十八反) - 함께 사용 금기',
|
||||
'severity': 5,
|
||||
'is_absolute': True
|
||||
},
|
||||
{
|
||||
'herb1': '인삼', 'herb2': '오령지',
|
||||
'relationship': '상반',
|
||||
'description': '십구외(十九畏) - 함께 사용 주의',
|
||||
'severity': 4,
|
||||
'is_absolute': False
|
||||
}
|
||||
]
|
||||
|
||||
for rule in rules:
|
||||
# herb_id 조회
|
||||
cursor.execute("""
|
||||
SELECT herb_id FROM herb_master_extended
|
||||
WHERE name_korean = ?
|
||||
""", (rule['herb1'],))
|
||||
herb1_result = cursor.fetchone()
|
||||
|
||||
cursor.execute("""
|
||||
SELECT herb_id FROM herb_master_extended
|
||||
WHERE name_korean = ?
|
||||
""", (rule['herb2'],))
|
||||
herb2_result = cursor.fetchone()
|
||||
|
||||
if herb1_result and herb2_result:
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO prescription_rules
|
||||
(herb1_id, herb2_id, relationship_type, description,
|
||||
severity_level, is_absolute)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
herb1_result[0], herb2_result[0],
|
||||
rule['relationship'], rule['description'],
|
||||
rule['severity'], rule.get('is_absolute', False)
|
||||
))
|
||||
print(f"✅ {rule['herb1']} - {rule['herb2']} 규칙 추가")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def main():
|
||||
"""메인 실행 함수"""
|
||||
print("\n" + "="*80)
|
||||
print("한약재 샘플 데이터 추가")
|
||||
print("="*80 + "\n")
|
||||
|
||||
try:
|
||||
# 1. 약재 확장 정보 및 태그 추가
|
||||
print("1. 약재 확장 정보 추가 중...")
|
||||
add_herb_extended_data()
|
||||
|
||||
# 2. 처방 규칙 추가
|
||||
print("\n2. 처방 배합 규칙 추가 중...")
|
||||
add_prescription_rules()
|
||||
|
||||
print("\n✨ 모든 샘플 데이터가 성공적으로 추가되었습니다!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 오류 발생: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
300
app.py
300
app.py
@ -2183,6 +2183,306 @@ def complete_survey(survey_token):
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
# ================ 한약재 확장 정보 API ================
|
||||
|
||||
@app.route('/api/herbs/<int:herb_id>/extended', methods=['GET'])
|
||||
def get_herb_extended_info(herb_id):
|
||||
"""약재 확장 정보 조회"""
|
||||
try:
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 기본 정보 + 확장 정보 조회
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
hme.*,
|
||||
hm.herb_name,
|
||||
hm.herb_name_hanja
|
||||
FROM herb_master_extended hme
|
||||
LEFT JOIN herb_masters hm ON hme.ingredient_code = hm.ingredient_code
|
||||
WHERE hme.herb_id = ?
|
||||
""", (herb_id,))
|
||||
|
||||
herb_info = cursor.fetchone()
|
||||
|
||||
if not herb_info:
|
||||
return jsonify({'error': '약재 정보를 찾을 수 없습니다'}), 404
|
||||
|
||||
# 효능 태그 조회
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
het.tag_name,
|
||||
het.tag_category,
|
||||
het.description,
|
||||
hit.strength
|
||||
FROM herb_item_tags hit
|
||||
JOIN herb_efficacy_tags het ON hit.tag_id = het.tag_id
|
||||
WHERE hit.herb_id = ?
|
||||
ORDER BY hit.strength DESC, het.tag_category
|
||||
""", (herb_id,))
|
||||
|
||||
tags = []
|
||||
for row in cursor.fetchall():
|
||||
tags.append({
|
||||
'name': row['tag_name'],
|
||||
'category': row['tag_category'],
|
||||
'description': row['description'],
|
||||
'strength': row['strength']
|
||||
})
|
||||
|
||||
# 안전성 정보 조회
|
||||
cursor.execute("""
|
||||
SELECT * FROM herb_safety_info
|
||||
WHERE herb_id = ?
|
||||
""", (herb_id,))
|
||||
|
||||
safety_info = cursor.fetchone()
|
||||
|
||||
result = dict(herb_info)
|
||||
result['efficacy_tags'] = tags
|
||||
result['safety_info'] = dict(safety_info) if safety_info else None
|
||||
|
||||
return jsonify(result)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/herbs/<int:herb_id>/extended', methods=['PUT'])
|
||||
def update_herb_extended_info(herb_id):
|
||||
"""약재 확장 정보 수정"""
|
||||
try:
|
||||
data = request.json
|
||||
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 업데이트할 필드 동적 생성
|
||||
update_fields = []
|
||||
update_values = []
|
||||
|
||||
allowed_fields = [
|
||||
'property', 'taste', 'meridian_tropism',
|
||||
'main_effects', 'indications', 'contraindications',
|
||||
'precautions', 'dosage_range', 'dosage_max',
|
||||
'preparation_method', 'active_compounds',
|
||||
'pharmacological_effects', 'clinical_applications'
|
||||
]
|
||||
|
||||
for field in allowed_fields:
|
||||
if field in data:
|
||||
update_fields.append(f"{field} = ?")
|
||||
update_values.append(data[field])
|
||||
|
||||
if update_fields:
|
||||
update_values.append(herb_id)
|
||||
cursor.execute(f"""
|
||||
UPDATE herb_master_extended
|
||||
SET {', '.join(update_fields)},
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE herb_id = ?
|
||||
""", update_values)
|
||||
|
||||
# 변경 로그 기록
|
||||
cursor.execute("""
|
||||
INSERT INTO data_update_logs
|
||||
(update_type, source, target_table, target_id, after_data)
|
||||
VALUES ('MANUAL', 'API', 'herb_master_extended', ?, ?)
|
||||
""", (herb_id, json.dumps(data, ensure_ascii=False)))
|
||||
|
||||
conn.commit()
|
||||
|
||||
return jsonify({'success': True, 'message': '정보가 업데이트되었습니다'})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/herbs/<int:herb_id>/tags', methods=['GET'])
|
||||
def get_herb_tags(herb_id):
|
||||
"""약재 효능 태그 조회"""
|
||||
try:
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
het.tag_id,
|
||||
het.tag_name,
|
||||
het.tag_category,
|
||||
het.description,
|
||||
hit.strength
|
||||
FROM herb_item_tags hit
|
||||
JOIN herb_efficacy_tags het ON hit.tag_id = het.tag_id
|
||||
WHERE hit.herb_id = ?
|
||||
ORDER BY hit.strength DESC
|
||||
""", (herb_id,))
|
||||
|
||||
tags = []
|
||||
for row in cursor.fetchall():
|
||||
tags.append({
|
||||
'tag_id': row['tag_id'],
|
||||
'name': row['tag_name'],
|
||||
'category': row['tag_category'],
|
||||
'description': row['description'],
|
||||
'strength': row['strength']
|
||||
})
|
||||
|
||||
return jsonify(tags)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/herbs/<int:herb_id>/tags', methods=['POST'])
|
||||
def add_herb_tag(herb_id):
|
||||
"""약재에 효능 태그 추가"""
|
||||
try:
|
||||
data = request.json
|
||||
tag_id = data.get('tag_id')
|
||||
strength = data.get('strength', 3)
|
||||
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
INSERT OR REPLACE INTO herb_item_tags
|
||||
(herb_id, tag_id, strength)
|
||||
VALUES (?, ?, ?)
|
||||
""", (herb_id, tag_id, strength))
|
||||
|
||||
conn.commit()
|
||||
|
||||
return jsonify({'success': True, 'message': '태그가 추가되었습니다'})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/herbs/search-by-efficacy', methods=['GET'])
|
||||
def search_herbs_by_efficacy():
|
||||
"""효능별 약재 검색"""
|
||||
try:
|
||||
tag_names = request.args.getlist('tags')
|
||||
|
||||
if not tag_names:
|
||||
return jsonify({'error': '검색할 태그를 지정해주세요'}), 400
|
||||
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
placeholders = ','.join('?' * len(tag_names))
|
||||
cursor.execute(f"""
|
||||
SELECT DISTINCT
|
||||
hme.herb_id,
|
||||
hme.name_korean,
|
||||
hme.name_hanja,
|
||||
hme.main_effects,
|
||||
GROUP_CONCAT(het.tag_name) as tags
|
||||
FROM herb_master_extended hme
|
||||
JOIN herb_item_tags hit ON hme.herb_id = hit.herb_id
|
||||
JOIN herb_efficacy_tags het ON hit.tag_id = het.tag_id
|
||||
WHERE het.tag_name IN ({placeholders})
|
||||
GROUP BY hme.herb_id
|
||||
ORDER BY hme.name_korean
|
||||
""", tag_names)
|
||||
|
||||
results = []
|
||||
for row in cursor.fetchall():
|
||||
results.append({
|
||||
'herb_id': row['herb_id'],
|
||||
'name_korean': row['name_korean'],
|
||||
'name_hanja': row['name_hanja'],
|
||||
'main_effects': row['main_effects'],
|
||||
'tags': row['tags'].split(',') if row['tags'] else []
|
||||
})
|
||||
|
||||
return jsonify(results)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/prescription-check', methods=['POST'])
|
||||
def check_prescription_safety():
|
||||
"""처방 안전성 검증"""
|
||||
try:
|
||||
data = request.json
|
||||
herb_ids = data.get('herb_ids', [])
|
||||
|
||||
if len(herb_ids) < 2:
|
||||
return jsonify({'safe': True, 'warnings': []})
|
||||
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
warnings = []
|
||||
|
||||
# 약재 조합 규칙 확인
|
||||
for i in range(len(herb_ids)):
|
||||
for j in range(i + 1, len(herb_ids)):
|
||||
cursor.execute("""
|
||||
SELECT
|
||||
relationship_type,
|
||||
description,
|
||||
severity_level,
|
||||
is_absolute
|
||||
FROM prescription_rules
|
||||
WHERE (herb1_id = ? AND herb2_id = ?)
|
||||
OR (herb1_id = ? AND herb2_id = ?)
|
||||
""", (herb_ids[i], herb_ids[j], herb_ids[j], herb_ids[i]))
|
||||
|
||||
rule = cursor.fetchone()
|
||||
if rule:
|
||||
# 상반(相反), 상살(相殺) 등 위험한 관계 체크
|
||||
if rule['relationship_type'] in ['상반', '상살']:
|
||||
warnings.append({
|
||||
'type': 'danger',
|
||||
'herbs': [herb_ids[i], herb_ids[j]],
|
||||
'relationship': rule['relationship_type'],
|
||||
'description': rule['description'],
|
||||
'is_absolute': rule['is_absolute']
|
||||
})
|
||||
elif rule['relationship_type'] == '상외':
|
||||
warnings.append({
|
||||
'type': 'warning',
|
||||
'herbs': [herb_ids[i], herb_ids[j]],
|
||||
'relationship': rule['relationship_type'],
|
||||
'description': rule['description']
|
||||
})
|
||||
|
||||
# 절대 금기 사항이 있으면 안전하지 않음
|
||||
is_safe = not any(w.get('is_absolute') for w in warnings)
|
||||
|
||||
return jsonify({
|
||||
'safe': is_safe,
|
||||
'warnings': warnings
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@app.route('/api/efficacy-tags', methods=['GET'])
|
||||
def get_all_efficacy_tags():
|
||||
"""모든 효능 태그 조회"""
|
||||
try:
|
||||
with get_db() as conn:
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
SELECT * FROM herb_efficacy_tags
|
||||
ORDER BY tag_category, tag_name
|
||||
""")
|
||||
|
||||
tags = []
|
||||
for row in cursor.fetchall():
|
||||
tags.append({
|
||||
'tag_id': row['tag_id'],
|
||||
'name': row['tag_name'],
|
||||
'category': row['tag_category'],
|
||||
'description': row['description']
|
||||
})
|
||||
|
||||
return jsonify(tags)
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
if __name__ == '__main__':
|
||||
# 데이터베이스 초기화
|
||||
if not os.path.exists(app.config['DATABASE']):
|
||||
|
||||
462
docs/한약재_정보_관리_시스템_설계.md
Normal file
462
docs/한약재_정보_관리_시스템_설계.md
Normal file
@ -0,0 +1,462 @@
|
||||
# 한약재 정보 관리 시스템 (K-Drug Information System)
|
||||
|
||||
## 1. 개요
|
||||
|
||||
### 1.1 목표
|
||||
- 양방약 DUR(Drug Utilization Review) 시스템처럼 한약재 정보를 체계적으로 관리
|
||||
- AI/API를 통한 지속적인 정보 업데이트
|
||||
- 근거 기반 한의학(Evidence-Based Korean Medicine) 데이터베이스 구축
|
||||
|
||||
### 1.2 벤치마킹
|
||||
- **건강보험심사평가원 의약품안전사용서비스(DUR)**
|
||||
- **KIMS (대한민국의약정보센터)**
|
||||
- **Micromedex (미국)**
|
||||
- **한국한의학연구원 전통의학정보포털**
|
||||
|
||||
## 2. 데이터베이스 설계
|
||||
|
||||
### 2.1 핵심 테이블 구조
|
||||
|
||||
```sql
|
||||
-- 1. 약재 기본 정보 (확장)
|
||||
CREATE TABLE herb_master_extended (
|
||||
herb_id INTEGER PRIMARY KEY,
|
||||
ingredient_code VARCHAR(10) UNIQUE,
|
||||
|
||||
-- 기본 명칭
|
||||
name_korean VARCHAR(100) NOT NULL,
|
||||
name_hanja VARCHAR(100),
|
||||
name_latin VARCHAR(200),
|
||||
name_english VARCHAR(200),
|
||||
name_pharmaceutical VARCHAR(200), -- 약전명
|
||||
|
||||
-- 분류 정보
|
||||
family_latin VARCHAR(100), -- 과명
|
||||
genus_species VARCHAR(200), -- 학명
|
||||
origin_plant TEXT, -- 기원식물
|
||||
medicinal_part VARCHAR(100), -- 약용부위
|
||||
|
||||
-- 성미귀경
|
||||
property VARCHAR(50), -- 성(性): 한/열/온/량/평
|
||||
taste VARCHAR(100), -- 미(味): 고/감/산/신/함/담
|
||||
meridian_tropism TEXT, -- 귀경: 입경 경락
|
||||
|
||||
-- 효능 효과
|
||||
main_effects TEXT, -- 주요 효능
|
||||
indications TEXT, -- 적응증
|
||||
contraindications TEXT, -- 금기증
|
||||
precautions TEXT, -- 주의사항
|
||||
|
||||
-- 용법 용량
|
||||
dosage_range VARCHAR(50), -- 상용량 (예: "3-12g")
|
||||
dosage_max VARCHAR(50), -- 극량
|
||||
preparation_method TEXT, -- 포제법
|
||||
|
||||
-- 성분 정보
|
||||
active_compounds TEXT, -- 주요 성분
|
||||
chemical_constituents JSON, -- 화학 성분 상세 (JSON)
|
||||
|
||||
-- 약리 작용
|
||||
pharmacological_effects TEXT, -- 약리작용
|
||||
clinical_applications TEXT, -- 임상응용
|
||||
|
||||
-- 상호작용
|
||||
drug_interactions JSON, -- 약물 상호작용 (JSON)
|
||||
food_interactions JSON, -- 음식 상호작용 (JSON)
|
||||
|
||||
-- 품질 기준
|
||||
quality_standards TEXT, -- 품질 기준
|
||||
identification_method TEXT, -- 감별법
|
||||
|
||||
-- 메타데이터
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
data_source VARCHAR(100), -- 데이터 출처
|
||||
reliability_score INTEGER, -- 신뢰도 점수 (1-10)
|
||||
review_status VARCHAR(20) -- 검토 상태
|
||||
);
|
||||
|
||||
-- 2. 약재 연구 문헌
|
||||
CREATE TABLE herb_research_papers (
|
||||
paper_id INTEGER PRIMARY KEY,
|
||||
herb_id INTEGER REFERENCES herb_master_extended(herb_id),
|
||||
|
||||
title TEXT NOT NULL,
|
||||
authors TEXT,
|
||||
journal VARCHAR(200),
|
||||
publication_year INTEGER,
|
||||
volume VARCHAR(50),
|
||||
pages VARCHAR(50),
|
||||
|
||||
doi VARCHAR(100),
|
||||
pubmed_id VARCHAR(20),
|
||||
|
||||
abstract TEXT,
|
||||
keywords TEXT,
|
||||
|
||||
study_type VARCHAR(50), -- RCT, 관찰연구, 리뷰 등
|
||||
evidence_level INTEGER, -- 근거수준 (1-5)
|
||||
|
||||
findings TEXT, -- 주요 발견
|
||||
clinical_relevance TEXT, -- 임상적 의미
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
indexed_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- 3. 약재 안전성 정보
|
||||
CREATE TABLE herb_safety_info (
|
||||
safety_id INTEGER PRIMARY KEY,
|
||||
herb_id INTEGER REFERENCES herb_master_extended(herb_id),
|
||||
|
||||
-- 독성 정보
|
||||
toxicity_level VARCHAR(20), -- 독성 등급
|
||||
ld50_value VARCHAR(50), -- 반수치사량
|
||||
toxic_compounds TEXT, -- 독성 성분
|
||||
|
||||
-- 부작용
|
||||
common_side_effects TEXT, -- 흔한 부작용
|
||||
rare_side_effects TEXT, -- 드문 부작용
|
||||
serious_adverse_events TEXT, -- 중대 이상반응
|
||||
|
||||
-- 특수 집단
|
||||
pregnancy_category VARCHAR(10), -- 임신 등급
|
||||
pregnancy_safety TEXT, -- 임신 안전성
|
||||
lactation_safety TEXT, -- 수유 안전성
|
||||
pediatric_use TEXT, -- 소아 사용
|
||||
geriatric_use TEXT, -- 노인 사용
|
||||
|
||||
-- 모니터링
|
||||
monitoring_parameters TEXT, -- 모니터링 항목
|
||||
laboratory_tests TEXT, -- 필요 검사
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 4. 처방 구성 규칙
|
||||
CREATE TABLE prescription_rules (
|
||||
rule_id INTEGER PRIMARY KEY,
|
||||
|
||||
-- 배합 규칙
|
||||
herb1_id INTEGER,
|
||||
herb2_id INTEGER,
|
||||
relationship_type VARCHAR(50), -- 상수/상사/상외/상오/상쇄/상반/상살
|
||||
|
||||
description TEXT,
|
||||
clinical_significance TEXT,
|
||||
evidence_source TEXT,
|
||||
|
||||
severity_level INTEGER, -- 심각도 (1-5)
|
||||
action_required VARCHAR(50), -- 조치사항
|
||||
|
||||
is_absolute BOOLEAN, -- 절대 금기 여부
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 5. 질병-약재 매핑
|
||||
CREATE TABLE disease_herb_mapping (
|
||||
mapping_id INTEGER PRIMARY KEY,
|
||||
|
||||
disease_code VARCHAR(20), -- KCD 코드
|
||||
disease_name VARCHAR(200),
|
||||
herb_id INTEGER REFERENCES herb_master_extended(herb_id),
|
||||
|
||||
indication_type VARCHAR(50), -- 주적응증/부적응증
|
||||
evidence_level INTEGER, -- 근거수준
|
||||
recommendation_grade VARCHAR(10), -- 권고등급
|
||||
|
||||
clinical_notes TEXT,
|
||||
references TEXT,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- 6. AI/API 업데이트 로그
|
||||
CREATE TABLE data_update_logs (
|
||||
log_id INTEGER PRIMARY KEY,
|
||||
|
||||
update_type VARCHAR(50), -- AI/API/MANUAL
|
||||
source VARCHAR(100), -- 데이터 소스
|
||||
target_table VARCHAR(50),
|
||||
target_id INTEGER,
|
||||
|
||||
before_data JSON, -- 변경 전 데이터
|
||||
after_data JSON, -- 변경 후 데이터
|
||||
|
||||
update_reason TEXT,
|
||||
confidence_score FLOAT, -- AI 신뢰도
|
||||
|
||||
is_reviewed BOOLEAN DEFAULT FALSE,
|
||||
reviewed_by VARCHAR(50),
|
||||
review_notes TEXT,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
```
|
||||
|
||||
## 3. API/AI 연동 방안
|
||||
|
||||
### 3.1 외부 데이터 소스
|
||||
|
||||
#### 국내 소스
|
||||
- **한국한의학연구원 API**
|
||||
- 한약재 데이터베이스
|
||||
- 처방 데이터베이스
|
||||
- 임상 연구 자료
|
||||
|
||||
- **건강보험심사평가원**
|
||||
- 한약제제 급여 정보
|
||||
- 안전성 정보
|
||||
|
||||
- **식품의약품안전처**
|
||||
- 한약재 품질 기준
|
||||
- 안전성 정보
|
||||
|
||||
#### 국제 소스
|
||||
- **PubMed API**
|
||||
- 한약재 연구 논문
|
||||
- 임상시험 결과
|
||||
|
||||
- **WHO Traditional Medicine**
|
||||
- 국제 표준 정보
|
||||
- 안전성 데이터
|
||||
|
||||
- **ClinicalTrials.gov**
|
||||
- 진행 중인 임상시험
|
||||
|
||||
### 3.2 AI 활용 방안
|
||||
|
||||
```python
|
||||
# AI 기반 정보 추출 및 업데이트 예시
|
||||
|
||||
class HerbInfoAIUpdater:
|
||||
def __init__(self):
|
||||
self.nlp_model = load_korean_medical_nlp()
|
||||
self.ocr_model = load_medical_ocr()
|
||||
|
||||
def extract_from_literature(self, pdf_path):
|
||||
"""의학 문헌에서 약재 정보 추출"""
|
||||
text = self.ocr_model.extract_text(pdf_path)
|
||||
|
||||
entities = self.nlp_model.extract_entities(text, types=[
|
||||
'HERB_NAME',
|
||||
'DOSAGE',
|
||||
'INDICATION',
|
||||
'CONTRAINDICATION',
|
||||
'SIDE_EFFECT',
|
||||
'INTERACTION'
|
||||
])
|
||||
|
||||
return self.validate_and_structure(entities)
|
||||
|
||||
def update_from_clinical_data(self, clinical_records):
|
||||
"""임상 데이터에서 패턴 분석"""
|
||||
# 처방 패턴 분석
|
||||
prescription_patterns = self.analyze_prescription_patterns(clinical_records)
|
||||
|
||||
# 효능 검증
|
||||
efficacy_data = self.validate_efficacy(clinical_records)
|
||||
|
||||
# 안전성 모니터링
|
||||
safety_signals = self.detect_safety_signals(clinical_records)
|
||||
|
||||
return {
|
||||
'patterns': prescription_patterns,
|
||||
'efficacy': efficacy_data,
|
||||
'safety': safety_signals
|
||||
}
|
||||
|
||||
def cross_reference_validation(self, herb_info):
|
||||
"""교차 검증"""
|
||||
sources = [
|
||||
self.query_kmri_api(herb_info['name']),
|
||||
self.query_pubmed(herb_info['latin_name']),
|
||||
self.query_who_database(herb_info['code'])
|
||||
]
|
||||
|
||||
return self.reconcile_information(sources)
|
||||
```
|
||||
|
||||
## 4. 기능 구현
|
||||
|
||||
### 4.1 약재 정보 조회 API
|
||||
|
||||
```python
|
||||
@app.route('/api/herbs/<int:herb_id>/full-info', methods=['GET'])
|
||||
def get_herb_full_info(herb_id):
|
||||
"""약재 종합 정보 조회"""
|
||||
return {
|
||||
'basic_info': get_basic_info(herb_id),
|
||||
'pharmacology': get_pharmacology(herb_id),
|
||||
'safety': get_safety_info(herb_id),
|
||||
'interactions': get_interactions(herb_id),
|
||||
'research': get_research_papers(herb_id),
|
||||
'clinical_use': get_clinical_applications(herb_id)
|
||||
}
|
||||
|
||||
@app.route('/api/herbs/search', methods=['POST'])
|
||||
def search_herbs_advanced():
|
||||
"""고급 검색"""
|
||||
criteria = request.json
|
||||
|
||||
# 증상으로 검색
|
||||
if criteria.get('symptoms'):
|
||||
return search_by_symptoms(criteria['symptoms'])
|
||||
|
||||
# 성분으로 검색
|
||||
if criteria.get('compounds'):
|
||||
return search_by_compounds(criteria['compounds'])
|
||||
|
||||
# 처방 호환성 검색
|
||||
if criteria.get('compatibility'):
|
||||
return check_prescription_compatibility(criteria['herbs'])
|
||||
```
|
||||
|
||||
### 4.2 안전성 검증 시스템
|
||||
|
||||
```python
|
||||
class HerbSafetyChecker:
|
||||
def check_prescription_safety(self, herbs, patient_info):
|
||||
"""처방 안전성 종합 검증"""
|
||||
|
||||
results = {
|
||||
'is_safe': True,
|
||||
'warnings': [],
|
||||
'contraindications': [],
|
||||
'interactions': [],
|
||||
'dosage_alerts': []
|
||||
}
|
||||
|
||||
# 1. 약재 간 상호작용 확인
|
||||
for herb1, herb2 in combinations(herbs, 2):
|
||||
interaction = self.check_herb_interaction(herb1, herb2)
|
||||
if interaction:
|
||||
results['interactions'].append(interaction)
|
||||
|
||||
# 2. 환자 특성별 금기 확인
|
||||
if patient_info.get('pregnancy'):
|
||||
self.check_pregnancy_safety(herbs, results)
|
||||
|
||||
if patient_info.get('allergies'):
|
||||
self.check_allergy_risk(herbs, patient_info['allergies'], results)
|
||||
|
||||
# 3. 용량 검증
|
||||
self.validate_dosages(herbs, results)
|
||||
|
||||
# 4. 질병-약물 상호작용
|
||||
if patient_info.get('conditions'):
|
||||
self.check_disease_interactions(herbs, patient_info['conditions'], results)
|
||||
|
||||
return results
|
||||
```
|
||||
|
||||
### 4.3 데이터 품질 관리
|
||||
|
||||
```python
|
||||
class DataQualityManager:
|
||||
def validate_herb_data(self, herb_data):
|
||||
"""데이터 품질 검증"""
|
||||
|
||||
scores = {
|
||||
'completeness': self.check_completeness(herb_data),
|
||||
'accuracy': self.verify_accuracy(herb_data),
|
||||
'consistency': self.check_consistency(herb_data),
|
||||
'timeliness': self.check_timeliness(herb_data)
|
||||
}
|
||||
|
||||
herb_data['quality_score'] = sum(scores.values()) / len(scores)
|
||||
herb_data['quality_details'] = scores
|
||||
|
||||
return herb_data
|
||||
|
||||
def reconcile_conflicts(self, data_sources):
|
||||
"""데이터 충돌 해결"""
|
||||
|
||||
# 신뢰도 기반 가중 평균
|
||||
weighted_data = {}
|
||||
for source in data_sources:
|
||||
weight = source['reliability_score']
|
||||
for field, value in source['data'].items():
|
||||
if field not in weighted_data:
|
||||
weighted_data[field] = []
|
||||
weighted_data[field].append((value, weight))
|
||||
|
||||
# 최종 값 결정
|
||||
final_data = {}
|
||||
for field, values in weighted_data.items():
|
||||
final_data[field] = self.select_best_value(values)
|
||||
|
||||
return final_data
|
||||
```
|
||||
|
||||
## 5. 사용자 인터페이스
|
||||
|
||||
### 5.1 약재 정보 대시보드
|
||||
- 약재 상세 정보 카드
|
||||
- 효능/효과 시각화
|
||||
- 안전성 정보 알림
|
||||
- 연구 논문 목록
|
||||
- 처방 활용 통계
|
||||
|
||||
### 5.2 처방 안전성 검증
|
||||
- 실시간 DUR 체크
|
||||
- 약재 조합 검증
|
||||
- 용량 적정성 평가
|
||||
- 환자별 맞춤 알림
|
||||
|
||||
### 5.3 지식 관리 도구
|
||||
- 새로운 연구 결과 알림
|
||||
- 데이터 품질 모니터링
|
||||
- AI 제안 검토
|
||||
- 전문가 협업 도구
|
||||
|
||||
## 6. 구현 로드맵
|
||||
|
||||
### Phase 1: 기반 구축 (1-2개월)
|
||||
- [ ] 확장 데이터베이스 스키마 구현
|
||||
- [ ] 기본 CRUD API 개발
|
||||
- [ ] 데이터 마이그레이션
|
||||
|
||||
### Phase 2: 외부 연동 (2-3개월)
|
||||
- [ ] 한의학연구원 API 연동
|
||||
- [ ] PubMed API 연동
|
||||
- [ ] 자동 업데이트 스케줄러
|
||||
|
||||
### Phase 3: AI 통합 (3-4개월)
|
||||
- [ ] NLP 모델 훈련
|
||||
- [ ] 문헌 자동 분석
|
||||
- [ ] 패턴 인식 시스템
|
||||
|
||||
### Phase 4: 안전성 시스템 (2개월)
|
||||
- [ ] DUR 체크 시스템
|
||||
- [ ] 실시간 경고 시스템
|
||||
- [ ] 보고서 생성
|
||||
|
||||
### Phase 5: 고도화 (지속)
|
||||
- [ ] 사용자 피드백 수집
|
||||
- [ ] 모델 개선
|
||||
- [ ] 새로운 데이터 소스 추가
|
||||
|
||||
## 7. 기대 효과
|
||||
|
||||
1. **근거 기반 처방**
|
||||
- 최신 연구 결과 반영
|
||||
- 객관적 데이터 기반 의사결정
|
||||
|
||||
2. **환자 안전성 향상**
|
||||
- 실시간 안전성 검증
|
||||
- 부작용 예방
|
||||
|
||||
3. **업무 효율성**
|
||||
- 자동화된 정보 관리
|
||||
- 빠른 정보 검색
|
||||
|
||||
4. **지식 축적**
|
||||
- 체계적인 데이터베이스
|
||||
- 지속적인 학습 시스템
|
||||
|
||||
5. **표준화**
|
||||
- 한약재 정보 표준화
|
||||
- 품질 관리 체계화
|
||||
448
migrations/add_herb_extended_info_tables.py
Normal file
448
migrations/add_herb_extended_info_tables.py
Normal file
@ -0,0 +1,448 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
한약재 확장 정보 테이블 추가
|
||||
- herb_master_extended: 약재 상세 정보
|
||||
- herb_research_papers: 연구 문헌
|
||||
- herb_safety_info: 안전성 정보
|
||||
- prescription_rules: 처방 구성 규칙
|
||||
- disease_herb_mapping: 질병-약재 매핑
|
||||
- data_update_logs: AI/API 업데이트 로그
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
from datetime import datetime
|
||||
|
||||
def get_connection():
|
||||
"""데이터베이스 연결"""
|
||||
return sqlite3.connect('../database/kdrug.db')
|
||||
|
||||
def create_herb_master_extended():
|
||||
"""약재 확장 정보 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 기존 테이블 확인
|
||||
cursor.execute("""
|
||||
SELECT name FROM sqlite_master
|
||||
WHERE type='table' AND name='herb_master_extended'
|
||||
""")
|
||||
|
||||
if cursor.fetchone():
|
||||
print("herb_master_extended 테이블이 이미 존재합니다.")
|
||||
else:
|
||||
cursor.execute("""
|
||||
CREATE TABLE herb_master_extended (
|
||||
herb_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
ingredient_code VARCHAR(10) UNIQUE,
|
||||
|
||||
-- 기본 명칭
|
||||
name_korean VARCHAR(100) NOT NULL,
|
||||
name_hanja VARCHAR(100),
|
||||
name_latin VARCHAR(200),
|
||||
name_english VARCHAR(200),
|
||||
name_pharmaceutical VARCHAR(200), -- 약전명
|
||||
|
||||
-- 분류 정보
|
||||
family_latin VARCHAR(100), -- 과명
|
||||
genus_species VARCHAR(200), -- 학명
|
||||
origin_plant TEXT, -- 기원식물
|
||||
medicinal_part VARCHAR(100), -- 약용부위
|
||||
|
||||
-- 성미귀경
|
||||
property VARCHAR(50), -- 성(性): 한/열/온/량/평
|
||||
taste VARCHAR(100), -- 미(味): 고/감/산/신/함/담
|
||||
meridian_tropism TEXT, -- 귀경: 입경 경락
|
||||
|
||||
-- 효능 효과
|
||||
main_effects TEXT, -- 주요 효능
|
||||
indications TEXT, -- 적응증
|
||||
contraindications TEXT, -- 금기증
|
||||
precautions TEXT, -- 주의사항
|
||||
|
||||
-- 용법 용량
|
||||
dosage_range VARCHAR(50), -- 상용량 (예: "3-12g")
|
||||
dosage_max VARCHAR(50), -- 극량
|
||||
preparation_method TEXT, -- 포제법
|
||||
|
||||
-- 성분 정보
|
||||
active_compounds TEXT, -- 주요 성분
|
||||
chemical_constituents TEXT, -- 화학 성분 상세 (JSON)
|
||||
|
||||
-- 약리 작용
|
||||
pharmacological_effects TEXT, -- 약리작용
|
||||
clinical_applications TEXT, -- 임상응용
|
||||
|
||||
-- 상호작용
|
||||
drug_interactions TEXT, -- 약물 상호작용 (JSON)
|
||||
food_interactions TEXT, -- 음식 상호작용 (JSON)
|
||||
|
||||
-- 품질 기준
|
||||
quality_standards TEXT, -- 품질 기준
|
||||
identification_method TEXT, -- 감별법
|
||||
|
||||
-- 메타데이터
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
data_source VARCHAR(100), -- 데이터 출처
|
||||
reliability_score INTEGER, -- 신뢰도 점수 (1-10)
|
||||
review_status VARCHAR(20) -- 검토 상태
|
||||
)
|
||||
""")
|
||||
print("✅ herb_master_extended 테이블이 생성되었습니다.")
|
||||
|
||||
# 기존 herb_masters 데이터 마이그레이션
|
||||
cursor.execute("""
|
||||
INSERT INTO herb_master_extended (
|
||||
ingredient_code, name_korean, name_hanja, name_latin
|
||||
)
|
||||
SELECT
|
||||
ingredient_code,
|
||||
herb_name AS name_korean,
|
||||
herb_name_hanja AS name_hanja,
|
||||
herb_name_latin AS name_latin
|
||||
FROM herb_masters
|
||||
""")
|
||||
|
||||
print(f" - {cursor.rowcount}개의 기존 데이터가 마이그레이션되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_herb_research_papers():
|
||||
"""약재 연구 문헌 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS herb_research_papers (
|
||||
paper_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
herb_id INTEGER,
|
||||
|
||||
title TEXT NOT NULL,
|
||||
authors TEXT,
|
||||
journal VARCHAR(200),
|
||||
publication_year INTEGER,
|
||||
volume VARCHAR(50),
|
||||
pages VARCHAR(50),
|
||||
|
||||
doi VARCHAR(100),
|
||||
pubmed_id VARCHAR(20),
|
||||
|
||||
abstract TEXT,
|
||||
keywords TEXT,
|
||||
|
||||
study_type VARCHAR(50), -- RCT, 관찰연구, 리뷰 등
|
||||
evidence_level INTEGER, -- 근거수준 (1-5)
|
||||
|
||||
findings TEXT, -- 주요 발견
|
||||
clinical_relevance TEXT, -- 임상적 의미
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
indexed_at TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
print("✅ herb_research_papers 테이블이 생성되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_herb_safety_info():
|
||||
"""약재 안전성 정보 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS herb_safety_info (
|
||||
safety_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
herb_id INTEGER,
|
||||
|
||||
-- 독성 정보
|
||||
toxicity_level VARCHAR(20), -- 독성 등급
|
||||
ld50_value VARCHAR(50), -- 반수치사량
|
||||
toxic_compounds TEXT, -- 독성 성분
|
||||
|
||||
-- 부작용
|
||||
common_side_effects TEXT, -- 흔한 부작용
|
||||
rare_side_effects TEXT, -- 드문 부작용
|
||||
serious_adverse_events TEXT, -- 중대 이상반응
|
||||
|
||||
-- 특수 집단
|
||||
pregnancy_category VARCHAR(10), -- 임신 등급
|
||||
pregnancy_safety TEXT, -- 임신 안전성
|
||||
lactation_safety TEXT, -- 수유 안전성
|
||||
pediatric_use TEXT, -- 소아 사용
|
||||
geriatric_use TEXT, -- 노인 사용
|
||||
|
||||
-- 모니터링
|
||||
monitoring_parameters TEXT, -- 모니터링 항목
|
||||
laboratory_tests TEXT, -- 필요 검사
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
print("✅ herb_safety_info 테이블이 생성되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_prescription_rules():
|
||||
"""처방 구성 규칙 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS prescription_rules (
|
||||
rule_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
-- 배합 규칙
|
||||
herb1_id INTEGER,
|
||||
herb2_id INTEGER,
|
||||
relationship_type VARCHAR(50), -- 상수/상사/상외/상오/상쇄/상반/상살
|
||||
|
||||
description TEXT,
|
||||
clinical_significance TEXT,
|
||||
evidence_source TEXT,
|
||||
|
||||
severity_level INTEGER, -- 심각도 (1-5)
|
||||
action_required VARCHAR(50), -- 조치사항
|
||||
|
||||
is_absolute BOOLEAN, -- 절대 금기 여부
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
# 인덱스 추가
|
||||
cursor.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_prescription_rules_herbs
|
||||
ON prescription_rules(herb1_id, herb2_id)
|
||||
""")
|
||||
|
||||
print("✅ prescription_rules 테이블이 생성되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_disease_herb_mapping():
|
||||
"""질병-약재 매핑 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS disease_herb_mapping (
|
||||
mapping_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
disease_code VARCHAR(20), -- KCD 코드
|
||||
disease_name VARCHAR(200),
|
||||
herb_id INTEGER,
|
||||
|
||||
indication_type VARCHAR(50), -- 주적응증/부적응증
|
||||
evidence_level INTEGER, -- 근거수준
|
||||
recommendation_grade VARCHAR(10), -- 권고등급
|
||||
|
||||
clinical_notes TEXT,
|
||||
references TEXT,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
# 인덱스 추가
|
||||
cursor.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_disease_herb_mapping
|
||||
ON disease_herb_mapping(disease_code, herb_id)
|
||||
""")
|
||||
|
||||
print("✅ disease_herb_mapping 테이블이 생성되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_data_update_logs():
|
||||
"""AI/API 업데이트 로그 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS data_update_logs (
|
||||
log_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
update_type VARCHAR(50), -- AI/API/MANUAL
|
||||
source VARCHAR(100), -- 데이터 소스
|
||||
target_table VARCHAR(50),
|
||||
target_id INTEGER,
|
||||
|
||||
before_data TEXT, -- 변경 전 데이터 (JSON)
|
||||
after_data TEXT, -- 변경 후 데이터 (JSON)
|
||||
|
||||
update_reason TEXT,
|
||||
confidence_score REAL, -- AI 신뢰도
|
||||
|
||||
is_reviewed BOOLEAN DEFAULT 0,
|
||||
reviewed_by VARCHAR(50),
|
||||
review_notes TEXT,
|
||||
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
print("✅ data_update_logs 테이블이 생성되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def create_herb_efficacy_tags():
|
||||
"""약재 효능 태그 시스템 테이블 생성"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 효능 태그 마스터 테이블
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS herb_efficacy_tags (
|
||||
tag_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
tag_name VARCHAR(50) UNIQUE NOT NULL,
|
||||
tag_category VARCHAR(30), -- 보익/거사/조리/기타
|
||||
description TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
""")
|
||||
|
||||
# 약재-태그 매핑 테이블
|
||||
cursor.execute("""
|
||||
CREATE TABLE IF NOT EXISTS herb_item_tags (
|
||||
item_tag_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
herb_id INTEGER,
|
||||
tag_id INTEGER,
|
||||
strength INTEGER DEFAULT 3, -- 효능 강도 (1-5)
|
||||
notes TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(herb_id, tag_id)
|
||||
)
|
||||
""")
|
||||
|
||||
# 기본 효능 태그 삽입
|
||||
basic_tags = [
|
||||
('보혈', '보익', '혈을 보하는 효능'),
|
||||
('보기', '보익', '기를 보하는 효능'),
|
||||
('보양', '보익', '양기를 보하는 효능'),
|
||||
('보음', '보익', '음액을 보하는 효능'),
|
||||
('활혈', '거사', '혈액순환을 개선하는 효능'),
|
||||
('거담', '거사', '담을 제거하는 효능'),
|
||||
('이수', '거사', '수분대사를 개선하는 효능'),
|
||||
('해표', '거사', '표증을 해소하는 효능'),
|
||||
('청열', '거사', '열을 내리는 효능'),
|
||||
('해독', '거사', '독을 해소하는 효능'),
|
||||
('이기', '조리', '기의 순환을 조절하는 효능'),
|
||||
('소화', '조리', '소화를 돕는 효능'),
|
||||
('안신', '조리', '정신을 안정시키는 효능'),
|
||||
('평간', '조리', '간기능을 조절하는 효능'),
|
||||
('지혈', '기타', '출혈을 멈추는 효능'),
|
||||
('진통', '기타', '통증을 완화하는 효능'),
|
||||
('항염', '기타', '염증을 억제하는 효능'),
|
||||
('항균', '기타', '균을 억제하는 효능')
|
||||
]
|
||||
|
||||
for tag_name, tag_category, description in basic_tags:
|
||||
cursor.execute("""
|
||||
INSERT OR IGNORE INTO herb_efficacy_tags (tag_name, tag_category, description)
|
||||
VALUES (?, ?, ?)
|
||||
""", (tag_name, tag_category, description))
|
||||
|
||||
print("✅ herb_efficacy_tags 테이블이 생성되었습니다.")
|
||||
print(f" - {len(basic_tags)}개의 기본 효능 태그가 등록되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def add_sample_data():
|
||||
"""샘플 데이터 추가"""
|
||||
conn = get_connection()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 인삼 상세 정보 업데이트
|
||||
cursor.execute("""
|
||||
UPDATE herb_master_extended
|
||||
SET
|
||||
property = '온',
|
||||
taste = '감,미고',
|
||||
meridian_tropism = '비,폐,심',
|
||||
main_effects = '대보원기, 보비익폐, 생진지갈, 안신증지',
|
||||
indications = '기허증, 비허증, 폐허증, 심기허증, 진액부족',
|
||||
contraindications = '실증, 열증',
|
||||
precautions = '복용 중 무 섭취 금지',
|
||||
dosage_range = '3-9g',
|
||||
dosage_max = '30g',
|
||||
active_compounds = '인삼사포닌(ginsenoside), 다당체, 아미노산',
|
||||
pharmacological_effects = '면역증강, 항피로, 항산화, 혈당조절',
|
||||
clinical_applications = '만성피로, 면역력저하, 당뇨병 보조치료'
|
||||
WHERE ingredient_code = '3400H1AHM'
|
||||
""")
|
||||
|
||||
# 감초 상세 정보 업데이트
|
||||
cursor.execute("""
|
||||
UPDATE herb_master_extended
|
||||
SET
|
||||
property = '평',
|
||||
taste = '감',
|
||||
meridian_tropism = '비,위,폐,심',
|
||||
main_effects = '보비익기, 청열해독, 거담지해, 완급지통, 조화제약',
|
||||
indications = '비허증, 해수, 인후통, 소화성궤양',
|
||||
contraindications = '습증, 수종',
|
||||
precautions = '장기복용 시 부종 주의',
|
||||
dosage_range = '2-10g',
|
||||
dosage_max = '30g',
|
||||
active_compounds = 'glycyrrhizin, flavonoid, triterpenoid',
|
||||
pharmacological_effects = '항염증, 항궤양, 간보호, 진해거담',
|
||||
clinical_applications = '위염, 위궤양, 기관지염, 약물조화'
|
||||
WHERE ingredient_code = '3400H1ADL'
|
||||
""")
|
||||
|
||||
print("✅ 샘플 데이터가 추가되었습니다.")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
def main():
|
||||
"""메인 실행 함수"""
|
||||
print("\n" + "="*80)
|
||||
print("한약재 확장 정보 시스템 테이블 생성")
|
||||
print("="*80 + "\n")
|
||||
|
||||
try:
|
||||
# 1. 확장 정보 테이블 생성
|
||||
create_herb_master_extended()
|
||||
|
||||
# 2. 연구 문헌 테이블 생성
|
||||
create_herb_research_papers()
|
||||
|
||||
# 3. 안전성 정보 테이블 생성
|
||||
create_herb_safety_info()
|
||||
|
||||
# 4. 처방 규칙 테이블 생성
|
||||
create_prescription_rules()
|
||||
|
||||
# 5. 질병-약재 매핑 테이블 생성
|
||||
create_disease_herb_mapping()
|
||||
|
||||
# 6. 업데이트 로그 테이블 생성
|
||||
create_data_update_logs()
|
||||
|
||||
# 7. 효능 태그 시스템 생성
|
||||
create_herb_efficacy_tags()
|
||||
|
||||
# 8. 샘플 데이터 추가
|
||||
add_sample_data()
|
||||
|
||||
print("\n✨ 모든 테이블이 성공적으로 생성되었습니다!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ 오류 발생: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue
Block a user