109 lines
4.3 KiB
Python
109 lines
4.3 KiB
Python
from pathlib import Path
|
|
from pypdf import PdfReader
|
|
import chromadb
|
|
from chromadb.utils import embedding_functions
|
|
|
|
# ==========================================
|
|
# FUNGSI BANTU
|
|
# ==========================================
|
|
|
|
def baca_pdf(path):
|
|
reader = PdfReader(path)
|
|
return "\n".join((p.extract_text() or "") for p in reader.pages)
|
|
|
|
def potong(teks, ukuran=800, tumpang=100):
|
|
hasil, mulai = [], 0
|
|
while mulai < len(teks):
|
|
hasil.append(teks[mulai:mulai + ukuran])
|
|
mulai += ukuran - tumpang
|
|
return [h for h in hasil if h.strip()]
|
|
|
|
# ==========================================
|
|
# SETUP EMBEDDING & CLIENT
|
|
# ==========================================
|
|
|
|
emb = embedding_functions.SentenceTransformerEmbeddingFunction(
|
|
model_name="paraphrase-multilingual-MiniLM-L12-v2")
|
|
|
|
client = chromadb.PersistentClient(path="./chroma_db")
|
|
|
|
def buat_koleksi(nama, ukuran, tumpang):
|
|
try:
|
|
client.delete_collection(nama)
|
|
except Exception:
|
|
pass
|
|
kol = client.get_or_create_collection(
|
|
name=nama, embedding_function=emb,
|
|
metadata={"hnsw:space": "cosine"})
|
|
for pdf in Path("dokumen").glob("*.pdf"):
|
|
chunks = potong(baca_pdf(pdf), ukuran, tumpang)
|
|
kol.upsert(
|
|
ids=[f"{nama}-{pdf.stem}-{i}" for i in range(len(chunks))],
|
|
documents=chunks,
|
|
metadatas=[{"sumber": pdf.name, "chunk": i} for i in range(len(chunks))],
|
|
)
|
|
print(f" {nama}: {pdf.name} -> {len(chunks)} chunk")
|
|
return kol
|
|
|
|
# ==========================================
|
|
# 15 PERTANYAAN + KATA KUNCI
|
|
# (disesuaikan dengan isi PDF probabilitas)
|
|
# ==========================================
|
|
|
|
UJI = [
|
|
("What is a sample space?", "sample space"),
|
|
("What is classical probability?", "classical probability"),
|
|
("What is empirical probability?", "empirical probability"),
|
|
("What is subjective probability?", "subjective probability"),
|
|
("What is a simple event?", "simple event"),
|
|
("What is the multiplication rule?", "multiplication rule"),
|
|
("What is the addition rule?", "addition rule"),
|
|
("What are mutually exclusive events?", "mutually exclusive"),
|
|
("What is conditional probability?", "conditional probability"),
|
|
("What is the law of large numbers?", "law of large numbers"),
|
|
("What is a discrete probability distribution?", "discrete probability distribution"),
|
|
("What is a binomial experiment?", "binomial experiment"),
|
|
("What is the fundamental counting principle?", "fundamental counting principle"),
|
|
("What is the difference between permutations and combinations?", "permutation"),
|
|
("What is a random variable?", "random variable"),
|
|
]
|
|
|
|
def hit_at_k(koleksi, uji, k):
|
|
benar = 0
|
|
for pertanyaan, kunci in uji:
|
|
docs = koleksi.query(query_texts=[pertanyaan], n_results=k)["documents"][0]
|
|
if any(kunci.lower() in d.lower() for d in docs):
|
|
benar += 1
|
|
return benar / len(uji)
|
|
|
|
# ==========================================
|
|
# JALANKAN: BUAT 2 KOLEKSI
|
|
# ==========================================
|
|
|
|
print("=== MEMBUAT KOLEKSI ===")
|
|
kol_500 = buat_koleksi("chunk_500", 500, 75)
|
|
kol_1500 = buat_koleksi("chunk_1500", 1500, 225)
|
|
|
|
print("\n=== CEK ISI KOLEKSI ===")
|
|
print(f" chunk_500 : {kol_500.count()} dokumen")
|
|
print(f" chunk_1500 : {kol_1500.count()} dokumen")
|
|
|
|
# ==========================================
|
|
# HITUNG HIT@K
|
|
# ==========================================
|
|
|
|
print("\n=== TABEL HIT@K ===")
|
|
print(f"{'k':<4}{'Chunk 500':<14}{'Chunk 1500':<14}")
|
|
for k in (1, 3, 5):
|
|
print(f"{k:<4}{hit_at_k(kol_500, UJI, k):<14.2f}{hit_at_k(kol_1500, UJI, k):<14.2f}")
|
|
|
|
print("\n=== PERTANYAAN GAGAL di k=3 ===")
|
|
for pertanyaan, kunci in UJI:
|
|
ok_500 = any(kunci.lower() in d.lower()
|
|
for d in kol_500.query(query_texts=[pertanyaan], n_results=3)["documents"][0])
|
|
ok_1500 = any(kunci.lower() in d.lower()
|
|
for d in kol_1500.query(query_texts=[pertanyaan], n_results=3)["documents"][0])
|
|
if not ok_500 and not ok_1500:
|
|
print(f"X {pertanyaan} (kunci: '{kunci}')")
|
|
|
|
print("\n=== SELESAI ===") |