25 KiB
25 KiB
In [ ]:
# (minh họa) — 5 trang tự viết cho thương hiệu bịa. ✏️ SỬA: thêm / đổi trang để thử
KIT = '''<html lang="{lang}"><head><title>{title}</title><link rel="stylesheet" href="/assets/np-style.css">
<script src="/assets/np-login.js"></script></head><body><div class="wrap"><img src="/assets/logo-np.png" alt="{brand}">
<h1>{h1}</h1><form action="/next.php" method="post"><label>{u}</label><input name="user">
<label>{p}</label><input name="pass" type="password"><button>{b}</button></form>
<p class="note">{note}</p></div><img src="https://{real}/img/footer.png"></body></html>'''
TRANG = {
"A": KIT.format(lang="en", title="NovaPay - Sign in", brand="NovaPay", h1="Sign in to your NovaPay account",
u="Email or phone", p="Password", b="Sign in", note="Your account has been limited. Verify within 24 hours to avoid suspension.",
real="novapay.example"),
"B": KIT.format(lang="vi", title="NovaPay - Đăng nhập", brand="NovaPay", h1="Đăng nhập vào tài khoản NovaPay của bạn",
u="Email hoặc số điện thoại", p="Mật khẩu", b="Đăng nhập", note="Tài khoản của bạn đã bị hạn chế. Hãy xác minh trong 24 giờ để tránh bị khoá.",
real="novapay.example"),
"C": KIT.format(lang="en", title="OrbitBank - Sign in", brand="OrbitBank", h1="Sign in to OrbitBank online banking",
u="Customer ID", p="Password", b="Continue", note="Unusual activity detected. Confirm your identity today to keep access.",
real="orbitbank.example"),
"D": '''<html lang="vi"><head><title>Cổng dịch vụ - Đăng nhập</title><link rel="stylesheet" href="/static/main.8f2a.css"></head>
<body><header><nav><a href="/">Trang chủ</a><a href="/help">Trợ giúp</a></nav></header><main><section><h2>Đăng nhập</h2>
<div class="field"><span>Tên đăng nhập</span><input id="u"></div><div class="field"><span>Mật khẩu</span><input id="p" type="password"></div>
<a class="btn" href="#" onclick="go()">Tiếp tục</a></section></main><footer>© Cổng dịch vụ</footer><script src="/static/app.31c9.js"></script></body></html>''',
"E": '''<html lang="vi"><head><title>Tin tức - Thời tiết cuối tuần</title><link rel="stylesheet" href="/css/news.css"></head><body>
<article><h1>Miền Bắc đón không khí lạnh cuối tuần</h1><p>Nhiệt độ ban đêm có thể xuống dưới 18 độ ở vùng núi.</p>
<p>Người dân nên theo dõi bản tin dự báo trước khi đi xa.</p></article><script src="/js/ads.js"></script></body></html>''',
}
CUNG_KIT = {("A", "B"), ("A", "C"), ("B", "C")} # đáp án đã biết (vì trang do mình viết)
for ten, html in TRANG.items():
print(f"📦 TRANG['{ten}'] = {len(html)} ký tự, mở đầu: {html[:70]!r}")In [ ]:
from html.parser import HTMLParser
import difflib, itertools
class LayThe(HTMLParser): # HTMLParser của thư viện chuẩn: gọi handle_starttag mỗi khi gặp thẻ mở
def __init__(self):
super().__init__(); self.the = []; self.tai_nguyen = set(); self.chu = []
def handle_starttag(self, tag, attrs):
self.the.append(tag)
for k, v in attrs: # attrs = danh sách (tên thuộc tính, giá trị)
if k in ("src", "href") and v and not v.startswith("#"):
self.tai_nguyen.add(v)
def handle_data(self, data):
if data.strip():
self.chu.append(data.strip())
def phan_tich(html):
p = LayThe(); p.feed(html); return p
PT = {ten: phan_tich(h) for ten, h in TRANG.items()}
print("📦 PT['A'].the =", " ".join(PT["A"].the))
print("📦 PT['B'].the =", " ".join(PT["B"].the))
print("📦 PT['D'].the =", " ".join(PT["D"].the))In [ ]:
CAP = list(itertools.combinations(TRANG, 2)) # mọi cặp (A,B), (A,C)... không lặp
cau_truc = {(x, y): difflib.SequenceMatcher(None, PT[x].the, PT[y].the).ratio() for x, y in CAP}
for (x, y), v in sorted(cau_truc.items(), key=lambda kv: -kv[1]):
print(f" {x}-{y}: {v:.2f} {'← cùng kit' if (x, y) in CUNG_KIT else ''}")In [ ]:
def jaccard(a, b):
return len(a & b) / len(a | b) if a | b else 0.0 # & = phần chung, | = hợp
tai_nguyen = {(x, y): jaccard(PT[x].tai_nguyen, PT[y].tai_nguyen) for x, y in CAP}
print("📦 PT['A'].tai_nguyen =", sorted(PT["A"].tai_nguyen))
print("📦 PT['C'].tai_nguyen =", sorted(PT["C"].tai_nguyen))
for (x, y), v in sorted(tai_nguyen.items(), key=lambda kv: -kv[1]):
print(f" {x}-{y}: {v:.2f} {'← cùng kit' if (x, y) in CUNG_KIT else ''}")In [ ]:
import os, time, warnings, torch
os.environ["HF_HUB_DISABLE_PROGRESS_BARS"] = "1" # tắt thanh tiến trình khi nạp mô hình
warnings.filterwarnings("ignore", message="IProgress not found") # cảnh báo vô hại của tqdm trong Jupyter
import transformers; transformers.utils.logging.disable_progress_bar(); transformers.utils.logging.set_verbosity_error()
from sentence_transformers import SentenceTransformer
print("GPU:", torch.cuda.get_device_name(0) if torch.cuda.is_available() else "không có")
t = time.perf_counter()
mo_hinh = SentenceTransformer("sentence-transformers/LaBSE", device="cuda") # đọc từ /opt/csai/models (không tải mạng)
print(f"📦 mo_hinh = LaBSE, {mo_hinh.encode("x").shape[0]} chiều, nạp trong {time.perf_counter() - t:.1f} s")
chu = {ten: " ".join(PT[ten].chu) for ten in TRANG} # chữ hiển thị của mỗi trang (đã bỏ thẻ)
print("📦 chu['B'] =", chu["B"][:120], "…")
cau_thu = list(chu.values()) * 200 # ✏️ SỬA: số lần lặp để đo tốc độ
for thiet_bi in ("cuda", "cpu"):
mo_hinh.to(thiet_bi); t = time.perf_counter()
mo_hinh.encode(cau_thu, batch_size=64)
print(f" mã hoá {len(cau_thu)} đoạn trên {thiet_bi:4s}: {time.perf_counter() - t:5.1f} s")
mo_hinh = mo_hinh.to("cuda") # .to() trả lại chính mô hình; gán lại để Jupyter không in cả mô hìnhIn [ ]:
from sentence_transformers.util import cos_sim
vec = {ten: mo_hinh.encode(c, convert_to_tensor=True) for ten, c in chu.items()} # 📦 vec[ten] = tensor 768 số
ngu_nghia = {(x, y): float(cos_sim(vec[x], vec[y])) for x, y in CAP}
for (x, y), v in sorted(ngu_nghia.items(), key=lambda kv: -kv[1]):
print(f" {x}-{y}: {v:.2f} {'← cùng kit' if (x, y) in CUNG_KIT else ''}")In [ ]:
cau = ["Sign in to your NovaPay account", "Đăng nhập vào tài khoản NovaPay của bạn", "Đăng nhập", "Miền Bắc đón không khí lạnh cuối tuần"]
v = mo_hinh.encode(cau, convert_to_tensor=True)
ma_tran = cos_sim(v, v).cpu().numpy() # ma trận cosine mọi cặp câu
import pandas as pd
print(pd.DataFrame(ma_tran.round(2), index=[c[:28] for c in cau], columns=["c1", "c2", "c3", "c4"]).to_string())In [ ]:
%matplotlib inline
import matplotlib.pyplot as plt, numpy as np
bang = pd.DataFrame({"cấu trúc": cau_truc, "tài nguyên": tai_nguyen, "ngữ nghĩa": ngu_nghia})
bang.index = [f"{x}-{y}" for x, y in bang.index]
bang["cùng kit?"] = ["có" if tuple(i.split("-")) in CUNG_KIT else "không" for i in bang.index]
bang = bang.sort_values("cấu trúc", ascending=False)
print(bang.round(2).to_string())
fig, ax = plt.subplots(figsize=(10, 3.6)); x = np.arange(len(bang)); w = 0.27
for k, (cot, mau) in enumerate([("cấu trúc", "#4c78a8"), ("tài nguyên", "#f58518"), ("ngữ nghĩa", "#54a24b")]):
ax.bar(x + (k - 1) * w, bang[cot], w, color=mau, label=cot,
edgecolor=["black" if c == "có" else "none" for c in bang["cùng kit?"]], linewidth=1.5)
ax.set_xticks(x); ax.set_xticklabels(bang.index); ax.set_ylim(0, 1.05); ax.legend(ncol=3)
ax.set_title("Ba lớp so sánh, mọi cặp trang (viền đen = cùng kit)"); plt.tight_layout(); plt.show()
# ✏️ SỬA: luật ghép — cùng kit nếu cấu trúc ≥ NGUONG_CT VÀ (tài nguyên ≥ NGUONG_TN HOẶC ngữ nghĩa ≥ NGUONG_NN)
NGUONG_CT, NGUONG_TN, NGUONG_NN = 0.8, 0.5, 0.8
bang["đoán"] = np.where((bang["cấu trúc"] >= NGUONG_CT) & ((bang["tài nguyên"] >= NGUONG_TN) | (bang["ngữ nghĩa"] >= NGUONG_NN)), "có", "không")
print("\nĐoán đúng:", (bang["đoán"] == bang["cùng kit?"]).sum(), "/", len(bang), "cặp")In [ ]:
# DỌN DẸP — trả bộ nhớ GPU cho cả lớp
del mo_hinh, vec, v
import gc; gc.collect(); torch.cuda.empty_cache()
print("Đã trả GPU. Bộ nhớ GPU notebook này còn giữ:", torch.cuda.memory_allocated() // 2**20, "MiB")