Bonosa2 commited on
Commit
3e19cd3
·
verified ·
1 Parent(s): a255cfc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -123
app.py CHANGED
@@ -1,140 +1,93 @@
1
  import os
2
- import torch
3
  import pandas as pd
4
- import easyocr
5
  import gradio as gr
6
- from transformers import (
7
- AutoConfig,
8
- AutoProcessor,
9
- AutoTokenizer,
10
- AutoModelForImageTextToText
11
- )
12
 
13
- MODEL_ID = "google/gemma-3n-e2b-it"
14
- HF_TOKEN = os.environ.get("HF_TOKEN") # set via Space secrets
15
 
16
- # 1) Load the model and OCR reader
17
- config = AutoConfig.from_pretrained(MODEL_ID, trust_remote_code=True, use_auth_token=HF_TOKEN)
18
  processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True, use_auth_token=HF_TOKEN)
19
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True, use_auth_token=HF_TOKEN)
20
- model = AutoModelForImageTextToText.from_pretrained(
21
- MODEL_ID,
22
- config=config,
23
- trust_remote_code=True,
24
- use_auth_token=HF_TOKEN,
25
- load_in_8bit=True,
26
- device_map="auto"
27
- )
28
- device = next(model.parameters()).device
29
-
30
- ocr_reader = easyocr.Reader(['en'], gpu=torch.cuda.is_available(), verbose=False)
31
-
32
- def generate_soap_note(text: str) -> str:
33
- prompt = f"""You are a medical AI assistant. Convert these notes into a SOAP note:
34
-
35
- {text}
36
-
37
- Format as:
38
- S - SUBJECTIVE:
39
- O - OBJECTIVE:
40
- A - ASSESSMENT:
41
- P - PLAN:
42
 
43
- Produce the complete SOAP."""
44
- inputs = processor.apply_chat_template(
45
- [
46
- {"role":"system","content":[{"type":"text","text":"Expert medical AI assistant."}]},
47
- {"role":"user", "content":[{"type":"text","text":prompt}]}
48
- ],
49
- add_generation_prompt=True,
50
- tokenize=True,
51
- return_dict=True,
52
- return_tensors="pt"
53
- ).to(device)
54
- input_len = inputs["input_ids"].shape[-1]
55
- with torch.no_grad():
 
 
 
 
 
 
 
 
 
 
56
  out = model.generate(
57
  **inputs,
58
  max_new_tokens=400,
59
  do_sample=True,
60
- top_p=0.95,
61
  temperature=0.1,
62
- pad_token_id=processor.tokenizer.eos_token_id,
63
- disable_compile=True
64
  )
65
- return processor.batch_decode(out[:, input_len:], skip_special_tokens=True)[0].strip()
66
-
67
- # 2) On startup: generate 100 synthetic note pairs and save TSVs
68
- docs, soaps = [], []
69
- for i in range(1, 101):
70
- doc = generate_soap_note("Generate a realistic, concise doctor's progress note for a single patient encounter.")
71
- docs.append(doc)
72
- soaps.append(generate_soap_note(doc))
73
- if i % 10 == 0:
74
- print(f"Generated {i}/100")
75
-
76
- pd.DataFrame({"doc_note": docs}).to_csv("doc_notes.tsv", sep="\t", index=False)
77
- pd.DataFrame({"soap_note": soaps}).to_csv("ground_truth_soap.tsv", sep="\t", index=False)
78
- print("✅ Saved doc_notes.tsv & ground_truth_soap.tsv")
79
-
80
- # Colab/Kaggle/Space Cell: Split, infer on train (70), infer on test (30), and save files
81
-
82
- import os
83
- import pandas as pd
84
- from sklearn.model_selection import train_test_split
85
-
86
- # Make outputs directory
87
- os.makedirs("outputs", exist_ok=True)
88
-
89
- # 1) Load generated notes and ground truths
90
- docs = pd.read_csv("doc_notes.tsv", sep="\t") # has column 'doc_note'
91
- gts = pd.read_csv("ground_truth_soap.tsv", sep="\t") # has column 'soap_note'
92
-
93
- full = pd.DataFrame({
94
- "doc_note": docs["doc_note"],
95
- "ground_truth_soap": gts["soap_note"]
96
- })
97
-
98
- # 2) Split 70% train / 30% test
99
- train_df, test_df = train_test_split(full, test_size=0.3, random_state=42)
100
-
101
- # 3) Run inference on the 70‑row train split and save inference.tsv
102
- train_preds = []
103
- for idx, row in train_df.reset_index(drop=True).iterrows():
104
- pred = generate_soap_note(row["doc_note"])
105
- train_preds.append(pred)
106
-
107
- inference_df = train_df.reset_index(drop=True).copy()
108
- inference_df["id"] = inference_df.index + 1
109
- inference_df["predicted_soap"] = train_preds
110
- inference_df = inference_df[["id","ground_truth_soap","predicted_soap"]]
111
- inference_df.to_csv("outputs/inference.tsv", sep="\t", index=False)
112
-
113
- # 4) Run inference on the 30��row test split and save eval.csv
114
- test_preds = []
115
- for idx, row in test_df.reset_index(drop=True).iterrows():
116
- pred = generate_soap_note(row["doc_note"])
117
- test_preds.append(pred)
118
-
119
- eval_df = pd.DataFrame({
120
- "id": range(1, len(test_preds) + 1),
121
- "predicted_soap": test_preds
122
- })
123
- eval_df.to_csv("outputs/eval.csv", index=False)
124
-
125
- print("✅ Saved:")
126
- print(" outputs/inference.tsv (70 rows: id, ground_truth_soap, predicted_soap)")
127
- print(" outputs/eval.csv (30 rows: id, predicted_soap)")
128
-
129
-
130
- # 3) Blank Gradio UI placeholder
131
- def noop():
132
- return "Data generated — check TSV files in the repo."
133
 
