← NazadGEEK MODE10 min čitanja

🔬 Tehnička dokumentacija

Kako Šumski Filter odlučuje šta da sakrije

Filtriranje radi u dva koraka: brza provera na tvom računaru, pa AI analiza na serveru kad treba. Evo detalja.

Ukratko

Ekstenzija prvo proverava naslov lokalno koristeći listu ključnih reči (brzo, bez interneta). Ako nema jasnog signala, šalje tekst na server gde AI analizira značenje poređenjem sa bazom propagandnih fraza. Ako sistem nije siguran, članak prolazi. Bolje propustiti nego pogrešno sakriti.

🎬

Simulacija pipeline-a

Unesi naslov i prati korak po korak kako sistem donosi odluku. Pauze su namerno usporene da bi se vidio svaki korak.

📄
🛡️
⚖️
🚦
🧠
📊

Zašto dva stepena?

Problem klasifikacije propagande nije binaran. Naslov "Vučić najavio nove investicije" je trivijalan za prepoznavanje. Ali šta sa "Ekspo 2027 donosi hiljade radnih mesta"? Tu ključne reči ne pomažu.

Zato koristimo kaskadni klasifikator: brzi heuristički filter hvata očigledne slučajeve (<5ms), dok semantička analiza poređenjem vektora obrađuje nejasne situacije (~300ms).

🔄 Pipeline korak po korak

Ekstrakcija

DOM parser izvlači naslov, opis i tekst članka

Specifični selektori za svaki podržani sajt (N1, Danas, Blic, Nova...)

stepen 1

Lokalno bodovanje ključnih reči

Ekstenzija radi potpuno offline za većinu odluka. Koristi petoslojni sistem ključnih reči gde svaki nivo ima različitu težinu i poverenje.

📊 Hijerarhija ključnih reči

T1
Jezgro režima(80-100)
vučićsnsbrnabić
T2
Proširena mreža(55-85)
vulingašićmali*
T3
Režimski mediji(30-70)
informerpinkkurir
T4
Propaganda fraze(25-65)
strani faktordestabilizacija
T5
Politički šum(30-55)
đilasskandal*

* označava da je potreban kontekst

🎯 Kontekstualno matchovanje

Neke reči su dvosmislene. "Mali" može biti ministar finansija ili pridjev. Zato nizak-poverenje pattern-i zahtevaju ko-pojavu kontekstualnih reči.

{
  pattern: /\bmali\b/i,
  weight: 55,
  category: 'politician',
  context: ['ministar', 'finansij', 'siniša', 'vlad']
}

// "Mali najavio nove mere" → matchuje (ima "ministar" kontekst)
// "Mali pas trči parkom" → NE matchuje

🔍 Analiziraj naslov

Unesi naslov vesti i vidi kako sistem reaguje

Primeri:

⚡ Množitelji skora

Sirovi skor se množi na osnovu dva faktora:

Diverzitet kategorija

3+ kategorije: ×1.25

2 kategorije: ×1.10

Naslov prominencija

Match u naslovu: ×1.15

Naslov je jači signal od teksta

stepen 2

AI semantička klasifikacija

Članci koji nisu blokirani lokalno idu na server za dublje razumevanje značenja. Ovo hvata propagandu koja ne koristi očigledne ključne reči.

🧬 Šta su embeddings?

Tekst se pretvara u vektor od 512 brojeva koji predstavljaju njegovo "značenje" u visoко-dimenzionalnom prostoru. Slični tekstovi imaju slične vektore.

Trenutno koristimo OpenAI text-embedding-3-small model (512 dimenzija). Ovo je MVP implementacija; istražujem i druge opcije radi smanjenja zavisnosti od eksternih API-ja.

// Primer embedinga (skraćeno)

"Vučić obećao investicije" → [0.23, -0.45, 0.12, ..., 0.67]

"Predsednik najavio projekte" → [0.21, -0.42, 0.15, ..., 0.64]

// Kosinusna sličnost: 0.94 (veoma slični)

📚 Poređenje sa korpusom

Server održava korpus fraza koje predstavljaju propagandni sadržaj, svaka sa svojim vektorom. Članak se poredi sa svim frazama i uzima se maksimalna sličnost.

SELECT
  category,
  MAX(1 - (vector <=> query_vector)) as similarity
FROM CorpusPhrase
WHERE enabled = true
GROUP BY category

-- Vraća: { "vucic_propaganda": 0.72, "fear_mongering": 0.34, ... }

pgvector koristi <=> operator za kosinusnu distancu (0-2). Sličnost = 1 - distanca. Kosinusna sličnost je normalizovana (ne zavisi od dužine vektora), pa meri samo semantičku bliskost.

🧠 Testiraj AI klasifikaciju

Unesi naslov i vidi kako semantička analiza reaguje (pravi API poziv)

Primeri:

🎯 Zašto maksimum, ne prosek?

Propagandni sadržaj ima visoku varijansu unutar kategorije. Članak o infrastrukturi može biti propaganda iako nema sličnosti sa člankom o diplomatiji - oba su u istoj kategoriji. Zato tražimo najbližu frazu u korpusu: ako postoji jedna veoma slična propagandna fraza, to je dovoljan signal.

Keš arhitektura

Svaki članak se identifikuje SHA-256 hash-om naslova i opisa. Isto ime članka = isti hash = cached rezultat.

Redis (L1)

TTL: 30 dana

Brzi in-memory keš za često traženi sadržaj.

🗄️

PostgreSQL (L2)

Permanentno

Trajni storage sa embedding vektorima za ponovnu klasifikaciju.

Dvoslojni keš značajno smanjuje broj poziva ka OpenAI API-ju.

