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 |
|