188 lines
7.3 KiB
Markdown
188 lines
7.3 KiB
Markdown
# Setup and Configuration Guide: AI Recruitment Platform
|
|
|
|
This guide covers the complete step-by-step setup process for the database (Supabase), the automation engine (n8n), the AI models, and the Next.js application.
|
|
|
|
---
|
|
|
|
## 1. Supabase (Database Setup)
|
|
|
|
Supabase provides the relational database, vector store, and API services.
|
|
|
|
### A. Extensions Needed
|
|
The semantic similarity matching uses vector calculations. You must enable the `vector` extension.
|
|
* Go to **Database** -> **Extensions** -> Search for `vector` -> Click **Enable**.
|
|
|
|
### B. Table Schemas
|
|
You need to create the following five tables. Run these SQL commands in the Supabase **SQL Editor**:
|
|
|
|
```sql
|
|
-- 1. Jobs Table
|
|
CREATE TABLE jobs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
title TEXT NOT NULL,
|
|
requirements JSONB NOT NULL DEFAULT '{}'::jsonb, -- Store raw text + lowercase buzzwords list
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
|
);
|
|
|
|
-- 2. Candidates Table
|
|
CREATE TABLE candidates (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name TEXT NOT NULL,
|
|
email TEXT UNIQUE NOT NULL,
|
|
phone TEXT,
|
|
embedding VECTOR(1536), -- 1536 dimensions matching gemini-embedding-001
|
|
contact_info JSONB DEFAULT '{}'::jsonb, -- Store A-Z summary, skills list, phone, etc.
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
|
);
|
|
|
|
-- 3. Scores Table (Decoupled Evaluations)
|
|
CREATE TABLE scores (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
candidate_id UUID REFERENCES candidates(id) ON DELETE CASCADE NOT NULL,
|
|
job_id UUID REFERENCES jobs(id) ON DELETE CASCADE NOT NULL,
|
|
ai_score INTEGER NOT NULL CHECK (ai_score >= 0 AND ai_score <= 100),
|
|
risk_level TEXT NOT NULL, -- 'Low', 'Medium', 'High'
|
|
evaluation JSONB NOT NULL DEFAULT '{}'::jsonb, -- Store { summary, classification, suggestions }
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
|
);
|
|
|
|
-- 4. Interviews Table
|
|
CREATE TABLE interviews (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
candidate_id UUID REFERENCES candidates(id) ON DELETE CASCADE NOT NULL,
|
|
job_id UUID REFERENCES jobs(id) ON DELETE CASCADE NOT NULL,
|
|
interview_date TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
stage TEXT DEFAULT 'Screening'::text NOT NULL, -- 'Screening', 'Technical', 'Cultural', 'Offer', 'Hired', 'Rejected'
|
|
feedback TEXT, -- Stores JSON string comments timeline array [{ id, text, timestamp, author, stage, isAi }]
|
|
pinned BOOLEAN DEFAULT false NOT NULL,
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
|
|
);
|
|
```
|
|
|
|
### C. pgvector Similarity Match Function
|
|
Next, create the PostgreSQL RPC function to rank candidates against job requirements using cosine distance. Run this in the SQL Editor:
|
|
|
|
```sql
|
|
CREATE OR REPLACE FUNCTION match_candidates (
|
|
query_embedding VECTOR(1536),
|
|
match_threshold DOUBLE PRECISION,
|
|
match_count INT
|
|
)
|
|
RETURNS TABLE (
|
|
id UUID,
|
|
name TEXT,
|
|
email TEXT,
|
|
phone TEXT,
|
|
contact_info JSONB,
|
|
similarity DOUBLE PRECISION
|
|
)
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
RETURN QUERY
|
|
SELECT
|
|
candidates.id,
|
|
candidates.name,
|
|
candidates.email,
|
|
candidates.phone,
|
|
candidates.contact_info,
|
|
1 - (candidates.embedding <=> query_embedding) AS similarity
|
|
FROM candidates
|
|
WHERE 1 - (candidates.embedding <=> query_embedding) > match_threshold
|
|
ORDER BY candidates.embedding <=> query_embedding
|
|
LIMIT match_count;
|
|
END;
|
|
$$;
|
|
```
|
|
|
|
---
|
|
|
|
## 2. n8n (Automation Engine Setup)
|
|
|
|
n8n acts as the central automation orchestrator, receiving hooks from Next.js, calling LLM chains, and saving responses.
|
|
|
|
### A. Minimum Requirements
|
|
* **n8n instance**: Self-hosted (Docker / npm package) or n8n Cloud.
|
|
* **Version**: n8n v1.0.0 or later (v1.30+ recommended for advanced LangChain integration features).
|
|
* **Network Access**: The n8n instance must be publicly reachable (using domain/tunnel like ngrok/Cloudflare) so Vercel can post webhook payloads.
|
|
|
|
### B. Supported LLM Models & Providers
|
|
The n8n Kickstarter script (`deploy-n8n-v2.ts`) supports credentials setup and deployment for:
|
|
|
|
| Provider | Choice ID | Default Model | Node Type | API Key Env Var |
|
|
| :--- | :--- | :--- | :--- | :--- |
|
|
| **Deepseek** | `1` | `deepseek-chat` | `@n8n/n8n-nodes-langchain.lmChatDeepSeek` | `DEEPSEEK_API_KEY` |
|
|
| **OpenAI** | `2` | `gpt-4o-mini` | `@n8n/n8n-nodes-langchain.lmChatOpenAi` | `OPENAI_API_KEY` |
|
|
| **Google Gemini** | `3` | `gemini-1.5-flash` | `@n8n/n8n-nodes-langchain.lmChatGoogleGemini` | `GEMINI_API_KEY` |
|
|
| **Anthropic** | `4` | `claude-3-5-sonnet-latest` | `@n8n/n8n-nodes-langchain.lmChatAnthropic` | `ANTHROPIC_API_KEY` |
|
|
|
|
### C. Deploying via Script
|
|
1. Configure the `.env` variables (`N8N_HOST`, `N8N_API_KEY`).
|
|
2. Run the deployment script:
|
|
```bash
|
|
npx ts-node -O '{"module": "commonjs"}' scripts/deploy-n8n-v2.ts \
|
|
--primary-provider=deepseek \
|
|
--fallback \
|
|
--fallback-provider=gemini
|
|
```
|
|
*Note: The script dynamically detects if a credential exists in n8n. If found, it safely reuses the credential to avoid entering keys repeatedly.*
|
|
|
|
---
|
|
|
|
## 3. Supported Webhooks / API Endpoints
|
|
|
|
The n8n workflow exposes the following endpoints (automatically registered upon deployment):
|
|
|
|
### 1. `POST /webhook/evaluate-candidate`
|
|
Triggered by Next.js when parsing CVs or running AI evaluations.
|
|
* **Payload**:
|
|
```json
|
|
{
|
|
"candidateId": "uuid-here",
|
|
"jobId": "uuid-here",
|
|
"candidateName": "John Doe",
|
|
"jobTitle": "React Developer",
|
|
"jobRequirements": "Stack: React, TypeScript, Tailwind...",
|
|
"text": "Extracted text contents of candidate resume..."
|
|
}
|
|
```
|
|
* **Workflow Operations**:
|
|
* Extracts resume data (Structured Output Parser).
|
|
* Inserts parsed details (skills list, summary) into `candidates` table.
|
|
* Runs the primary evaluation chain (Deepseek) with a fallback to Google Gemini.
|
|
* Calculates calibrated scores (0-100), risk classifications (`Qualified`, `Unqualified`, `Review`), and appends next-step suggestions.
|
|
* Stores result in `scores` table.
|
|
|
|
### 2. `POST /webhook/suggest-next-steps`
|
|
Triggered by Next.js when clicking "Get AI Suggestion" inside Interviews.
|
|
* **Payload**:
|
|
```json
|
|
{
|
|
"candidateName": "John Doe",
|
|
"jobTitle": "React Developer",
|
|
"currentStage": "Technical",
|
|
"candidateSummary": "Extracted summary...",
|
|
"candidateSkills": ["react", "typescript"],
|
|
"jobRequirements": "Stack: React...",
|
|
"commentHistory": [ ... ],
|
|
"lang": "en" | "es"
|
|
}
|
|
```
|
|
* **Workflow Operations**:
|
|
* Assembles context of the candidate, job description, and interview timeline.
|
|
* Queries LLM to output a brief, actionable list of next steps.
|
|
* Instructs LLM to write in Spanish if `lang` is `"es"`, otherwise English.
|
|
|
|
---
|
|
|
|
## 4. Next.js (Application Setup)
|
|
|
|
### A. Environment variables
|
|
Make sure all items in `.env` are configured:
|
|
* `APP_PASSWORD`: Protects the lock screen. Default fallback is `Semillero2026!`.
|
|
* `GEMINI_API_KEY`: Mandatory for client-side embedding generation (`models/gemini-embedding-001`) and candidate comparisons.
|
|
* `NEXT_PUBLIC_SUPABASE_URL` & `SUPABASE_SECRET_KEY`: Service role keys to read/write without RLS checks.
|
|
|
|
### B. Deployment
|
|
Deploy to Vercel with all environment variables matching your local setup. Ensure the API routes can freely reach the database and the n8n webhooks.
|