From 62f42e61a9a47ebf5f8f6ccbbeded61fdc532a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ruthotto?= Date: Tue, 8 Oct 2024 10:12:52 +0200 Subject: [PATCH 1/6] results are now saved in db --- src/Ai/interence.py | 3 ++- src/controller/mainFrameController.py | 30 ++++++++++++++++++++++----- src/models/data.py | 1 + 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Ai/interence.py b/src/Ai/interence.py index d68e9b6..c7c9bed 100644 --- a/src/Ai/interence.py +++ b/src/Ai/interence.py @@ -34,5 +34,6 @@ class VeraMindInference: return { "result": "FAKE" if is_fake else "REAL", - "confidence": float(confidence) + "confidence": float(confidence), + "is_fake": is_fake } \ No newline at end of file diff --git a/src/controller/mainFrameController.py b/src/controller/mainFrameController.py index 762fa99..2f778dd 100644 --- a/src/controller/mainFrameController.py +++ b/src/controller/mainFrameController.py @@ -1,14 +1,14 @@ from views.mainScreen import MainFrame from models.data import TextData from Ai.interence import VeraMindInference - - +from utils.database.database import FakeNewsChecker +from urllib.parse import urlparse class MainFrameController: def __init__(self,frame:MainFrame) -> None: self.frame = frame self.model_inference = VeraMindInference('VeraMind-Mini') - + self.db = FakeNewsChecker() def get_textdata(self) -> TextData: text_data = TextData() @@ -21,7 +21,9 @@ class MainFrameController: def press_check_button(self): text_data = self.get_textdata() print(f"text:{text_data.text}") - self.prediction(text_data) + text_data = self.prediction(text_data) + + self.addDB(textData=text_data) self.frame.output_textbox.configure(state="normal") self.frame.output_textbox.delete("0.0", "end") self.frame.output_textbox.insert("0.0",f"{text_data.get_output()}") @@ -31,6 +33,24 @@ class MainFrameController: result = self.model_inference.predict(text_data.text) text_data.confidence = result["confidence"] text_data.result = result["result"] + text_data.is_fake_news = result["is_fake"] print(f"Prediction: {text_data.result}") print(f"Confidence: {text_data.confidence}") - return text_data \ No newline at end of file + return text_data + + def addDB(self, textData: TextData): + if self.is_valid_url(textData.url): + parsed_url = urlparse(textData.url) + anbieter = parsed_url.netloc.split('.')[-2] + '.' + parsed_url.netloc.split('.')[-1] + print("Hauptdomain:", anbieter) + self.db.insert_data(url= textData.url, anbieter= anbieter,is_fake_news=textData.is_fake_news) + else: + self.db.insert_data(url= textData.url, anbieter= "None",is_fake_news=textData.is_fake_news) + + def is_valid_url(self, url): + try: + result = urlparse(url) + return all([result.scheme, result.netloc]) + except ValueError: + return False + \ No newline at end of file diff --git a/src/models/data.py b/src/models/data.py index 7f8f03b..2f15286 100644 --- a/src/models/data.py +++ b/src/models/data.py @@ -5,6 +5,7 @@ class TextData: self.url = url self.text = "" self.result = "" + self.is_fake_news = False self.confidence = None self._extractor = None From 56fc70dfe0571a9483e17989906a9da54e38b213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ruthotto?= Date: Tue, 8 Oct 2024 12:03:22 +0200 Subject: [PATCH 2/6] add provider in to scrollview --- fake_news_checker.db | Bin 12288 -> 12288 bytes src/controller/mainFrameController.py | 145 +++++++++++++++++++------- src/models/data.py | 44 +++++++- src/models/provider.py | 5 + src/views/mainScreen.py | 4 + 5 files changed, 155 insertions(+), 43 deletions(-) create mode 100644 src/models/provider.py diff --git a/fake_news_checker.db b/fake_news_checker.db index e06e2636198e68ab59cb797b30cc80155d1a06fa..acf0f5581a033753b16ff7807e582c78d5e9d709 100644 GIT binary patch delta 256 zcmYMuKTg9i7zJ<#NQR2q?Z5;Qg8hq0h-g4!V(Y*a=$FK)jhsJpq~mu?CBW?$@s zz0&P4{Ltsksq2v!enO?SwYlQFZCl^eN-Tx;Gr?;ts|E|?_bX%76E~>!Bjifx3=+|( zR9a!-p(;TNRp_CM0!%7fESI7gfVnl8B+V+7P$&z*3=lBJ@bdgDfa@>{Vu*r)7)H?$ i7-exX%fpNK{{v&}(e9tS&*Qs^P>_I delta 60 zcmV-C0K@-)V1Qtd8vz56977QU04{F14FCWD0uH(W4-5{vvmp>l4zs!rN&yH051{}L S(GQ`s5g?Thv!Nee5CH None: + """ + Controller class for the main frame of the application. + Handles user interactions, data processing, and database operations. + """ + + def __init__(self, frame: MainFrame) -> None: + """ + Initialize the controller with the main frame and required components. + + :param frame: The main frame of the application + """ self.frame = frame self.model_inference = VeraMindInference('VeraMind-Mini') self.db = FakeNewsChecker() - - def get_textdata(self) -> TextData: + self._fetch_db_data() + self.update_provider_list() + + def get_text_data(self) -> TextData: + """ + Retrieve text data from the UI input fields. + + :return: TextData object containing URL and text content + """ text_data = TextData() text_data.url = self.frame.entry_url.get() - if text_data.text_from_url(): + if not text_data.text_from_url(): text_data.text = self.frame.input_textbox.get("0.0", "end") - return text_data - - def press_check_button(self): - text_data = self.get_textdata() - print(f"text:{text_data.text}") - text_data = self.prediction(text_data) - - self.addDB(textData=text_data) - self.frame.output_textbox.configure(state="normal") - self.frame.output_textbox.delete("0.0", "end") - self.frame.output_textbox.insert("0.0",f"{text_data.get_output()}") - self.frame.output_textbox.configure(state="disabled") - - def prediction(self, text_data:TextData) -> TextData: + + def press_check_button(self) -> None: + """ + Handle the 'Check' button press event. + Processes the input, makes a prediction, updates the database, and displays the result. + """ + text_data = self.get_text_data() + text_data = self._predict(text_data) + self._add_to_db(text_data) + self._update_output(text_data.get_output()) + self.update_provider_list() + + def _predict(self, text_data: TextData) -> TextData: + """ + Make a prediction using the VeraMind model. + + :param text_data: TextData object containing the text to analyze + :return: Updated TextData object with prediction results + """ result = self.model_inference.predict(text_data.text) text_data.confidence = result["confidence"] - text_data.result = result["result"] + text_data.result = result["result"] text_data.is_fake_news = result["is_fake"] print(f"Prediction: {text_data.result}") print(f"Confidence: {text_data.confidence}") return text_data - - def addDB(self, textData: TextData): - if self.is_valid_url(textData.url): - parsed_url = urlparse(textData.url) - anbieter = parsed_url.netloc.split('.')[-2] + '.' + parsed_url.netloc.split('.')[-1] - print("Hauptdomain:", anbieter) - self.db.insert_data(url= textData.url, anbieter= anbieter,is_fake_news=textData.is_fake_news) - else: - self.db.insert_data(url= textData.url, anbieter= "None",is_fake_news=textData.is_fake_news) - - def is_valid_url(self, url): - try: - result = urlparse(url) - return all([result.scheme, result.netloc]) - except ValueError: - return False - \ No newline at end of file + + def _add_to_db(self, text_data: TextData) -> None: + """ + Add the analyzed data to the database. + + :param text_data: TextData object containing the analyzed information + """ + + self.db.insert_data(url=text_data.url, anbieter=text_data.get_provider(), is_fake_news=text_data.is_fake_news) + + def _fetch_db_data(self): + self.text_data_list = [] + data = self.db.fetch_data() + if data: + for row in data: + print(f"ID: {row[0]}, URL: {row[1]}, Anbieter: {row[2]}, Fake News: {'Ja' if row[3] else 'Nein'}") + text_data = TextData(url=row[1], provider=row[2], is_fake_news= row[3]) + self.text_data_list.append(text_data) + + def sort_provider(self, text_data_list): + provider_names = [text_data.provider for text_data in text_data_list if text_data.provider] + provider_counts = Counter(provider_names) + sorted_providers = [ + Provider(name, count) + for name, count in sorted(provider_counts.items(), key=lambda x: x[1], reverse=True) + ] + return sorted_providers + + def update_provider_list(self): + self._fetch_db_data() + # Lösche vorhandene Einträge in der scrollbaren Ansicht + for widget in self.frame.provider_container.winfo_children(): + widget.destroy() + + # Sortiere und zähle die Provider + sorted_providers = self.sort_provider(self.text_data_list) + + # Füge die sortierten Provider zur scrollbaren Ansicht hinzu + for i, provider in enumerate(sorted_providers): + provider_frame = ctk.CTkFrame(self.frame.provider_container) + provider_frame.pack(fill="x", padx=5, pady=2) + + name_label = ctk.CTkLabel(provider_frame, text=provider.title) + name_label.pack(side="left", padx=5) + + count_label = ctk.CTkLabel(provider_frame, text=str(provider.count)) + count_label.pack(side="right", padx=5) + + + + def _update_output(self, output: str) -> None: + """ + Update the output text box with the result. + + :param output: String containing the output to display + """ + self.frame.output_textbox.configure(state="normal") + self.frame.output_textbox.delete("0.0", "end") + self.frame.output_textbox.insert("0.0", output) + self.frame.output_textbox.configure(state="disabled") + + \ No newline at end of file diff --git a/src/models/data.py b/src/models/data.py index 2f15286..3f28398 100644 --- a/src/models/data.py +++ b/src/models/data.py @@ -1,11 +1,15 @@ +from urllib.parse import urlparse +from typing import Optional + from utils.webTextExtractor import WebTextExtractor class TextData: - def __init__(self, url: str = "") -> None: + def __init__(self, url: str = "",text: str = "",result: str = "", is_fake_news: bool = False, provider: str = "") -> None: self.url = url - self.text = "" - self.result = "" - self.is_fake_news = False + self.text = text + self.result = result + self.is_fake_news = is_fake_news + self.provider = provider self.confidence = None self._extractor = None @@ -32,4 +36,34 @@ class TextData: if self.confidence != None: output = f"Prediction: {self.result}" + f" Confidence: {self.confidence:.4f}" print(output) - return output \ No newline at end of file + return output + + def get_provider(self)-> str: + self.extract_provider() + return self.provider + + def extract_provider(self): + """ + Extract the domain (anbieter) from a given URL. + + :param url: The URL to process + :return: The extracted domain or None if the URL is invalid + """ + if not self._is_valid_url(self.url): + self.provider = "None" + parsed_url = urlparse(self.url) + domain_parts = parsed_url.netloc.split('.') + self.provider = f"{domain_parts[-2]}.{domain_parts[-1]}" if len(domain_parts) >= 2 else "None" + + def _is_valid_url(self, url: str) -> bool: + """ + Check if a given URL is valid. + + :param url: The URL to validate + :return: True if the URL is valid, False otherwise + """ + try: + result = urlparse(url) + return all([result.scheme, result.netloc]) + except ValueError: + return False \ No newline at end of file diff --git a/src/models/provider.py b/src/models/provider.py new file mode 100644 index 0000000..92e2e54 --- /dev/null +++ b/src/models/provider.py @@ -0,0 +1,5 @@ +class Provider(): + + def __init__(self, title: str, count: int) -> None: + self.title = title + self.count = count \ No newline at end of file diff --git a/src/views/mainScreen.py b/src/views/mainScreen.py index ef41506..eda2cbd 100644 --- a/src/views/mainScreen.py +++ b/src/views/mainScreen.py @@ -38,6 +38,10 @@ class MainFrame(ctk.CTkFrame): self.header = ctk.CTkLabel(self.scrollview, text="Leaderboard", font=("Arial", 24, "bold")) self.header.pack(pady=10, padx=10, anchor="w") + # Container für Provider-Einträge + self.provider_container = ctk.CTkFrame(self.scrollview) + self.provider_container.pack(fill="both", expand=True) + def set_controller(self, controller): self.controller = controller From 1d962c388f321593354a0adb3bd549f2d21341ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ruthotto?= Date: Tue, 8 Oct 2024 12:46:23 +0200 Subject: [PATCH 3/6] add percentage --- fake_news_checker.db | Bin 12288 -> 12288 bytes src/controller/mainFrameController.py | 19 +++++++++++++++---- src/models/provider.py | 22 ++++++++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/fake_news_checker.db b/fake_news_checker.db index acf0f5581a033753b16ff7807e582c78d5e9d709..3badb6d9564e81f477932e7396b0d1418373b018 100644 GIT binary patch delta 53 zcmZojXh@hK&B#7c#+i|QW5N=C0X9B+2L6lu3;Cz=ck(^qv)@>#&BxrR#5Vc4+@j4- J None: + def __init__(self, title: str, count: int, text_data_list) -> None: self.title = title - self.count = count \ No newline at end of file + self.count = count + self.text_data_list = text_data_list + + def get_fake_percentage(self) -> float: + + count_all = 0 + count_fake = 0 + for text_data in self.text_data_list: + print(text_data.is_fake_news) + count_all += 1 + if text_data.is_fake_news: + count_fake += 1 + + if count_all == 0: + return 0.0 + + return (count_fake / count_all) * 100 + + \ No newline at end of file From c41b37e04593a9fad13a72433cd9a57f0e0f564d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ruthotto?= Date: Thu, 10 Oct 2024 09:29:27 +0200 Subject: [PATCH 4/6] fix database --- fake_news_checker.db | Bin 12288 -> 798720 bytes src/controller/mainFrameController.py | 3 +- src/models/provider.py | 3 +- src/utils/database/database.py | 43 +++++++++++++------------- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/fake_news_checker.db b/fake_news_checker.db index 3badb6d9564e81f477932e7396b0d1418373b018..43543be20e50883482598fc36192431ab4938246 100644 GIT binary patch literal 798720 zcmeI*&u=4F9RTp>IJ+BGAWGH4A`TUtIMn&wZqfq+6$vUz1uH?-Q)GL_v58|xv9l=% zX;(dQ;jkz83sBE+0de7g(Cz|fu0>pW2GZGP@&vd+AjdGp?z&p1)O zo|*6d^&e}~i?1yI;+sEs<2zpuC!6liO~R}=arC4Z$$@OZh(+Z*3STEKU|MKvKMs+P;>EzqJm3lL;ujQM2RUe0`t` zZ!mZoZp3kwABWPD5T1ro>~JtBMjF?o!bB>RQ(<^eMOzO?Q#`O=#jTAnF&t-X;KlFV zd-J>BxcBZ#I--@?e6M;V+|0tAJd{GCaG5NIR4O$?>7(1NxUx9R+2Y$*_p0RKqv6Ph z)jqtLs{Jw!GYdbvG5r2QIu%##tz^6e2oNAZfB*pk1PBlyaQOv_h(9kP{uoCO5GafMlIs!wBv(f$B6?wrfNlCo2r%bFm+THQ_X&VqxbsE z%#*NNd>X=^L+LN!QS7>yPS@RU<8WhWeqdzrV~XBJD__mq)3Lu)O#Q_m{gmB3IE*mT ziysJ#^oE~2JY)Nl@e_spmfIloOSzW zJbcX)AV7cs0Rq=hU>MpI*GCV;6T30j*zikiasA#5V;=jzeh2D^2oNAZ;6el@E~HnT zCIO#GB?F1ZLX&g10hg8+f&Q()&8^I&lGkKUg&SN|M30s;gGoJQd2 z5My}L(-F5?#izbToeZyf6wkJ0dyjGrZ%I3_+$?TcdpMfneN=xNKBBd6#h->ZmBpS; zGj{tBAV7cs0RjZhULeK&=|W8UYbY(J`Q&IQ#d5kipqQunX`~;H8cfUP1PBlyK!5-N z0t5&UAV7e?#R;Ui|2fXO0RjXF5FkK+ z009Ew*6@DFa*@|B-oSV`3Ept?US7YL`)_9&CE6SA_~39#yHstI*Keo&JjB%Xhr5_c zr(tYjiQT+@&)D4`j?U}%cDIukeU5v`>{Q(yfpBbIzmpu!ae4hlXJq(bT+Eypo0Qit zy`i3Q{=c`dJmc=FUvh!7KEG$({w3!%JOTs=5FkL{5(?}DWry=F&>xf+Vkq^{QKzHzmNduX&{VvOT1xd<^1Nm@aG0D(_Q zAYGCFl$yK1X8cKWf%v*UR>1r7SRxe&oLb=M5aWb-{o?&m`||q5C%@uuTZo5%_%i z!6{9opP^#St2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk P1PBlyK!5;&GZ6SM0{nKN literal 12288 zcmeI&O>Wab6ae6H(j*YIF&orX#83&TRXcH=xNTqqDKaP`aY}F{vWmvexEb(IVowOL z3#>Q*2jCjL1$W>CoPcqVsgf=#b_l&Ek3BPa^K5;)C*{@44i^l2Q5;Z#8|V&F6!ZjR zgiuM2yc}65axUH~aXk-|n{h1N_1q;MTd_Yg@8N*RRBKSuwp}zltc%1no;;@*zW5EP@7lmZZc;L%53rOOQ=QO-v zv7As(B-C-@nL8!{7eqfHl+Y%vKWrT8q;BXxLn3)EG6L6R&>Uy!r^V*eU$` zA6ecgpsl+VD+(DZ=db3qTmg0O-OhZ|zCLa1Yi<;1G#1?TnPwavKa=~|l0OiofXoNC zvV8WQ1{0qx)6;XBUT>Jc_m=5t|F5V&k-Q*400ck)1V8`;KmY_l00ck)1V8`;{u_Z! MC0|vte=ih&0WSjlZ~y=R diff --git a/src/controller/mainFrameController.py b/src/controller/mainFrameController.py index 3c1e706..62d7fb6 100644 --- a/src/controller/mainFrameController.py +++ b/src/controller/mainFrameController.py @@ -21,7 +21,6 @@ class MainFrameController: self.frame = frame self.model_inference = VeraMindInference('VeraMind-Mini') self.db = FakeNewsChecker() - self._fetch_db_data() self.update_provider_list() def get_text_data(self) -> TextData: @@ -69,7 +68,7 @@ class MainFrameController: :param text_data: TextData object containing the analyzed information """ - self.db.insert_data(url=text_data.url, anbieter=text_data.get_provider(), is_fake_news=text_data.is_fake_news) + self.db.insert_data(url=text_data.url, anbieter=text_data.get_provider(),is_fake_news= text_data.is_fake_news) def _fetch_db_data(self): self.text_data_list = [] diff --git a/src/models/provider.py b/src/models/provider.py index ca860d9..3a82610 100644 --- a/src/models/provider.py +++ b/src/models/provider.py @@ -10,7 +10,8 @@ class Provider(): count_all = 0 count_fake = 0 for text_data in self.text_data_list: - print(text_data.is_fake_news) + #print(text_data.provider) + #print("FAKE" if text_data.is_fake_news else "REAL") count_all += 1 if text_data.is_fake_news: count_fake += 1 diff --git a/src/utils/database/database.py b/src/utils/database/database.py index 00ede72..79fb0ad 100644 --- a/src/utils/database/database.py +++ b/src/utils/database/database.py @@ -1,4 +1,4 @@ -import sqlite3 +import duckdb class FakeNewsChecker: def __init__(self, db_name='fake_news_checker.db'): @@ -6,49 +6,50 @@ class FakeNewsChecker: self.create_table() def create_connection(self): - return sqlite3.connect(self.db_name) + return duckdb.connect(self.db_name) def create_table(self): conn = self.create_connection() - cursor = conn.cursor() - cursor.execute(''' + conn.execute(''' CREATE TABLE IF NOT EXISTS url_info ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - url TEXT NOT NULL, - anbieter TEXT NOT NULL, + id INTEGER PRIMARY KEY, + url VARCHAR NOT NULL, + anbieter VARCHAR NOT NULL, is_fake_news BOOLEAN NOT NULL ) ''') - conn.commit() conn.close() + def get_next_id(self): + conn = self.create_connection() + result = conn.execute('SELECT COALESCE(MAX(id), 0) + 1 FROM url_info').fetchone() + conn.close() + return result[0] + def insert_data(self, url, anbieter, is_fake_news): conn = self.create_connection() - cursor = conn.cursor() - cursor.execute(''' - INSERT INTO url_info (url, anbieter, is_fake_news) - VALUES (?, ?, ?) - ''', (url, anbieter, is_fake_news)) - conn.commit() + next_id = self.get_next_id() + conn.execute(''' + INSERT INTO url_info (id, url, anbieter, is_fake_news) + VALUES (?, ?, ?, ?) + ''', [next_id, url, anbieter, bool(is_fake_news)]) conn.close() def fetch_data(self): conn = self.create_connection() - cursor = conn.cursor() - cursor.execute('SELECT * FROM url_info') - rows = cursor.fetchall() + result = conn.execute('SELECT * FROM url_info').fetchall() conn.close() - return rows + return result # Beispielnutzung der Klasse if __name__ == '__main__': checker = FakeNewsChecker() # Daten hinzufügen - checker.insert_data('https://example.com/news/123', 'Example News', 0) - checker.insert_data('https://fakenews.com/article/456', 'Fake News', 1) + checker.insert_data('https://example.com/news/123', 'Example News', False) + checker.insert_data('https://fakenews.com/article/456', 'Fake News', True) # Daten abrufen data = checker.fetch_data() for row in data: - print(f"ID: {row[0]}, URL: {row[1]}, Anbieter: {row[2]}, Fake News: {'Ja' if row[3] else 'Nein'}") + print(f"ID: {row[0]}, URL: {row[1]}, Anbieter: {row[2]}, Fake News: {'Ja' if row[3] else 'Nein'}") \ No newline at end of file From 42bec19d7b23d53270d3a70f14e55aaad8b43fb5 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Thu, 10 Oct 2024 09:38:58 +0200 Subject: [PATCH 5/6] updated FrameController --- src/controller/mainFrameController.py | 83 +++++++++++++++++++++------ 1 file changed, 67 insertions(+), 16 deletions(-) diff --git a/src/controller/mainFrameController.py b/src/controller/mainFrameController.py index 62d7fb6..cd06495 100644 --- a/src/controller/mainFrameController.py +++ b/src/controller/mainFrameController.py @@ -1,3 +1,4 @@ +from collections import deque import customtkinter as ctk from views.mainScreen import MainFrame from models.data import TextData @@ -5,6 +6,14 @@ from Ai.interence import VeraMindInference from utils.database.database import FakeNewsChecker from models.provider import Provider from collections import Counter +from Ai.llm import ArticleRater + +BAD_WORDS = ["FAKE", "SATIRE", "Fake", "fake"] +GOOD_WORDS = ["REAL", "real", "Real"] +BAD_COLOR = "#ff8080" +GOOD_COLOR = "#80ff8f" +WORDS = BAD_WORDS + GOOD_WORDS + class MainFrameController: """ @@ -22,6 +31,7 @@ class MainFrameController: self.model_inference = VeraMindInference('VeraMind-Mini') self.db = FakeNewsChecker() self.update_provider_list() + self.rater = ArticleRater() def get_text_data(self) -> TextData: """ @@ -35,16 +45,63 @@ class MainFrameController: text_data.text = self.frame.input_textbox.get("0.0", "end") return text_data - def press_check_button(self) -> None: - """ - Handle the 'Check' button press event. - Processes the input, makes a prediction, updates the database, and displays the result. - """ - text_data = self.get_text_data() - text_data = self._predict(text_data) - self._add_to_db(text_data) - self._update_output(text_data.get_output()) + def press_check_button(self): + text_data = self.get_textdata() + print(text_data.text) + self._predict(text_data) + self.frame.output_textbox.configure(state="normal") + self.frame.output_textbox.delete("0.0", "end") + + response_stream = self.rater.get_response(text_data.text, text_data.result, float(f"{text_data.confidence * 100:.2f}")) + + highlight_buffer = deque(maxlen=5) + + for chunk in response_stream: + # Display the chunk immediately + self.frame.output_textbox.insert("end", chunk) + self.frame.output_textbox.see("end") + self.frame.update_idletasks() + + # Add to highlight buffer + highlight_buffer.append(chunk) + + # Process highlighting when buffer is full + if len(highlight_buffer) == 5: + self.process_highlighting(highlight_buffer) + + # Process any remaining chunks in the buffer + if highlight_buffer: + self.process_highlighting(highlight_buffer) + + self.frame.output_textbox.configure(state="disabled") self.update_provider_list() + + def process_highlighting(self, highlight_buffer): + start_index = self.frame.output_textbox.index(f"end-{sum(len(c) for c in highlight_buffer)}c") + end_index = self.frame.output_textbox.index("end") + self.highlight_words(start_index, end_index) + + # Keep overlap of 2 chunks + highlight_buffer = deque(list(highlight_buffer)[-2:], maxlen=5) + + def highlight_words(self, start_index, end_index): + content = self.frame.output_textbox.get(start_index, end_index) + + for word in WORDS: + start = 0 + while True: + pos = content.find(word, start) + if pos == -1: + break + word_start = f"{start_index}+{pos}c" + word_end = f"{word_start}+{len(word)}c" + tag_name = f"{word.lower()}_color" + self.frame.output_textbox.tag_add(tag_name, word_start, word_end) + if word in BAD_WORDS: + self.frame.output_textbox.tag_config(tag_name, foreground=BAD_COLOR) + elif word in GOOD_WORDS: + self.frame.output_textbox.tag_config(tag_name, foreground=GOOD_COLOR) + start = pos + len(word) def _predict(self, text_data: TextData) -> TextData: """ @@ -57,8 +114,6 @@ class MainFrameController: text_data.confidence = result["confidence"] text_data.result = result["result"] text_data.is_fake_news = result["is_fake"] - print(f"Prediction: {text_data.result}") - print(f"Confidence: {text_data.confidence}") return text_data def _add_to_db(self, text_data: TextData) -> None: @@ -119,8 +174,6 @@ class MainFrameController: count_label = ctk.CTkLabel(provider_frame, text=str(provider.get_fake_percentage())+"%") count_label.pack(side="right", padx=5) - - def _update_output(self, output: str) -> None: """ Update the output text box with the result. @@ -130,6 +183,4 @@ class MainFrameController: self.frame.output_textbox.configure(state="normal") self.frame.output_textbox.delete("0.0", "end") self.frame.output_textbox.insert("0.0", output) - self.frame.output_textbox.configure(state="disabled") - - \ No newline at end of file + self.frame.output_textbox.configure(state="disabled") \ No newline at end of file From ec3e542030a25a8b8af82377c573dbc720cd9100 Mon Sep 17 00:00:00 2001 From: Falko Habel Date: Thu, 10 Oct 2024 09:40:13 +0200 Subject: [PATCH 6/6] bg --- src/controller/mainFrameController.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controller/mainFrameController.py b/src/controller/mainFrameController.py index cd06495..b9416d2 100644 --- a/src/controller/mainFrameController.py +++ b/src/controller/mainFrameController.py @@ -183,4 +183,6 @@ class MainFrameController: self.frame.output_textbox.configure(state="normal") self.frame.output_textbox.delete("0.0", "end") self.frame.output_textbox.insert("0.0", output) - self.frame.output_textbox.configure(state="disabled") \ No newline at end of file + self.frame.output_textbox.configure(state="disabled") + + \ No newline at end of file