Pushing app.py + requirements.txt + custom dataset
Browse files- .gitignore +3 -0
- app.py +126 -0
- custom_terms.csv +11 -0
- requirements.txt +7 -0
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
venv
|
| 2 |
+
keys.txt
|
| 3 |
+
.gradio\flagged
|
app.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
import random
|
| 4 |
+
import numpy as np
|
| 5 |
+
import pandas as pd
|
| 6 |
+
import gradio as gr
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
|
| 9 |
+
from transformers import pipeline, set_seed
|
| 10 |
+
from sentence_transformers import SentenceTransformer
|
| 11 |
+
from datasets import load_dataset
|
| 12 |
+
|
| 13 |
+
# 1. Initialize LLM
|
| 14 |
+
print("Loading BioMistral LLM...")
|
| 15 |
+
llm = pipeline('text-generation', model='BioMistral/BioMistral-7B')
|
| 16 |
+
|
| 17 |
+
# 2. Load Datasets
|
| 18 |
+
print("Loading datasets...")
|
| 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 |
+
# 3. Format dataset rows into strings
|
| 25 |
+
texts = []
|
| 26 |
+
for row in dataset:
|
| 27 |
+
content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
|
| 28 |
+
texts.append(content)
|
| 29 |
+
for row in dataset2:
|
| 30 |
+
content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
|
| 31 |
+
texts.append(content)
|
| 32 |
+
for row in dataset3:
|
| 33 |
+
content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
|
| 34 |
+
texts.append(content)
|
| 35 |
+
for row in dataset4:
|
| 36 |
+
content = f"Medical Context: {row['Expert']}\nSimplified Explanation: {row['Simple']}\nTerms: {row['expert_terms']}, {row['layman_terms']}"
|
| 37 |
+
texts.append(content)
|
| 38 |
+
|
| 39 |
+
print(f"Total processed documents: {len(texts)}")
|
| 40 |
+
|
| 41 |
+
# 4. Generate Embeddings & Index
|
| 42 |
+
print("Indexing dataset embeddings...")
|
| 43 |
+
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
|
| 44 |
+
embeddings = embedding_model.encode(texts)
|
| 45 |
+
|
| 46 |
+
df = pd.DataFrame({
|
| 47 |
+
"Document": texts,
|
| 48 |
+
"Embedding": list(embeddings)
|
| 49 |
+
})
|
| 50 |
+
|
| 51 |
+
# 5. Retrieval Helper Function
|
| 52 |
+
def retrieve_with_pandas(query, top_k=3):
|
| 53 |
+
query_embedding = embedding_model.encode([query])[0]
|
| 54 |
+
df['Similarity'] = df['Embedding'].apply(
|
| 55 |
+
lambda x: np.dot(query_embedding, x) / (np.linalg.norm(query_embedding) * np.linalg.norm(x))
|
| 56 |
+
)
|
| 57 |
+
results = df.sort_values(by="Similarity", ascending=False).head(top_k)
|
| 58 |
+
return results["Document"].tolist()
|
| 59 |
+
|
| 60 |
+
# 6. Prompt Builder Helper Function
|
| 61 |
+
def build_prompt(context_docs: list, user_query: str) -> str:
|
| 62 |
+
context = "\n\n".join(context_docs)
|
| 63 |
+
prompt = f"""<s>[INST] You are a helpful medical assistant.
|
| 64 |
+
Use the following retrieved medical context to answer the user's question clearly and concisely.
|
| 65 |
+
Explain it in very simple terms as if the user has the vocabulary of an elementary school student.
|
| 66 |
+
If the context does not contain enough information to answer, state that you don't know based on the provided text.
|
| 67 |
+
Answer in 2 to 3 sentences maximum.
|
| 68 |
+
|
| 69 |
+
Context:
|
| 70 |
+
{context}
|
| 71 |
+
|
| 72 |
+
Question:
|
| 73 |
+
{user_query} [/INST]"""
|
| 74 |
+
return prompt
|
| 75 |
+
|
| 76 |
+
# 7. Answer Generation Helper Function
|
| 77 |
+
def generate_answer(prompt: str, max_new_tokens: int = 150) -> str:
|
| 78 |
+
set_seed(42)
|
| 79 |
+
|
| 80 |
+
if llm.model.config.pad_token_id is None:
|
| 81 |
+
llm.model.config.pad_token_id = llm.model.config.eos_token_id
|
| 82 |
+
|
| 83 |
+
output = llm(
|
| 84 |
+
prompt,
|
| 85 |
+
max_new_tokens=max_new_tokens,
|
| 86 |
+
num_return_sequences=1,
|
| 87 |
+
do_sample=False,
|
| 88 |
+
)[0]["generated_text"]
|
| 89 |
+
|
| 90 |
+
# Strip out the prompt text to leave only the model's new response
|
| 91 |
+
answer = output[len(prompt):].strip()
|
| 92 |
+
return answer
|
| 93 |
+
|
| 94 |
+
# 8. RAG Handler Function
|
| 95 |
+
def respond_to_query(user_query: str) -> str:
|
| 96 |
+
if not user_query.strip():
|
| 97 |
+
return "Please enter a valid medical question or term."
|
| 98 |
+
|
| 99 |
+
# Step A: Retrieve context documents based on user input
|
| 100 |
+
context_docs = retrieve_with_pandas(user_query, top_k=3)
|
| 101 |
+
|
| 102 |
+
# Step B: Build prompt with retrieved context
|
| 103 |
+
prompt = build_prompt(context_docs, user_query)
|
| 104 |
+
|
| 105 |
+
# Step C: Generate model answer
|
| 106 |
+
answer = generate_answer(prompt, max_new_tokens=150)
|
| 107 |
+
|
| 108 |
+
return answer
|
| 109 |
+
|
| 110 |
+
# 9. Gradio Web Interface
|
| 111 |
+
demo = gr.Interface(
|
| 112 |
+
fn=respond_to_query,
|
| 113 |
+
inputs=gr.Textbox(lines=2, placeholder="e.g., What is necrosis? or What is cholera?"),
|
| 114 |
+
outputs=gr.Textbox(label="BioMistral RAG Response", lines=4),
|
| 115 |
+
title="🩺 Medical Terminology RAG Assistant",
|
| 116 |
+
description="Ask a medical question to retrieve context from Med-EASi + custom terms and generate simplified explanations.",
|
| 117 |
+
examples=[
|
| 118 |
+
["What causes necrosis?"],
|
| 119 |
+
["What is cholera?"],
|
| 120 |
+
["What is asbestosis?"],
|
| 121 |
+
["How can syphilis be treated?"]
|
| 122 |
+
]
|
| 123 |
+
)
|
| 124 |
+
|
| 125 |
+
if __name__ == "__main__":
|
| 126 |
+
demo.launch()
|
custom_terms.csv
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Expert,Simple,expert_terms,layman_terms
|
| 2 |
+
Necrosis is a form of cell injury which results in the premature death of cells in living tissue by destruction of the cell through the action of its own enzymes,"Unnatural cell death caused by severe damage, where cells are broken down by themselves.",necrosis,cell death
|
| 3 |
+
"Anaphylaxis is a severe, systemic, and potentially life-threatening allergic reaction that occurs rapidly following exposure to an allergen.","A sudden, severe, and dangerous allergic reaction that affects the whole body.",anaphylaxis,severe allergic reaction
|
| 4 |
+
"Ischemia is a restriction in blood supply to tissues, causing a shortage of oxygen needed for cellular metabolism.",A lack of adequate blood flow and oxygen to a part of the body.,ischemia,restricted blood flow
|
| 5 |
+
Thoracentesis is a procedure in which a needle is inserted into the pleural space between the lungs and chest wall to remove excess fluid.,A medical procedure where a doctor uses a needle to drain fluid from around the lungs.,thoracentesis,lung fluid removal
|
| 6 |
+
Thrombolysis is the breakdown or dissolution of blood clots formed in blood vessels using pharmacological agents.,The use of special medication to quickly dissolve dangerous blood clots.,thrombolysis,clot dissolving
|
| 7 |
+
"Atelectasis is a complete or partial collapse of the entire lung or lobe of the lung, occurring when the alveoli become deflated or filled with alveolar fluid.",A condition where part or all of a lung collapses because the air sacs deflate.,atelectasis,collapsed lung
|
| 8 |
+
"Kinetosis is a neurological condition caused by a sensory conflict between the vestibular, visual, and proprioceptive systems during real or perceived motion.","A feeling of nausea, dizziness, or cold sweats when your brain gets conflicting signals from your eyes and inner ears about movement.",kinetosis,motion sickness
|
| 9 |
+
"Dyspnea is the clinical term for shortness of breath, often described as an intense tightening in the chest, air hunger, or difficulty breathing.",Difficulty breathing or feeling short of breath.,dyspnea,shortness of breath
|
| 10 |
+
Idiopathic describes any disease or condition that arises spontaneously and for which the cause is currently unknown or obscure.,A medical condition or symptom that happens without any known cause.,idiopathic,unknown cause
|
| 11 |
+
Metastasis is the pathogenic process by which cancer cells spread from the primary site of origin to distant tissues or organs.,The process where cancer cells spread from where they started to other parts of the body.,metastasis,cancer spread
|
requirements.txt
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
transformers
|
| 2 |
+
sentence-transformers
|
| 3 |
+
datasets
|
| 4 |
+
pandas
|
| 5 |
+
numpy
|
| 6 |
+
torch
|
| 7 |
+
gradio
|