Chz0 commited on
Commit
aec92b4
·
verified ·
1 Parent(s): e29bfe0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -73
app.py CHANGED
@@ -1,67 +1,45 @@
1
  import spaces
2
  import os
3
  import torch
4
- import random
5
  import numpy as np
6
  import pandas as pd
7
  import gradio as gr
8
- from pathlib import Path
9
-
10
  from transformers import pipeline, set_seed
11
  from sentence_transformers import SentenceTransformer
12
  from datasets import load_dataset
13
 
14
- # 1. Initialize LLM
15
- print("Loading BioMistral LLM...")
16
- llm = pipeline('text-generation', model='BioMistral/BioMistral-7B')
 
 
 
17
 
18
- # 2. Load Datasets
19
- print("Loading datasets...")
20
  dataset = load_dataset("cbasu/Med-EASi", split="train")
21
  dataset2 = load_dataset("cbasu/Med-EASi", split="validation")
22
  dataset3 = load_dataset("cbasu/Med-EASi", split="test")
23
  dataset4 = load_dataset("csv", data_files="custom_terms.csv", split="train")
24
 
25
- # 3. Format dataset rows into strings
26
  texts = []
27
- for row in dataset:
28
- content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
29
- texts.append(content)
30
- for row in dataset2:
31
- content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
32
- texts.append(content)
33
- for row in dataset3:
34
- content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
35
- texts.append(content)
36
- for row in dataset4:
37
- content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
38
- texts.append(content)
39
-
40
- print(f"Total processed documents: {len(texts)}")
41
-
42
- # 4. Generate Embeddings & Index
43
- print("Indexing dataset embeddings...")
44
- embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
45
- embeddings = embedding_model.encode(texts)
46
 
47
- df = pd.DataFrame({
48
- "Document": texts,
49
- "Embedding": list(embeddings)
50
- })
51
 
52
- # 5. Retrieval Helper Function
53
  def retrieve_with_pandas(query, top_k=3):
54
  query_embedding = embedding_model.encode([query])[0]
55
  df['Similarity'] = df['Embedding'].apply(
56
  lambda x: np.dot(query_embedding, x) / (np.linalg.norm(query_embedding) * np.linalg.norm(x))
57
  )
58
- results = df.sort_values(by="Similarity", ascending=False).head(top_k)
59
- return results["Document"].tolist()
60
 
61
- # 6. Prompt Builder Helper Function
62
  def build_prompt(context_docs: list, user_query: str) -> str:
63
  context = "\n\n".join(context_docs)
64
- prompt = f"""<s>[INST] You are a helpful medical assistant.
65
  Use the following retrieved medical context to answer the user's question clearly and concisely.
66
  Explain it in very simple terms as if the user has the vocabulary of an elementary school student.
67
  If the context does not contain enough information to answer, state that you don't know based on the provided text.
@@ -72,56 +50,45 @@ Context:
72
 
73
  Question:
74
  {user_query} [/INST]"""
75
- return prompt
76
 
77
- # 7. Answer Generation Helper Function
78
- def generate_answer(prompt: str, max_new_tokens: int = 150) -> str:
79
- set_seed(42)
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
 
 
 
 
81
  if llm.model.config.pad_token_id is None:
82
  llm.model.config.pad_token_id = llm.model.config.eos_token_id
83
 
84
  output = llm(
85
  prompt,
86
- max_new_tokens=max_new_tokens,
87
  num_return_sequences=1,
88
  do_sample=False,
89
  )[0]["generated_text"]
90
 
91
- # Strip out the prompt text to leave only the model's new response
92
- answer = output[len(prompt):].strip()
93
- return answer
94
-
95
- # 8. RAG Handler Function
96
- @spaces.GPU(duration=60)
97
- def respond_to_query(user_query: str) -> str:
98
- if not user_query.strip():
99
- return "Please enter a valid medical question or term."
100
-
101
- # Step A: Retrieve context documents based on user input
102
- context_docs = retrieve_with_pandas(user_query, top_k=3)
103
-
104
- # Step B: Build prompt with retrieved context
105
- prompt = build_prompt(context_docs, user_query)
106
-
107
- # Step C: Generate model answer
108
- answer = generate_answer(prompt, max_new_tokens=80)
109
-
110
- return answer
111
 
