File size: 4,358 Bytes
7c2e31a
 
 
 
 
 
 
 
 
 
50b94ce
7c2e31a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
---
title: RAG QA (BM25 + Dense + Reranker)
emoji: 🔎
colorFrom: indigo
colorTo: pink
sdk: gradio
sdk_version: "6.1.0"
python_version: "3.10"
app_file: app.py
pinned: false
short_description: RAG QA demo BM25 + Dense + reranker
---

# RAG QA (BM25 + Dense + OpenAI-compatible providers)

Це навчальний проєкт **Retrieval-Augmented Generation (RAG)** для задачі **Question Answering**: система знаходить релевантні уривки в корпусі документів і відповідає на питання, спираючись лише на знайдений контекст. :contentReference[oaicite:2]{index=2}

## Demo
- Hugging Face Space: *(посилання після деплою)*  
- GitHub: https://github.com/DunasAnastasiia/llm-chat-project

---

## Як працює система (архітектура)

**Джерело даних (Dataset)**  
- Hugging Face dataset: `rag-datasets/rag-mini-wikipedia` :contentReference[oaicite:3]{index=3}

**Chunking**  
- Простий character-based chunking з overlap: `chunk_chars=900`, `overlap_chars=150` 

**Retriever**
- **BM25** (лексичний пошук по ключових словах)
- **Dense retrieval** (Sentence-Transformers embeddings)
- Можна **вмикати/вимикати** BM25 та Dense окремо (для порівняння якості). 

**Reranker (optional)**
- Cross-encoder `cross-encoder/ms-marco-MiniLM-L-6-v2` для реранкінгу кандидатів (опціонально). 

**LLM (Generation)**
- Використовується **OpenAI-compatible Chat Completions API** через бібліотеку `openai` із параметром `base_url`.
- Працює з провайдерами типу **Groq** / **OpenRouter** (ключ вводиться в UI). 

**Citations**
- В промпті LLM проситься цитувати чанки як `[1] [2] ...`, а в UI показується список retrieved chunks з `source_id` / `chunk_id`. 

**UI**
- Gradio (web app), тумблери `Use BM25 / Use Dense / Use Reranker`, поле для API key. :contentReference[oaicite:9]{index=9}

## Приклади запитів: де BM25 кращий, а де Dense

### Запити, де краще справляється BM25

**Q:** Was Abraham Lincoln the first President of the United States?  
**Очікувана відповідь:** No  
**Чому BM25 кращий:** запит містить дуже конкретні ключові слова (Abraham Lincoln, first President, United States). BM25 добре працює, коли відповідь лежить у чанку з тими самими словами/формулюванням.

**Q:** Who was the general in charge at the Battle of Antietam?  
**Очікувана відповідь:** General McClellan  
**Чому BM25 кращий:** тут є точні “якорі” (Battle of Antietam, general in charge). BM25 зазвичай підтягує уривок, де ці терміни зустрічаються буквально.

---

### Запити, де кращі результати повертає Dense retriever

**Q:** Who assassinated Lincoln?  
**Очікувана відповідь:** John Wilkes Booth  
**Чому dense кращий:** типовий приклад “семантичного” запиту — відповідь може бути в уривку, який не повторює точну форму запиту (наприклад, “Lincoln was assassinated by …”). Dense краще ловить перефразування й зв’язки “подія ↔ учасник”.

**Q:** What caused Calvin Jr.'s death?  
**Очікувана відповідь:** heart attack  
**Чому dense кращий:** питання може збігатися з текстом не дослівно (наприклад, у корпусі “died of a heart attack”). Dense часто краще дістає такі уривки навіть без точного збігу слів.


---

## Швидкий старт локально

### 1) Встановлення
```bash
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install -r requirements.txt