File size: 28,888 Bytes
d81b812
26a0c00
 
 
 
 
 
 
 
 
d81b812
c880343
bf52102
c880343
bf52102
d81b812
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9594045
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d11f763
 
 
d46a4fb
d11f763
 
 
9594045
 
 
 
 
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
2cb87af
 
 
 
 
 
 
 
 
 
4b76abe
2cb87af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34b937c
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d81b812
bf52102
d81b812
bf52102
 
 
d81b812
bf52102
 
 
 
 
 
 
 
 
d81b812
bf52102
d81b812
bf52102
d81b812
bf52102
d81b812
 
bf52102
 
 
d81b812
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
964dddf
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d81b812
964dddf
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26a0c00
d81b812
675aa29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34b937c
bf52102
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34b937c
bf52102
 
 
 
 
 
d81b812
bf52102
d81b812
2564704
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
---
title: Document AI Analyst
emoji: 🧠
colorFrom: indigo
colorTo: purple
sdk: docker
app_port: 7860
pinned: true
license: mit
short_description: Enterprise Agentic RAG β€” upload PDFs and chat with AI
---

<div align="center">

<br/>

```
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•    β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•
β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—      β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•      β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘
β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘         β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘
β•šβ•β•     β•šβ•β•β•β•β•β• β•šβ•β•         β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•šβ•β•β•β•β•β•β•   β•šβ•β•   β•šβ•β•  β•šβ•β•β•šβ•β•  β•šβ•β•β•β•   β•šβ•β•
                                                                                                    
                        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—
                        β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•
                        β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ–ˆβ•—
                        β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘
                        β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•
                        β•šβ•β•  β•šβ•β•β•šβ•β•  β•šβ•β• β•šβ•β•β•β•β•β•
```

### Enterprise Agentic Retrieval-Augmented Generation System

<br/>

