This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
What I Built
Aalas 🦥: Let the Job Hunt Run While You Sleep
The most boring part of looking for a job, for me, is looking for a job.
Searching across job listings, checking whether a role matches my experience, tailoring my resume for every application, and writing cover letters can take hours. And after all that effort, there is still no guarantee that I'll even get an interview.
So, for Hacktoberfest Week 3's Slow and Steady challenge, I built Aalas — a privacy-first job-hunting platform that does the tedious parts of job searching for you.
Aalas means laziness in Hindi. And honestly, why should we spend hours doing repetitive work that can be automated?
The idea is simple: let Aalas search for jobs while you sleep, so you can wake up to a fresh list of relevant opportunities waiting to be explored.
Here's what Aalas does:
Automates job discovery: Search for jobs based on your preferred roles, locations, job type, experience level, and salary preferences. Scheduled refreshes keep listings up to date.
Ranks jobs by relevance: Instead of displaying jobs in a random or purely chronological order, Aalas considers your resume, skills, preferences, projects, and additional experience to surface opportunities that are more relevant to you.
Tailors your resume: Upload your existing LaTeX resume (.tex), select a job, and let AI tailor your resume to its description while preserving the original format. Download the resulting PDF and use it for your application.
Generates cover letters: Get a separate, job-specific cover letter without having to start from a blank page every time.
Keeps AI processing local: Resume tailoring and cover-letter generation run using a local LLM, so your resume and additional candidate context don't need to be sent to a hosted AI generation API.
The goal isn't to automate applying blindly to hundreds of jobs. It's to reduce repetitive work so that job seekers can spend more time preparing for interviews, improving their skills, and applying thoughtfully.
Demo
Code
💻 GitHub repository:
sujalamati
/
aalas
Hacktoberfest Week3 Dev Challenge Submission
Aalas — Job Hunter Backend (FastAPI)
Backend scaffold for a job discovery tool with PostgreSQL/pgvector hybrid ranking and Ollama-powered resume/cover-letter generation.
Important integration notes
-
app/services/jobs_provider.pyis a native Python port of the supplied JavaScript implementation. It useshttpxand BeautifulSoup; the unrelatedlinkedin-jobs-apiPython package has been removed. It requests LinkedIn guest-job listing HTML, so the endpoint and HTML selectors can change and requests may be rate-limited. This is not an official LinkedIn API; verify applicable terms before deployment and keep request rates conservative. - Search results do not contain the full description, so the provider makes a second request to each job URL and extracts
descriptionfrom the page’s schema.orgJobPostingJSON-LD. It falls back to common visible-description selectors. A failed detail-page request does not discard the listing; its description remains empty. - Check LinkedIn and provider terms, rate limits, privacy obligations, and any applicable API terms before deploying scraping-based ingestion.
- …
The project uses a React frontend and a Python FastAPI backend, with a PostgreSQL-based search layer and local AI inference.
How I Built It
I wanted Aalas to be more than a wrapper around an AI API. The interesting part was combining job discovery, personalized retrieval, and document generation into one workflow while keeping control over the AI processing.
Here's the stack behind it.
1.FastAPI and React
The backend is built with Python and FastAPI. It handles user profiles, job ingestion, search, ranking, and document generation. The React frontend provides the interface for uploading resumes, exploring jobs, and downloading generated documents.
2.TigerData, pgvector, and hybrid search
This is one of the core parts of Aalas.
A keyword-only search can miss a job described using different terminology from the candidate's resume. On the other hand, semantic search alone may retrieve conceptually similar jobs that don't contain important role-specific keywords.
To combine the strengths of both approaches, Aalas uses hybrid search with Reciprocal Rank Fusion (RRF).
The search pipeline has two retrieval methods:
- BM25 keyword search: Uses TigerData's pg_textsearch extension to retrieve jobs based on textual relevance.
- Vector search: Uses pgvector embeddings to compare the user's profile and resume context with job listings based on semantic similarity. The two ranked lists are then combined using Reciprocal Rank Fusion:
Here, (r_{\text{BM25}}(d)) and (r_{\text{vector}}(d)) are the ranks assigned to a job by the two retrieval methods, and (k) is a smoothing constant.
Rather than directly adding BM25 and cosine-similarity scores, RRF combines their rankings. This helps Aalas prioritize jobs that rank well across both methods.
TigerData is the partner tool I use for the PostgreSQL search layer, including the pgvector-based embedding retrieval and pg_textsearch-based BM25 search. During development, the database runs in Docker with persistent storage, making it easier to test the complete search workflow locally.
One additional detail: salary is not treated as a mandatory field. When a listing doesn't specify salary, it can still appear in the results instead of being discarded simply because that information is missing.
3.Gemma 4 through Ollama
For the AI features, I use gemma4:e4b through Ollama for local inference.
Resume tailoring and cover-letter generation use separate model calls and carefully designed prompts.
For resume tailoring, the model receives the original LaTeX resume, the job description, and additional candidate context such as projects or experience that may not be included in the original resume. It returns a complete LaTeX document that aims to preserve the original template while emphasizing relevant, supported experience.
For cover letters, the model uses the same candidate information and the selected job description to generate a separate letter tailored to that opportunity.
The prompts explicitly instruct the model not to invent skills, qualifications, achievements, or experience. A job description tells the model what the employer is looking for; it is not evidence that the candidate possesses those qualifications.
The generated LaTeX is compiled into a PDF that the user can download.
4.Job descriptions and scheduled discovery
The initial job listing response doesn't always include a full description, so Aalas makes an additional request to the job's detail page when needed and extracts the description for ranking and document generation.
Job discovery can also run on a schedule, including a noon and midnight refresh, so that new listings can be available without the user having to initiate every search manually.
The job ingestion layer uses public LinkedIn job pages through a custom Python implementation, rather than assuming that a similarly named Python package has the same API as the original JavaScript library.
Why Does Open Innovation Matter?
A resume is personal. It contains a person's education, work history, contact information, projects, and sometimes much more.
I didn't want the core AI workflow of a job-hunting application to require sending all that information to a hosted AI API.
Using an open-weight model through local inference gives me more control over where document generation happens. Combined with a locally running database during development, it lets me experiment with the complete workflow without making a cloud AI service a mandatory part of every resume-tailoring request.
Open tools also make the system easier to inspect and improve. I can change the embedding model, adjust the hybrid search algorithm, refine the prompts, or replace the job ingestion provider without rebuilding the entire application around a single closed platform.
For me, open innovation is about more than access to a model's weights. It's about having the freedom to understand, modify, and improve the whole system.
Prize Categories
- TigerData: Partner tool used for the PostgreSQL search layer, including pgvector embeddings and pg_textsearch-based BM25 retrieval.




Top comments (0)