radames commited on
Commit
a6fd849
1 Parent(s): 1b06101
Files changed (3) hide show
  1. Makefile +2 -6
  2. README.md +23 -7
  3. frontend/src/App.svelte +142 -187
Makefile CHANGED
@@ -1,9 +1,5 @@
1
  build-client:
2
- cd client && npm install && npm run build && pwd && rm -r ../static && cp -r dist/ ../static/
3
- build-client-dev:
4
- cd client && npm install && NODE_ENV=development npm run build && pwd && rm -r ../static/* && cp -r dist/ ../static/
5
- dev:
6
- cd client && npm run dev
7
  run:
8
  FLASK_ENV=development python app.py
9
- build-all: install-node build-client run
 
1
  build-client:
2
+ cd frontend && npm install && npm run build && cp -r dist/ ../dist
 
 
 
 
3
  run:
4
  FLASK_ENV=development python app.py
5
+ build-all: build-client run
README.md CHANGED
@@ -12,16 +12,32 @@ pinned: false
12
 
13
  This project is an experiment running sentiment analysis on the current [New York Times](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml) homepage headlines RSS. It also provides a sorting button to toggle between good and bad news first😛 . It's built with a [custom SvelveKit front-end](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/tree/main/client) , served by a [Flask application](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/app.py) and using [transformers pipeline for the sentiment analysis.](https://huggingface.co/siebert/sentiment-roberta-large-english)
14
 
15
- ### Notes
16
 
17
- #### Install Node with NVM
18
 
19
- This [Node script](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/install-node.sh) install node LTS and create symbolic links to `/home/user/.local/bin/` as it seems like we don't have permission to update `$PATH` env
 
 
 
 
 
20
 
21
- #### main.py
22
 
23
- Because the Spaces run a python application, see [`app_file`](https://huggingface.co/docs/hub/spaces#:~:text=0.88.0%2C%200.89.0%2C%201.0.0.-,app_file,-%3A%20string%0APath%20to) on docs. main.py is just a simple python subprocess to run `make build-all` See [`Makefile`](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/Makefile)
 
 
 
 
24
 
25
- #### SvelteKit Node Adapter?
26
 
27
- SvelteKit eventually can be used as our primary web application with [`@sveltejs/adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node) adaptor and Flask the API application with your ML project. However, there is an unsolved issue to enable [dynamic basepath](https://github.com/sveltejs/kit/issues/595), which blocks the possibility to embedded deployment or using a relative path.
 
 
 
 
 
 
 
 
12
 
13
  This project is an experiment running sentiment analysis on the current [New York Times](https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml) homepage headlines RSS. It also provides a sorting button to toggle between good and bad news first😛 . It's built with a [custom SvelveKit front-end](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/tree/main/client) , served by a [Flask application](https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/app.py) and using [transformers pipeline for the sentiment analysis.](https://huggingface.co/siebert/sentiment-roberta-large-english)
14
 
15
+ ### Running
16
 
17
+ #### Server
18
 
19
+ ```bash
20
+ python -m venv venv
21
+ source venv/bin/activate
22
+ pip3 install -r requirements.txt
23
+ python app.py
24
+ ```
25
 
26
+ #### Client
27
 
28
+ ```bash
29
+ cd frontend
30
+ npm install
31
+ npm run dev
32
+ ```
33
 
34
+ go http://localhost:5173/
35
 
36
+ or
37
+
38
+ ```bash
39
+ make build-all
40
+ make run
41
+ ```
42
+
43
+ go http://127.0.0.1:7860
frontend/src/App.svelte CHANGED
@@ -1,195 +1,150 @@
1
  <script>
2
- import NewsBlock from './components/NewsBlock.svelte';
3
- let feeds = [
4
- {
5
- label: 'NYTimes',
6
- value: 'https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml'
7
- },
8
- {
9
- label: 'SF Gate Bay Area',
10
- value: 'https://www.sfgate.com/bayarea/feed/Bay-Area-News-429.php'
11
- },
12
- {
13
- label: 'BBC News',
14
- value: 'https://feeds.bbci.co.uk/news/rss.xml'
15
- },
16
- {
17
- label: 'Buzz Feed World',
18
- value: 'https://www.buzzfeed.com/world.xml'
19
- },
20
- {
21
- label: 'Al Jazeera',
22
- value: 'https://aljazeera.com/xml/rss/all.xml'
23
- },
24
- {
25
- label: 'Hacker News Front Page',
26
- value: 'https://hnrss.org/frontpage'
27
- },
28
- {
29
- label: 'Reddit World News',
30
- value: 'https://www.reddit.com/r/worldnews/.rss'
31
- }
32
- ];
33
- let selectedFeedUrl = feeds[0].value;
34
- let predictions;
35
- let lastUpdate;
36
- let positiveOrder = true;
37
- async function fecthPredictions(feedUrl) {
38
- console.log(feedUrl);
39
- try {
40
- predictions = await fetch(`/api/news?feed_url=${feedUrl}`).then((d) => d.json());
41
- } catch (e) {
42
- // hack to develop locally without having to run the server
43
- predictions = await fetch('test.json').then((d) => d.json());
44
- }
45
- lastUpdate = new Date(predictions.last_update);
46
- predictions = predictions.entries.sort((a, b) => b.sentiment - a.sentiment);
47
- positiveOrder = true;
48
- console.log(lastUpdate, predictions);
49
- }
 
 
50
 
51
- function toggleOrder() {
52
- positiveOrder = !positiveOrder;
53
- predictions = predictions
54
- .slice()
55
- .sort((a, b) => (positiveOrder ? b.sentiment - a.sentiment : a.sentiment - b.sentiment));
56
- }
 
 
57
  </script>
58
 
59
  <article class="prose px-6 py-3 max-w-4xl mx-auto">
60
- <h1 class="font-serif mb-0">The New York Times Sentiment Analysis</h1>
61
- <h5 class="mt-0 {lastUpdate ? 'visibile' : 'invisible'}">
62
- <b>Last Updated:</b>
63
- {lastUpdate ? lastUpdate.toLocaleString() : ''}
64
- </h5>
65
 
66
- <p class="py-3 max-w-prose leading-normal">
67
- This project is an experiment running sentiment analysis on the current
68
- <a
69
- class="text-blue-500 underline hover:no-underline"
70
- target="_blank"
71
- href="https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml">New York Times</a
72
- >
73
- homepage headlines RSS. It also provides a sorting button to toggle between {positiveOrder
74
- ? 'good and bad news'
75
- : 'bad and good news'} first😛 . It's built with a
76
- <a
77
- class="text-blue-500 underline hover:no-underline"
78
- target="_blank"
79
- href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/tree/main/client"
80
- >
81
- custom SvelveKit front-end
82
- </a>
83
- , served by a
84
- <a
85
- class="text-blue-500 underline hover:no-underline"
86
- target="_blank"
87
- href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/app.py"
88
- >
89
- Flask application
90
- </a>
91
- and using
92
- <a
93
- class="text-blue-500 underline hover:no-underline"
94
- target="_blank"
95
- href="https://huggingface.co/siebert/sentiment-roberta-large-english"
96
- >
97
- transformers pipeline for the sentiment analysis.
98
- </a>
99
- </p>
100
- <details>
101
- <summary class="cursor-pointer">Notes</summary>
102
- <h4>Install Node with NVM</h4>
103
- <p class="max-w-prose leading-normal">
104
- This <a
105
- class="text-blue-500 underline hover:no-underline"
106
- target="_blank"
107
- href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/install-node.sh"
108
- >Node script</a
109
- >
110
 
111
- install node LTS and create symbolic links to <code>/home/user/.local/bin/</code> as it seems
112
- like we don't have permission to update <code>$PATH</code> env
113
- </p>
114
- <h4>main.py</h4>
115
- <p class="max-w-prose leading-normal">
116
- Because the Spaces run a python application, see
117
- <a
118
- class="text-blue-500 underline hover:no-underline"
119
- target="_blank"
120
- href="https://huggingface.co/docs/hub/spaces#:~:text=0.88.0%2C%200.89.0%2C%201.0.0.-,app_file,-%3A%20string%0APath%20to"
121
- >
122
- <code> app_file </code>
123
- </a>
124
- on docs. <b>main.py</b> is just a simple python subprocess to run
125
- <code> make build-all </code>
126
- See
127
- <a
128
- class="text-blue-500 underline hover:no-underline"
129
- target="_blank"
130
- href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/Makefile"
131
- >
132
- <code>Makefile</code>
133
- </a>
134
- </p>
135
- <h4>SvelteKit Node Adapter?</h4>
136
- <p class="max-w-prose leading-normal">
137
- SvelteKit eventually can be used as our primary web application with
138
- <a
139
- class="text-blue-500 underline hover:no-underline"
140
- target="_blank"
141
- href="https://github.com/sveltejs/kit/tree/master/packages/adapter-node"
142
- >
143
- <code>@sveltejs/adapter-node</code></a
144
- >
145
- adaptor and Flask the API application with your ML project. However, there is an unsolved issue
146
- to enable
147
- <a
148
- href="https://github.com/sveltejs/kit/issues/595"
149
- class="text-blue-500 underline hover:no-underline"
150
- >
151
- dynamic basepath</a
152
- >, which blocks the possibility to embedded deployment or using a relative path.
153
- </p>
154
- </details>
155
-
156
- <p class="max-w-prose leading-normal">
157
- You can try other news feeds <select
158
- class="inline-block text-xs bg-gray-200 border border-gray-200 text-gray-700 px-0 py-0 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
159
- bind:value={selectedFeedUrl}
160
- >
161
- {#each feeds as feed (feed.value)}
162
- <option value={feed.value}>{feed.label}</option>
163
- {/each}
164
- </select>; however the NYTimes feed comes with more information than the other feeds, such as
165
- the thumbnail image, author, and more.
166
- </p>
167
- <div class="py-4" />
168
- <button
169
- class="{positiveOrder
170
- ? 'bg-emerald-600'
171
- : 'bg-red-600'} hover:bg-zinc-300 text-white font-bold py-2 px-4 rounded"
172
- on:click={toggleOrder}
173
- >
174
- {!positiveOrder ? 'Sorted by negative scores' : 'Sorted by positive scores'}
175
- </button>
176
- {#await fecthPredictions(selectedFeedUrl)}
177
- <div class="py-4">
178
- <svg class="animate-spin inline-block" width="25" height="25" viewBox="0 0 100 100">
179
- <path d="M0,50 a1,1 0 0,0 100,0" fill="lightgrey" />
180
- </svg>
181
- Loading feed and running sentiment analysis on headlines...
182
- </div>
183
- {:then data}
184
- <ul class="m-0 p-0">
185
- {#each predictions as entry, i}
186
- <li class="py-5">
187
- <NewsBlock feedEntry={entry} />
188
- <div class="border-b border-gray-200 py-2" />
189
- </li>
190
- {/each}
191
- </ul>
192
- {:catch error}
193
- <p>An error occurred!</p>
194
- {/await}
195
  </article>
 
1
  <script>
2
+ import NewsBlock from "./components/NewsBlock.svelte";
3
+ let feeds = [
4
+ {
5
+ label: "NYTimes",
6
+ value: "https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml",
7
+ },
8
+ {
9
+ label: "SF Gate Bay Area",
10
+ value: "https://www.sfgate.com/bayarea/feed/Bay-Area-News-429.php",
11
+ },
12
+ {
13
+ label: "BBC News",
14
+ value: "https://feeds.bbci.co.uk/news/rss.xml",
15
+ },
16
+ {
17
+ label: "Buzz Feed World",
18
+ value: "https://www.buzzfeed.com/world.xml",
19
+ },
20
+ {
21
+ label: "Al Jazeera",
22
+ value: "https://aljazeera.com/xml/rss/all.xml",
23
+ },
24
+ {
25
+ label: "Hacker News Front Page",
26
+ value: "https://hnrss.org/frontpage",
27
+ },
28
+ {
29
+ label: "Reddit World News",
30
+ value: "https://www.reddit.com/r/worldnews/.rss",
31
+ },
32
+ ];
33
+ let selectedFeedUrl = feeds[0].value;
34
+ let predictions;
35
+ let lastUpdate;
36
+ let positiveOrder = true;
37
+ async function fecthPredictions(feedUrl) {
38
+ console.log(feedUrl);
39
+ try {
40
+ predictions = await fetch(`/api/news?feed_url=${feedUrl}`).then((d) =>
41
+ d.json()
42
+ );
43
+ } catch (e) {
44
+ // hack to develop locally without having to run the server
45
+ predictions = await fetch("test.json").then((d) => d.json());
46
+ }
47
+ lastUpdate = new Date(predictions.last_update);
48
+ predictions = predictions.entries.sort((a, b) => b.sentiment - a.sentiment);
49
+ positiveOrder = true;
50
+ console.log(lastUpdate, predictions);
51
+ }
52
 
53
+ function toggleOrder() {
54
+ positiveOrder = !positiveOrder;
55
+ predictions = predictions
56
+ .slice()
57
+ .sort((a, b) =>
58
+ positiveOrder ? b.sentiment - a.sentiment : a.sentiment - b.sentiment
59
+ );
60
+ }
61
  </script>
62
 
63
  <article class="prose px-6 py-3 max-w-4xl mx-auto">
64
+ <h1 class="font-serif mb-0">The New York Times Sentiment Analysis</h1>
65
+ <h5 class="mt-0 {lastUpdate ? 'visibile' : 'invisible'}">
66
+ <b>Last Updated:</b>
67
+ {lastUpdate ? lastUpdate.toLocaleString() : ""}
68
+ </h5>
69
 
70
+ <p class="py-3 max-w-prose leading-normal">
71
+ This project is an experiment running sentiment analysis on the current
72
+ <a
73
+ class="text-blue-500 underline hover:no-underline"
74
+ target="_blank"
75
+ href="https://rss.nytimes.com/services/xml/rss/nyt/HomePage.xml"
76
+ >New York Times</a
77
+ >
78
+ homepage headlines RSS. It also provides a sorting button to toggle between {positiveOrder
79
+ ? "good and bad news"
80
+ : "bad and good news"} first😛 . It's built with a
81
+ <a
82
+ class="text-blue-500 underline hover:no-underline"
83
+ target="_blank"
84
+ href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/tree/main/client"
85
+ >
86
+ custom SvelveKit front-end
87
+ </a>
88
+ , served by a
89
+ <a
90
+ class="text-blue-500 underline hover:no-underline"
91
+ target="_blank"
92
+ href="https://huggingface.co/spaces/radames/NYTimes-homepage-rearranged/blob/main/app.py"
93
+ >
94
+ Flask application
95
+ </a>
96
+ and using
97
+ <a
98
+ class="text-blue-500 underline hover:no-underline"
99
+ target="_blank"
100
+ href="https://huggingface.co/siebert/sentiment-roberta-large-english"
101
+ >
102
+ transformers pipeline for the sentiment analysis.
103
+ </a>
104
+ </p>
 
 
 
 
 
 
 
 
 
105
 
106
+ <p class="max-w-prose leading-normal">
107
+ You can try other news feeds <select
108
+ class="inline-block text-xs bg-gray-200 border border-gray-200 text-gray-700 px-0 py-0 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
109
+ bind:value={selectedFeedUrl}
110
+ >
111
+ {#each feeds as feed (feed.value)}
112
+ <option value={feed.value}>{feed.label}</option>
113
+ {/each}
114
+ </select>; however the NYTimes feed comes with more information than the
115
+ other feeds, such as the thumbnail image, author, and more.
116
+ </p>
117
+ <div class="py-4" />
118
+ <button
119
+ class="{positiveOrder
120
+ ? 'bg-emerald-600'
121
+ : 'bg-red-600'} hover:bg-zinc-300 text-white font-bold py-2 px-4 rounded"
122
+ on:click={toggleOrder}
123
+ >
124
+ {!positiveOrder ? "Sorted by negative scores" : "Sorted by positive scores"}
125
+ </button>
126
+ {#await fecthPredictions(selectedFeedUrl)}
127
+ <div class="py-4">
128
+ <svg
129
+ class="animate-spin inline-block"
130
+ width="25"
131
+ height="25"
132
+ viewBox="0 0 100 100"
133
+ >
134
+ <path d="M0,50 a1,1 0 0,0 100,0" fill="lightgrey" />
135
+ </svg>
136
+ Loading feed and running sentiment analysis on headlines...
137
+ </div>
138
+ {:then data}
139
+ <ul class="m-0 p-0">
140
+ {#each predictions as entry, i}
141
+ <li class="py-5">
142
+ <NewsBlock feedEntry={entry} />
143
+ <div class="border-b border-gray-200 py-2" />
144
+ </li>
145
+ {/each}
146
+ </ul>
147
+ {:catch error}
148
+ <p>An error occurred!</p>
149
+ {/await}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  </article>