Add button to force send next vacancy
All checks were successful
release / docker (push) Successful in 55s

This commit is contained in:
estromenko 2025-11-03 18:38:11 +03:00
parent d0131ab2a1
commit ffffa973a6
3 changed files with 59 additions and 21 deletions

View File

@ -1,14 +1,14 @@
import os
import io
import traceback
from telegram import Update
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, ReplyKeyboardMarkup, KeyboardButton
from telegram.ext import filters, ApplicationBuilder, MessageHandler, CommandHandler, ContextTypes
from pypdf import PdfReader
from vacancies.main.models import Customer, CustomerCV
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.postgres.aio import AsyncPostgresSaver
from vacancies.main.vector_store import add_vectors, extract_features
from vacancies.main.vector_store import add_vectors, extract_features, get_next_vacancy
from vacancies.conf.settings import DB_URI
SYSTEM_PROMPT = """
@ -34,8 +34,36 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
chat_id=update.effective_chat.id,
),
)
keyboard = [[KeyboardButton("Получить следующую вакансию")]]
reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=False)
text = "Привет! Я карьерный копилот: помогу с работой, интервью и расскажу новости по рынку, специально для тебя. С чего начнем?"
await context.bot.send_message(chat_id=update.effective_chat.id, text=text)
await context.bot.send_message(chat_id=update.effective_chat.id, text=text, reply_markup=reply_markup)
async def next_vacancy(update: Update, context: ContextTypes.DEFAULT_TYPE):
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:
message = "Пришлите мне свое резюме, чтобы я мог подобрать вам вакансии!"
await context.bot.send_message(chat_id=update.effective_chat.id, text=message)
return
result = get_next_vacancy(customer_cv)
if not result:
message = "Вакансии закончились, возвращайтесь позже!"
await context.bot.send_message(chat_id=update.effective_chat.id, text=message)
return
recommendation, vacancy_content, link = result
await context.bot.send_message(
chat_id=update.effective_chat.id,
text=vacancy_content,
reply_markup=InlineKeyboardMarkup([[
InlineKeyboardButton("Откликнуться", url=link),
]]),
)
async def prompt(update: Update, context: ContextTypes.DEFAULT_TYPE):
@ -92,6 +120,7 @@ async def handle_document(update: Update, context: ContextTypes.DEFAULT_TYPE):
application = ApplicationBuilder().token(os.environ["BOT_TOKEN"]).concurrent_updates(True).build()
application.add_handler(CommandHandler('start', start, block=False))
application.add_handler(MessageHandler(filters.Text("Получить следующую вакансию"), next_vacancy, block=False))
application.add_handler(MessageHandler(filters.TEXT & (~filters.COMMAND), prompt, block=False))
application.add_handler(MessageHandler((filters.Document.ALL | filters.PHOTO) & (~filters.COMMAND), handle_document, block=False))
application.add_error_handler(error_handler)

View File

@ -1,11 +1,10 @@
import asyncio
from django.core.management import BaseCommand
from vacancies.main.vector_store import search_similarities
from vacancies.main.models import CustomerCV, RecommendedVacancy
from vacancies.main.models import CustomerCV
from vacancies.main.bot import application
from vacancies.main.vector_store import get_next_vacancy
from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from qdrant_client.models import Filter, HasIdCondition
class Command(BaseCommand):
@ -15,24 +14,12 @@ class Command(BaseCommand):
asyncio.run(self.ahandle(*args, **options))
async def ahandle(self, *args, **options):
customer_cvs = CustomerCV.objects.all()
for customer_cv in customer_cvs:
recommended_vacancy_ids = RecommendedVacancy.objects.filter(
customer=customer_cv.customer,
).values_list('vacancy_id', flat=True)
query_filter = Filter(must_not=[HasIdCondition(has_id=recommended_vacancy_ids)])
result = search_similarities(query_filter, customer_cv.id)
for customer_cv in CustomerCV.objects.all():
result = get_next_vacancy(customer_cv)
if not result:
continue
search_result_id, vacancy_content, link = result
recommendation = RecommendedVacancy.objects.create(
customer=customer_cv.customer,
vacancy_id=search_result_id,
)
recommendation, vacancy_content, link = result
await application.bot.send_message(
chat_id=recommendation.customer.chat_id,

View File

@ -5,6 +5,8 @@ from qdrant_client import QdrantClient
from qdrant_client.models import Filter
from vacancies.main.models import VacancyFeatures
from vacancies.conf.settings import QDRANT_URL
from vacancies.main.models import CustomerCV, RecommendedVacancy
from qdrant_client.models import Filter, HasIdCondition
qdrant_client = QdrantClient(url=QDRANT_URL)
@ -184,3 +186,23 @@ def extract_features(content: str) -> VacancyFeatures:
structured_llm = openai_client.with_structured_output(VacancyFeatures)
response = structured_llm.invoke(prompt)
return response
def get_next_vacancy(customer_cv):
recommended_vacancy_ids = RecommendedVacancy.objects.filter(
customer=customer_cv.customer,
).values_list('vacancy_id', flat=True)
query_filter = Filter(must_not=[HasIdCondition(has_id=recommended_vacancy_ids)])
result = search_similarities(query_filter, customer_cv.id)
if not result:
return None
search_result_id, vacancy_content, link = result
recommendation = RecommendedVacancy.objects.create(
customer=customer_cv.customer,
vacancy_id=search_result_id,
)
return recommendation, vacancy_content, link