Johnnnys3 commited on
Commit
6930708
·
verified ·
1 Parent(s): 79bd4d9

Upload README.md with huggingface_hub

Browse files
Files changed (1) hide show
  1. README.md +96 -0
README.md ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: apache-2.0
3
+ base_model: distilbert-base-uncased
4
+ tags:
5
+ - text-classification
6
+ - retrieval
7
+ - rag
8
+ - distilbert
9
+ datasets: []
10
+ metrics:
11
+ - accuracy
12
+ - precision
13
+ - recall
14
+ - f1
15
+ pipeline_tag: text-classification
16
+ ---
17
+
18
+ # StudyWise Chunk Relevance Classifier
19
+
20
+ A DistilBERT model fine-tuned to judge whether a retrieved text chunk is actually relevant to a user's question, for the [StudyWise](https://github.com/johnnnys3/Studywise-ai) RAG pipeline.
21
+
22
+ Given a `(question, chunk_text)` pair, the model predicts one of two labels:
23
+
24
+ - `relevant` — the chunk should be used to answer the question
25
+ - `not_relevant` — the chunk is off-topic or was a weak retrieval candidate
26
+
27
+ ## Intended use
28
+
29
+ Meant as a lightweight re-ranking / filtering signal sitting after StudyWise's hybrid retriever (keyword + proposition + embedding search) and before answer generation — catching cases where the hybrid retriever's score doesn't reflect true relevance.
30
+
31
+ This is a small-scale training exercise tied to a specific student project, not a production-grade reranker. See **Limitations** before relying on it.
32
+
33
+ ## Training data
34
+
35
+ Built from StudyWise's own `rag_traces` — real (question, retrieved-chunk, hybrid-retrieval-score) records logged by the app's retriever — plus explicit cross-document negatives, via [`prepare_data.py`](./prepare_data.py):
36
+
37
+ - **Positive** (`relevant`, label `1`): chunk ranked in the top 2 hybrid-retrieval results for a question.
38
+ - **Hard negative** (`not_relevant`, label `0`): chunk was retrieved as a candidate for the question but ranked below the top 2.
39
+ - **Easy negative** (`not_relevant`, label `0`): chunk sampled from a document unrelated to the question's source document — guaranteed irrelevant.
40
+
41
+ Split **by question** (not by row) to prevent the same question's phrasing from leaking across train/validation/test.
42
+
43
+ | Split | Examples | Unique questions | % relevant |
44
+ |---|---|---|---|
45
+ | train | 481 | 8 | 23.1% |
46
+ | validation | 172 | 2 | 22.1% |
47
+ | test | 99 | 2 | 26.3% |
48
+
49
+ ## Training procedure
50
+
51
+ - Base model: `distilbert-base-uncased`
52
+ - Input: `question` and `chunk_text` encoded as a sentence pair (`[CLS] question [SEP] chunk_text [SEP]`), max length 256
53
+ - 6 epochs, learning rate 2e-5, batch size 16, weight decay 0.01
54
+ - Best checkpoint selected by validation F1
55
+ - Full script: [`train.py`](./train.py)
56
+
57
+ ## Results (held-out test split)
58
+
59
+ | Metric | Value |
60
+ |---|---|
61
+ | Accuracy | 0.717 |
62
+ | Precision | 0.458 |
63
+ | Recall | 0.423 |
64
+ | F1 | 0.440 |
65
+
66
+ Confusion matrix (test, n=99):
67
+
68
+ | | Predicted not_relevant | Predicted relevant |
69
+ |---|---|---|
70
+ | **Actual not_relevant** | 60 | 13 |
71
+ | **Actual relevant** | 15 | 11 |
72
+
73
+ ## Limitations
74
+
75
+ - **Small, low-diversity source data.** The underlying trace log covers only 12 unique questions (all biology/ecology content from test/eval documents), split 8/2/2. The reported metrics are indicative of the approach, not a reliable estimate of real-world performance — treat them as a training exercise, not a benchmark.
76
+ - **Below-baseline raw accuracy.** A trivial "always predict not_relevant" baseline scores 0.737 accuracy on this test split (since ~74% of pairs are negative), higher than this model's 0.717. The model trades some accuracy for actually catching relevant chunks (F1 0.44 vs. the baseline's 0.0 F1 on the positive class), which is the more useful trade-off for a retrieval filter, but it means accuracy alone is a misleading headline metric here.
77
+ - **Domain-narrow.** Trained entirely on biology/ecology chunks; unlikely to generalize to other subjects without more data.
78
+
79
+ ## Usage
80
+
81
+ ```python
82
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
83
+ import torch
84
+
85
+ tokenizer = AutoTokenizer.from_pretrained("REPO_ID")
86
+ model = AutoModelForSequenceClassification.from_pretrained("REPO_ID")
87
+
88
+ question = "What happens during the electron transport chain?"
89
+ chunk = "The electron transport chain is located in the inner mitochondrial membrane."
90
+
91
+ inputs = tokenizer(question, chunk, return_tensors="pt", truncation=True, max_length=256)
92
+ with torch.no_grad():
93
+ logits = model(**inputs).logits
94
+ prediction = model.config.id2label[logits.argmax().item()]
95
+ print(prediction)
96
+ ```