WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
저장소 정보는 아직 수집하지 않았습니다.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
Multi-agent job search for the Middle East: Careerjet, Jooble and JSearch, hybrid ranking, resume fit analysis (Next.js, LangGraph, Prisma)
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A Next.js app for the Middle East job market that combines job discovery, PostgreSQL persistence, hybrid job ranking, resume profile analysis, job-specific fitment analysis, LangGraph orchestration, LangChain model integrations, and optional LangSmith tracing.
app/tokens.css, iim- components in app/iim.css), with light and dark themes.This is a single-user prototype, not a production-ready multi-tenant service. It has no login or authorization. Do not deploy it publicly with a real resume or personal data until authentication, per-user data isolation, rate limiting, upload controls, and a privacy/retention policy are added. Any visitor who can reach the API could otherwise access or modify shared saved-job/profile data. Use test data during demos.
Unzip and open this folder in VS Code.
In the integrated terminal:
npm install
Copy .env.example to .env.local.
Configure at minimum:
DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/DATABASE?sslmode=require"
OPENAI_API_KEY="your-key"
To retrieve real job listings, set one or more source keys:
CAREERJET_API_KEY="your-careerjet-key"
JOOBLE_API_KEY="your-jooble-key"
JSEARCH_API_KEY="your-rapidapi-key"
See Middle East job sources for coverage and sign-up. The app deliberately does not scrape LinkedIn, Indeed, Bayt or Naukrigulf.
Optional LangSmith observability:
LANGSMITH_TRACING=true
LANGSMITH_API_KEY="your-langsmith-key"
LANGSMITH_PROJECT="job-scout-multi-agent"
LangChain can automatically emit traces when these variables are set. Keep API keys server-side.
Create/update the database schema:
npx prisma generate
npx prisma db push
Run:
npm run dev
Open http://localhost:3000.
Create an empty GitHub repository.
From the project folder:
git init
git add .
git commit -m "Build Job Scout multi-agent portal"
git branch -M main
git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPOSITORY.git
git push -u origin main
Import the GitHub repository into Vercel.
Configure DATABASE_URL, OPENAI_API_KEY, and any optional provider/observability variables in Vercel Project Settings → Environment Variables.
Ensure the database schema is applied with npx prisma db push from a trusted environment before first use. For a team/production environment, replace db push with reviewed Prisma migrations.
Deploy.
Do not commit .env.local.
Adzuna, the source in earlier versions, covers no Middle East country, so it was replaced with these official APIs:
| Source | Countries | Key | Notes |
|---|---|---|---|
| Careerjet | UAE, Saudi Arabia, Qatar, Kuwait, Oman | Free partner key | API v4. Sends the visitor's IP and user agent, which Careerjet requires. Bahrain, Egypt and Jordan have no Careerjet locale and are skipped. |
| Jooble | All 8 | Free key by request | Searched with "city, country" as the location. |
| JSearch | All 8 | RapidAPI key (free tier, then paid) | Google for Jobs aggregate, which indexes Gulf boards and employer career pages. Postings outside the searched country are dropped. |
How a search fans out (lib/jobs/provider.ts):
Considered and not used: JobSpy covers Bayt and Middle East Indeed, but it scrapes those sites (against their terms), is Python, and does not run on Vercel's Node runtime. Hosted scraper services for Bayt and GulfTalent exist but have the same terms problem.
The Jooble and JSearch adapters follow their published request and response formats. They were tested against recorded response shapes, not live calls, so confirm them with a real key before relying on them.
The ranking implementation combines four signals:
| Signal | Weight | Purpose |
|---|---|---|
| Semantic cosine similarity | 55% | Finds conceptually relevant jobs even when wording differs |
| Keyword/title overlap | 25% | Preserves exact role/skill matches and rewards title relevance |
| Resume/profile overlap | 15% | Gives a small boost to jobs whose vocabulary overlaps the candidate's resume |
| Recency | 5% | Helps newer listings without letting recency dominate relevance |
The weights are transparent starter heuristics, not universal constants. Evaluate them against a labelled set of queries and relevant jobs before treating the ranking as production-quality.
A keyword-only search misses semantic matches. For example, “customer retention” may be relevant to “lifecycle growth” even if the exact phrase is absent. Embeddings can capture some of that conceptual similarity.
Pure vector search may rank a broadly related job above one with an exact title or skill match. A lexical component helps preserve exact-match precision. The resume-overlap and recency signals are modest tie-breakers.
No. This V1 uses a transparent token-overlap score, not BM25. For a larger production corpus, consider PostgreSQL full-text search with tsvector/tsquery and ts_rank_cd, combine it with vector retrieval (pgvector or an external vector store), and use reciprocal rank fusion (RRF) to combine the two ranked lists. This project stores embeddings in JSON for simplicity; it computes query-to-job embedding similarities in application code and is intended for a small prototype, not a large corpus.
User keyword + Middle East country / city
|
v
LangGraph workflow
|
Search Agent / node
(Careerjet + Jooble + JSearch, or labelled demo provider)
|
v
Persistence Agent / node
(PostgreSQL upsert + search history)
|
v
Ranking Agent / node
(semantic + lexical + profile + recency)
|
v
Ranked opportunities in UI
|
+---- Resume Analyst
| PDF text extraction → strengths/gaps/skills/targets → PostgreSQL
|
+---- Fitment Analyst
Resume + selected JD → structured fit score, evidence-backed strengths,
gaps/missing evidence, keywords to surface, validation questions
The search workflow is explicitly orchestrated with LangGraph. Resume and fitment analyses are separate model-powered workflows in V1; they can be added as nodes in a larger graph when you want a single end-to-end orchestrated run.
Set LANGSMITH_TRACING=true, LANGSMITH_API_KEY, and LANGSMITH_PROJECT. LangChain model calls can then be traced. Check traces in LangSmith to inspect latency, inputs/outputs, and errors. Avoid sending sensitive resume data to an observability workspace unless your privacy controls and retention settings permit it; use synthetic resumes while teaching.
Job.embedding JSON field is reserved for a future persistent vector index; current scoring computes embeddings on demand.