Skip to content

1window2/MedBuddy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

107 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

CodeQL FastAPI Flutter

πŸ’Š MedBuddy

AI-Powered Medication Management System
An intelligent platform that digitizes prescriptions via OCR and fine-tuned LLMs, providing a personalized AI pharmacist for safe medication management.


🌟 Key Features

  • πŸ“Έ AI Vision Prescription Parsing
    • Simply snap a photo of a prescription or pill envelope. Our AI instantly extracts structured data (hospital name, prescription date, medication names, and dosage).
    • Automatically masks Personally Identifiable Information (PII) to ensure data privacy.
  • πŸ‘©β€βš•οΈ Personalized AI Pharmacist
    • Leverages public health data to translate complex medical jargon into friendly, easy-to-understand instructions.
  • πŸ—‚οΈ Smart Pillbox Management
    • Easily track and manage your current medications, their efficacy, and important precautions in one place.

πŸ›  Tech Stack

Frontend

Flutter Dart

Backend

FastAPI Python SQLite

AI & API

Gemini OpenCV Public Data


βš™οΈ System Architecture

flowchart TD
    %% Custom Styling
    classDef client fill:#02569B,stroke:#fff,stroke-width:2px,color:#fff,rx:8px,ry:8px
    classDef server fill:#005571,stroke:#fff,stroke-width:2px,color:#fff,rx:8px,ry:8px
    classDef ai fill:#8E75B2,stroke:#fff,stroke-width:2px,color:#fff,rx:8px,ry:8px
    classDef db fill:#07405e,stroke:#fff,stroke-width:2px,color:#fff,rx:8px,ry:8px

    subgraph Frontend [πŸ“± Client Tier - Flutter]
        C1(πŸ“Έ Capture<br/>Prescription):::client
        C2(πŸ–₯️ Structured<br/>UI Display):::client
        C3(πŸ” Request<br/>Detail & Save):::client
        C4(πŸ—‚οΈ Update<br/>Pillbox UI):::client
    end

    subgraph Backend [πŸš€ Server Tier - FastAPI]
        S1(βš™οΈ Image Preprocessing<br/>OpenCV):::server
        S2(πŸ›‘οΈ PII Masking &<br/>Data Structuring):::server
        S3(🧠 Routing &<br/>Business Logic):::server
        DB[(πŸ’Ύ SQLite<br/>Database)]:::db
    end

    subgraph External [πŸ€– AI & External APIs]
        AI1{{✨ Fine-Tuned<br/>LLM Vision}}:::ai
        PUB{{πŸ›οΈ Public Drug<br/>Safety API}}:::ai
        AI2{{✨ Fine-Tuned<br/>LLM Text}}:::ai
    end

    %% Flow 1: Vision Parsing (Current)
    C1 -->|Multipart Image| S1
    S1 -->|Processed Bytes| AI1
    AI1 -->|Raw JSON| S2
    S2 -->|Response DTO| C2

    %% Flow 2: Detail & Save (Planned)
    C2 -.->|User Click| C3
    C3 -->|Drug Name| S3
    S3 -->|Query| PUB
    PUB -->|Raw Efficacy Data| AI2
    AI2 -->|Pharmacist Summary| S3
    S3 -->|ORM Entity| DB
    S3 -->|Success Response| C4
Loading
πŸ“ŠClass Diagram

Class Diagram

