Skip to content

Commit 1e27965

Browse files
docker set up and documentation
1 parent 2ecb3c0 commit 1e27965

File tree

15 files changed

+293
-65
lines changed

15 files changed

+293
-65
lines changed

.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
dist
3+
.env
4+
npm-debug.log
5+
chroma-data

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
3+
PORT = 4000
4+
5+
REDIS_HOST=redis
6+
REDIS_PORT=6379
7+
REDIS_PASSWORD=1234
8+
9+
CHROMA_HOST=chroma
10+
CHROMA_PORT=8000
11+
12+
GEMINI_API_KEY=

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ lerna-debug.log*
99

1010
/node_modules
1111
node_modules
12+
/chroma-data
1213
dist
1314
dist-ssr
1415
*.local

Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
FROM node:18-alpine
3+
4+
WORKDIR /usr/src/app
5+
6+
COPY package.json pnpm-lock.yaml ./
7+
8+
RUN npm install -g pnpm
9+
RUN pnpm install
10+
11+
COPY . .
12+
13+
RUN pnpm run build
14+
15+
EXPOSE 4000
16+
17+
CMD [ "node", "dist/src/index.js" ]

README.MD

Lines changed: 132 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,132 @@
1-
- [x] Upload Multiple Files
2-
- [x] implement queue worker
3-
- [x] read pdf and chunk the text
4-
- [x] combine those knowledge
5-
- [x] store in vector db
1+
# Insight Engine
2+
3+
This is the backend for **Insight Engine**, an intelligent application designed to transform a collection of documents into a conversational knowledge base. It allows a user to upload documents (e.g., PDFs), and then ask questions in natural language to receive AI-powered answers based on the information contained within those documents.
4+
5+
The system is built as a multi-container application orchestrated with Docker Compose, ensuring a clean separation of concerns and a production-ready setup.
6+
7+
## System Architecture
8+
9+
The application operates using a **Retrieval-Augmented Generation (RAG)** architecture.
10+
11+
- **API Server (`app`)**: An Express.js server that handles incoming requests. It manages file uploads, adds processing jobs to the queue, and exposes the chat endpoint to the user.
12+
- **Worker (`worker`)**: A background service using BullMQ that processes long-running tasks. It listens for jobs from the queue, extracts text from documents, generates vector embeddings using the Gemini API, and stores them in ChromaDB.
13+
- **Redis (`redis`)**: Acts as a high-speed message broker for the BullMQ task queue, facilitating communication between the API Server and the Worker.
14+
- **ChromaDB (`chroma`)**: The vector database that stores the document embeddings. It enables efficient semantic search to find information relevant to a user's query.
15+
- **Shared Volume (`uploads`)**: A Docker volume mounted to both the API Server and the Worker, allowing the server to save an uploaded file and the worker to access it for processing.
16+
17+
### How it Works (Step-by-Step)
18+
19+
1. **Knowledge Ingestion**:
20+
21+
- A user uploads PDF files to the `POST /api/v1/pdf/uploads` endpoint.
22+
- The API Server clears the old ChromaDB collection to start a fresh session.
23+
- It adds a job for each file to the Redis queue.
24+
- The Worker picks up each job, processes the PDF, creates chunks, generates embeddings with the Gemini API, and stores them in ChromaDB.
25+
- The worker then deletes the temporary file from the shared volume.
26+
27+
2. **Knowledge Retrieval**:
28+
- A user sends a question to the `POST /api/v1/pdf/chat` endpoint.
29+
- The API Server queries ChromaDB to retrieve the most relevant text chunks based on the question's meaning.
30+
- It _augments_ a prompt by combining this retrieved context with the original question.
31+
- This detailed prompt is sent to the Gemini generative model.
32+
- The model _generates_ a final answer based on the provided context, which is then sent back to the user.
33+
34+
## Project Setup & How to Run
35+
36+
1. **Clone the Repository**
37+
38+
```bash
39+
git clone <your-repo-url>
40+
cd insight-engine
41+
```
42+
43+
2. **Create Environment File**
44+
Create a `.env` file in the root directory and add your configuration.
45+
46+
```env
47+
# Server Port
48+
PORT=4000
49+
50+
# Redis Configuration for Docker
51+
REDIS_HOST=redis
52+
REDIS_PORT=6379
53+
54+
# ChromaDB Configuration for Docker
55+
CHROMA_HOST=chroma
56+
CHROMA_PORT=8000
57+
58+
# Your Gemini API Key
59+
GEMINI_API_KEY=AIzaSy...
60+
```
61+
62+
3. **Run with Docker Compose**
63+
Make sure you have Docker Desktop running. Then, from the project root, run:
64+
65+
```bash
66+
docker-compose up --build
67+
```
68+
69+
This command will build the Docker images and start all the necessary services (`app`, `worker`, `redis`, `chroma`).
70+
71+
4. **Interact with the API**
72+
- **Upload Files:** Send a `POST` request with `form-data` to `http://localhost:4000/api/v1/pdf/uploads`. The key for your files should be `files`.
73+
- **Chat:** Send a `POST` request with a JSON body to `http://localhost:4000/api/v1/pdf/chat`. The body should look like: `{ "question": "your question here" }`.
74+
75+
## Development
76+
77+
For local development with hot-reloading, create a `docker-compose.override.yml` file to mount your source code into the containers and use `nodemon` (as configured in your `package.json`). This allows changes to your code to be reflected instantly without rebuilding the image.
78+
79+
## Architecture Diagram
80+
81+
```mermaid
82+
graph TD
83+
subgraph "User / Client"
84+
User(["<br><b>User</b><br>via Frontend / Postman"])
85+
end
86+
87+
subgraph "Backend Application (Docker)"
88+
subgraph "API Server (app-1)"
89+
API[("Express.js API<br>localhost:4000")]
90+
end
91+
92+
subgraph "Background Worker (worker-1)"
93+
Worker[("BullMQ Worker")]
94+
end
95+
96+
subgraph "Databases & Services"
97+
Redis[("Redis<br>Queue")]
98+
Chroma[("ChromaDB<br>Vector Store")]
99+
end
100+
101+
subgraph "Shared Storage"
102+
Volume[("</br>uploads</br>Shared Volume")]
103+
end
104+
end
105+
106+
subgraph "External Services"
107+
Gemini[("Google Gemini AI<br>Embeddings & Generation")]
108+
end
109+
110+
%% Ingestion Flow (Uploading a document)
111+
User -- "1. Uploads PDF (POST /uploads)" --> API
112+
API -- "2. Saves file to" --> Volume
113+
API -- "3. Enqueues Job" --> Redis
114+
Worker -- "4. Dequeues Job" --> Redis
115+
Worker -- "5. Reads file from" --> Volume
116+
Worker -- "6. Generates Embeddings" --> Gemini
117+
Worker -- "7. Stores Embeddings" --> Chroma
118+
Worker -- "8. Deletes file from" --> Volume
119+
120+
%% Retrieval Flow (Asking a question)
121+
User -- "9. Asks Question (POST /chat)" --> API
122+
API -- "10. Retrieves Context" --> Chroma
123+
API -- "11. Augments Prompt & Generates Answer" --> Gemini
124+
API -- "12. Sends Answer" --> User
125+
126+
classDef default fill:#1E293B,stroke:#334155,stroke-width:2px,color:#fff;
127+
classDef user fill:#2563EB,stroke:#1D4ED8,stroke-width:2px,color:#fff;
128+
classDef external fill:#166534,stroke:#14532D,stroke-width:2px,color:#fff;
129+
130+
class User user;
131+
class Gemini external;
132+
```

