ai-code-detector / main.py
Karim Krklec
'first'
dcce181
Raw
History Blame Contribute Delete
10.4 kB
from feature_extraction import extract_all_features
# ─────────────────────────────────────────────────────────────────────────────
# UČITAVANJE MODELA
# ─────────────────────────────────────────────────────────────────────────────
MODEL_NAME = "Salesforce/codegen-350M-mono"
def ucitaj_model():
try:
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
print(f" Učitavam model '{MODEL_NAME}'...")
print(" (Pri prvom pokretanju ovo moΕΎe potrajati par minuta.)\n")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
model = AutoModelForCausalLM.from_pretrained(
MODEL_NAME,
torch_dtype=torch.float32, # float32 radi na CPU bez GPU-a
)
model.eval() # isključi dropout β€” samo inferenca, ne treniranje
num_params = sum(p.numel() for p in model.parameters()) // 1_000_000
print(f" Model učitan ({num_params}M parametara).\n")
return model, tokenizer
except ImportError:
print(" [UPOZORENJE] transformers ili torch nisu instalirani.")
print(" Pokreni: pip install transformers torch\n")
return None, None
except Exception as e:
print(f" [UPOZORENJE] Model nije mogao biti učitan: {e}\n")
return None, None
# ─────────────────────────────────────────────────────────────────────────────
# UNOS KODA
# ─────────────────────────────────────────────────────────────────────────────
def ucitaj_kod() -> str:
print("Zalijepi kod ispod, a kad zavrΕ‘iΕ‘ pritisni Enter dva puta:\n")
linije = []
prazni_zaredom = 0
while True:
linija = input()
if linija == "":
prazni_zaredom += 1
if prazni_zaredom >= 2:
break
linije.append(linija)
else:
prazni_zaredom = 0
linije.append(linija)
return "\n".join(linije).strip()
def ucitaj_iz_datoteke(putanja: str) -> str:
try:
with open(putanja, "r", encoding="utf-8") as f:
sadrzaj = f.read()
print(f" Učitano {len(sadrzaj.splitlines())} linija iz '{putanja}'.")
return sadrzaj
except FileNotFoundError:
print(f"\n [GREΕ KA] Datoteka '{putanja}' nije pronaΔ‘ena.")
print( " Provjeri je li datoteka u istom folderu kao main.py.")
return ""
except Exception as e:
print(f"\n [GREŠKA] Problem pri čitanju datoteke: {e}")
return ""
# ─────────────────────────────────────────────────────────────────────────────
# ISPIS REZULTATA
# ─────────────────────────────────────────────────────────────────────────────
def ispisi_znacajke(features: dict) -> None:
jezik = features.get("detected_language", "nepoznat")
print(f"\n{'═' * 55}")
print(f" Prepoznat jezik: {jezik.upper()}")
print(f"{'═' * 55}")
# ── Stilska detekcija ──────────────────────────────────────
print("\n [ STILSKA DETEKCIJA β€” komentari, imenovanje, formatiranje ]\n")
stilske = [
("Broj linija s komentarom", "num_comment_lines"),
("Udio komentara (%)", "comment_ratio"),
("Prosj. duljina komentara (rij.)", "avg_comment_length_words"),
("Udio komentara u znakovima", "comment_to_code_ratio"),
("Broj blok komentara", "num_block_comments"),
("Broj docstringova / JSDoc", "num_docstrings"),
("Prosj. duljina identifikatora", "avg_identifier_length"),
("Prosj. duljina naziva funkcija", "avg_function_name_length"),
("Udio jednoslovnih naziva", "single_char_name_ratio"),
("Leksička raznolikost naziva", "lexical_diversity"),
("Udio snake_case stila", "snake_case_ratio"),
("Udio camelCase stila", "camel_case_ratio"),
("Konzistentnost imenovanja", "naming_consistency"),
("Ukupno linija", "total_lines"),
("Udio praznih linija", "empty_line_ratio"),
("Prosj. duljina linije (znakovi)", "avg_line_length"),
("Max duljina linije", "max_line_length"),
("Koristi tabove (1=da, 0=ne)", "uses_tabs"),
("Udio linija s trailing space", "trailing_whitespace_ratio"),
("Konzistentnost razmaka operatori", "operator_spacing_consistency"),
]
for naziv, kljuc in stilske:
val = features.get(kljuc, "N/A")
if isinstance(val, float):
print(f" {naziv:<38} {val:.4f}")
else:
print(f" {naziv:<38} {val}")
# ── Strukturna detekcija ───────────────────────────────────
print("\n [ STRUKTURNA DETEKCIJA β€” AST, sloΕΎenost, tok kontrole ]\n")
strukturne = [
("Dubina AST stabla", "ast_depth"),
("Broj čvorova u AST stablu", "ast_node_count"),
("Raznolikost tipova čvorova", "unique_node_type_ratio"),
("Broj funkcija / metoda", "num_functions"),
("Prosj. duljina funkcije (linije)", "avg_function_length"),
("Max duljina funkcije (linije)", "max_function_length"),
("Prosj. broj argumenata", "avg_args_per_function"),
("Broj klasa", "num_classes"),
("Broj importa", "num_imports"),
("Broj if naredbi", "num_if_statements"),
("Broj for petlji", "num_for_loops"),
("Broj while petlji", "num_while_loops"),
("Broj try/catch blokova", "num_try_blocks"),
("Broj lambda izraza", "num_lambdas"),
("Max dubina ugnijeΕΎΔ‘enosti", "max_nesting_depth"),
("Prosj. dubina ugnijeΕΎΔ‘enosti", "avg_nesting_depth"),
("Aproks. ciklomatska sloΕΎenost", "cyclomatic_complexity_approx"),
]
for naziv, kljuc in strukturne:
val = features.get(kljuc, "N/A")
if isinstance(val, float):
print(f" {naziv:<38} {val:.4f}")
else:
print(f" {naziv:<38} {val}")
# ── Statistička detekcija ──────────────────────────────────
print("\n [ STATISTIČKA DETEKCIJA β€” perplexity ]\n")
perp = features.get("perplexity", -1.0)
dostupan = features.get("model_available", 0)
if dostupan == 0:
print(" Model nije učitan β€” perplexity nije izračunat.")
else:
print(f" {'Perplexity':<38} {perp:.4f}")
# Grubo tumačenje perplexityja za CodeGEN-350M
if perp < 5:
tumacenje = "vrlo nizak β†’ vjerojatno AI"
elif perp < 20:
tumacenje = "nizak → moguće AI"
elif perp < 60:
tumacenje = "srednji β†’ nejasno"
else:
tumacenje = "visok β†’ vjerojatno čovjek"
print(f" {'Tumačenje':<38} {tumacenje}")
print(f"\n{'═' * 55}")
print(f" Ukupno izvučeno značajki: {len(features) - 1}")
print(f"{'═' * 55}\n")
# ─────────────────────────────────────────────────────────────────────────────
# GLAVNI PROGRAM
# ─────────────────────────────────────────────────────────────────────────────
def main():
print("=" * 55)
print(" Ekstraktor značajki koda")
print(" (za detekciju AI generiranog koda)")
print("=" * 55)
# Pitaj korisnika želi li učitati model za perplexity
print("\nŽeliő li učitati model za izračun perplexityja?")
print(" d β€” Da (skida ~700 MB pri prvom pokretanju)")
print(" n β€” Ne (perplexity Δ‡e biti preskočen)\n")
odabir_model = input("Odabir (d/n): ").strip().lower()
model, tokenizer = None, None
if odabir_model in ("d", "da", "y", "yes"):
model, tokenizer = ucitaj_model()
# Način unosa koda
print("\nNačin unosa koda:")
print(" 1 β€” Zalijepi kod direktno u terminal")
print(" 2 β€” Učitaj iz datoteke (npr. kod.txt)")
while True:
print()
odabir = input("Odaberi način unosa (1 ili 2): ").strip()
if odabir == "1":
kod = ucitaj_kod()
elif odabir == "2":
putanja = input("Putanja do datoteke (Enter za 'kod.txt'): ").strip()
if putanja == "":
putanja = "kod.txt"
kod = ucitaj_iz_datoteke(putanja)
else:
print(" Unesi 1 ili 2.")
continue
if not kod:
print(" Kod je prazan. PokuΕ‘aj ponovno.")
continue
print("\nIzvlačim značajke...")
znacajke = extract_all_features(kod, model=model, tokenizer=tokenizer)
ispisi_znacajke(znacajke)
odgovor = input("Želiő li analizirati joő jedan isječak koda? (da/ne): ")
if odgovor.strip().lower() not in ("da", "d", "yes", "y"):
print("\nZatvaram program.")
break
if __name__ == "__main__":
main()