File size: 6,029 Bytes
f1fe629
094cc8d
2a7f012
 
 
 
 
f1fe629
 
 
094cc8d
f1fe629
1198f97
 
 
 
 
 
 
 
 
f1fe629
1198f97
7a95605
1198f97
7a95605
1198f97
f1fe629
1198f97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1fe629
ba6b3cf
d37a494
 
1198f97
d37a494
1198f97
fd1a31f
1198f97
 
 
 
 
 
 
 
fd1a31f
1198f97
fd1a31f
1198f97
fd1a31f
1198f97
 
 
 
fd1a31f
1198f97
fd1a31f
1198f97
fd1a31f
1198f97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd1a31f
 
1198f97
 
 
 
 
 
 
 
 
 
 
 
 
fd1a31f
1198f97
 
 
 
 
 
fd1a31f
1198f97
 
 
fd1a31f
1198f97
fd1a31f
1198f97
fd1a31f
1198f97
 
 
 
 
fd1a31f
 
1198f97
 
fd1a31f
 
1198f97
fd1a31f
1198f97
 
 
 
 
fd1a31f
1198f97
fd1a31f
1198f97
 
fd1a31f
1198f97
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
fd1a31f
 
 
1198f97
 
 
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
---
title: GnosisPages
emoji: 📚
colorFrom: blue
colorTo: green
sdk: docker
app_port: 8501
pinned: false
---

# GnosisPages

GnosisPages is a RAG + LLM chatbot for querying private document collections. Upload PDF files, build a semantic knowledge base, and ask questions in natural language — no keyword matching required.

**[▶ Try the live demo](https://huggingface.co/spaces/maclenn77/pdf-explainer)** · **[Watch a walkthrough](https://youtu.be/OEQTusJGHFQ)**

---

## Use Case: CV Discovery for Recruiters

Managing large volumes of CVs is difficult. Recruiters often don't know the exact technologies or skill names to search for, and keyword-based search misses semantically equivalent terms (e.g. "machine learning" vs "aprendizaje automático", or experience in a framework analogous to the one required).

GnosisPages solves this with semantic retrieval: a recruiter can ask "Who has experience with distributed systems and has worked in startups?" and the system finds relevant profiles even when the exact phrasing doesn't match.

Candidate data is sensitive (contact details, personal history). GnosisPages keeps it private by design: documents live in a local or private vector database, and the LLM never trains on them — it only reads the retrieved context at inference time.

The demo ships with a pre-loaded collection of synthetic CVs generated with Claude Sonnet 4.6 and vectorized with OpenAI's `text-embedding-3-small`.

---

## Data flow

```
PDF documents
      │
      ▼
  Text extraction (PyMuPDF)
      │
      ▼
  Chunking (LangChain TextSplitter)
      │
      ▼
  Embedding (text-embedding-3-small · OpenAI)
      │
      ▼
  Vector storage (ChromaDB)
      │
      ▼
  User query (natural language)
      │
      ├─► Embed query ──► Semantic search (ChromaDB cosine similarity)
      │                         │
      │                   Top-k chunks
      │                         │
      └─────────────────► Prompt construction
                                │
                          GPT-4o-Mini (LangChain)
                                │
                          Answer → Streamlit UI
```


## Architecture

<img width="2000" height="1292" alt="image" src="https://github.com/user-attachments/assets/17f5f557-0334-47b7-9f62-a7f27f5522c7" />

### Components

| Layer | Technology | Role |
|---|---|---|
| UI | Streamlit 1.58 | Web interface and file upload |
| Orchestration | LangChain 0.3 | RAG chain, prompt management |
| Vector store | ChromaDB 1.5 | Semantic storage and retrieval |
| Embeddings | `text-embedding-3-small` (OpenAI) | Document and query vectorization |
| LLM | GPT-4o-Mini (OpenAI) | Answer generation |
| PDF parsing | PyMuPDF 1.24 | Text extraction from PDF files |

`text-embedding-3-small` replaces ChromaDB's default (`all-MiniLM-L6-v2`) for better semantic quality, especially across mixed-language content.

### Why GPT-4o-Mini

- Fast response times for conversational QA over retrieved context
- Lower cost per token than GPT-4o or GPT-4 Turbo
- Native LangChain integration
- Stable OpenAI API with no additional infrastructure

### Why RAG

The knowledge base is private, dynamic, and cannot be baked into model weights. RAG provides on-demand access to documents the LLM was never trained on, without exposing them to external services beyond the query moment.

---

## Features

- **Upload PDFs** up to 200 MB (programmatically created or OCR-processed)
- **Semantic search** across your document collection — finds relevant content even without exact keyword matches
- **Conversational interface** — ask follow-up questions in the same session
- **Pre-loaded dataset** — the demo includes synthetic CVs so you can try it immediately without uploading anything
- **Private by design** — documents stay in your vector store; the LLM only sees retrieved chunks

---

## Demo Usage

The live demo on HuggingFace requires only an OpenAI API Key.

**Example questions to try with the pre-loaded CV dataset:**

```
Who has experience with Python and machine learning?
Find candidates who have worked in startups or early-stage companies.
Who has the most experience in technical leadership roles?
Is there anyone with a background in both data engineering and backend development?
Which candidates mention experience with cloud infrastructure?
```

---

## Local Setup

**Requirements:** Python 3.11, OpenAI API Key

```bash
# 1. Clone
git clone https://github.com/maclenn77/pdf-explainer.git
cd pdf-explainer

# 2. Create environment file
touch .env
```

Add your key to `.env`:

```
OPENAI_API_KEY=your_key_here
```

```bash
# 3. Install dependencies
pip install -r requirements.txt

# 4. Run
streamlit run GnosisPages.py
```

---

## Deployment

The repo includes three GitHub Actions workflows that run on every PR and deploy automatically on merge to `main`:

| Workflow | What it does |
|---|---|
| Check file size | Blocks merges with files above HuggingFace's size limit |
| Check lints | Runs `pylint` on the codebase |
| Deploy to HuggingFace | Pushes the latest `main` to the HuggingFace Space |

To deploy your own fork, add these secrets in your repository settings:

- `HF_TOKEN` — your HuggingFace access token
- `HF_USERNAME` — your HuggingFace username

---

## Project Structure

```
pdf-explainer/
├── GnosisPages.py          # App entry point
├── gnosis/
│   ├── chroma_client.py    # ChromaDB wrapper
│   ├── settings.py         # Collection bootstrap (loads pre-built DB)
│   ├── gui_messages.py     # UI copy
│   └── components/
│       ├── sidebar.py      # File upload and DB controls
│       └── main.py         # Chat interface and RAG chain
├── pages/                  # Additional Streamlit pages
├── requirements.txt
├── Dockerfile
└── .github/workflows/      # CI/CD
```

---

## License

MIT — see [LICENSE](LICENSE) for details.