{
 "nbformat": 4,
 "nbformat_minor": 0,
 "metadata": {
  "colab": {
   "provenance": [],
   "gpuType": "T4",
   "authorship_tag": "ABX9TyOddh2zT/4LUUYT9JJYvrRa"
  },
  "kernelspec": {
   "name": "python3",
   "display_name": "Python 3"
  },
  "language_info": {
   "name": "python"
  },
  "accelerator": "GPU",
  "widgets": {
   "application/vnd.jupyter.widget-state+json": {
    "cd2512514a8041abb0c0d31fabab8f76": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "HBoxModel",
     "model_module_version": "1.5.0",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HBoxModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HBoxView",
      "box_style": "",
      "children": [
       "IPY_MODEL_465e65a123f34ac4905afed4249e6bf0",
       "IPY_MODEL_9d9a9b9e16904d35b117db11a392c8a1",
       "IPY_MODEL_2bd7abbef788485d97ec0fac410173b3"
      ],
      "layout": "IPY_MODEL_04302eb4662c4f19abe8fab89a56286f"
     }
    },
    "465e65a123f34ac4905afed4249e6bf0": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "HTMLModel",
     "model_module_version": "1.5.0",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HTMLModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HTMLView",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_72c6908fff01432a8795e7862d6a5164",
      "placeholder": "​",
      "style": "IPY_MODEL_1c55480c8a424cd5acc28d22165912f2",
      "value": "Loading checkpoint shards: 100%"
     }
    },
    "9d9a9b9e16904d35b117db11a392c8a1": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "FloatProgressModel",
     "model_module_version": "1.5.0",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "FloatProgressModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "ProgressView",
      "bar_style": "success",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_eeaa436de40c4fc28d21bb467b634c06",
      "max": 2,
      "min": 0,
      "orientation": "horizontal",
      "style": "IPY_MODEL_ed3220b06c784d81b47c6d5ff54972b2",
      "value": 2
     }
    },
    "2bd7abbef788485d97ec0fac410173b3": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "HTMLModel",
     "model_module_version": "1.5.0",
     "state": {
      "_dom_classes": [],
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "HTMLModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/controls",
      "_view_module_version": "1.5.0",
      "_view_name": "HTMLView",
      "description": "",
      "description_tooltip": null,
      "layout": "IPY_MODEL_7a26ad48ee284ca7a0e5de95d4cb5ab4",
      "placeholder": "​",
      "style": "IPY_MODEL_35bc36b284cd490ca448b9f9707b3878",
      "value": " 2/2 [00:00&lt;00:00,  2.52it/s]"
     }
    },
    "04302eb4662c4f19abe8fab89a56286f": {
     "model_module": "@jupyter-widgets/base",
     "model_name": "LayoutModel",
     "model_module_version": "1.2.0",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "72c6908fff01432a8795e7862d6a5164": {
     "model_module": "@jupyter-widgets/base",
     "model_name": "LayoutModel",
     "model_module_version": "1.2.0",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "1c55480c8a424cd5acc28d22165912f2": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "DescriptionStyleModel",
     "model_module_version": "1.5.0",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "DescriptionStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "description_width": ""
     }
    },
    "eeaa436de40c4fc28d21bb467b634c06": {
     "model_module": "@jupyter-widgets/base",
     "model_name": "LayoutModel",
     "model_module_version": "1.2.0",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "ed3220b06c784d81b47c6d5ff54972b2": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "ProgressStyleModel",
     "model_module_version": "1.5.0",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "ProgressStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "bar_color": null,
      "description_width": ""
     }
    },
    "7a26ad48ee284ca7a0e5de95d4cb5ab4": {
     "model_module": "@jupyter-widgets/base",
     "model_name": "LayoutModel",
     "model_module_version": "1.2.0",
     "state": {
      "_model_module": "@jupyter-widgets/base",
      "_model_module_version": "1.2.0",
      "_model_name": "LayoutModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "LayoutView",
      "align_content": null,
      "align_items": null,
      "align_self": null,
      "border": null,
      "bottom": null,
      "display": null,
      "flex": null,
      "flex_flow": null,
      "grid_area": null,
      "grid_auto_columns": null,
      "grid_auto_flow": null,
      "grid_auto_rows": null,
      "grid_column": null,
      "grid_gap": null,
      "grid_row": null,
      "grid_template_areas": null,
      "grid_template_columns": null,
      "grid_template_rows": null,
      "height": null,
      "justify_content": null,
      "justify_items": null,
      "left": null,
      "margin": null,
      "max_height": null,
      "max_width": null,
      "min_height": null,
      "min_width": null,
      "object_fit": null,
      "object_position": null,
      "order": null,
      "overflow": null,
      "overflow_x": null,
      "overflow_y": null,
      "padding": null,
      "right": null,
      "top": null,
      "visibility": null,
      "width": null
     }
    },
    "35bc36b284cd490ca448b9f9707b3878": {
     "model_module": "@jupyter-widgets/controls",
     "model_name": "DescriptionStyleModel",
     "model_module_version": "1.5.0",
     "state": {
      "_model_module": "@jupyter-widgets/controls",
      "_model_module_version": "1.5.0",
      "_model_name": "DescriptionStyleModel",
      "_view_count": null,
      "_view_module": "@jupyter-widgets/base",
      "_view_module_version": "1.2.0",
      "_view_name": "StyleView",
      "description_width": ""
     }
    }
   }
  }
 },
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 실습 03 · 규칙 기반 의료 전문가 시스템 vs LLM\n",
    "\n",
    "> **연계 강의자료:** M3 「지식표현과 전문가시스템」 · 4주차\n",
    "> **목표:** 온톨로지+IF-THEN 규칙으로 진단 시스템을 직접 구현하고(신뢰도 = 매칭 증상/질병 증상), 같은 질문을 LLM에 던져 기호주의와 연결주의를 대비한다.\n",
    ">\n",
    "> 강의자료 M3 실습 2(신뢰도 계산 코드)의 전체 구현판.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "UO10Xi3ziqcO"
   },
   "outputs": [],
   "source": [
    "class Symptom:\n",
    "    def __init__(self, name):\n",
    "        self.name = name\n",
    "\n",
    "class Disease:\n",
    "    def __init__(self, name, symptoms):\n",
    "        self.name = name\n",
    "        self.symptoms = symptoms\n",
    "\n",
    "class MedicalOntology:\n",
    "    def __init__(self):\n",
    "        self.symptoms = {}\n",
    "        self.diseases = {}\n",
    "\n",
    "    def add_symptom(self, name):\n",
    "        if name not in self.symptoms:\n",
    "            self.symptoms[name] = Symptom(name)\n",
    "        return self.symptoms[name]\n",
    "\n",
    "    def add_disease(self, name, symptom_names):\n",
    "        symptoms = [self.add_symptom(s) for s in symptom_names]\n",
    "        disease = Disease(name, symptoms)\n",
    "        self.diseases[name] = disease\n",
    "\n",
    "    def describe_structure(self):\n",
    "        print(\"의료 온톨로지 구조:\")\n",
    "        print(\"1. 증상 (Symptoms):\")\n",
    "        for symptom in self.symptoms.values():\n",
    "            print(f\"   - {symptom.name}\")\n",
    "\n",
    "        print(\"\\n2. 질병 (Diseases):\")\n",
    "        for disease in self.diseases.values():\n",
    "            print(f\"   - {disease.name}\")\n",
    "            print(\"     관련 증상:\")\n",
    "            for symptom in disease.symptoms:\n",
    "                print(f\"       * {symptom.name}\")\n",
    "            print()\n",
    "\n",
    "class MedicalExpertSystem:\n",
    "    def __init__(self):\n",
    "        self.ontology = MedicalOntology()\n",
    "        self._initialize_ontology()\n",
    "\n",
    "    def _initialize_ontology(self):\n",
    "        self.ontology.add_disease(\"편두통\", [\"두통\", \"시각 장애\", \"메스꺼움\"])\n",
    "        self.ontology.add_disease(\"긴장성 두통\", [\"두통\", \"목 통증\"])\n",
    "        self.ontology.add_disease(\"감기\", [\"발열\", \"기침\", \"인후통\"])\n",
    "        self.ontology.add_disease(\"독감\", [\"발열\", \"근육통\", \"피로\"])\n",
    "        self.ontology.add_disease(\"위염\", [\"복통\", \"메스꺼움\", \"소화불량\"])\n",
    "        self.ontology.add_disease(\"빈혈\", [\"피로\", \"어지러움\", \"창백\"])\n",
    "\n",
    "    def diagnose(self, symptom_names):\n",
    "        input_symptoms = set(symptom_names)\n",
    "        possible_diseases = []\n",
    "\n",
    "        for disease in self.ontology.diseases.values():\n",
    "            disease_symptoms = set(s.name for s in disease.symptoms)\n",
    "            matching_symptoms = input_symptoms.intersection(disease_symptoms)\n",
    "\n",
    "            if matching_symptoms:\n",
    "                confidence = len(matching_symptoms) / len(disease_symptoms)\n",
    "                possible_diseases.append((disease.name, confidence))\n",
    "\n",
    "        return sorted(possible_diseases, key=lambda x: x[1], reverse=True)\n",
    "\n",
    "    def describe_ontology(self):\n",
    "        self.ontology.describe_structure()\n",
    "\n",
    "def get_symptoms():\n",
    "    print(\"증상을 입력하세요 (여러 개일 경우 쉼표로 구분):\")\n",
    "    return [symptom.strip() for symptom in input().split(',')]\n",
    "\n",
    "def main():\n",
    "    expert_system = MedicalExpertSystem()\n",
    "\n",
    "    print(\"의료 진단 익스퍼트 시스템에 오신 것을 환영합니다.\")\n",
    "    while True:\n",
    "\n",
    "      print(\"1. 온톨로지 구조 설명\")\n",
    "      print(\"2. 진단 시작\")\n",
    "      choice = input(\"선택하세요 (1 또는 2): \")\n",
    "\n",
    "      if choice == '1':\n",
    "          expert_system.describe_ontology()\n",
    "      elif choice == '2':\n",
    "          while True:\n",
    "              symptoms = get_symptoms()\n",
    "              if not symptoms:\n",
    "                  break\n",
    "\n",
    "              diagnosis = expert_system.diagnose(symptoms)\n",
    "\n",
    "              if diagnosis:\n",
    "                  print(\"\\n가능한 질병 (신뢰도 순):\")\n",
    "                  for disease, confidence in diagnosis:\n",
    "                      print(f\"- {disease} (신뢰도: {confidence:.2f})\")\n",
    "              else:\n",
    "                  print(\"\\n입력한 증상에 해당하는 질병을 찾을 수 없습니다.\")\n",
    "\n",
    "              print(\"\\n다른 증상을 진단하려면 새로운 증상을 입력하세요.\")\n",
    "              print(\"종료하려면 Enter 키를 누르세요.\")\n",
    "      else:\n",
    "          print(\"잘못된 선택입니다.\")\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    main()"
   ]
  },
  {
   "cell_type": "markdown",
   "source": "[참고] https://huggingface.co/meta-llama/Llama-3.2-3B-Instruct\n\n\n모델 사용 권한을 신청하고 토큰을 발행해야 사용할 수 있다(승인까지 시간이 다소 걸린다).",
   "metadata": {
    "id": "huquCyQ-nsKc"
   }
  },
  {
   "cell_type": "code",
   "source": [
    "import torch\n",
    "from transformers import pipeline\n",
    "\n",
    "access_token =\"당신의 토큰을 넣으세요\"\n",
    "\n",
    "\n",
    "model_id = \"meta-llama/Llama-3.2-3B-Instruct\"\n",
    "pipe = pipeline(\n",
    "    \"text-generation\",\n",
    "    model=model_id,\n",
    "    torch_dtype=torch.bfloat16,\n",
    "    device_map=\"auto\",\n",
    ")\n",
    "messages = [\n",
    "    {\"role\": \"system\", \"content\": \"당신은 야식 전문가 입니다.\"},\n",
    "    {\"role\": \"user\", \"content\": \"오늘 야식을 추천해줘요.\"},\n",
    "]\n",
    "outputs = pipe(\n",
    "    messages,\n",
    "    max_new_tokens=256,\n",
    ")\n",
    "print(outputs[0][\"generated_text\"][-1])\n"
   ],
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 106,
     "referenced_widgets": [
      "cd2512514a8041abb0c0d31fabab8f76",
      "465e65a123f34ac4905afed4249e6bf0",
      "9d9a9b9e16904d35b117db11a392c8a1",
      "2bd7abbef788485d97ec0fac410173b3",
      "04302eb4662c4f19abe8fab89a56286f",
      "72c6908fff01432a8795e7862d6a5164",
      "1c55480c8a424cd5acc28d22165912f2",
      "eeaa436de40c4fc28d21bb467b634c06",
      "ed3220b06c784d81b47c6d5ff54972b2",
      "7a26ad48ee284ca7a0e5de95d4cb5ab4",
      "35bc36b284cd490ca448b9f9707b3878"
     ]
    },
    "id": "hjRgSFNalof5",
    "executionInfo": {
     "status": "ok",
     "timestamp": 1728232857809,
     "user_tz": -540,
     "elapsed": 209595,
     "user": {
      "displayName": "‍배주호[교수 / Global Business & Technology학부]",
      "userId": "05734973157924058529"
     }
    },
    "outputId": "f44e7118-74b2-47ae-9c96-b26cd3c421fb"
   },
   "execution_count": 10,
   "outputs": [
    {
     "output_type": "display_data",
     "data": {
      "text/plain": [
       "Loading checkpoint shards:   0%|          | 0/2 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "cd2512514a8041abb0c0d31fabab8f76"
      }
     },
     "metadata": {}
    },
    {
     "output_type": "stream",
     "name": "stderr",
     "text": [
      "Setting `pad_token_id` to `eos_token_id`:128001 for open-end generation.\n"
     ]
    },
    {
     "output_type": "stream",
     "name": "stdout",
     "text": [
      "{'role': 'assistant', 'content': '오늘 야식을 추천해드릴게요.\\n\\n1. **치즈 피자**: 치즈가 melts된 피자, 소스, 마늘,과 함께 한 완전한 야식입니다.\\n2. **스파게티**: 이탈리아의 전통 야식으로 파스타를 뿌리다, 토마토 소스, 치즈,과 함께 해요.\\n3. **버거**: 버거는 전 세계의 야식 중 하나로, 다양한 topping을 선택해 보세요.\\n4. **라เมن**: 이탈리아의 전통 야식으로 파스타를 뿌리다, 소스, 치즈,과 함께 해요.\\n5. **요거라스**: 요거라스는 전 세계의 야식 중 하나로, 치즈, 소스, 마늘,과 함께 해요.\\n\\n이러한 야식을 추천해드렸습니다. 어떤 야식을 liked 하신가요?'}\n"
     ]
    }
   ]
  }
 ]
}