JayNightmare commited on
Commit
4160327
·
verified ·
1 Parent(s): aadc000

Add FakeNews Gradio interface

Browse files
Files changed (4) hide show
  1. README.md +15 -7
  2. __pycache__/app.cpython-313.pyc +0 -0
  3. app.py +219 -0
  4. requirements.txt +7 -0
README.md CHANGED
@@ -1,13 +1,21 @@
1
  ---
2
- title: FakeNews Interface
3
- emoji: 🏢
4
- colorFrom: yellow
5
- colorTo: yellow
6
  sdk: gradio
7
  sdk_version: 6.19.0
8
- python_version: '3.13'
9
  app_file: app.py
10
- pinned: false
 
 
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: FakeNews Classifier
 
 
 
3
  sdk: gradio
4
  sdk_version: 6.19.0
 
5
  app_file: app.py
6
+ license: mit
7
+ models:
8
+ - JayNightmare/FakeNews
9
  ---
10
 
11
+ # FakeNews Classifier
12
+
13
+ Gradio interface for the `JayNightmare/FakeNews` PEFT LoRA adapter.
14
+
15
+ The model repo stores adapter files in `adapter/`, so the Space loads the base model from the adapter config and attaches the adapter with `subfolder="adapter"`.
16
+
17
+ Optional Space environment variables:
18
+
19
+ - `MODEL_REPO`: defaults to `JayNightmare/FakeNews`
20
+ - `ADAPTER_SUBFOLDER`: defaults to `adapter`
21
+ - `BASE_MODEL_ID`: optional override if the adapter config points to a local path
__pycache__/app.cpython-313.pyc ADDED
Binary file (7.77 kB). View file
 
