Compare commits

..

No commits in common. "b224ef29d33a1df9ca79365843c4cddf21fd67bf" and "41b3a250a7524f0327fa1887f0f8d7ddd6ec3bde" have entirely different histories.

6 changed files with 18 additions and 73 deletions

View File

@ -1,14 +1,12 @@
import asyncio
import io
import os
import asyncio
import traceback
from typing import Literal
from asgiref.sync import sync_to_async
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from pydantic import BaseModel
from pypdf import PdfReader
from telegram import (
InlineKeyboardButton,
@ -25,6 +23,8 @@ from telegram.ext import (
filters,
)
from pydantic import BaseModel
from typing import Literal
from vacancies.conf.settings import DB_URI
from vacancies.main.models import Customer, CustomerCV, JobTitle
from vacancies.main.recommendations import get_next_vacancy
@ -59,7 +59,7 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
async def next_vacancy(update: Update, context: ContextTypes.DEFAULT_TYPE):
await context.bot.send_message(update.effective_chat.id, " Обрабатываю твой запрос. Пожалуйста, подождите...")
await context.bot.send_message(update.effective_chat.id, "📝 Обрабатываю твой запрос. Пожалуйста, подождите...")
customer_cv = await CustomerCV.objects.filter(customer__telegram_id=update.effective_user.id).afirst()
if not customer_cv:
@ -75,8 +75,7 @@ async def next_vacancy(update: Update, context: ContextTypes.DEFAULT_TYPE):
await context.bot.send_message(
chat_id=update.effective_chat.id,
parse_mode="Markdown",
text=vacancy.get_formatted_response(),
text=vacancy.content,
reply_markup=InlineKeyboardMarkup([[
InlineKeyboardButton("Откликнуться", url=vacancy.link),
]]),
@ -92,7 +91,7 @@ async def prompt(update: Update, context: ContextTypes.DEFAULT_TYPE):
checkpointer=checkpointer,
)
message = await context.bot.send_message(update.effective_chat.id, " Обрабатываю твой запрос. Пожалуйста, подождите...")
message = await context.bot.send_message(update.effective_chat.id, "📝 Обрабатываю твой запрос. Пожалуйста, подождите...")
response = await agent.ainvoke(
input={"messages": [{"role": "user", "content": f'user_id = {update.effective_user.id}\n{update.message.text}'}]},
@ -108,7 +107,7 @@ async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> N
async def handle_document(update: Update, context: ContextTypes.DEFAULT_TYPE):
message = await context.bot.send_message(update.effective_chat.id, " Обрабатываю твой запрос. Пожалуйста, подождите...")
message = await context.bot.send_message(update.effective_chat.id, "📝 Обрабатываю твой запрос. Пожалуйста, подождите...")
if not update.message.document:
await context.bot.send_message(chat_id=update.effective_chat.id, text="Не удалось прочитать информацию из файла! Попробуйте другой формат.")

View File

@ -1,15 +1,14 @@
from datetime import timedelta
from itertools import batched
from datetime import timedelta
from django.utils import timezone
from pydantic import BaseModel
from typing import Literal
from vacancies.main.models import Vacancy, JobTitle
from langchain_openai import ChatOpenAI
import clickhouse_connect
from django.conf import settings
from django.core.management import BaseCommand
from django.utils import timezone
from langchain_openai import ChatOpenAI
from pydantic import BaseModel
from vacancies.main.models import JobTitle, Vacancy
from django.conf import settings
query = """
SELECT DISTINCT ON (message) id, chat_username, telegram_id, message, timestamp
@ -43,8 +42,6 @@ class Command(BaseCommand):
job_title: Literal[tuple(job_titles)]
min_salary_rub: int | None
max_salary_rub: int | None
company_name: str
requirements: str
openai_client = ChatOpenAI(model_name="gpt-5-mini", temperature=0, seed=42, top_p=1)
structured_llm = openai_client.with_structured_output(Structure)
@ -79,8 +76,6 @@ 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,
company_name=response.company_name,
requirements=response.requirements,
content=message,
timestamp=timezone.make_aware(timestamp),
link=f"https://t.me/{chat_username}/{telegram_id}",

View File

@ -1,11 +1,10 @@
import asyncio
from django.core.management import BaseCommand
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from vacancies.main.bot import application
from vacancies.main.models import CustomerCV
from vacancies.main.bot import application
from vacancies.main.recommendations import get_next_vacancy
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
class Command(BaseCommand):
@ -19,8 +18,7 @@ class Command(BaseCommand):
if vacancy := get_next_vacancy(customer_cv):
await application.bot.send_message(
chat_id=customer_cv.customer.chat_id,
text=vacancy.get_formatted_response(),
parse_mode="Markdown",
text=vacancy.content,
reply_markup=InlineKeyboardMarkup([[
InlineKeyboardButton("Откликнуться", url=vacancy.link),
]]),

View File

@ -1,25 +0,0 @@
# Generated by Django 5.2.7 on 2025-11-09 19:56
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='vacancy',
name='company_name',
field=models.CharField(default='test', max_length=255),
preserve_default=False,
),
migrations.AddField(
model_name='vacancy',
name='requirements',
field=models.TextField(default='test'),
preserve_default=False,
),
]

View File

@ -45,8 +45,6 @@ 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)
company_name = models.CharField(max_length=255)
requirements = models.TextField()
content = models.TextField()
timestamp = models.DateTimeField()
link = models.URLField()
@ -54,25 +52,6 @@ class Vacancy(models.Model):
def __str__(self):
return self.job_title.title
def get_formatted_response(self):
response = f"""
💼 **Вакансия**: {self.job_title}
\n🏢 **Компания**: {self.company_name}
\n📝 **Требования**: {self.requirements}
"""
if self.min_salary_rub:
if self.max_salary_rub:
response += f"\n💸 **ЗП**: от {self.min_salary_rub} т.р."
else:
response += f"\n💸 **ЗП**: {self.min_salary_rub} т.р. - {self.max_salary_rub} т.р."
elif self.max_salary_rub:
response += f"\n💸 **ЗП**: до {self.max_salary_rub} т.р."
return response
class Meta:
verbose_name_plural = 'Vacancies'
class RecommendedVacancy(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="recommended_vacancies")

View File

@ -1,6 +1,5 @@
from django.db.models import Q
from vacancies.main.models import Vacancy
from django.db.models import Q
def get_next_vacancy(customer_cv):
@ -8,7 +7,7 @@ def get_next_vacancy(customer_cv):
~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),
job_title__title__in=customer_cv.job_titles.values_list("title", flat=True),
).order_by("-timestamp").first()
).first()
if vacancy:
customer_cv.customer.recommended_vacancies.create(vacancy=vacancy)