classDiagram
    direction TD
    skinparam classAttributeIconSize 0

    %% ==========================================
    %% πŸ“± 1. FRONTEND TIER (Flutter Dart Files)
    %% ==========================================
    namespace Frontend_Application {
        
        class main_dart {
            <<Entry Point : main.dart>>
            +main() void
        }
        
        class MedBuddyApp {
            <<Widget : main.dart>>
            +build(context) Widget
        }

        class HomeScreen {
            <<View : home_screen.dart>>
            +build(context) Widget
            -_buildInfoBadge(label, value) Widget
        }

        class PillboxScreen {
            <<View : pillbox_screen.dart>>
            +createState() _PillboxScreenState
        }

        class _PillboxScreenState {
            <<State : pillbox_screen.dart>>
            +initState() void
            +build(context) Widget
        }

        class MedicationViewModel {
            <<ViewModel : medication_viewmodel.dart>>
            -_apiService : ApiService
            -_picker : ImagePicker
            -_apiUrl : String
            -_isLoading : bool
            -_statusMessage : String
            -_hospitalName : String
            -_prescriptionDate : String
            -_parsedDrugList : List~dynamic~
            -_savedDrugs : List~DrugInfo~
            +processMedicationImage() void
            -_setLoading(value) void
            +saveDrugToPillbox(drug) bool
            +fetchPillbox() void
            +removeDrugFromPillbox(id) void
        }

        class ApiService {
            <<Service : api_service.dart>>
            +baseUrl : String
            +identifyMedication(text) List~DrugInfo~
            +saveMedication(drug) bool
            +getSavedMedications() List~DrugInfo~
            +deleteMedication(id) bool
            +parsePrescription(ocrText) Map
        }
        
        class VisionService {
            <<Service : vision_service.dart>>
            -_picker : ImagePicker
            -_textRecognizer : TextRecognizer
            +captureAndRecognizeText() String
            +dispose() void
        }
        
        class PrescriptionParser_Dart {
            <<Utility : prescription_parser.dart>>
            +maskPrivacyInfo(text) String
            +extractDosageInfo(text) Map
        }

        class DrugInfo_Dart {
            <<Model : drug_info.dart>>
            +itemName : String
            +efficacy : String
            +useMethod : String
            +warningMessage : String
            +aiGuide : String
            +id : int
            +fromJson(json) DrugInfo
        }
    }

    %% ==========================================
    %% πŸš€ 2. BACKEND API & CONTROLLER TIER
    %% ==========================================
    namespace Backend_API {
        
        class FastAPIApp {
            <<Entry Point : main.py>>
            +app : FastAPI
            +include_router() void
        }

        class MedicationRouter {
            <<Controller : api/router.py>>
            +identify_medication(request, ocr, drug) MedicationResponse
            +save_medication(medication, db) dict
            +get_saved_medications(db) dict
            +delete_medication(drug_id, db) dict
            +parse_prescription_endpoint(request, ocr) dict
            +upload_and_parse_prescription(file, ocr) PrescriptionData
        }
    }

    %% ==========================================
    %% 🧠 3. BACKEND BUSINESS LOGIC TIER
    %% ==========================================
    namespace Backend_Services {
        
        class Settings {
            <<Config : core/config.py>>
            +GEMINI_API_KEY : str
            +PUBLIC_DATA_API_KEY : str
            +BASIC_DRUG_API_BASE_URL : str
            +ADVANCED_DRUG_API_BASE_URL : str
        }

        class OCRService {
            <<Service : services/ocr_service.py>>
            +process_text(raw_text) str
            +split_lines(raw_text) List~str~
            +parse_prescription_text(raw_text) dict
            +extract_prescription_data(image_bytes) PrescriptionData
            -_apply_secondary_masking(data) dict
        }

        class DrugService {
            <<Service : services/drug_service.py>>
            +api_key : str
            +basic_url : str
            +advanced_url : str
            +fetch_drug_info(drug_name) List~DrugInfo~
        }

        class PrescriptionParser_Python {
            <<Utility : utils/prescription_parser.py>>
            +normalize_text(text) str
            +normalize_date(text) str
            +extract_patient_name(line) str
            +parse_medication_line(line) dict
            +parse_prescription(lines) dict
        }
    }

    %% ==========================================
    %% πŸ—„οΈ 4. BACKEND DATA TIER (DB & Schemas)
    %% ==========================================
    namespace Backend_Data {
        
        class DatabaseModule {
            <<Config : core/database.py>>
            +engine : Engine
            +SessionLocal : sessionmaker
            +Base : declarative_base
            +get_db() Iterator~Session~
        }

        class SavedMedication {
            <<Entity : models/db_models.py>>
            +id : Integer
            +item_name : String
            +efficacy : String
            +use_method : String
            +warning_message : String
            +ai_guide : String
        }

        class MedicationSchemas {
            <<DTO : schemas/medication.py>>
            +class MedicationRequest
            +class DrugInfo
            +class SavedMedicationCreate
            +class MedicationResponse
        }

        class OCRSchemas {
            <<DTO : schemas/ocr.py>>
            +class MedicationItem
            +class PrescriptionData
        }
    }

    %% ==========================================
    %% πŸ”— RELATIONSHIPS (관계망 μ—°κ²°)
    %% ==========================================
    
    %% Frontend Relationships
    main_dart ..> MedBuddyApp : Runs
    MedBuddyApp ..> HomeScreen : Uses
    MedBuddyApp ..> MedicationViewModel : Provides
    
    PillboxScreen ..> _PillboxScreenState : Creates
    HomeScreen ..> MedicationViewModel : Observes
    _PillboxScreenState ..> MedicationViewModel : Observes
    
    MedicationViewModel --> ApiService : Uses
    MedicationViewModel o-- DrugInfo_Dart : Aggregation
    ApiService ..> DrugInfo_Dart : Maps Data
    
    VisionService ..> PrescriptionParser_Dart : Can Use
    
    %% Client-Server Connection
    MedicationViewModel ..> FastAPIApp : HTTP Multipart Request
    ApiService ..> FastAPIApp : HTTP Network Protocol

    %% Backend Controller Relationships
    FastAPIApp --> MedicationRouter : Registers
    FastAPIApp ..> DatabaseModule : Creates Tables
    MedicationRouter ..> DatabaseModule : Uses get_db()
    MedicationRouter --> SavedMedication : DB CRUD Operations
    MedicationRouter --> OCRService : Injects
    MedicationRouter --> DrugService : Injects
    MedicationRouter ..> MedicationSchemas : Request/Response
    MedicationRouter ..> OCRSchemas : Request/Response

    %% Backend Service Dependencies
    OCRService --> PrescriptionParser_Python : Uses
    OCRService ..> OCRSchemas : Returns
    DrugService ..> Settings : Reads Config
    DrugService ..> MedicationSchemas : Returns