112
- # 9. Gradio Web Interface
113
  demo = gr.Interface(
114
  fn=respond_to_query,
115
- inputs=gr.Textbox(lines=2, placeholder="e.g., What is necrosis? or What is cholera?"),
116
- outputs=gr.Textbox(label="BioMistral RAG Response", lines=4),
117
- title="🩺 Medical Terminology RAG Assistant",
118
- description="Ask a medical question to retrieve context from Med-EASi + custom terms and generate simplified explanations.",
119
- examples=[
120
- ["What causes necrosis?"],
121
- ["What is cholera?"],
122
- ["What is asbestosis?"],
123
- ["How can syphilis be treated?"]
124
- ]
125
  )
126
 
127
  if __name__ == "__main__":
 
1
  import spaces
2
  import os
3
  import torch
 
4
  import numpy as np
5
  import pandas as pd
6
  import gradio as gr
 
 
7
  from transformers import pipeline, set_seed
8
  from sentence_transformers import SentenceTransformer
9
  from datasets import load_dataset
10
 
11
+ # 1. Keep LLM instance uninitialized globally
12
+ llm = None
13
+
14
+ # 2. Keep lightweight embeddings on CPU during startup
15
+ print("Indexing dataset embeddings on CPU...")
16
+ embedding_model = SentenceTransformer('all-MiniLM-L6-v2', device='cpu')
17
 
18
+ # Load and process datasets at startup
 
19
  dataset = load_dataset("cbasu/Med-EASi", split="train")
20
  dataset2 = load_dataset("cbasu/Med-EASi", split="validation")
21
  dataset3 = load_dataset("cbasu/Med-EASi", split="test")
22
  dataset4 = load_dataset("csv", data_files="custom_terms.csv", split="train")
23
 
 
24
  texts = []
25
+ for ds in [dataset, dataset2, dataset3, dataset4]:
26
+ for row in ds:
27
+ content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
28
+ texts.append(content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ embeddings = embedding_model.encode(texts)
31
+ df = pd.DataFrame({"Document": texts, "Embedding": list(embeddings)})
 
 
32
 
 
33
  def retrieve_with_pandas(query, top_k=3):
34
  query_embedding = embedding_model.encode([query])[0]
35
  df['Similarity'] = df['Embedding'].apply(
36
  lambda x: np.dot(query_embedding, x) / (np.linalg.norm(query_embedding) * np.linalg.norm(x))
37
  )
38
+ return df.sort_values(by="Similarity", ascending=False).head(top_k)["Document"].tolist()
 
39
 
 
40
  def build_prompt(context_docs: list, user_query: str) -> str:
41
  context = "\n\n".join(context_docs)
42
+ return f"""<s>[INST] You are a helpful medical assistant.
43
  Use the following retrieved medical context to answer the user's question clearly and concisely.
44
  Explain it in very simple terms as if the user has the vocabulary of an elementary school student.
45
  If the context does not contain enough information to answer, state that you don't know based on the provided text.
 
50
 
51
  Question:
52
  {user_query} [/INST]"""
 
53
 
54
+ # 3. Decorate the master generation function
55
+ @spaces.GPU(duration=60)
56
+ def respond_to_query(user_query: str) -> str:
57
+ global llm
58
+ if not user_query.strip():
59
+ return "Please enter a valid medical question."
60
+
61
+ # Lazy-load BioMistral ONLY inside the GPU context
62
+ if llm is None:
63
+ print("Initializing BioMistral on ZeroGPU...")
64
+ llm = pipeline(
65
+ 'text-generation',
66
+ model='BioMistral/BioMistral-7B',
67
+ torch_dtype=torch.bfloat16,
68
+ device_map="auto"
69
+ )
70
 
71
+ context_docs = retrieve_with_pandas(user_query, top_k=3)
72
+ prompt = build_prompt(context_docs, user_query)
73
+
74
+ set_seed(42)
75
  if llm.model.config.pad_token_id is None:
76
  llm.model.config.pad_token_id = llm.model.config.eos_token_id
77
 
78
  output = llm(
79
  prompt,
80
+ max_new_tokens=120,
81
  num_return_sequences=1,
82
  do_sample=False,
83
  )[0]["generated_text"]
84
 
85
+ return output[len(prompt):].strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
 
87
  demo = gr.Interface(
88
  fn=respond_to_query,
89
+ inputs=gr.Textbox(lines=2, placeholder="e.g., What causes necrosis?"),
90
+ outputs=gr.Textbox(label="BioMistral Response", lines=4),
91
+ title="🩺 Medical Terminology RAG Assistant"
 
 
 
 
 
 
 
92
  )
93
 
94
  if __name__ == "__main__":