Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,30 +9,9 @@ from nltk.tokenize import sent_tokenize
|
|
| 9 |
from newspaper import Article
|
| 10 |
|
| 11 |
from sentence_transformers import SentenceTransformer, util
|
| 12 |
-
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 13 |
import torch
|
| 14 |
|
| 15 |
-
# --- Download GGUF model from Hugging Face Hub at startup (if not present) ---
|
| 16 |
-
from huggingface_hub import hf_hub_download
|
| 17 |
-
|
| 18 |
-
GGUF_FILENAME = "gemma-3b-it-Q4_K_M.gguf"
|
| 19 |
-
GGUF_REPO = "unsloth/gemma-3n-E4B-it-GGUF"
|
| 20 |
-
print("Checking for GGUF model...")
|
| 21 |
-
gguf_path = hf_hub_download(
|
| 22 |
-
repo_id=GGUF_REPO,
|
| 23 |
-
filename=GGUF_FILENAME,
|
| 24 |
-
cache_dir="./"
|
| 25 |
-
)
|
| 26 |
-
print(f"GGUF model path: {gguf_path}")
|
| 27 |
-
|
| 28 |
-
# Load Llama GGUF model via llama-cpp-python
|
| 29 |
-
from llama_cpp import Llama
|
| 30 |
-
llm = Llama(
|
| 31 |
-
model_path=gguf_path,
|
| 32 |
-
n_ctx=2048,
|
| 33 |
-
n_threads=4 # or set to number of CPU cores
|
| 34 |
-
)
|
| 35 |
-
|
| 36 |
# --------- App settings ---------
|
| 37 |
PUBMED_N = 100 # Number of abstracts to retrieve initially
|
| 38 |
TOP_ABSTRACTS = 10 # Number of top semantic abstracts to keep per claim
|
|
@@ -70,6 +49,16 @@ nli_tokenizer = AutoTokenizer.from_pretrained(NLI_MODEL_NAME)
|
|
| 70 |
nli_model = AutoModelForSequenceClassification.from_pretrained(NLI_MODEL_NAME)
|
| 71 |
sbert_model = SentenceTransformer(SBERT_MODEL_NAME)
|
| 72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
def extract_claims_pattern(article_text):
|
| 74 |
sentences = sent_tokenize(article_text)
|
| 75 |
claims = [
|
|
@@ -144,23 +133,29 @@ def extract_evidence_nli(claim, title, abstract):
|
|
| 144 |
def summarize_evidence_llm(claim, evidence_list):
|
| 145 |
support = [ev['sentence'] for ev in evidence_list if ev['label'] == 'ENTAILMENT']
|
| 146 |
contradict = [ev['sentence'] for ev in evidence_list if ev['label'] == 'CONTRADICTION']
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
"
|
| 152 |
-
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
try:
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
temperature=0.
|
| 160 |
-
echo=False
|
| 161 |
)
|
| 162 |
-
|
| 163 |
-
|
|
|
|
|
|
|
|
|
|
| 164 |
except Exception as e:
|
| 165 |
return f"Summary could not be generated: {e}"
|
| 166 |
|
|
@@ -225,7 +220,7 @@ This app extracts key scientific claims from a news article, finds the most rele
|
|
| 225 |
3. For each claim, you will see:<br>
|
| 226 |
- A plain summary of what research says.<br>
|
| 227 |
- Color-coded evidence sentences (green=support, red=contradict, gray=neutral).<br>
|
| 228 |
-
-
|
| 229 |
<b>Everything is 100% open source and runs on this website—no personal info or cloud API needed.</b>
|
| 230 |
"""
|
| 231 |
|
|
|
|
| 9 |
from newspaper import Article
|
| 10 |
|
| 11 |
from sentence_transformers import SentenceTransformer, util
|
| 12 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
|
| 13 |
import torch
|
| 14 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
# --------- App settings ---------
|
| 16 |
PUBMED_N = 100 # Number of abstracts to retrieve initially
|
| 17 |
TOP_ABSTRACTS = 10 # Number of top semantic abstracts to keep per claim
|
|
|
|
| 49 |
nli_model = AutoModelForSequenceClassification.from_pretrained(NLI_MODEL_NAME)
|
| 50 |
sbert_model = SentenceTransformer(SBERT_MODEL_NAME)
|
| 51 |
|
| 52 |
+
# --- Load fast Llama-3.2-1B-Instruct summarizer pipeline ---
|
| 53 |
+
model_id = "meta-llama/Llama-3.2-1B-Instruct"
|
| 54 |
+
pipe = pipeline(
|
| 55 |
+
"text-generation",
|
| 56 |
+
model=model_id,
|
| 57 |
+
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
| 58 |
+
device_map="auto",
|
| 59 |
+
max_new_tokens=128,
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
def extract_claims_pattern(article_text):
|
| 63 |
sentences = sent_tokenize(article_text)
|
| 64 |
claims = [
|
|
|
|
| 133 |
def summarize_evidence_llm(claim, evidence_list):
|
| 134 |
support = [ev['sentence'] for ev in evidence_list if ev['label'] == 'ENTAILMENT']
|
| 135 |
contradict = [ev['sentence'] for ev in evidence_list if ev['label'] == 'CONTRADICTION']
|
| 136 |
+
|
| 137 |
+
# Compose prompt for summarization.
|
| 138 |
+
messages = [
|
| 139 |
+
{"role": "system", "content": "You are a helpful biomedical assistant. Summarize scientific evidence in plain English for the general public."},
|
| 140 |
+
{"role": "user", "content":
|
| 141 |
+
f"Claim: {claim}\n"
|
| 142 |
+
f"Supporting evidence:\n" + ("\n".join(support) if support else "None") + "\n"
|
| 143 |
+
f"Contradicting evidence:\n" + ("\n".join(contradict) if contradict else "None") + "\n"
|
| 144 |
+
"Explain to a layperson: Is this claim likely true, false, or uncertain based on the evidence above? Give a brief and simple explanation in 2-3 sentences."
|
| 145 |
+
}
|
| 146 |
+
]
|
| 147 |
try:
|
| 148 |
+
outputs = pipe(
|
| 149 |
+
messages,
|
| 150 |
+
max_new_tokens=96,
|
| 151 |
+
do_sample=False,
|
| 152 |
+
temperature=0.1,
|
|
|
|
| 153 |
)
|
| 154 |
+
out = outputs[0]["generated_text"]
|
| 155 |
+
# If the model returns all messages, just take the last message (often the answer).
|
| 156 |
+
if isinstance(out, list) and "content" in out[-1]:
|
| 157 |
+
return out[-1]["content"].strip()
|
| 158 |
+
return out.strip()
|
| 159 |
except Exception as e:
|
| 160 |
return f"Summary could not be generated: {e}"
|
| 161 |
|
|
|
|
| 220 |
3. For each claim, you will see:<br>
|
| 221 |
- A plain summary of what research says.<br>
|
| 222 |
- Color-coded evidence sentences (green=support, red=contradict, gray=neutral).<br>
|
| 223 |
+
- The titles of the most relevant PubMed articles.<br><br>
|
| 224 |
<b>Everything is 100% open source and runs on this website—no personal info or cloud API needed.</b>
|
| 225 |
"""
|
| 226 |
|