app.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import threading
4
+
5
+ import gradio as gr
6
+ import torch
7
+ from huggingface_hub import hf_hub_download
8
+ from peft import PeftModel
9
+ from transformers import AutoModelForCausalLM, AutoTokenizer
10
+
11
+
12
+ MODEL_REPO = os.getenv("MODEL_REPO", "JayNightmare/FakeNews")
13
+ BASE_MODEL_ID = os.getenv("BASE_MODEL_ID")
14
+ ADAPTER_SUBFOLDER = os.getenv("ADAPTER_SUBFOLDER", "adapter")
15
+
16
+ ADAPTER_SUBFOLDER_CANDIDATES = tuple(
17
+ dict.fromkeys(
18
+ [
19
+ ADAPTER_SUBFOLDER,
20
+ "adapter",
21
+ "FakeNews_Model/adapter",
22
+ "artifacts/FakeNews_Model/adapter",
23
+ "model_adapter",
24
+ "FakeNews_Model/model_adapter",
25
+ "artifacts/FakeNews_Model/model_adapter",
26
+ "",
27
+ ]
28
+ )
29
+ )
30
+
31
+ generation_lock = threading.Lock()
32
+
33
+
34
+ def download_adapter_config():
35
+ last_error = None
36
+
37
+ for subfolder in ADAPTER_SUBFOLDER_CANDIDATES:
38
+ try:
39
+ path = hf_hub_download(
40
+ repo_id=MODEL_REPO,
41
+ filename="adapter_config.json",
42
+ subfolder=subfolder or None,
43
+ )
44
+ return path, subfolder or None
45
+ except Exception as error:
46
+ last_error = error
47
+
48
+ tried = ", ".join(
49
+ subfolder or "<repo root>" for subfolder in ADAPTER_SUBFOLDER_CANDIDATES
50
+ )
51
+ raise RuntimeError(
52
+ "Could not find adapter_config.json. Set ADAPTER_SUBFOLDER to the repo "
53
+ "folder that contains adapter_config.json and adapter_model.safetensors. "
54
+ f"Tried: {tried}."
55
+ ) from last_error
56
+
57
+
58
+ def resolve_base_model_id(adapter_config_path):
59
+ with open(adapter_config_path, "r", encoding="utf-8") as file:
60
+ adapter_config = json.load(file)
61
+
62
+ base_model_id = BASE_MODEL_ID or adapter_config.get("base_model_name_or_path")
63
+
64
+ if not base_model_id:
65
+ raise RuntimeError(
66
+ "Could not resolve the base model. Set BASE_MODEL_ID in the Space environment."
67
+ )
68
+
69
+ if base_model_id.startswith(("/", "./", "../")) and not BASE_MODEL_ID:
70
+ raise RuntimeError(
71
+ "adapter_config.json points to a local base model path. "
72
+ "Set BASE_MODEL_ID to the original Hugging Face base model id."
73
+ )
74
+
75
+ return base_model_id
76
+
77
+
78
+ def load_tokenizer(base_model_id, adapter_subfolder):
79
+ try:
80
+ return AutoTokenizer.from_pretrained(
81
+ MODEL_REPO,
82
+ subfolder=adapter_subfolder,
83
+ trust_remote_code=True,
84
+ )
85
+ except Exception:
86
+ return AutoTokenizer.from_pretrained(
87
+ base_model_id,
88
+ trust_remote_code=True,
89
+ )
90
+
91
+
92
+ def load_model():
93
+ adapter_config_path, adapter_subfolder = download_adapter_config()
94
+ base_model_id = resolve_base_model_id(adapter_config_path)
95
+
96
+ device = "cuda" if torch.cuda.is_available() else "cpu"
97
+ torch_dtype = torch.float16 if device == "cuda" else torch.float32
98
+
99
+ tokenizer = load_tokenizer(base_model_id, adapter_subfolder)
100
+ if tokenizer.pad_token is None:
101
+ tokenizer.pad_token = tokenizer.eos_token
102
+
103
+ base_model = AutoModelForCausalLM.from_pretrained(
104
+ base_model_id,
105
+ torch_dtype=torch_dtype,
106
+ trust_remote_code=True,
107
+ )
108
+
109
+ model = PeftModel.from_pretrained(
110
+ base_model,
111
+ MODEL_REPO,
112
+ subfolder=adapter_subfolder,
113
+ )
114
+ model.to(device)
115
+ model.eval()
116
+
117
+ return model, tokenizer, device, base_model_id, adapter_subfolder
118
+
119
+
120
+ model, tokenizer, device, base_model_id, adapter_subfolder = load_model()
121
+
122
+
123
+ def build_prompt(claim, context):
124
+ context = context.strip() or "No additional context provided."
125
+ messages = [
126
+ {
127
+ "role": "system",
128
+ "content": (
129
+ "You are FakeNews, a misinformation classifier. "
130
+ "Classify the claim using the available context. "
131
+ "Return a concise label and explanation."
132
+ ),
133
+ },
134
+ {
135
+ "role": "user",
136
+ "content": (
137
+ f"Claim:\n{claim.strip()}\n\n"
138
+ f"Context:\n{context}\n\n"
139
+ "Classify this as fake, real, misleading, or uncertain."
140
+ ),
141
+ },
142
+ ]
143
+
144
+ try:
145
+ return tokenizer.apply_chat_template(
146
+ messages,
147
+ tokenize=False,
148
+ add_generation_prompt=True,
149
+ )
150
+ except Exception:
151
+ return (
152
+ "System: You are FakeNews, a misinformation classifier.\n\n"
153
+ f"User: Claim:\n{claim.strip()}\n\n"
154
+ f"Context:\n{context}\n\n"
155
+ "Classify this as fake, real, misleading, or uncertain.\n\n"
156
+ "Assistant:"
157
+ )
158
+
159
+
160
+ def classify(claim, context):
161
+ if not claim or not claim.strip():
162
+ return "Enter a claim to classify."
163
+
164
+ prompt = build_prompt(claim, context or "")
165
+ inputs = tokenizer(
166
+ prompt,
167
+ return_tensors="pt",
168
+ truncation=True,
169
+ max_length=2048,
170
+ ).to(device)
171
+
172
+ with generation_lock:
173
+ with torch.no_grad():
174
+ output_ids = model.generate(
175
+ **inputs,
176
+ max_new_tokens=160,
177
+ do_sample=False,
178
+ pad_token_id=tokenizer.pad_token_id,
179
+ eos_token_id=tokenizer.eos_token_id,
180
+ )
181
+
182
+ generated_ids = output_ids[0][inputs["input_ids"].shape[-1] :]
183
+ return tokenizer.decode(generated_ids, skip_special_tokens=True).strip()
184
+
185
+
186
+ description = (
187
+ f"Loaded adapter from `{MODEL_REPO}`"
188
+ + (f" subfolder `{adapter_subfolder}`" if adapter_subfolder else "")
189
+ + f" on base model `{base_model_id}`."
190
+ )
191
+
192
+ demo = gr.Interface(
193
+ fn=classify,
194
+ inputs=[
195
+ gr.Textbox(label="Claim", lines=3, placeholder="Enter a news claim..."),
196
+ gr.Textbox(
197
+ label="Optional context",
198
+ lines=6,
199
+ placeholder="Paste article or source context here...",
200
+ ),
201
+ ],
202
+ outputs=gr.Textbox(label="FakeNews result", lines=8),
203
+ title="FakeNews Classifier",
204
+ description=description,
205
+ examples=[
206
+ [
207
+ "The Eiffel Tower was originally built for the 1889 World's Fair.",
208
+ "",
209
+ ],
210
+ [
211
+ "A viral post claims drinking salt water cures all viral infections.",
212
+ "No credible medical source supports this claim.",
213
+ ],
214
+ ],
215
+ )
216
+
217
+
218
+ if __name__ == "__main__":
219
+ demo.queue().launch()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ accelerate>=1.7.0
2
+ gradio>=6.19.0
3
+ huggingface_hub>=0.35.0
4
+ peft>=0.16.0
5
+ safetensors>=0.4.5
6
+ torch>=2.7.1
7
+ transformers>=4.52.4