Job Descriptions That Find the Perfect Candidate
Every HR manager knows: a single job description takes 30–90 minutes to write. Yet 70% of texts on hh.ru and LinkedIn look like template copies — same phrases, no tone of voice, and SEO ignored. Candidates scroll past such ads in seconds. We developed an AI system that generates a structured job description in 15–30 seconds based on the job title, tech stack, and requirements — with gender neutrality control, SEO optimization for each platform, and alignment with the employer brand.
How Generation Works
At the core is a fine-tuned GPT-4o model with prompt engineering for HR tasks. We pass a JobBrief dataclass with fields for title, department, tech_stack, responsibilities, and tone parameters (professional, startup, corporate, creative). The model returns JSON with sections: title_seo, about_company, responsibilities, requirements_hard, requirements_soft, nice_to_have, conditions, and cta. The generator uses asyncio to process up to 10 requests in parallel. We use the OpenAI API with temperature and top_p settings to balance creativity and accuracy.
from openai import AsyncOpenAI
from dataclasses import dataclass, field
client = AsyncOpenAI()
@dataclass
class JobBrief:
title: str
department: str
employment_type: str # full-time, part-time, contract, freelance
experience_years: tuple # (min, max)
tech_stack: list[str]
responsibilities: list[str]
company_description: str
tone: str = "professional" # professional, startup, corporate, creative
language: str = "ru"
include_salary_range: bool = False
salary_range: tuple = None
async def generate_job_description(brief: JobBrief) -> dict:
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"""Ты — HR-копирайтер, специалист по employer branding.
Создай описание вакансии для job-агрегаторов (hh.ru, LinkedIn, Habr Career).
ТРЕБОВАНИЯ:
- Заголовок: должность + ключевые технологии (для SEO в поиске)
- О компании: 2–3 предложения, конкретные факты, без «лидер рынка»
- Обязанности: 5–7 пунктов с глаголами действия, конкретных
- Требования: hard skills отдельно от soft skills, must-have vs nice-to-have
- Условия: без воды, только факты
- Гендерно нейтральные формулировки (не «программист», а «разработчик/разработчица» или нейтрально)
- Tone of voice: {brief.tone}
Верни JSON: {{title_seo, about_company, responsibilities, requirements_hard, requirements_soft, nice_to_have, conditions, cta}}"""
}, {
"role": "user",
"content": f"""
Должность: {brief.title}
Отдел: {brief.department}
Тип занятости: {brief.employment_type}
Опыт: {brief.experience_years[0]}–{brief.experience_years[1]} лет
Стек: {', '.join(brief.tech_stack)}
Ключевые задачи: {', '.join(brief.responsibilities)}
О компании: {brief.company_description}
{"Зарплата: " + f"{brief.salary_range[0]}–{brief.salary_range[1]} руб." if brief.include_salary_range and brief.salary_range else ""}
"""
}],
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
Why Adapt Descriptions for Each Platform?
hh.ru, LinkedIn, and Habr Career have different requirements for structure and style. hh.ru values brevity — a maximum of 100 characters for the title and strict sections. LinkedIn, on the other hand, encourages expanded descriptions with keywords for search. Habr Career requires technical details and metrics. We implemented platform templates with constraints and stylistic rules — the adaptation code uses the same model with an additional prompt.
JOB_PLATFORM_FORMATS = {
"hh.ru": {
"max_title": 100,
"sections": ["about_company", "responsibilities", "requirements_hard", "conditions"],
"style": "структурированный, без маркетинга"
},
"linkedin": {
"max_title": 120,
"sections": ["about_company", "responsibilities", "requirements_hard", "requirements_soft", "nice_to_have"],
"style": "профессиональный, с ключевыми словами для LinkedIn Search"
},
"habr_career": {
"max_title": 100,
"sections": ["responsibilities", "requirements_hard", "nice_to_have", "conditions"],
"style": "технический, для IT-аудитории, конкретные метрики"
}
}
async def adapt_for_platform(job_data: dict, platform: str) -> str:
fmt = JOB_PLATFORM_FORMATS.get(platform, JOB_PLATFORM_FORMATS["hh.ru"])
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": f"Адаптируй описание вакансии для платформы {platform}. Стиль: {fmt['style']}. Используй разделы: {fmt['sections']}."
}, {
"role": "user",
"content": str(job_data)
}]
)
return response.choices[0].message.content
Mass Generation for Hiring: When You Need to Fill 50+ Positions
For mass hiring, the system accepts a CSV with a list of positions and tech stacks, generates descriptions in batches of 10–15 vacancies in parallel via asyncio.gather, and saves the result in formats for all platforms. For companies hiring more than 50 people per year, this saves 200–300 hours of HR team time. Below is a comparison of effort:
| Stage | Manual Process | AI System |
|---|---|---|
| Writing one description | 30–90 min | 15–30 sec |
| Adaptation for 3 platforms | 20–40 min | 1–2 min |
| Gender neutrality check | 5–10 min | automatic |
| SEO tuning for job aggregators | 10–15 min | built-in |
The AI system is 10x faster than manual drafting — confirmed by our measurements on client projects.
Evaluation and Iterations: How to Ensure the Text Works
async def score_job_description(text: str) -> dict:
"""Оцениваем описание по факторам привлечения кандидатов"""
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "system",
"content": """Оцени описание вакансии по критериям (1–10):
- clarity: ясность требований
- appeal: привлекательность для кандидата
- seo_score: SEO для job-агрегаторов
- gender_neutrality: гендерная нейтральность
- specificity: конкретность (vs абстрактные требования)
Верни JSON с оценками и рекомендациями."""
}, {
"role": "user",
"content": text
}],
response_format={"type": "json_object"}
)
import json
return json.loads(response.choices[0].message.content)
The system doesn't just generate text — it evaluates it on a scale of 1–10 by criteria: clarity, appeal, seo_score, gender_neutrality, and specificity. Based on the evaluation, we adjust the prompt and consistently achieve high quality. Our experience shows that after 3–4 iterations, the text quality matches the best manual samples.
What's Included in Our Development
- Architecture design: LLM selection (GPT-4o or LLaMA 3), dataset preparation for few-shot learning.
- Module development: generator, platform adapter, quality analyzer.
- Integration with ATS (Huntflow, Talantix, Greenhouse) and HRM systems.
- Testing and A/B testing of generated descriptions on real vacancies.
- Deployment in your infrastructure (Kubernetes, SageMaker, or on-premise).
- API documentation and HR team training.
Implementation Stages
- Analysis of the current HR process and gathering requirements for tone of voice, platforms, and ATS.
- Architecture design and LLM selection — we recommend GPT-4o or LLaMA 3 depending on confidentiality requirements.
- Development of generation, platform adaptation, and quality evaluation modules.
- Integration with your ATS via REST API.
- Testing on 5–10 vacancies, prompt adjustments.
- Deployment to cloud or on-premise, team training.
Timelines and Cost
MVP development with support for one platform takes 1–2 weeks. Integration with ATS and mass generation takes another 2–3 weeks. The exact cost is calculated individually after an audit of your HR infrastructure. We guarantee text quality on par with manual drafting — confirmed by over 30 projects completed in 5 years of work in the AI HR solutions market.
Why Implement AI Generation Now?
The job market is changing — candidates choose companies that speak their language. An automatic job description generation system gives a competitive advantage: speed, quality, and a consistent tone of voice across all postings. Request a demo — we'll show you on your data.