Loading
πŸ“ŠSequence Diagram

Phase 1. AI Vision Parsing & Secure Data Extraction

sequenceDiagram
    autonumber
    
    actor User as μ‚¬μš©μž
    participant View as HomeScreen
    participant VM as MedicationViewModel
    participant API as FastAPI (main.py)
    participant Router as MedicationRouter
    participant OCR as OCRService
    participant AI as Gemini Vision API
    
    User->>View: 'μ²˜λ°©μ „ 촬영' λ²„νŠΌ 클릭
    
    activate View
    View->>VM: processMedicationImage()
    activate VM
    
    VM->>VM: _picker.pickImage(camera) 호좜
    
    alt 촬영 μ™„λ£Œ μ‹œ
        VM->>VM: _setLoading(true)
        VM-->>View: notifyListeners() (μŠ€ν”Όλ„ˆ λ Œλ”λ§)
        
        Note over VM, API: HTTP Multipart POST /upload-prescription
        VM->>API: μ²˜λ°©μ „ 이미지 파일(imageFile) 전솑
        activate API
        
        API->>Router: upload_and_parse_prescription()
        activate Router
        
        Router->>OCR: extract_prescription_data(image_bytes)
        activate OCR
        
        OCR->>OCR: preprocess_prescription_image() μ „μ²˜λ¦¬
        
        OCR->>AI: model.generate_content_async() 호좜
        activate AI
        Note over OCR, AI: λ³΄μ•ˆ ν”„λ‘¬ν”„νŠΈ + 이미지 전솑
        AI-->>OCR: κ΅¬μ‘°ν™”λœ JSON Text 응닡 λ°˜ν™˜
        deactivate AI
        
        OCR->>OCR: λ§ˆν¬λ‹€μš΄ 제거 및 JSON λ””μ½”λ”©
        OCR->>OCR: _apply_secondary_masking() (μ •κ·œμ‹ 2μ°¨ λ§ˆμŠ€ν‚Ή)
        
        OCR-->>Router: PrescriptionData (DTO 객체) λ°˜ν™˜
        deactivate OCR
        
        Router-->>API: HTTP 200 OK
        deactivate Router
        
        API-->>VM: JSON 응닡 μˆ˜μ‹  (decodedBody)
        deactivate API
        
        VM->>VM: _parsedDrugList μ—…λ°μ΄νŠΈ & _setLoading(false)
        VM-->>View: notifyListeners() (κ²°κ³Ό ν™”λ©΄ λ Œλ”λ§)
    end
    deactivate VM
    View-->>User: 병원 정보 및 μΆ”μΆœλœ μ•½ν’ˆ λͺ©λ‘ UI ν‘œμ‹œ
    deactivate View

    Note over User, View: μ‚¬μš©μžκ°€ ν™”λ©΄μ˜ μ•½ν’ˆ 리슀트λ₯Ό ν™•μΈν•˜λ©° λŒ€κΈ°
Loading

Phase 2. Public API Enrichment & AI Pharmacist Summary

