diff --git a/vacancies/main/__init__.py b/vacancies/main/__init__.py index e69de29..ca0e42e 100644 --- a/vacancies/main/__init__.py +++ b/vacancies/main/__init__.py @@ -0,0 +1,3 @@ +import logging + +logging.basicConfig(level=logging.INFO) diff --git a/vacancies/main/bot.py b/vacancies/main/bot.py index d360fd9..c4892fa 100644 --- a/vacancies/main/bot.py +++ b/vacancies/main/bot.py @@ -126,25 +126,24 @@ async def handle_document(update: Update, context: ContextTypes.DEFAULT_TYPE): job_titles: list[Literal[tuple(db_job_titles)]] min_salary_rub: int | None max_salary_rub: int | None + years_of_experience: int | None + work_format: Literal["Удаленный", "Офис", "Гибрид", None] - openai_client = ChatOpenAI(model_name="gpt-5-mini", temperature=0, seed=42, top_p=1) + openai_client = ChatOpenAI(model_name="gpt-5-mini") structured_llm = openai_client.with_structured_output(Structure) - prompt = f""" - Ты — HR-классификатор. Ниже приведён список допустимых профессий. - Твоя задача — выбрать наиболее подходящие по смыслу. - Качество классификации - самое важное. - Игнорируй орфографические и стилистические различия. - Резюме: - {resume} - """ + prompt = f"Extract sturcture from following CV. {resume}" + print('1') response = await structured_llm.ainvoke(prompt) + print('2') customer = await Customer.objects.aget(telegram_id=update.effective_user.id) customer_cv, _ = await CustomerCV.objects.aupdate_or_create(customer=customer, defaults=dict( content=resume, min_salary_rub=response.min_salary_rub, max_salary_rub=response.max_salary_rub, + years_of_experience=response.years_of_experience, + work_format=response.work_format, )) await customer_cv.job_titles.aset([job_title_map[job_title] for job_title in response.job_titles]) diff --git a/vacancies/main/management/commands/collect_vacancies_from_telegram_messages.py b/vacancies/main/management/commands/collect_vacancies_from_telegram_messages.py index 9276fbb..4877e0b 100644 --- a/vacancies/main/management/commands/collect_vacancies_from_telegram_messages.py +++ b/vacancies/main/management/commands/collect_vacancies_from_telegram_messages.py @@ -42,6 +42,8 @@ class Command(BaseCommand): job_title: Literal[tuple(job_titles)] min_salary_rub: int | None max_salary_rub: int | None + min_years_of_experience: int + work_format: Literal["remote", "office", None] openai_client = ChatOpenAI(model_name="gpt-5-mini", temperature=0, seed=42, top_p=1) structured_llm = openai_client.with_structured_output(Structure) @@ -76,6 +78,8 @@ class Command(BaseCommand): job_title_id=job_title_map[response.job_title], min_salary_rub=response.min_salary_rub, max_salary_rub=response.max_salary_rub, + min_years_of_experience=response.min_years_of_experience, + work_format=response.work_format, content=message, timestamp=timezone.make_aware(timestamp), link=f"https://t.me/{chat_username}/{telegram_id}", diff --git a/vacancies/main/migrations/0012_customercv_work_format_and_more.py b/vacancies/main/migrations/0012_customercv_work_format_and_more.py new file mode 100644 index 0000000..b4ad3ba --- /dev/null +++ b/vacancies/main/migrations/0012_customercv_work_format_and_more.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2.7 on 2025-11-09 12:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0011_remove_customercv_job_title_customercv_job_titles_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='customercv', + name='work_format', + field=models.CharField(blank=True, max_length=64, null=True), + ), + migrations.AddField( + model_name='customercv', + name='years_of_experience', + field=models.PositiveBigIntegerField(default=0), + preserve_default=False, + ), + migrations.AddField( + model_name='vacancy', + name='min_years_of_experience', + field=models.PositiveBigIntegerField(default=0), + preserve_default=False, + ), + migrations.AddField( + model_name='vacancy', + name='work_format', + field=models.CharField(blank=True, max_length=64, null=True), + ), + ] diff --git a/vacancies/main/models.py b/vacancies/main/models.py index a2eaa28..204c417 100644 --- a/vacancies/main/models.py +++ b/vacancies/main/models.py @@ -28,6 +28,8 @@ class CustomerCV(models.Model): job_titles = models.ManyToManyField(JobTitle, related_name="vacancies") min_salary_rub = models.PositiveIntegerField(null=True, blank=True, default=None) max_salary_rub = models.PositiveIntegerField(null=True, blank=True, default=None) + years_of_experience = models.PositiveBigIntegerField() + work_format = models.CharField(max_length=64, null=True, blank=True) content = models.TextField() created_at = models.DateTimeField(auto_now_add=True) @@ -45,6 +47,8 @@ class Vacancy(models.Model): external_id = models.CharField(max_length=255, unique=True) min_salary_rub = models.PositiveIntegerField(null=True, blank=True, default=None) max_salary_rub = models.PositiveIntegerField(null=True, blank=True, default=None) + min_years_of_experience = models.PositiveBigIntegerField() + work_format = models.CharField(max_length=64, null=True, blank=True) content = models.TextField() timestamp = models.DateTimeField() link = models.URLField() diff --git a/vacancies/main/recommendations.py b/vacancies/main/recommendations.py index 8e11db5..7421858 100644 --- a/vacancies/main/recommendations.py +++ b/vacancies/main/recommendations.py @@ -6,7 +6,9 @@ def get_next_vacancy(customer_cv): vacancy = Vacancy.objects.filter( ~Q(id__in=customer_cv.customer.recommended_vacancies.values_list("vacancy_id", flat=True)), Q(min_salary_rub__isnull=True) | Q(min_salary_rub__gt=customer_cv.min_salary_rub), + Q(work_format__isnull=True) | Q(work_format=customer_cv.work_format), job_title__title__in=customer_cv.job_titles.values_list("title", flat=True), + min_years_of_experience__lte=customer_cv.years_of_experience, ).first() if vacancy: customer_cv.customer.recommended_vacancies.create(vacancy=vacancy)