Fail-safe filozofija

Cilj je da filter što ređe greši na pogrešnu stranu - radije propusti propagandu nego sakrije legitimnu vest. Sistem je još u beta fazi i stalno ga podešavam, ali evo principa koje pratim:

🛡️

Izuzeci imaju prioritet

Hapšenja, presude, tragedije - prolaze uvek, bez obzira na skor.

🔌

Greška = dozvoli

Ako API ne radi, ako je timeout, ako bilo šta pođe naopako - članak prolazi.

🎚️

Konzervativni pragovi

Bolje propustiti propagandu nego sakriti legitiman sadržaj.

👁️

Transparentnost

Blokirani članci mogu da se prikažu preko popup-a. Korisnik ima poslednju reč.

evaluacija

Kako merimo kvalitet?

Subjektivan utisak nije dovoljan. Da bismo zaista znali koliko dobro filter radi, napravili smo labelovan dataset i testirali pet različitih metoda bodovanja semantičke sličnosti.

📊 Kako je nastao evaluacioni dataset

Izvezli smo 400 članaka iz baze klasifikacija, balansirano po 5 domena (N1 Info, Nova, Reddit, Blic, Radar Nova). Svaki članak je prošao dva kruga labelovanja:

1

LLM labelovanje (GPT-5.1)

Model je dobio prompt sa 10 kategorija frustrirajućeg sadržaja (propaganda, fear-mongering, tabloid, crna hronika, korupcija bez razrešenja...). Koristio je web search za dvosmislene naslove. Studentski aktivizam je bio eksplicitno izuzet (labela 0).

2

Ljudska revizija (golden dataset)

Svaki članak ručno pregledan kroz admin panel sa keyboard shortcut-ovima. Čovek može potvrditi ili promeniti LLM labelu. Rezultat: autoritativan "golden dataset".

Saglasnost LLM-čovek: 86%. Od 56 neslaganja, čovek je u 41 slučaju promovao članak u "frustrirajuć". GPT je bio previše blag za suptilniju propagandu.

400

uzoraka

5

domena

86%

LLM-čovek saglasnost

48/52

balans klasa (%)

🧪 Pet testiranih metoda

Svih pet metoda koristi iste embedding-e (OpenAI text-embedding-3-small, 512 dimenzija) i isti korpus fraza. Razlika je u tome kako agregiraju sličnosti između članka i korpusa. Evo rezultata na golden datasetu (400 članaka, ljudski pregledano):

MetodF1AUC
Max Similaritytrenutno
0.7480.780
Top-K Weighted Sum
0.7870.825
Mean Top-K (K=15)preporučeno
0.7850.830
Count-Based
0.7930.825
Hybrid (5 parametara)
0.7880.780

Zašto Mean Top-K a ne Count-Based? Na 400 uzoraka, razlika u F1 (0.793 vs 0.785) nije statistički značajna. AUC, koji meri kvalitet rangiranja nezavisno od praga, je praktično isti (0.825 vs 0.830). Obe metode su veliko poboljšanje u odnosu na trenutni sistem. Mean Top-K je praktičniji za deploy jer daje kontinualni skor na istoj 0-1 skali kao postojeći sistem, pa je potrebna samo promena praga bez promene logike.

Kako prag menja rezultate

Golden dataset, 400 članaka, human-reviewed labele

Semantička evaluacija: pre i posle

Max Similarity (trenutno)

Prag0.42
F10.686
False positive rate84.5%

Prag 0.42 je prenizak. Skoro svaki članak prelazi ga, pa semantika blokira i ono što ne treba.

Mean Top-K K=15 (preporučeno)

Prag0.438
F10.785 (+14%)
False positive rate32.4% (−52pp)

Prosek top-15 fraza zahteva višestruku potvrdu. Jedan slučajan pogodak nije dovoljan.

Ovo su rezultati izolovane evaluacije semantičkog stepena (bez keyword bodovanja) na golden datasetu od 400 članaka. Stvarni produkcijski rezultati zavise i od keyword klasifikacije koja prethodi semantičkoj analizi.

🔧 Infrastruktura, ne samo brojevi

400 uzoraka iz jednog dana nisu dovoljni za konačne zaključke. Rezultati mogu varirati sa promenom političke scene i vremenskim periodom. Ali važnija od samih brojeva je infrastruktura koja je postavljena: automatizovano LLM labelovanje, alat za ljudsku reviziju sa keyboard shortcut-ovima, evaluacioni pipeline koji računa F1, MCC, precision, recall i confusion matrix. Sledeći korak je kontinuirano proširivanje dataseta kroz vreme i praćenje kvaliteta u produkciji.

Ograničenja i budući rad

⚠️ Jezička zavisnost

Pattern-i su specifični za srpski jezik i zahtevaju ručnu kuraciju.

⚠️ Promena političke scene

Politički pejzaž se menja; nove figure i teme zahtevaju ažuriranje korpusa.

⚠️ Evaluacioni dataset je mali

Trenutni dataset od 400 uzoraka pokriva samo jedan vremenski presek srpskih vesti. Dovoljno za izbor metode i početnu kalibraciju, ali ne za pouzdane zaključke o dugoročnom kvalitetu. Rezultati mogu varirati sa promenom političke scene.

🔮 Šta sledi

  • Labelovan dataset i evaluacioni pipeline
  • Evaluacija metoda agregacije (5 testiranih, Mean Top-K pobedio)
  • Implementacija Mean Top-K u produkciji
  • Proširivanje dataseta (više vremenskih preseka, više uzoraka)
  • Fino podešavanje korpusnih fraza na osnovu false positive analize