docker-compose.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
services:
2+
app:
3+
build: .
4+
ports:
5+
- "4000:4000"
6+
volumes:
7+
- ./uploads:/usr/src/app/uploads
8+
env_file:
9+
- .env
10+
depends_on:
11+
- redis
12+
- chroma
13+
command: node dist/index.js
14+
15+
worker:
16+
build: . # Use the same image as the app service
17+
env_file:
18+
- .env
19+
depends_on:
20+
- redis
21+
- chroma
22+
volumes:
23+
- ./uploads:/usr/src/app/uploads
24+
command: node dist/jobs/workers/filesWorker.js
25+
26+
redis:
27+
image: "redis:alpine"
28+
ports:
29+
- "6379:6379"
30+
31+
chroma:
32+
image: "chromadb/chroma:1.0.13.dev120"
33+
ports:
34+
- "8000:8000"
35+
volumes:
36+
- chroma_data:/chroma/chroma
37+
38+
volumes:
39+
chroma_data:

dump.rdb

0 Bytes
Binary file not shown.

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,41 @@
55
"main": "index.js",
66
"scripts": {
77
"dev": "nodemon src/index.ts",
8-
"build": "tsc --project tsconfig.prod.json",
8+
"build": "tsc",
99
"work": "nodemon src/jobs/workers/filesWorker.ts",
10-
"start": "node dist/src/index.js",
10+
"start": "node dist/index.js",
1111
"inspect": "ts-node src/inspect-db.ts"
1212
},
1313
"keywords": [],
1414
"author": "",
1515
"license": "ISC",
1616
"devDependencies": {
17-
"@types/cors": "^2.8.17",
18-
"@types/express": "^5.0.0",
19-
"@types/morgan": "^1.9.9",
20-
"@types/multer": "^1.4.12",
21-
"@types/node": "^22.13.9",
22-
"nodemon": "^3.1.9",
23-
"prisma": "^6.4.1",
17+
"@types/cors": "^2.8.19",
18+
"@types/express": "^5.0.3",
19+
"@types/morgan": "^1.9.10",
20+
"@types/multer": "^1.4.13",
21+
"@types/node": "^22.15.32",
22+
"nodemon": "^3.1.10",
23+
"prisma": "^6.9.0",
2424
"ts-node": "^10.9.2",
25-
"tsx": "^4.19.3",
26-
"typescript": "^5.8.2"
25+
"tsx": "^4.20.3",
26+
"typescript": "^5.8.3"
2727
},
2828
"dependencies": {
2929
"@google/generative-ai": "^0.24.1",
30-
"@types/cookie-parser": "^1.4.8",
30+
"@types/cookie-parser": "^1.4.9",
3131
"@types/node-cron": "^3.0.11",
32-
"axios": "^1.8.2",
33-
"bullmq": "^5.53.3",
32+
"axios": "^1.10.0",
33+
"bullmq": "^5.54.0",
3434
"chromadb": "^3.0.3",
3535
"chromadb-default-embed": "^2.14.0",
3636
"cookie-parser": "^1.4.7",
3737
"cors": "^2.8.5",
38-
"dotenv": "^16.4.7",
39-
"express": "^5.0.1",
38+
"dotenv": "^16.5.0",
39+
"express": "^5.1.0",
4040
"express-rate-limit": "^7.5.0",
4141
"express-validator": "^7.2.1",
42-
"helmet": "^8.0.0",
42+
"helmet": "^8.1.0",
4343
"ioredis": "^5.6.1",
4444
"langchain": "^0.3.28",
4545
"morgan": "^1.10.0",

0 commit comments

Comments
 (0)