Spaces:
Running
Running
File size: 8,767 Bytes
60494ed fd19f35 60494ed 6ab2eb1 2ce0a69 230eb9d 6ab2eb1 60494ed 6ab2eb1 97c98c3 fd19f35 6ab2eb1 60494ed 6ab2eb1 038c199 ec31743 6ab2eb1 038c199 60494ed 038c199 60494ed 6ab2eb1 60494ed 6ab2eb1 b1255dd fd19f35 2ce0a69 fd19f35 b1255dd fd19f35 b1255dd fd19f35 b1255dd fd19f35 160d6ec fd19f35 c1d8f2f bb76d8d c1d8f2f fd19f35 aaf2b16 b1255dd fd19f35 aaf2b16 fd19f35 2ce0a69 fd19f35 2ce0a69 fd19f35 8d38f4a fd19f35 aaf2b16 fd19f35 68c6b90 fd19f35 6ab2eb1 b1255dd |
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 |
import os
import json
import re
import gradio as gr
from google import genai
from google.genai import types
import asyncio
from datasets import load_dataset, DatasetDict, Dataset
from huggingface_hub import login
import datetime
# Authenticate with HF token
hf_token = os.getenv("HF_TOKEN")
login(token=hf_token)
dataset_name = "spriambada3/ehealth_transcribe"
def init_dataset():
try:
dataset = load_dataset(dataset_name)
except Exception as e:
print(e)
dataset = DatasetDict(
{"data": Dataset.from_dict({"logintime": [], "email": [], "wa": []})}
)
print("init dataset result ")
print(dataset)
return dataset
def add_user(dataset, email, wa):
new_data = {
"logintime": datetime.datetime.now(),
"email": email,
"wa": wa,
}
dataset["data"] = dataset["data"].add_item(new_data)
dataset.push_to_hub(dataset_name) # Save to HF Hub
print("add data successful")
def audio_from_bytes(audio_file_path: str):
"""Converts an audio file into Gemini-compatible format."""
try:
with open(audio_file_path, "rb") as f:
audio_data = f.read()
mime_type = "audio/mp3" # Adjust based on your audio type
return types.Part.from_bytes(data=audio_data, mime_type=mime_type)
except FileNotFoundError:
return "Error: Audio file not found!"
except Exception as e:
return f"An error occurred: {e}"
def transcribe_and_summarize(audio_file, session):
"""Processes audio with Gemini API and returns a SOAP summary."""
if audio_file is None:
return "No audio file uploaded."
# Ensure API Key is set
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
if not GEMINI_API_KEY:
return "Error: GEMINI_API_KEY environment variable is missing."
asyncio.set_event_loop(asyncio.new_event_loop())
client = genai.Client(api_key=GEMINI_API_KEY)
model = "gemini-2.0-flash"
# Prepare the request
contents = [
types.Content(
role="user",
parts=[
types.Part.from_text(
text="""Anda adalah asisten medis yang membantu dokter dalam menyusun catatan medis dalam bentuk paragraf menggunakan bahasa Indonesia.
Buat ringkasan SOAP berdasarkan percakapan dokter dan pasien dalam format berikut:
Subjective:
ICD10:
Objective:
Assessment:
Plan:
Identifikasi dan berikan saran dalam bahasa Indonesia tindakan logis selanjutnya dalam format:
ICD10:
Obat:
Laboratorium:
Radiologi:
"""
),
audio_from_bytes(audio_file),
],
)
]
generate_content_config = types.GenerateContentConfig(
temperature=0,
top_p=0.95,
top_k=40,
max_output_tokens=8192,
response_mime_type="text/plain",
)
# Process the audio
response_text = ""
for chunk in client.models.generate_content_stream(
model=model,
contents=contents,
config=generate_content_config,
):
response_text += chunk.text
counter_display, session = click_button(session)
return response_text, counter_display, session
DATA_FILE = "user_data.json"
def load_user_data():
"""Load user data from JSON file."""
if os.path.exists(DATA_FILE):
with open(DATA_FILE, "r") as file:
return json.load(file)
return {} # Return empty dictionary if no data
def save_user_data(username, email):
"""Save user data to JSON file with default counter = 10 if new."""
data = load_user_data()
if username not in data: # New user
data[username] = {"email": email, "counter": 10} # Set default counter to 10
with open(DATA_FILE, "w") as file:
json.dump(data, file, indent=4)
wa = username
dataset = init_dataset()
add_user(dataset, email, wa)
return data
def is_valid_wa(username):
"""Check if username is all numbers, at least 11 characters, and starts with 08 or 62."""
return re.fullmatch(r"^(08|62)\d{9,}$", username) is not None
def is_valid_email(email):
"""Check if email format is valid."""
return re.fullmatch(r"^[\w\.-]+@[\w\.-]+\.\w+$", email) is not None
def login(username, email, session):
"""Handles user login or registration with validation."""
if not is_valid_wa(username):
return (
"❌ Invalid WA! Nomor WA minimal 12 digits dimulai '08' atau '62'.",
session,
gr.update(visible=True),
gr.update(visible=False),
)
if not is_valid_email(email):
return (
"❌ Invalid email format! Please enter a valid email.",
session,
gr.update(visible=True),
gr.update(visible=False),
)
data = save_user_data(username, email) # Save or retrieve user data
session["username"] = username
session["counter"] = data[username]["counter"]
return "", session, gr.update(visible=False), gr.update(visible=True)
def click_button(session):
"""Decrease counter on button click."""
err = f"⚠️ Quota habis. Silahkan mengunjungi https://ehealth.co.id atau WA 6285777779926 untuk menambah kuota"
if session["counter"] > 0:
session["counter"] -= 1
# Update the user data in JSON file
data = load_user_data()
data[session["username"]]["counter"] = session["counter"]
with open(DATA_FILE, "w") as file:
json.dump(data, file, indent=4)
if session["counter"] == 0:
return (err, session)
return f"Quota: {session['counter']}", session
else:
return (err, session)
# Gradio Interface
with gr.Blocks(theme=gr.themes.Default()) as demo:
session = gr.State({"username": None, "counter": 0}) # Manage session state
# Login Section
login_block = gr.Column(visible=True)
with login_block:
gr.HTML(
"""
<div style="text-align: center;">
<a href="https://youtube.com/shorts/DmiVhj9ROag?si=j5Opmjny3kNdLlrf" target="_blank" style="font-size: 20px;">
<strong>Klik disini untuk Demo Video <img src="https://upload.wikimedia.org/wikipedia/commons/b/b8/YouTube_Logo_2017.svg" alt="YouTube" width="100"><br></strong>
</a>
</div>
"""
)
email_input = gr.Textbox(label="Email")
username_input = gr.Textbox(label="WA", type="password") # Hide input
login_button = gr.Button("🔑 Login / Register")
gr.Markdown(
"""### dengan login, saya menyetujui ketentuan penggunaan data perusahaan https://eHealth.co.id dan tidak akan menuntut eHealth.co.id dalam uji coba gratis AI Transkripsi Medis ini
seluruh data yang saya sediakan adalah data yang benar dan tidak melanggar hukum
saya memahami bahwa tidak ada data suara maupun tulisan medis yang akan disimpan oleh eHealth.co.id, namun perusahaan tidak dapat menjamin perlakuan data penyedia model AI (OpenAI, DeepSeek, Google, Mistral, dll.)
### setelah quota habis, saya dapat menambah quota dengan mengunjungi https://ehealth.co.id atau WA 6285777779926"""
)
output_text = gr.Textbox(label="Status", interactive=False)
# Main User Interface (After Login)
user_block = gr.Column(visible=False)
with user_block:
counter_display = gr.Textbox(label="Status Message", interactive=False)
gr.Interface(
fn=transcribe_and_summarize,
inputs=[gr.Audio(type="filepath", sources="microphone"), session],
outputs=["text", counter_display, session],
description="Halo, pastikan HP/Laptop memiliki microphone untuk merekam percakapan dokter-pasien menjadi rekam medis SOAP. Akun berlangganan https://ehealth.co.id dapat terintegrasi SATUSEHAT & BPJS secara otomatis",
allow_flagging="never",
theme="light",
)
use_case_description = gr.Markdown(
"""
Selain Rekam Medis Pasien, dokumen lain yang dapat digitalisasi:
- Surgery Notes atau Catatan Tindakan Lain
- Inform Concern (Dokter dan Keluarga Pasien/Pasien)
- Counseling
- Nursing reports
- Clinical documentation
- Continue Care Document (untuk RS dokumentasi pemberian obat, infus, dll)."""
)
# Login button action
login_button.click(
login,
[username_input, email_input, session],
[output_text, session, login_block, user_block],
trigger_mode="once",
)
demo.launch(allowed_paths=["./images/eHwhite.png", "eHwhite.png", "./images/pp.png"])
|