[![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-009688?style=for-the-badge&logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
[![Next.js](https://img.shields.io/badge/Next.js-16-000000?style=for-the-badge&logo=next.js&logoColor=white)](https://nextjs.org/)
[![Python](https://img.shields.io/badge/Python-3.11-3776AB?style=for-the-badge&logo=python&logoColor=white)](https://python.org/)
[![LangChain](https://img.shields.io/badge/LangChain-RAG-1C3C3C?style=for-the-badge&logo=langchain&logoColor=white)](https://langchain.com/)
[![ChromaDB](https://img.shields.io/badge/ChromaDB-VectorStore-FF6B35?style=for-the-badge)](https://trychroma.com/)
[![HuggingFace](https://img.shields.io/badge/HuggingFace-Inference-FFD21E?style=for-the-badge&logo=huggingface&logoColor=black)](https://huggingface.co/)
[![Docker](https://img.shields.io/badge/Docker-Multi--Stage-2496ED?style=for-the-badge&logo=docker&logoColor=white)](https://docker.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-F59E0B?style=for-the-badge)](LICENSE)

<br/>

> **Upload Β· Embed Β· Retrieve Β· Chat** β€” A production-grade AI document assistant built end-to-end with an agentic RAG pipeline, streaming responses, and per-user data isolation.

<br/>

[Features](#-key-features) Β· [Tech Stack](#-tech-stack) Β· [Getting Started](#-getting-started) Β· [Architecture](#-architecture) Β· [RAG Pipeline](#-rag-pipeline) Β· [API Reference](#-api-reference) Β· [Deployment](#-deployment) Β· [Contributing](#-contributing)

---

</div>

## 🀝 Contributors

Thanks to all the amazing people who have contributed to **PDF-Assistant-RAG**! πŸŽ‰

<br/>

<div align="center">

<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/param20h">
          <img src="https://avatars.githubusercontent.com/u/140331071?v=4" width="80px;" style="border-radius:50%" alt="param20h"/>
          <br/><sub><b>param20h</b></sub>
        </a>
        <br/>πŸ’» πŸš‡ πŸ“–
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/Yuvraj-Sarathe">
          <img src="https://avatars.githubusercontent.com/u/216678101?v=4" width="80px;" style="border-radius:50%" alt="Yuvraj-Sarathe"/>
          <br/><sub><b>Yuvraj-Sarathe</b></sub>
        </a>
        <br/>πŸ’» πŸ§ͺ πŸ”’
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/SatyamPrakash09">
          <img src="https://avatars.githubusercontent.com/u/195105483?v=4" width="80px;" style="border-radius:50%" alt="SatyamPrakash09"/>
          <br/><sub><b>SatyamPrakash09</b></sub>
        </a>
        <br/>πŸ’» πŸ”’ ⚑
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/akmhatey-ai">
          <img src="https://avatars.githubusercontent.com/u/260399619?v=4" width="80px;" style="border-radius:50%" alt="akmhatey-ai"/>
          <br/><sub><b>akmhatey-ai</b></sub>
        </a>
        <br/>πŸ’» πŸ›
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/drishtisharma14052007-eng">
          <img src="https://avatars.githubusercontent.com/u/233135226?v=4" width="80px;" style="border-radius:50%" alt="drishtisharma14052007-eng"/>
          <br/><sub><b>drishtisharma14052007-eng</b></sub>
        </a>
        <br/>πŸ’» 🎨
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/Pika-pika06">
          <img src="https://avatars.githubusercontent.com/u/253691302?v=4" width="80px;" style="border-radius:50%" alt="Pika-pika06"/>
          <br/><sub><b>Pika-pika06</b></sub>
        </a>
        <br/>πŸ’»
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/algojogacor">
          <img src="https://avatars.githubusercontent.com/u/239139125?v=4" width="80px;" style="border-radius:50%" alt="algojogacor"/>
          <br/><sub><b>algojogacor</b></sub>
        </a>
        <br/>πŸ’»
      </td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/HirenGajjar">
          <img src="https://avatars.githubusercontent.com/u/40492198?v=4" width="80px;" style="border-radius:50%" alt="HirenGajjar"/>
          <br/><sub><b>HirenGajjar</b></sub>
        </a>
        <br/>πŸ’»
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/Kaustub26Pvgda">
          <img src="https://avatars.githubusercontent.com/u/152937301?v=4" width="80px;" style="border-radius:50%" alt="Kaustub26Pvgda"/>
          <br/><sub><b>Kaustub26Pvgda</b></sub>
        </a>
        <br/>πŸ’»
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/blinkerbit">
          <img src="https://avatars.githubusercontent.com/u/9065654?v=4" width="80px;" style="border-radius:50%" alt="blinkerbit"/>
          <br/><sub><b>blinkerbit</b></sub>
        </a>
        <br/>πŸ’»
      </td>
      <td align="center" valign="top" width="14.28%">
        <a href="https://github.com/akshy-yy">
          <img src="https://avatars.githubusercontent.com/u/220587504?v=4" width="80px;" style="border-radius:50%" alt="akshy-yy"/>
          <br/><sub><b>akshy-yy</b></sub>
        </a>
        <br/>πŸ’»
      </td>
    </tr>
  </tbody>
</table>

</div>

---

<br/>

## 🌟 Overview

**PDF-Assistant-RAG** is a complete, production-ready AI document assistant that lets users upload complex PDFs, financial reports, legal contracts, and research papers β€” then chat with an AI that provides **accurate, cited answers** powered by a multi-stage Retrieval-Augmented Generation pipeline.

The system uses **semantic search + cross-encoder reranking** to find the most relevant document chunks, streams AI-generated answers token-by-token, and highlights exact source citations with page numbers β€” all inside a sleek Next.js UI with JWT-secured per-user data isolation.

<br/>

## πŸ—οΈ Architecture

```mermaid
graph TD
    subgraph Frontend["Frontend (Next.js 16)"]
        UI["Dashboard UI (React)"]
        Chat["Chat Panel (SSE)"]
        Viewer["PDF Viewer (iframe)"]
    end

    subgraph Backend["Backend (FastAPI 0.115+)"]
        API["API Router (/api/v1)"]
        Auth["Auth (JWT/bcrypt)"]
        DB[(SQLite Metadata)]

        subgraph RAG["RAG Pipeline"]
            Upload["Ingestion Task (Chunking)"]
            Embed["Local Embeddings (all-MiniLM-L6-v2)"]
            Retriever["Two-Stage Retriever"]
            Rerank["Cross-Encoder Reranker"]
            Agent["Agent/Generator"]
        end
    end

    subgraph Storage["Vector Storage"]
        Chroma[(ChromaDB)]
    end

    subgraph External["External Services"]
        HF["HuggingFace Inference API (Qwen 72B)"]
    end

    %% Frontend to Backend Connections
    UI <-->|REST / Auth| API
    Chat <-->|SSE Streaming| API
    Viewer -->|Fetch PDF| API

    %% Backend Internals
    API <--> Auth
    API <--> DB
    API --> Upload
    API <--> Retriever
    API <--> Agent

    %% RAG Ingestion Flow
    Upload --> Embed
    Embed -->|Store Vectors| Chroma

    %% RAG Query Flow
    Retriever -->|1. Semantic Search| Chroma
    Retriever -->|2. Score & Sort| Rerank
    Retriever -->|Context| Agent

    %% External LLM Flow
    Agent <-->|LLM Generation| HF
```

<br/>

## πŸ›  Tech Stack

<div align="center">

### Backend

| | Technology | Purpose |
|---|---|---|
| <img src="https://skillicons.dev/icons?i=fastapi" width="30"/> | **FastAPI 0.115+** | Async REST API framework |
| <img src="https://skillicons.dev/icons?i=python" width="30"/> | **Python 3.11** | Runtime environment |
| <img src="https://skillicons.dev/icons?i=sqlite" width="30"/> | **SQLite + SQLAlchemy** | User & document metadata storage |
| <img src="https://img.shields.io/badge/JWT-000000?style=flat&logo=jsonwebtokens&logoColor=white" height="24"/> | **JWT + Passlib** | Authentication & authorization |
| <img src="https://img.shields.io/badge/LangChain-1C3C3C?style=flat&logo=langchain&logoColor=white" height="24"/> | **LangChain** | RAG orchestration |
| <img src="https://img.shields.io/badge/ChromaDB-FF6B35?style=flat" height="24"/> | **ChromaDB** | Persistent vector store (per-user) |
| <img src="https://img.shields.io/badge/HuggingFace-FFD21E?style=flat&logo=huggingface&logoColor=black" height="24"/> | **HuggingFace Hub** | LLM inference API |

### Frontend

| | Technology | Purpose |
|---|---|---|
| <img src="https://skillicons.dev/icons?i=nextjs" width="30"/> | **Next.js 16** | React framework (App Router) |
| <img src="https://skillicons.dev/icons?i=tailwind" width="30"/> | **Tailwind CSS v4** | Utility-first styling |
| <img src="https://img.shields.io/badge/shadcn/ui-000000?style=flat&logo=shadcnui&logoColor=white" height="24"/> | **shadcn/ui** | Accessible component library |
| <img src="https://skillicons.dev/icons?i=ts" width="30"/> | **TypeScript** | Type-safe frontend |
| <img src="https://img.shields.io/badge/react--pdf-FF0000?style=flat" height="24"/> | **react-pdf** | In-browser PDF viewer |
| <img src="https://img.shields.io/badge/react--markdown-000000?style=flat" height="24"/> | **react-markdown + GFM** | Markdown-rendered AI responses |

### AI / ML Pipeline

| | Technology | Purpose |
|---|---|---|
| <img src="https://img.shields.io/badge/MiniLM-L6-v2-FFD21E?style=flat" height="24"/> | **all-MiniLM-L6-v2** | Local sentence embeddings |
| <img src="https://img.shields.io/badge/ms--marco--MiniLM-1C3C3C?style=flat" height="24"/> | **ms-marco-MiniLM-L-6-v2** | Cross-encoder reranker |
| <img src="https://img.shields.io/badge/Qwen2.5-72B-Instruct-626BDF?style=flat" height="24"/> | **Qwen2.5-72B-Instruct** | LLM (HuggingFace Inference API) |
| <img src="https://img.shields.io/badge/PyMuPDF-FF0000?style=flat" height="24"/> | **PyMuPDF + python-docx** | Document parsing |

### DevOps & Tooling

| | Technology | Purpose |
|---|---|---|
| <img src="https://skillicons.dev/icons?i=docker" width="30"/> | **Docker Multi-Stage** | Containerized deployment |
| <img src="https://skillicons.dev/icons?i=githubactions" width="30"/> | **GitHub Actions** | CI pipeline (dev branch) |
| <img src="https://skillicons.dev/icons?i=git" width="30"/> | **Git LFS** | Binary asset management |
| <img src="https://img.shields.io/badge/HuggingFace_Spaces-FFD21E?style=flat&logo=huggingface&logoColor=black" height="24"/> | **HuggingFace Spaces** | Production deployment |

</div>

<br/>

## ✨ Key Features

<table>
<tr>
<td width="33%" valign="top">

### πŸ‘€ Users
- πŸ” JWT-secured register & login
- πŸ“„ Upload **PDF** and **DOCX** documents
- πŸ’¬ Ask questions in natural language
- 🌊 **Streaming AI responses** token-by-token
- πŸ“š Inline **source citations** with page numbers
- πŸ—‚οΈ Per-user complete data isolation

</td>
<td width="33%" valign="top">

### πŸ€– RAG Pipeline
- πŸ”ͺ Smart **recursive text chunking** (configurable size & overlap)
- 🧠 **Local embeddings** β€” no data leaves your machine
- πŸ” **Two-stage retrieval** β€” semantic search β†’ cross-encoder rerank
- βœ‚οΈ Top-K filtering for precision answers
- πŸ“ Custom **system prompts** with citation instructions
- 🧾 Source scoring with confidence levels

</td>
<td width="33%" valign="top">

### βš™οΈ Engineering
- πŸš€ **Async FastAPI** with Server-Sent Events streaming
- πŸ—„οΈ **ChromaDB** with persistent per-user collections
- 🐳 **Multi-stage Docker** build (Node β†’ Python)
- πŸ”„ **GitHub Actions CI** on `dev` branch
- πŸ›‘οΈ CORS, file validation, JWT expiry
- πŸ“Š Chat **history persistence** per document

</td>
</tr>
</table>

<br/>

## πŸ“ Project Structure

```
PDF-Assistant-RAG/
β”‚
β”œβ”€β”€ backend/                          # FastAPI + RAG server
β”‚   β”œβ”€β”€ app/
β”‚   β”‚   β”œβ”€β”€ main.py                   # App entrypoint, middleware, static files
β”‚   β”‚   β”œβ”€β”€ config.py                 # Pydantic settings (env vars)
β”‚   β”‚   β”œβ”€β”€ database.py               # SQLAlchemy async engine
β”‚   β”‚   β”œβ”€β”€ models.py                 # ORM models (User, Document, Message)
β”‚   β”‚   β”œβ”€β”€ schemas.py                # Pydantic request/response schemas
β”‚   β”‚   β”œβ”€β”€ auth.py                   # JWT creation & verification
β”‚   β”‚   β”‚
β”‚   β”‚   β”œβ”€β”€ routes/
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.py               # POST /register, /login, /me
β”‚   β”‚   β”‚   β”œβ”€β”€ documents.py          # Upload, list, delete, retrieve
β”‚   β”‚   β”‚   └── chat.py               # Streaming chat + history
β”‚   β”‚   β”‚
β”‚   β”‚   └── rag/
β”‚   β”‚       β”œβ”€β”€ agent.py              # Main RAG orchestrator
β”‚   β”‚       β”œβ”€β”€ chunker.py            # Recursive text splitter
β”‚   β”‚       β”œβ”€β”€ embeddings.py         # SentenceTransformer wrapper
β”‚   β”‚       β”œβ”€β”€ vectorstore.py        # ChromaDB collection manager
β”‚   β”‚       β”œβ”€β”€ retriever.py          # Semantic search + reranking
β”‚   β”‚       └── prompts.py            # System & user prompt templates
β”‚   β”‚
β”‚   β”œβ”€β”€ requirements.txt
β”‚   └── .env                          # Local env (never committed)
β”‚
β”œβ”€β”€ frontend/                         # Next.js 16 App Router
β”‚   └── src/
β”‚       β”œβ”€β”€ app/
β”‚       β”‚   β”œβ”€β”€ layout.tsx            # Root layout + fonts
β”‚       β”‚   β”œβ”€β”€ page.tsx              # Landing / redirect
β”‚       β”‚   β”œβ”€β”€ login/                # Auth pages
β”‚       β”‚   β”œβ”€β”€ register/
β”‚       β”‚   └── dashboard/            # Main app page
β”‚       β”‚
β”‚       β”œβ”€β”€ components/
β”‚       β”‚   β”œβ”€β”€ chat/
β”‚       β”‚   β”‚   β”œβ”€β”€ ChatPanel.tsx     # Chat UI + SSE streaming
β”‚       β”‚   β”‚   β”œβ”€β”€ MessageBubble.tsx # User / assistant message
β”‚       β”‚   β”‚   └── SourceCard.tsx    # Citation cards
β”‚       β”‚   β”œβ”€β”€ document/             # Upload + sidebar components
β”‚       β”‚   └── layout/               # Navbar, sidebar shell
β”‚       β”‚
β”‚       └── lib/
β”‚           └── api.ts                # Typed API client + SSE stream helper
β”‚
β”œβ”€β”€ .github/
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   β”œβ”€β”€ ci.yml                    # CI β€” runs on dev branch only
β”‚   β”‚   β”œβ”€β”€ deploy.yml                # Docker build β€” main branch only
β”‚   β”‚   └── devsecops.yml             # Security scans β€” main branch only
β”‚   β”œβ”€β”€ ISSUE_TEMPLATE/               # Bug report & feature request forms
β”‚   β”œβ”€β”€ pull_request_template.md      # PR checklist
β”‚   └── CODEOWNERS                    # Auto-review assignment
β”‚
β”œβ”€β”€ Dockerfile                        # Multi-stage: Node build β†’ Python serve
β”œβ”€β”€ docker-compose.yml                # Local Docker stack
β”œβ”€β”€ CONTRIBUTING.md                   # contributor guide
└── .env.example                      # Template for environment variables
```

<br/>

## πŸš€ Getting Started

### Prerequisites

- ![Python](https://img.shields.io/badge/Python-3.11+-3776AB?style=flat&logo=python&logoColor=white) **Python 3.11+**
- ![Node.js](https://img.shields.io/badge/Node.js-20+-339933?style=flat&logo=node.js&logoColor=white) **Node.js 20+**
- ![HuggingFace](https://img.shields.io/badge/HuggingFace-Token-FFD21E?style=flat&logo=huggingface&logoColor=black) **HuggingFace account** (free) for LLM inference

---

### 1. Clone the Repository

```bash
git clone https://github.com/param20h/PDF-Assistant-RAG.git
cd PDF-Assistant-RAG
```

### 2. Configure Environment

```bash
cp .env.example backend/.env
```

Edit `backend/.env`:

```env
SECRET_KEY=your-strong-random-secret
DATABASE_URL=sqlite:///./data/app.db
HF_TOKEN=hf_your_huggingface_token_here
UPLOAD_DIR=./data/uploads
CHROMA_PERSIST_DIR=./data/chroma_db
```

> Get your free HuggingFace token at [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens)

### 3. Run Locally

Open **two terminals**:

```bash
# Terminal A β€” Backend
cd backend
python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
# β†’ API running at http://localhost:8000
# β†’ Swagger docs at http://localhost:8000/docs
```

```bash
# Terminal B β€” Frontend
cd frontend
npm install
npm run dev
# β†’ App running at http://localhost:3000
```

### 4. Run with Docker

```bash
docker compose up --build
# β†’ Full stack at http://localhost:7860
```

<br/>

## 🧠 RAG Pipeline

```
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚              PDF / DOCX Upload               β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚         PyMuPDF / python-docx Parser         β”‚
                    β”‚         (text extraction per page)           β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚      Recursive Character Text Splitter       β”‚
                    β”‚   chunk_size=1000  |  overlap=200            β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    all-MiniLM-L6-v2  (local embeddings)      β”‚
                    β”‚    384-dim dense vectors                      β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                        β”‚
                                        β–Ό
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚   ChromaDB  β€” per-user persistent collection β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

                              ── At Query Time ──

  User Question ──▢ Embed ──▢ Semantic Search (Top-K=10)
                                        β”‚
                                        β–Ό
                         Cross-Encoder Reranker (Top-K=5)
                         ms-marco-MiniLM-L-6-v2
                                        β”‚
                                        β–Ό
                    Prompt Assembly (system + context + question)
                                        β”‚
                                        β–Ό
                    Qwen2.5-72B-Instruct (HF Inference API)
                                        β”‚
                                        β–Ό
                    Streamed SSE tokens ──▢ Frontend ChatPanel
```

<br/>

## πŸ“‘ API Reference

| Method | Endpoint | Auth | Description |
|--------|----------|------|-------------|
| `POST` | `/api/v1/auth/register` | ❌ | Create a new user account |
| `POST` | `/api/v1/auth/login` | ❌ | Login and receive JWT token |
| `GET` | `/api/v1/auth/me` | βœ… | Get current user profile |
| `POST` | `/api/v1/documents/upload` | βœ… | Upload PDF/DOCX and trigger indexing |
| `GET` | `/api/v1/documents` | βœ… | List all documents for current user |
| `DELETE` | `/api/v1/documents/{id}` | βœ… | Delete a document and its vector data |
| `POST` | `/api/v1/chat/ask/stream` | βœ… | Ask a question (SSE streaming response) |
| `GET` | `/api/v1/chat/history/{doc_id}` | βœ… | Get chat history for a document |
| `DELETE` | `/api/v1/chat/history/{doc_id}` | βœ… | Clear chat history for a document |
| `GET` | `/health` | ❌ | Health check (db + chroma status) |

> Full interactive docs available at `/docs` (Swagger UI) when running locally.

<br/>

## πŸ“¦ Environment Variables

| Variable | Required | Default | Description | Where to Get It |
|---|---|---|---|---|
| `SECRET_KEY` | βœ… | β€” | JWT signing & session secret. Use a strong random string. | Generate: `python -c "import secrets; print(secrets.token_urlsafe(32))"` |
| `HF_TOKEN` | βœ… | β€” | HuggingFace API token for LLM inference via Inference API. | [huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) (free) |
| `ENVIRONMENT` | ❌ | `development` | Runtime mode. Set to `production` for deployment to lock CORS. | β€” |
| `DEBUG` | ❌ | `False` | Enable debug mode with detailed error pages. Never enable in production. | β€” |
| `ALLOWED_ORIGINS` | ❌ | `http://localhost:3000,http://localhost:7860` | Comma-separated CORS origins (only enforced in production). | Your deployed domain(s) |
| `DATABASE_URL` | ❌ | `sqlite:///./data/app.db` | SQLAlchemy database connection string. | SQLite (default), or your Postgres/MySQL connection string |
| `JWT_ALGORITHM` | ❌ | `HS256` | JWT signing algorithm. | β€” |
| `JWT_EXPIRY_HOURS` | ❌ | `72` | JWT token lifetime in hours before re-login is required. | β€” |
| `UPLOAD_DIR` | ❌ | `./data/uploads` | Local directory for storing uploaded documents. | β€” |
| `MAX_FILE_SIZE_MB` | ❌ | `50` | Maximum allowed upload file size in MB. | β€” |
| `ALLOWED_EXTENSIONS` | ❌ | `pdf,docx,txt,md` | Comma-separated list of permitted file extensions. | β€” |
| `CHROMA_PERSIST_DIR` | ❌ | `./data/chroma_db` | Directory where ChromaDB persists its vector index. | β€” |
| `LLM_MODEL` | ❌ | `Qwen/Qwen2.5-72B-Instruct` | HuggingFace model ID for answer generation. | [huggingface.co/models](https://huggingface.co/models?inference=warm&sort=trending) |
| `LLM_TEMPERATURE` | ❌ | `0.3` | LLM sampling temperature (0 = deterministic, 1 = creative). | β€” |
| `LLM_MAX_NEW_TOKENS` | ❌ | `1024` | Maximum tokens per LLM response. | β€” |
| `EMBEDDING_MODEL` | ❌ | `sentence-transformers/all-MiniLM-L6-v2` | SentenceTransformer model for local embeddings (no external API). | [huggingface.co/sentence-transformers](https://huggingface.co/sentence-transformers) |
| `EMBEDDING_DIMENSION` | ❌ | `384` | Embedding vector dimension (must match the model). | β€” |
| `RERANKER_MODEL` | ❌ | `cross-encoder/ms-marco-MiniLM-L-6-v2` | Cross-encoder model for reranking retrieved chunks by relevance. | [huggingface.co/cross-encoder](https://huggingface.co/cross-encoder) |
| `CHUNK_SIZE` | ❌ | `1000` | Characters per document chunk. Larger = more context, smaller = better precision. | β€” |
| `CHUNK_OVERLAP` | ❌ | `200` | Overlap between consecutive chunks to maintain boundary context. | β€” |
| `TOP_K_RETRIEVAL` | ❌ | `10` | Candidate chunks retrieved from vector store during semantic search. | β€” |
| `TOP_K_RERANK` | ❌ | `5` | Final chunks passed to the LLM after reranking (must be ≀ `TOP_K_RETRIEVAL`). | β€” |

<br/>

## πŸ“œ Scripts

### Backend (`backend/`)

| Command | Description |
|---------|-------------|
| `uvicorn app.main:app --reload` | Start FastAPI with hot reload |
| `uvicorn app.main:app --port 8000` | Start FastAPI on port 8000 |

### Frontend (`frontend/`)

| Command | Description |
|---------|-------------|
| `npm run dev` | Start **Next.js** dev server |
| `npm run build` | Production build β†’ `out/` (static export) |
| `npm run lint` | Run ESLint |

### Docker

| Command | Description |
|---------|-------------|
| `docker compose up --build` | Build and start the full stack |
| `docker compose down` | Stop all containers |

<br/>

## 🌐 Deployment

This project is deployed on **HuggingFace Spaces** using Docker.

### HuggingFace Spaces

1. Fork this repo and create a new Space at [huggingface.co/new-space](https://huggingface.co/new-space) (SDK: Docker)
2. Set the following Space secrets:
   - `HF_TOKEN` β€” your HuggingFace API token
   - `SECRET_KEY` β€” a strong random string
3. Push to the `hf` remote β€” the Space will auto-build

```bash
git remote add hf https://<username>:<HF_TOKEN>@huggingface.co/spaces/<username>/<space-name>
git push hf main
```

### Self-Hosted / VPS

```bash
docker compose up -d --build
# App available at http://your-server:7860
```

<br/>

## 🀝 Contributing

This project is participating in **GirlScript Summer of Code**! We welcome contributors of all skill levels.

**Branch Strategy:**

| Branch | Purpose |
|--------|---------|
| `main` | Production β€” HuggingFace deployed (admin only) |
| `dev` | All contributor PRs target here |
| `feature/*` / `fix/*` / `docs/*` | Your working branches |

```bash
# Always branch from dev
git checkout -b feature/my-feature upstream/dev
```

**Quick links:**
- πŸ“‹ [Good First Issues](https://github.com/param20h/PDF-Assistant-RAG/issues?q=label%3A%22good+first+issue%22)
- πŸ“– [Contributing Guide](CONTRIBUTING.md)
- πŸ’¬ [Discussions](https://github.com/param20h/PDF-Assistant-RAG/discussions)

<br/>

## πŸ“„ License

Distributed under the **MIT License**. See [`LICENSE`](license) for more information.

---

<div align="center">

<br/>

**Built with πŸ’™ as a flagship AI engineering project**

*If you found this project helpful, please give it a ⭐ β€” it helps contributors discover it!*

<br/>

[![FastAPI](https://skillicons.dev/icons?i=fastapi,python,nextjs,ts,tailwind,docker)](https://skillicons.dev)

<br/>

**[⬆ Back to top](#)**

</div>