From 757eb7626e9f3982e30382d17ea93692dbb8210d Mon Sep 17 00:00:00 2001 From: rhauteki <rafaelhautekiet@gmail.com> Date: Fri, 29 Dec 2017 14:39:44 +0100 Subject: [PATCH] minor update of web front-end --- .gitignore | 1 - demo/.gitignore | 1 + demo/README.md | 19 -------- demo/package-lock.json | 5 +++ demo/package.json | 3 +- demo/src/components/About.vue | 65 +++++++++++++++++----------- demo/src/components/Contact.vue | 20 ++++----- demo/src/components/Demo.vue | 7 ++- demo/src/components/FactRanker.vue | 3 +- demo/src/components/ResultsTable.vue | 17 ++++++-- demo/src/main.js | 3 ++ 11 files changed, 80 insertions(+), 64 deletions(-) delete mode 100644 demo/README.md diff --git a/.gitignore b/.gitignore index 9d6d465..c18dd8d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1 @@ __pycache__/ -demo/dist diff --git a/demo/.gitignore b/demo/.gitignore index aba914c..1622bc4 100644 --- a/demo/.gitignore +++ b/demo/.gitignore @@ -1,5 +1,6 @@ .DS_Store node_modules/ +dist/ npm-debug.log* yarn-debug.log* yarn-error.log* diff --git a/demo/README.md b/demo/README.md deleted file mode 100644 index bf600d4..0000000 --- a/demo/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# factrank - -> Dutch Check-Worthy Detection - -We attempt to classify Dutch tweets from Belgian politicians based on their check-worthyness. For this we follow the general approach taken by Claimbuster. -The data will be gathered using the twitter API. The gathered data set will be manually classified in three categories: - -- Non-factual Sentence **(NFS)**, -- Unimportant Factual Sentence **(UFS)**, -- Check-worthy Factual Sentence **(CFS)**, whilst irrelevant tweets (emoticons, too short, not containing coherent sentences...) will be discarded. - -For the manual classification we will use a set of general guidelines. To verify that our judgement is similar, we will individually analyse the same, small dataset, allowing us to check our Inter-rater agreement (and change our guidelines if necessary). -From the tweets we will extract a range of features, inspired by the Claimbuster feature importance. Example features are: - -- Sentiment (eg. using https://www.clips.uantwerpen.be/pages/sentiment-analysis-for-dutch) -- Sentence length -- Parts of Speech (eg. https://languagemachines.github.io/frog/) - -These features will then be inserted in a learning algorithm. We will certainly use SVM, as this was the most successful for Claimbuster, but other learning algorithms could also be considered. Especially an algorithm that gives interpretable results would be very interesting. diff --git a/demo/package-lock.json b/demo/package-lock.json index 574fe19..d019a6b 100644 --- a/demo/package-lock.json +++ b/demo/package-lock.json @@ -9515,6 +9515,11 @@ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-2.8.1.tgz", "integrity": "sha512-MC4jacHBhTPKtmcfzvaj2N7g6jgJ/Z/eIjZdt+yUaUOM1iKC0OUIlO/xCtz6OZFFTNUJs/1YNro2GN/lE+nOXA==" }, + "vue-spinner": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/vue-spinner/-/vue-spinner-1.0.3.tgz", + "integrity": "sha512-Phh6QC/Bh80ZE/0SH9ADw4irbRGwFK6VZsTksPHpPm16xga2OXwNC2nI7SEPnndUZP+Lgu1wu+pbH6i6+5siBQ==" + }, "vue-style-loader": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-3.0.3.tgz", diff --git a/demo/package.json b/demo/package.json index 6b7179e..dc83f63 100644 --- a/demo/package.json +++ b/demo/package.json @@ -17,7 +17,8 @@ "vue-awesome": "^2.3.4", "vue-markdown": "^2.2.4", "vue-octicon": "^2.1.1", - "vue-router": "^2.7.0" + "vue-router": "^2.7.0", + "vue-spinner": "^1.0.3" }, "devDependencies": { "autoprefixer": "^7.1.2", diff --git a/demo/src/components/About.vue b/demo/src/components/About.vue index a42e32c..25fd276 100644 --- a/demo/src/components/About.vue +++ b/demo/src/components/About.vue @@ -1,35 +1,45 @@ <template> <main> - <pre> - - ├── demo - | └─ Vue.js front-end to provide insight in prediction process - | - ├── helper.py - | └─ Custom feature transformer classes allowing for easy predictions - ├── extractor.py - | └─ Exctractor class enables retrieving all nlp features from `sentence` - | - ├── learner.py - | └─ Preprocess data, construct pipeline, train SVM and export model. - └── parser.py - | └─ Parse latest transcript of plenary meeting, detect Check-Worthy statements - | and save predictions together with feedback to be served on demo page. - | - └── endpoint.py - └─ Load pre-trained model and provide endpoint for predictions. - </pre> + <vue-markdown> + **Fake news and the spread of misinformation** is nothing new. But, due to recent events, big players like Google and Facebook are now trying to clamp down on the problem. Automated end-to-end fact-checking can play a crucial role in this fight and recent success of [the Claimbuster-project](http://idir-server2.uta.edu/claimbuster/) has paved the way for developing such a system. + + The starting point for any fact-checking process is the **identification of** interesting claims or statements that present facts. These kinds of sentences are defined as **Check-worthy Factual Statement**. Only when such sentences can be reliably identified, can they be sent to the next step in the pipeline that actually tries to falsify the interesting claims. + + The goal of this project to take the first step towards developing such a fact-checking system for the **Dutch** language, with a focus on identifying Check-worthy Factual Statements. A classifier was trained using a linear classifier on **800** hand-classified **statements** and later calibrated in order to predict the probability of check-worthiness when provided with a statement. A demonstration of its current ability can be found on the [front page](/#/) in the from of a rank of Dutch statements made during the last Plenary Meeting of the Belgian parliament based on their check-worthiness. To provide you with the ability to play around with input of your own and see how this is interpreted by FactRank, we made a little [demo](/#/demo). + + ### Classifier + + ![confusion matrix](cnf_matrix.svg) + + ### Project Structure + + ``` + ├── demo + | └─ Vue.js front-end to provide insight in prediction process + | + ├── helper.py + | └─ Custom feature transformer classes allowing for easy predictions + ├── extractor.py + | └─ Exctractor class enables retrieving all nlp features from `sentence` + | + ├── learner.py + | └─ Preprocess data, construct pipeline, train SVM and export model. + └── parser.py + | └─ Parse latest transcript of plenary meeting, detect Check-Worthy statements + | and save predictions together with feedback to be served on demo page. + | + └── endpoint.py + └─ Load pre-trained model and provide endpoint for predictions. + ``` + + </vue-markdown> + </main> </template> <script> -import VueMarkdown from 'vue-markdown' - export default { name: 'About', - components: { - 'vue-markdown': VueMarkdown - }, data () { return { } @@ -38,8 +48,13 @@ export default { </script> <!-- Add "scoped" attribute to limit CSS to this component only --> -<style scoped> +<style> pre{ background-color: #f6f8fa; + padding: 20px; + border-radius: 5px; +} +h3 { + margin-bottom: 2rem; } </style> diff --git a/demo/src/components/Contact.vue b/demo/src/components/Contact.vue index 0427a83..eda0c42 100644 --- a/demo/src/components/Contact.vue +++ b/demo/src/components/Contact.vue @@ -2,7 +2,7 @@ <div class="hello"> <vue-markdown> - FactRank is written and maintained by: + FactRank was created as a project for the course *Knowledge and the Web* by prof. Bettina Berendt at KU Leuven and is written and maintained by: - Brecht Laperre (brecht.laperre@student.kuleuven.be) - Ivo merchiers (ivo.merchiers@student.kuleuven.be) @@ -11,10 +11,9 @@ You can always contact us for questions or suggestions. If you find any bugs, please file a bug report on [github](https://github.com/lejafar/KaW-project/issues). - We have an open api at https://api.factrank.org/sentence - </vue-markdown> - <pre> + Our API is openly available on https://api.factrank.org/, a minimal example: + ```javascript makePrediction (input) { fetch("https://api.factrank.org/sentence", { body: JSON.stringify(input), @@ -28,19 +27,14 @@ console.log(data.predictions); }) } - - </pre> + ``` + </vue-markdown> </div> </template> <script> -import VueMarkdown from 'vue-markdown' - export default { name: 'Contact', - components: { - 'vue-markdown': VueMarkdown - }, props: [ 'name' ], @@ -52,8 +46,10 @@ export default { </script> <!-- Add "scoped" attribute to limit CSS to this component only --> -<style scoped> +<style> pre{ background-color: #f6f8fa; + padding: 20px; + border-radius: 5px; } </style> diff --git a/demo/src/components/Demo.vue b/demo/src/components/Demo.vue index ab1c2e5..82d97e9 100644 --- a/demo/src/components/Demo.vue +++ b/demo/src/components/Demo.vue @@ -22,7 +22,7 @@ <b-btn variant="outline-primary" class="submit_button" v-on:click="makePrediction(sentence_input)">submit</b-btn> </b-col> </b-row> - <results-table v-bind:result="sentence_result"/> + <results-table v-if="show_result" v-bind:result="sentence_result"/> </div> </template> @@ -34,7 +34,8 @@ export default { data () { return { sentence_input: '', - sentence_result: {} + sentence_result: {}, + show_result: false } }, components: { @@ -59,6 +60,8 @@ export default { }, methods: { makePrediction (sentences) { + this.sentence_result= {} + this.show_result = true fetch("https://api.factrank.org/sentence", { body: JSON.stringify(sentences), method: "POST", diff --git a/demo/src/components/FactRanker.vue b/demo/src/components/FactRanker.vue index 222ff88..66dda9f 100644 --- a/demo/src/components/FactRanker.vue +++ b/demo/src/components/FactRanker.vue @@ -1,11 +1,12 @@ <template> - <main v-if="result"> + <main> <results-table v-bind:result="result"/> </main> </template> <script> import ResultsTable from '@/components/ResultsTable' +import VueMarkdown from 'vue-markdown' export default { name: 'FactRanker', diff --git a/demo/src/components/ResultsTable.vue b/demo/src/components/ResultsTable.vue index 9bf2dc8..3b85532 100644 --- a/demo/src/components/ResultsTable.vue +++ b/demo/src/components/ResultsTable.vue @@ -1,5 +1,5 @@ <template> - <b-table show-empty + <b-table v-if="result.predictions" :fields="fields" :items="result.predictions" :sort-compare="customSortCompare" @@ -8,7 +8,7 @@ <!-- Information about Source of Statements IF meta is set --> <template v-if="result.meta" slot="table-caption"> <p v-if="result.meta.date" > - Top Check-Whorty Factual statements from + Top 50 Check-Whorty Factual statements from <span v-if="this.last"> last Plenary Meeting ({{result.meta.date}}, <strong>{{result.meta.amount}}</strong> statements)</span> <span v-else> Plenary Meeting on {{result.meta.date}} ({{result.meta.amount}} statements)</span></p> <a v-if="result.meta.url.length" :href="result.meta.url"><icon name="link" /> {{result.meta.url}} </a> @@ -26,16 +26,21 @@ </b-card> </template> </b-table> + <div v-else class="loader-container"> + <rotate-loader :color="'#ffc107'"></rotate-loader> + </div> </template> <script> import SentenceExtended from '@/components/SentenceExtended' +import RotateLoader from 'vue-spinner/src/RotateLoader' export default { name: 'ResultsTable', props: ['result'], components: { - 'sentence-extended': SentenceExtended + 'sentence-extended': SentenceExtended, + 'rotate-loader': RotateLoader }, data () { return { @@ -85,4 +90,10 @@ blockquote{ abbr{ margin-right: 35px; } + +.loader-container{ + text-align: center; + vertical-align: middle; + line-height: 300px; +} </style> diff --git a/demo/src/main.js b/demo/src/main.js index 9d45587..22561f1 100644 --- a/demo/src/main.js +++ b/demo/src/main.js @@ -22,6 +22,9 @@ Vue.component('icon', Icon) Vue.config.productionTip = false +import VueMarkdown from 'vue-markdown' +Vue.component('vue-markdown', VueMarkdown) + /* eslint-disable no-new */ new Vue({ el: '#app',