134
  with gr.Blocks() as demo:
135
- gr.Markdown("# SOAP Generator Space")
136
- gr.Button("Generate Completed (see logs)").click(noop, [], "output")
137
- gr.Textbox(label="Status", interactive=False, lines=2, placeholder="Ready", elem_id="output")
 
138
 
139
- if __name__ == "__main__":
140
- demo.queue().launch(server_name="0.0.0.0", server_port=7860)
 
1
  import os
 
2
  import pandas as pd
 
3
  import gradio as gr
4
+ from kaggle_secrets import UserSecretsClient
5
+ from transformers import AutoProcessor, AutoTokenizer, AutoModelForImageTextToText
6
+ from sklearn.model_selection import train_test_split
7
+ import torch
 
 
8
 
9
+ HF_TOKEN = UserSecretsClient().get_secret("HF_TOKEN")
10
+ MODEL_ID = "google/gemma-3n-e2b-it"
11
 
12
+ # Only load small pieces at startup
 
13
  processor = AutoProcessor.from_pretrained(MODEL_ID, trust_remote_code=True, use_auth_token=HF_TOKEN)
14
  tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True, use_auth_token=HF_TOKEN)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ def generate_all_notes():
17
+ # 1) Load the full 8‑bit model on demand
18
+ model = AutoModelForImageTextToText.from_pretrained(
19
+ MODEL_ID,
20
+ trust_remote_code=True,
21
+ use_auth_token=HF_TOKEN,
22
+ load_in_8bit=True,
23
+ device_map="auto"
24
+ )
25
+ device = next(model.parameters()).device
26
+
27
+ # helper to turn text→SOAP
28
+ def to_soap(text):
29
+ inputs = processor.apply_chat_template(
30
+ [
31
+ {"role":"system","content":[{"type":"text","text":"You are a medical AI assistant."}]},
32
+ {"role":"user", "content":[{"type":"text","text":text}]}
33
+ ],
34
+ add_generation_prompt=True,
35
+ tokenize=True,
36
+ return_tensors="pt",
37
+ return_dict=True
38
+ ).to(device)
39
  out = model.generate(
40
  **inputs,
41
  max_new_tokens=400,
42
  do_sample=True,
 
43
  temperature=0.1,
44
+ top_p=0.95,
45
+ pad_token_id=processor.tokenizer.eos_token_id
46
  )
47
+ return processor.batch_decode(out[:, inputs["input_ids"].shape[-1]:], skip_special_tokens=True)[0].strip()
48
+
49
+ # 2) Generate 100 raw docs + ground truths
50
+ docs, gts = [], []
51
+ for i in range(100):
52
+ doc = to_soap("Generate a realistic, concise doctor's progress note for a single patient encounter.")
53
+ docs.append(doc)
54
+ gts.append(to_soap(doc))
55
+ if (i+1) % 20 == 0:
56
+ torch.cuda.empty_cache()
57
+
58
+ # 3) Split 70/30
59
+ full_df = pd.DataFrame({"doc_note": docs, "ground_truth_soap": gts})
60
+ train_df, test_df = train_test_split(full_df, test_size=0.3, random_state=42)
61
+
62
+ os.makedirs("outputs", exist_ok=True)
63
+
64
+ # 4) Inference on train split → inference.tsv
65
+ train_preds = [to_soap(d) for d in train_df["doc_note"]]
66
+ inf = train_df.reset_index(drop=True).copy()
67
+ inf["id"] = inf.index + 1
68
+ inf["predicted_soap"] = train_preds
69
+ inf[["id","ground_truth_soap","predicted_soap"]].to_csv(
70
+ "outputs/inference.tsv", sep="\t", index=False
71
+ )
72
+
73
+ # 5) Inference on test split → eval.csv
74
+ test_preds = [to_soap(d) for d in test_df["doc_note"]]
75
+ pd.DataFrame({
76
+ "id": range(1, len(test_preds)+1),
77
+ "predicted_soap": test_preds
78
+ }).to_csv("outputs/eval.csv", index=False)
79
+
80
+ return (
81
+ "✅ Done!\n"
82
+ f"– outputs/inference.tsv (70 rows with id, GT & pred)\n"
83
+ f"– outputs/eval.csv (30 rows with id & pred)"
84
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  with gr.Blocks() as demo:
87
+ gr.Markdown("## Gemma‑3n SOAP Generator")
88
+ btn = gr.Button("Generate 100 split 70/30 → inference & eval")
89
+ out = gr.Textbox(interactive=False, label="Status")
90
+ btn.click(fn=generate_all_notes, inputs=None, outputs=out)
91
 
92
+ if __name__=="__main__":
93
+ demo.launch()