Text Classification
Transformers
ONNX
PEFT
English
cross-encoder
reranker
thread-matching
conversational-ai
lora
Eval Results (legacy)
Instructions to use Algokruti/thread-reranker with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Algokruti/thread-reranker with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("text-classification", model="Algokruti/thread-reranker")# Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("Algokruti/thread-reranker", device_map="auto") - PEFT
How to use Algokruti/thread-reranker with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Create README.md
Browse files
README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
language:
|
| 3 |
+
- en
|
| 4 |
+
license: apache-2.0
|
| 5 |
+
library_name: transformers
|
| 6 |
+
tags:
|
| 7 |
+
- cross-encoder
|
| 8 |
+
- reranker
|
| 9 |
+
- thread-matching
|
| 10 |
+
- conversational-ai
|
| 11 |
+
- lora
|
| 12 |
+
- peft
|
| 13 |
+
- onnx
|
| 14 |
+
pipeline_tag: text-classification
|
| 15 |
+
datasets:
|
| 16 |
+
- Algokruti/thread-reranker-data
|
| 17 |
+
base_model: nreimers/MiniLM-L6-H384-uncased
|
| 18 |
+
model-index:
|
| 19 |
+
- name: thread-reranker
|
| 20 |
+
results:
|
| 21 |
+
- task:
|
| 22 |
+
type: text-classification
|
| 23 |
+
name: Thread Relevance Ranking
|
| 24 |
+
dataset:
|
| 25 |
+
name: thread-reranker-data
|
| 26 |
+
type: Algokruti/thread-reranker-data
|
| 27 |
+
split: test
|
| 28 |
+
metrics:
|
| 29 |
+
- name: Hit Rate @ 1 (Overall)
|
| 30 |
+
type: accuracy
|
| 31 |
+
value: 0.9049
|
| 32 |
+
- name: Hit Rate @ 1 (Easy)
|
| 33 |
+
type: accuracy
|
| 34 |
+
value: 1.0000
|
| 35 |
+
- name: Hit Rate @ 1 (Medium)
|
| 36 |
+
type: accuracy
|
| 37 |
+
value: 0.8211
|
| 38 |
+
- name: Hit Rate @ 1 (Hard)
|
| 39 |
+
type: accuracy
|
| 40 |
+
value: 0.8413
|
| 41 |
+
---
|
| 42 |
+
|
| 43 |
+
# Thread Reranker
|
| 44 |
+
|
| 45 |
+
A cross-encoder reranker that scores how relevant a conversation thread is to a new user message. Designed for unified conversation architectures where a single chat stream replaces explicit thread management β the model determines which internal thread a message belongs to so the right context can be retrieved automatically.
|
| 46 |
+
|
| 47 |
+
## How It Works
|
| 48 |
+
|
| 49 |
+
In a unified conversation system, users interact through a single continuous chat. Behind the scenes, the system maintains multiple internal threads (topics the user has discussed before). When a new message arrives, candidate threads are retrieved using fast heuristics (entity matching, recency, flow continuity), and this reranker scores each candidate to pick the best match.
|
| 50 |
+
|
| 51 |
+
The model takes two inputs simultaneously: the text pair (user message + thread summary) processed through the encoder, and structured retrieval features computed by the upstream pipeline. It fuses both signals to produce a relevance score.
|
| 52 |
+
|
| 53 |
+
### Architecture
|
| 54 |
+
|
| 55 |
+
```
|
| 56 |
+
User Message + Thread Summary βββΊ MiniLM-L6 (frozen + LoRA r=8) βββΊ CLS token βββ
|
| 57 |
+
ββββΊ MLP Head βββΊ Score
|
| 58 |
+
Step 3 Structured Features βββββββΊ Feature Projection (LinearβReLUβLinear) βββββββ
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
**Base model:** nreimers/MiniLM-L6-H384-uncased (22M parameters, encoder-only)
|
| 62 |
+
|
| 63 |
+
**LoRA configuration:** Rank 8, alpha 16, applied to query and value projections, dropout 0.1
|
| 64 |
+
|
| 65 |
+
**Structured features (5 inputs):**
|
| 66 |
+
- `entity_overlap` β count of thread entities found in the user message
|
| 67 |
+
- `keyword_matches` β keyword overlap between message and thread content
|
| 68 |
+
- `flow_continuity` β 1.0 if this thread was the most recently active, 0.0 otherwise
|
| 69 |
+
- `recency_score` β exponential decay score based on hours since thread was last active
|
| 70 |
+
- `hours_since_active` β raw hours since thread was last active
|
| 71 |
+
|
| 72 |
+
## Intended Use
|
| 73 |
+
|
| 74 |
+
This model is one component in a 7-step unified conversation pipeline:
|
| 75 |
+
|
| 76 |
+
1. **User sends message** β single chat stream, no thread selector
|
| 77 |
+
2. **Entity & signal extraction** β lightweight NER and pattern matching (no ML)
|
| 78 |
+
3. **Layered context retrieval** β database queries using entity match, recency, flow continuity
|
| 79 |
+
4. **Reranker (this model)** β scores candidate threads from Step 3
|
| 80 |
+
5. **Confidence threshold** β auto-select if confident, ask user if ambiguous
|
| 81 |
+
6. **LLM responds** β with the correct thread context injected
|
| 82 |
+
7. **Update thread store** β extract new entities and facts, write back to database
|
| 83 |
+
|
| 84 |
+
The model only fires when the deterministic heuristics in Step 3 produce multiple plausible candidates. Clear-cut cases (unique entity match + high recency) are resolved without the model.
|
| 85 |
+
|
| 86 |
+
## Performance
|
| 87 |
+
|
| 88 |
+
Evaluated on synthetic test data with three difficulty tiers:
|
| 89 |
+
|
| 90 |
+
| Difficulty | Hit Rate @ 1 | Description |
|
| 91 |
+
|---|---|---|
|
| 92 |
+
| **Easy** | 100.0% | Message contains explicit entity references ("fix the React bug") |
|
| 93 |
+
| **Medium** | 82.1% | Indirect references ("that bug we were debugging") |
|
| 94 |
+
| **Hard** | 84.1% | No entity signal, relies on recency and flow ("let's keep going") |
|
| 95 |
+
| **Overall** | 90.5% | Weighted across all tiers |
|
| 96 |
+
|
| 97 |
+
**Note:** In the hybrid pipeline, easy cases are handled by deterministic heuristics without calling the model. The model's effective contribution is on medium and hard cases, where the combined system achieves 95%+ accuracy when including heuristic pre-filtering.
|
| 98 |
+
|
| 99 |
+
## Training
|
| 100 |
+
|
| 101 |
+
**Dataset:** Algokruti/thread-reranker-data β 50,543 synthetic examples (12,500 positive, 38,043 negative) generated from 500 simulated user profiles across 12 topic types in 5 domains.
|
| 102 |
+
|
| 103 |
+
**Training strategy:** Curriculum learning β epochs 1-2 trained on easy examples only, epochs 3-5 on all difficulty tiers. Binary cross-entropy loss with cosine learning rate schedule and warmup.
|
| 104 |
+
|
| 105 |
+
**Hyperparameters:**
|
| 106 |
+
- Batch size: 64
|
| 107 |
+
- Learning rate: 2e-4
|
| 108 |
+
- Epochs: 5 (2 curriculum + 3 full)
|
| 109 |
+
- Max sequence length: 256
|
| 110 |
+
- LoRA rank: 8, alpha: 16
|
| 111 |
+
- Optimizer: AdamW with weight decay 0.01
|
| 112 |
+
- Gradient clipping: max norm 1.0
|
| 113 |
+
|
| 114 |
+
**Training domains covered:**
|
| 115 |
+
- Web Development (React Dashboard, Authentication, CSS Grid)
|
| 116 |
+
- Backend Development (Python API, Docker Deployment)
|
| 117 |
+
- Personal (Meal Planning, Job Search, Fitness)
|
| 118 |
+
- Data Science (ML Training, Data Pipeline)
|
| 119 |
+
- Mobile Development (iOS/Swift, Android/Kotlin)
|
| 120 |
+
|
| 121 |
+
## Limitations
|
| 122 |
+
|
| 123 |
+
- **Trained on synthetic data only.** Performance on real user conversations may differ, particularly for domains and linguistic patterns not represented in the training set.
|
| 124 |
+
- **Limited domain coverage.** 12 topics across 5 domains, heavily skewed toward software development. Non-technical topics (travel, health, education, finance, creative writing) are underrepresented.
|
| 125 |
+
- **English only.** Not tested on multilingual conversations.
|
| 126 |
+
- **Cold start.** With no conversation history, the model has nothing to rank. The system falls back to treating each message as a new thread.
|
| 127 |
+
- **Ambiguity resolution.** On genuinely ambiguous messages with no entity, recency, or flow signal, the model may select incorrectly. The confidence threshold mechanism is designed to catch these cases and ask the user instead.
|
| 128 |
+
|
| 129 |
+
## How to Use
|
| 130 |
+
|
| 131 |
+
### PyTorch Inference
|
| 132 |
+
|
| 133 |
+
```python
|
| 134 |
+
import torch
|
| 135 |
+
from transformers import AutoTokenizer, AutoModel
|
| 136 |
+
from peft import PeftModel
|
| 137 |
+
|
| 138 |
+
# Load model and tokenizer
|
| 139 |
+
tokenizer = AutoTokenizer.from_pretrained("nreimers/MiniLM-L6-H384-uncased")
|
| 140 |
+
|
| 141 |
+
# Load the full ThreadReranker (see training notebook for class definition)
|
| 142 |
+
model = ThreadReranker()
|
| 143 |
+
model.load_state_dict(torch.load("model.pt", map_location="cpu"))
|
| 144 |
+
model.eval()
|
| 145 |
+
|
| 146 |
+
# Score a message against a candidate thread
|
| 147 |
+
message = "can you fix that chart rendering issue"
|
| 148 |
+
thread_text = "Building a metrics dashboard with Chart.js | the bar chart overflows on mobile | React, Chart.js"
|
| 149 |
+
|
| 150 |
+
encoding = tokenizer(message, thread_text, max_length=256,
|
| 151 |
+
padding="max_length", truncation=True, return_tensors="pt")
|
| 152 |
+
|
| 153 |
+
features = torch.tensor([[1.0, 1.0, 1.0, 0.92, 2.0]]) # Step 3 features
|
| 154 |
+
|
| 155 |
+
with torch.no_grad():
|
| 156 |
+
score = torch.sigmoid(model(encoding["input_ids"], encoding["attention_mask"], features))
|
| 157 |
+
|
| 158 |
+
print(f"Relevance score: {score.item():.4f}")
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
### ONNX Inference (On-Device)
|
| 162 |
+
|
| 163 |
+
```python
|
| 164 |
+
import onnxruntime as ort
|
| 165 |
+
import numpy as np
|
| 166 |
+
|
| 167 |
+
session = ort.InferenceSession("thread_reranker.onnx")
|
| 168 |
+
|
| 169 |
+
# Prepare inputs (tokenized text + structured features)
|
| 170 |
+
result = session.run(None, {
|
| 171 |
+
"input_ids": input_ids_np,
|
| 172 |
+
"attention_mask": attention_mask_np,
|
| 173 |
+
"structured_features": features_np,
|
| 174 |
+
})
|
| 175 |
+
|
| 176 |
+
score = 1 / (1 + np.exp(-result[0])) # sigmoid
|
| 177 |
+
```
|
| 178 |
+
|
| 179 |
+
## Files
|
| 180 |
+
|
| 181 |
+
| File | Description |
|
| 182 |
+
|---|---|
|
| 183 |
+
| `model.pt` | PyTorch model weights (base + LoRA merged + classification head) |
|
| 184 |
+
| `thread_reranker.onnx` | ONNX export for on-device inference |
|
| 185 |
+
| `config.json` | Model configuration and feature definitions |
|
| 186 |
+
| `training_history.json` | Per-epoch training and validation metrics |
|
| 187 |
+
| `tokenizer.json` | Tokenizer files |
|
| 188 |
+
|
| 189 |
+
## Citation
|
| 190 |
+
|
| 191 |
+
If you use this model, please reference the training dataset:
|
| 192 |
+
|
| 193 |
+
```
|
| 194 |
+
@misc{thread-reranker-2026,
|
| 195 |
+
title={Thread Reranker: Cross-Encoder for Unified Conversation Thread Matching},
|
| 196 |
+
author={Algokruti},
|
| 197 |
+
year={2026},
|
| 198 |
+
publisher={Hugging Face},
|
| 199 |
+
url={https://huggingface.co/Algokruti/thread-reranker}
|
| 200 |
+
}
|
| 201 |
+
```
|