sequenceDiagram
    autonumber
    
    actor User as μ‚¬μš©μž
    participant View as HomeScreen
    participant VM as MedicationViewModel
    participant ApiS as ApiService (Dart)
    participant Router as MedicationRouter
    participant OCR as OCRService
    participant DrugS as DrugService
    participant PubAPI as 곡곡데이터 API
    participant AI as Gemini Text API
    participant DB as SQLite DB

    Note over User, View: Phase 1μ—μ„œ μΆ”μΆœλœ μ•½ν’ˆ λͺ©λ‘ 쀑 ν•˜λ‚˜λ₯Ό μ„ νƒν•˜μ—¬ μ§„ν–‰
    
    User->>View: μ•½ν’ˆ λ¦¬μŠ€νŠΈμ—μ„œ '상세 뢄석 & μ €μž₯' 클릭
    activate View
    
    View->>VM: saveDrugToPillbox(DrugInfo)
    activate VM
    VM-->>View: μƒνƒœ λ©”μ‹œμ§€ μ—…λ°μ΄νŠΈ (μ €μž₯ 쀑...)
    
    VM->>ApiS: identifyMedication(text) 호좜
    activate ApiS
    Note over ApiS, Router: HTTP POST /identify
    ApiS->>Router: μ•½ν’ˆλͺ…(extracted_text) 전솑
    activate Router
    
    Router->>OCR: process_text() λ…Έμ΄μ¦ˆ 제거
    OCR-->>Router: μ •μ œλœ 검색어(search_keyword) λ°˜ν™˜
    
    Router->>DrugS: fetch_drug_info(search_keyword)
    activate DrugS
    DrugS->>PubAPI: HTTP GET eμ•½μ€μš” API 호좜
    PubAPI-->>DrugS: XML/JSON 원본 데이터 λ°˜ν™˜
    DrugS-->>Router: List<DrugInfo> λ°˜ν™˜ (효λŠ₯, μ£Όμ˜μ‚¬ν•­ 포함)
    deactivate DrugS
    
    Router->>AI: model.generate_content_async(μ‹μ•½μ²˜ 원본 데이터)
    activate AI
    Note over Router, AI: "μΉœμ ˆν•œ 약사 말투둜 1~2쀄 μš”μ•½ν•΄μ€˜" ν”„λ‘¬ν”„νŠΈ 전솑
    AI-->>Router: μΉœμ ˆν•œ AI κ°€μ΄λ“œ ν…μŠ€νŠΈ(ai_guide) λ°˜ν™˜
    deactivate AI
    
    Router-->>ApiS: MedicationResponse JSON λ°˜ν™˜
    deactivate Router
    
    ApiS->>ApiS: DrugInfo.fromJson() λͺ¨λΈ λ§€ν•‘
    
    Note over ApiS, Router: HTTP POST /save
    ApiS->>Router: μ™„μ„±λœ DrugInfo 전솑
    activate Router
    
    Router->>DB: db.add(SavedMedication) & db.commit()
    activate DB
    DB-->>Router: DB μ €μž₯ 성곡 확인
    deactivate DB
    
    Router-->>ApiS: μ €μž₯ 성곡 응닡
    deactivate Router
    
    ApiS-->>VM: boolean(success) λ°˜ν™˜
    deactivate ApiS
    
    VM->>VM: fetchPillbox() 호좜 (데이터 μ΅œμ‹ ν™”)
    VM-->>View: μ €μž₯ μ™„λ£Œ λ©”μ‹œμ§€ ν‘œμ‹œ
    deactivate VM
    
    View-->>User: SnackBar μ•Œλ¦Ό ("μ„±κ³΅μ μœΌλ‘œ μ €μž₯λ˜μ—ˆμŠ΅λ‹ˆλ‹€!")
    deactivate View
Loading

πŸš€ Getting Started

1. Backend Setup

$ cd backend
$ pip install -r requirements.txt
$ uvicorn main:app --reload

2. Frontend Setup

$ cd frontend
$ flutter pub get
$ flutter run

πŸ‘₯ Contributors

Profile Name Role GitHub
1window2 Lead Full-Stack Developer & AI Pipeline Architecture @1window2
tmdgusdl9647 Backend Developer & AI Logic @tmdgusdl9647
jeeon0318 Backend Developer & Compliance Specialist @jeeon0318
onlyone130 Frontend Designer & UI/UX Lead @onlyone130

About

MedBuddy is a AI-powered medication management system digitizing prescriptions via OCR and LLM for patient safety

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors