Vargock commited on
Commit
5cdaf63
·
0 Parent(s):

First commit

Browse files
Files changed (10) hide show
  1. .gitignore +4 -0
  2. README.MD +18 -0
  3. app.py +42 -0
  4. db.py +68 -0
  5. requirements.txt +0 -0
  6. static/normalize.css +379 -0
  7. static/style.css +79 -0
  8. templates/history.html +46 -0
  9. templates/index.html +31 -0
  10. utils.py +85 -0
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .venv/
2
+ db/
3
+ __pycache__/
4
+ .env
README.MD ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Smart Notes
2
+
3
+ A quite basic small demo using Hugging Face public APIs to summarize notes, extract tags, and detect sentiment.
4
+ It saves everything to a SQLite database, and you can see your recent notes in a basic history page.
5
+
6
+ Built with Python and Flask. All credit goes to the people who made the models — I’m just calling them.
7
+
8
+ ## Models used
9
+ - facebook/bart-large-cnn (summarization)
10
+ - dslim/bert-base-NER (tags)
11
+ - cardiffnlp/twitter-roberta-base-sentiment (sentiment)
12
+
13
+ ## Notes
14
+ - Works best with English text. Non-English input may not work.
15
+ - Stores notes locally in SQLite; you can view recent notes in a history page.
16
+
17
+ ## Disclaimer
18
+ All credit goes to the teams behind the Hugging Face models. This project is just a small interface for their APIs.
app.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import uuid
2
+ from flask import Flask, render_template, request, session
3
+ from db import init_db, save_history, get_user_history, enforce_history_limit
4
+ from utils import summarize_text, extract_tags, detect_sentiment
5
+
6
+ app = Flask(__name__)
7
+ app.secret_key = "dev-secret" # creates an ID for session cookies
8
+ init_db()
9
+
10
+ @app.before_request
11
+ def assign_user_id():
12
+ if "user_id" not in session:
13
+ session["user_id"] = str(uuid.uuid4())
14
+
15
+ @app.route("/", methods=["GET", "POST"])
16
+ def index():
17
+ summary = tags = sentiment = None
18
+ if request.method == "POST":
19
+ text = request.form["text"].strip()
20
+ if not text:
21
+ return render_template("index.html", error="Please enter some text.")
22
+
23
+ user_id = session["user_id"]
24
+ enforce_history_limit(user_id)
25
+
26
+ summary = summarize_text(text)
27
+ tags = extract_tags(text)
28
+ sentiment = detect_sentiment(text)
29
+
30
+ save_history(user_id, text, summary, tags, sentiment)
31
+
32
+ print(session)
33
+ return render_template("index.html", summary=summary, tags=tags, sentiment=sentiment)
34
+
35
+ @app.route("/history")
36
+ def history():
37
+ user_id = session.get("user_id")
38
+ notes = get_user_history(user_id)
39
+ return render_template("history.html", notes=notes)
40
+
41
+ if __name__ == "__main__":
42
+ app.run(debug=True)
db.py ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+ import os
3
+ from datetime import datetime
4
+
5
+ DB_PATH = "db/data.db"
6
+ os.makedirs("db", exist_ok=True)
7
+
8
+ def get_connection():
9
+ return sqlite3.connect(DB_PATH)
10
+
11
+ def init_db():
12
+ conn = get_connection()
13
+ cur = conn.cursor()
14
+ cur.execute("""
15
+ CREATE TABLE IF NOT EXISTS history (
16
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
17
+ user_id TEXT NOT NULL,
18
+ original TEXT,
19
+ summary TEXT,
20
+ tags TEXT,
21
+ sentiment TEXT,
22
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
23
+ )
24
+ """)
25
+ conn.commit()
26
+ conn.close()
27
+
28
+ def save_history(user_id, original, summary, tags, sentiment):
29
+ conn = get_connection()
30
+ cur = conn.cursor()
31
+ cur.execute("""
32
+ INSERT INTO history (user_id, original, summary, tags, sentiment)
33
+ VALUES (?, ?, ?, ?, ?)
34
+ """, (user_id, original, summary, tags, sentiment))
35
+ conn.commit()
36
+ conn.close()
37
+
38
+ def get_user_history(user_id, limit=20):
39
+ conn = get_connection()
40
+ cur = conn.cursor()
41
+ cur.execute("""
42
+ SELECT original, summary, tags, sentiment, created_at
43
+ FROM history
44
+ WHERE user_id = ?
45
+ ORDER BY created_at DESC
46
+ LIMIT ?
47
+ """, (user_id, limit))
48
+ rows = cur.fetchall()
49
+ conn.close()
50
+ return rows
51
+
52
+ def enforce_history_limit(user_id, max_entries=20):
53
+ conn = get_connection()
54
+ cur = conn.cursor()
55
+ cur.execute("SELECT COUNT(*) FROM history WHERE user_id = ?", (user_id,))
56
+ count = cur.fetchone()[0]
57
+ if count >= max_entries:
58
+ to_delete = count - max_entries + 1
59
+ cur.execute("""
60
+ DELETE FROM history
61
+ WHERE id IN (
62
+ SELECT id FROM history WHERE user_id = ?
63
+ ORDER BY created_at ASC
64
+ LIMIT ?
65
+ )
66
+ """, (user_id, to_delete))
67
+ conn.commit()
68
+ conn.close()
requirements.txt ADDED
Binary file (106 Bytes). View file
 
static/normalize.css ADDED
@@ -0,0 +1,379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
2
+
3
+ /* Document
4
+ ========================================================================== */
5
+
6
+ /**
7
+ * 1. Correct the line height in all browsers.
8
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
9
+ */
10
+
11
+ html {
12
+ line-height: 1.15;
13
+ /* 1 */
14
+ -webkit-text-size-adjust: 100%;
15
+ /* 2 */
16
+ }
17
+
18
+ /* Sections
19
+ ========================================================================== */
20
+
21
+ /**
22
+ * Remove the margin in all browsers.
23
+ */
24
+
25
+ body {
26
+ margin: 0;
27
+ }
28
+
29
+ /**
30
+ * Render the `main` element consistently in IE.
31
+ */
32
+
33
+ main {
34
+ display: block;
35
+ }
36
+
37
+ /**
38
+ * Correct the font size and margin on `h1` elements within `section` and
39
+ * `article` contexts in Chrome, Firefox, and Safari.
40
+ */
41
+
42
+ h1 {
43
+ font-size: 2em;
44
+ margin: 0.67em 0;
45
+ }
46
+
47
+ /* Grouping content
48
+ ========================================================================== */
49
+
50
+ /**
51
+ * 1. Add the correct box sizing in Firefox.
52
+ * 2. Show the overflow in Edge and IE.
53
+ */
54
+
55
+ hr {
56
+ box-sizing: content-box;
57
+ /* 1 */
58
+ height: 0;
59
+ /* 1 */
60
+ overflow: visible;
61
+ /* 2 */
62
+ }
63
+
64
+ /**
65
+ * 1. Correct the inheritance and scaling of font size in all browsers.
66
+ * 2. Correct the odd `em` font sizing in all browsers.
67
+ */
68
+
69
+ pre {
70
+ font-family: monospace, monospace;
71
+ /* 1 */
72
+ font-size: 1em;
73
+ /* 2 */
74
+ }
75
+
76
+ /* Text-level semantics
77
+ ========================================================================== */
78
+
79
+ /**
80
+ * Remove the gray background on active links in IE 10.
81
+ */
82
+
83
+ a {
84
+ background-color: transparent;
85
+ }
86
+
87
+ /**
88
+ * 1. Remove the bottom border in Chrome 57-
89
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
90
+ */
91
+
92
+ abbr[title] {
93
+ border-bottom: none;
94
+ /* 1 */
95
+ text-decoration: underline;
96
+ /* 2 */
97
+ text-decoration: underline dotted;
98
+ /* 2 */
99
+ }
100
+
101
+ /**
102
+ * Add the correct font weight in Chrome, Edge, and Safari.
103
+ */
104
+
105
+ b,
106
+ strong {
107
+ font-weight: bolder;
108
+ }
109
+
110
+ /**
111
+ * 1. Correct the inheritance and scaling of font size in all browsers.
112
+ * 2. Correct the odd `em` font sizing in all browsers.
113
+ */
114
+
115
+ code,
116
+ kbd,
117
+ samp {
118
+ font-family: monospace, monospace;
119
+ /* 1 */
120
+ font-size: 1em;
121
+ /* 2 */
122
+ }
123
+
124
+ /**
125
+ * Add the correct font size in all browsers.
126
+ */
127
+
128
+ small {
129
+ font-size: 80%;
130
+ }
131
+
132
+ /**
133
+ * Prevent `sub` and `sup` elements from affecting the line height in
134
+ * all browsers.
135
+ */
136
+
137
+ sub,
138
+ sup {
139
+ font-size: 75%;
140
+ line-height: 0;
141
+ position: relative;
142
+ vertical-align: baseline;
143
+ }
144
+
145
+ sub {
146
+ bottom: -0.25em;
147
+ }
148
+
149
+ sup {
150
+ top: -0.5em;
151
+ }
152
+
153
+ /* Embedded content
154
+ ========================================================================== */
155
+
156
+ /**
157
+ * Remove the border on images inside links in IE 10.
158
+ */
159
+
160
+ img {
161
+ border-style: none;
162
+ }
163
+
164
+ /* Forms
165
+ ========================================================================== */
166
+
167
+ /**
168
+ * 1. Change the font styles in all browsers.
169
+ * 2. Remove the margin in Firefox and Safari.
170
+ */
171
+
172
+ button,
173
+ input,
174
+ optgroup,
175
+ select,
176
+ textarea {
177
+ font-family: inherit;
178
+ /* 1 */
179
+ font-size: 100%;
180
+ /* 1 */
181
+ line-height: 1.15;
182
+ /* 1 */
183
+ margin: 0;
184
+ /* 2 */
185
+ }
186
+
187
+ /**
188
+ * Show the overflow in IE.
189
+ * 1. Show the overflow in Edge.
190
+ */
191
+
192
+ button,
193
+ input {
194
+ /* 1 */
195
+ overflow: visible;
196
+ }
197
+
198
+ /**
199
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
200
+ * 1. Remove the inheritance of text transform in Firefox.
201
+ */
202
+
203
+ button,
204
+ select {
205
+ /* 1 */
206
+ text-transform: none;
207
+ }
208
+
209
+ /**
210
+ * Correct the inability to style clickable types in iOS and Safari.
211
+ */
212
+
213
+ button,
214
+ [type="button"],
215
+ [type="reset"],
216
+ [type="submit"] {
217
+ -webkit-appearance: button;
218
+ }
219
+
220
+ /**
221
+ * Remove the inner border and padding in Firefox.
222
+ */
223
+
224
+ button::-moz-focus-inner,
225
+ [type="button"]::-moz-focus-inner,
226
+ [type="reset"]::-moz-focus-inner,
227
+ [type="submit"]::-moz-focus-inner {
228
+ border-style: none;
229
+ padding: 0;
230
+ }
231
+
232
+ /**
233
+ * Restore the focus styles unset by the previous rule.
234
+ */
235
+
236
+ button:-moz-focusring,
237
+ [type="button"]:-moz-focusring,
238
+ [type="reset"]:-moz-focusring,
239
+ [type="submit"]:-moz-focusring {
240
+ outline: 1px dotted ButtonText;
241
+ }
242
+
243
+ /**
244
+ * Correct the padding in Firefox.
245
+ */
246
+
247
+ fieldset {
248
+ padding: 0.35em 0.75em 0.625em;
249
+ }
250
+
251
+ /**
252
+ * 1. Correct the text wrapping in Edge and IE.
253
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
254
+ * 3. Remove the padding so developers are not caught out when they zero out
255
+ * `fieldset` elements in all browsers.
256
+ */
257
+
258
+ legend {
259
+ box-sizing: border-box;
260
+ /* 1 */
261
+ color: inherit;
262
+ /* 2 */
263
+ display: table;
264
+ /* 1 */
265
+ max-width: 100%;
266
+ /* 1 */
267
+ padding: 0;
268
+ /* 3 */
269
+ white-space: normal;
270
+ /* 1 */
271
+ }
272
+
273
+ /**
274
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
275
+ */
276
+
277
+ progress {
278
+ vertical-align: baseline;
279
+ }
280
+
281
+ /**
282
+ * Remove the default vertical scrollbar in IE 10+.
283
+ */
284
+
285
+ textarea {
286
+ overflow: auto;
287
+ }
288
+
289
+ /**
290
+ * 1. Add the correct box sizing in IE 10.
291
+ * 2. Remove the padding in IE 10.
292
+ */
293
+
294
+ [type="checkbox"],
295
+ [type="radio"] {
296
+ box-sizing: border-box;
297
+ /* 1 */
298
+ padding: 0;
299
+ /* 2 */
300
+ }
301
+
302
+ /**
303
+ * Correct the cursor style of increment and decrement buttons in Chrome.
304
+ */
305
+
306
+ [type="number"]::-webkit-inner-spin-button,
307
+ [type="number"]::-webkit-outer-spin-button {
308
+ height: auto;
309
+ }
310
+
311
+ /**
312
+ * 1. Correct the odd appearance in Chrome and Safari.
313
+ * 2. Correct the outline style in Safari.
314
+ */
315
+
316
+ [type="search"] {
317
+ -webkit-appearance: textfield;
318
+ /* 1 */
319
+ outline-offset: -2px;
320
+ /* 2 */
321
+ }
322
+
323
+ /**
324
+ * Remove the inner padding in Chrome and Safari on macOS.
325
+ */
326
+
327
+ [type="search"]::-webkit-search-decoration {
328
+ -webkit-appearance: none;
329
+ }
330
+
331
+ /**
332
+ * 1. Correct the inability to style clickable types in iOS and Safari.
333
+ * 2. Change font properties to `inherit` in Safari.
334
+ */
335
+
336
+ ::-webkit-file-upload-button {
337
+ -webkit-appearance: button;
338
+ /* 1 */
339
+ font: inherit;
340
+ /* 2 */
341
+ }
342
+
343
+ /* Interactive
344
+ ========================================================================== */
345
+
346
+ /*
347
+ * Add the correct display in Edge, IE 10+, and Firefox.
348
+ */
349
+
350
+ details {
351
+ display: block;
352
+ }
353
+
354
+ /*
355
+ * Add the correct display in all browsers.
356
+ */
357
+
358
+ summary {
359
+ display: list-item;
360
+ }
361
+
362
+ /* Misc
363
+ ========================================================================== */
364
+
365
+ /**
366
+ * Add the correct display in IE 10+.
367
+ */
368
+
369
+ template {
370
+ display: none;
371
+ }
372
+
373
+ /**
374
+ * Add the correct display in IE 10.
375
+ */
376
+
377
+ [hidden] {
378
+ display: none;
379
+ }
static/style.css ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ body {
2
+ box-sizing: border-box;
3
+ margin: 2rem;
4
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
5
+ background-color: #f5f5f5;
6
+ color: #333;
7
+ line-height: 1.6;
8
+ }
9
+
10
+ h1 {
11
+ text-align: center;
12
+ margin-bottom: 2rem;
13
+ }
14
+
15
+ form {
16
+ max-width: 800px;
17
+ margin: 0 auto;
18
+ }
19
+
20
+ textarea {
21
+ width: 100%;
22
+ min-height: 150px;
23
+ padding: 0.75rem;
24
+ border: 1px solid #ccc;
25
+ border-radius: 5px;
26
+ font-size: 1rem;
27
+ resize: vertical;
28
+ }
29
+
30
+
31
+
32
+ button {
33
+ padding: 0.6rem 1.2rem;
34
+ background-color: #4a90e2;
35
+ color: white;
36
+ border: none;
37
+ border-radius: 5px;
38
+ cursor: pointer;
39
+ font-size: 1rem;
40
+ margin-top: 1rem;
41
+ }
42
+
43
+ button:hover {
44
+ background-color: #357ab8;
45
+ }
46
+
47
+
48
+ table {
49
+ width: 100%;
50
+ border-collapse: collapse;
51
+ margin-top: 1.5rem;
52
+ }
53
+
54
+ th,
55
+ td {
56
+ border: 1px solid #ccc;
57
+ padding: 0.75rem;
58
+ text-align: center;
59
+ }
60
+
61
+ th {
62
+ background-color: #4a90e2;
63
+ color: white;
64
+ }
65
+
66
+ a {
67
+ display: inline-block;
68
+ margin-top: 1rem;
69
+ text-decoration: none;
70
+ color: #4a90e2;
71
+ }
72
+
73
+ a:hover {
74
+ text-decoration: underline;
75
+ }
76
+
77
+ .link-wrapper {
78
+ text-align: center;
79
+ }
templates/history.html ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>History - Smart Notes</title>
8
+ <link rel="stylesheet" href="{{ url_for('static', filename='normalize.css') }}">
9
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
10
+ </head>
11
+
12
+ <body>
13
+ <h1>History</h1>
14
+ <a href="/" class="btn">← Back</a>
15
+
16
+ {% if notes %}
17
+ <table>
18
+ <thead>
19
+ <tr>
20
+ <th>#</th>
21
+ <th>Original Text</th>
22
+ <th>Summary</th>
23
+ <th>Tags</th>
24
+ <th>Sentiment</th>
25
+ <th>Created</th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ {% for note in notes %}
30
+ <tr>
31
+ <td>{{ loop.index }}</td>
32
+ <td>{{ note[0][:150] }}{% if note[0]|length > 150 %}...{% endif %}</td>
33
+ <td>{{ note[1] }}</td>
34
+ <td>{{ note[2] }}</td>
35
+ <td>{{ note[3] }}</td>
36
+ <td>{{ note[4][:19] }}</td>
37
+ </tr>
38
+ {% endfor %}
39
+ </tbody>
40
+ </table>
41
+ {% else %}
42
+ <p>No notes yet. Try creating one!</p>
43
+ {% endif %}
44
+ </body>
45
+
46
+ </html>
templates/index.html ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Smart Notes Summarizer</title>
8
+ <link rel="stylesheet" href="{{ url_for('static', filename='normalize.css') }}">
9
+ <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
10
+ </head>
11
+
12
+ <body class="p-4">
13
+ <h1>Notes Summarizer</h1>
14
+ <form method="POST">
15
+ <textarea name="text" rows="8" class="form-control" placeholder="Paste your text here..."></textarea>
16
+ <button class="btn btn-primary mt-3">Analyze</button>
17
+ </form>
18
+
19
+ {% if summary %}
20
+ <hr>
21
+ <h4>Summary:</h4>
22
+ <p>{{ summary }}</p>
23
+ <h4>Tags:</h4>
24
+ <p>{{ tags }}</p>
25
+ <h4>Sentiment:</h4>
26
+ <p>{{ sentiment }}</p>
27
+ {% endif %}
28
+ <p class="link-wrapper"><a href="{{ url_for('history') }}" class="btn btn-secondary mt-3">View History</a></p>
29
+ </body>
30
+
31
+ </html>
utils.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from dotenv import load_dotenv
4
+
5
+ load_dotenv()
6
+
7
+ HF_API_TOKEN = os.getenv("HF_API_TOKEN")
8
+ SUMMARIZATION_MODEL = "facebook/bart-large-cnn"
9
+ TAGS_MODEL = "dslim/bert-base-NER"
10
+ SENTIMENT_MODEL = "cardiffnlp/twitter-roberta-base-sentiment"
11
+ LABEL_MAP = {"LABEL_0": "Negative", "LABEL_1": "Neutral", "LABEL_2": "Positive"}
12
+
13
+ ERROR_400_MSG = "Oops! Error 400 — this model might not understand that language. Try using English! If you did, then something went wrong on our end. Sorry x("
14
+ TIMEOUT = 30
15
+
16
+ def summarize_text(text):
17
+ headers = {"Authorization": f"Bearer {HF_API_TOKEN}"}
18
+ payload = {"inputs": text, "parameters": {"min_length": 30, "max_length": 130}}
19
+
20
+ try:
21
+ resp = requests.post(
22
+ f"https://api-inference.huggingface.co/models/{SUMMARIZATION_MODEL}",
23
+ headers=headers,
24
+ json=payload,
25
+ timeout=TIMEOUT
26
+ )
27
+ resp.raise_for_status()
28
+ out = resp.json()
29
+ if isinstance(out, list) and out:
30
+ return out[0]["summary_text"]
31
+ return str(out)
32
+ except requests.exceptions.HTTPError as e:
33
+ if e.response.status_code == 400:
34
+ return ERROR_400_MSG
35
+ return f"Hugging Face API inference failed: {e}"
36
+
37
+
38
+ def extract_tags(text):
39
+ headers = {"Authorization": f"Bearer {HF_API_TOKEN}"}
40
+ payload = {"inputs": text}
41
+
42
+ try:
43
+ resp = requests.post(
44
+ f"https://api-inference.huggingface.co/models/{TAGS_MODEL}",
45
+ headers=headers,
46
+ json=payload,
47
+ timeout=TIMEOUT
48
+ )
49
+ resp.raise_for_status()
50
+ out = resp.json()
51
+
52
+ entities = [item.get("word") for item in out if "word" in item]
53
+ tags = list(set(entities))
54
+ return ", ".join(tags) if tags else "No tags found."
55
+ except requests.exceptions.HTTPError as e:
56
+ if e.response.status_code == 400:
57
+ return ERROR_400_MSG
58
+ return f"Hugging Face API inference failed: {e}"
59
+
60
+
61
+
62
+ def detect_sentiment(text):
63
+ headers = {"Authorization": f"Bearer {HF_API_TOKEN}"}
64
+ payload = {"inputs": text}
65
+
66
+ try:
67
+ resp = requests.post(
68
+ f"https://api-inference.huggingface.co/models/{SENTIMENT_MODEL}",
69
+ headers=headers,
70
+ json=payload,
71
+ timeout=TIMEOUT
72
+ )
73
+ resp.raise_for_status()
74
+ out = resp.json()
75
+
76
+ if isinstance(out, list) and len(out) > 0:
77
+ result = out[0] if isinstance(out[0], list) else out
78
+
79
+ best = max(result, key=lambda x: x["score"])
80
+ return LABEL_MAP.get(best["label"], "Unknown")
81
+ return "Unknown"
82
+ except requests.exceptions.HTTPError as e:
83
+ if e.response.status_code == 400:
84
+ return ERROR_400_MSG
85
+ return f"Hugging Face API inference failed: {e}"