Привет! Мы команда ResumeAI и сегодня расскажем, как наша личная боль с написанием резюме вдохновила нас создать чат-бота, который решает эту проблему за 10 минут. Ключевой частью нашего решения стала интеграция с LLM, которая позволяет делать резюме максимально качественным и персонализированным.
Когда ты хочешь сделать хорошее резюме, которое будет замечать hr, ты начинаешь гуглить «как написать резюме» и получаешь много информации с советами для составления резюме или различные конструкторы. Но нет какого‑то удобного решения, так сказать, «под ключ».
На одном из митапов я узнал об ИИ‑агентах, и меня вдохновила идея создать продукт на основе этой технологии. Обсудив это с друзьями, мы решили сосредоточиться на решении проблемы написания резюме. Эта задача идеально подходила для использования ИИ, так как требовала работы с текстом, и на рынке ещё не было продукта, который решал бы её полноценно.
Для создания MVP мы выбрали Telegram‑бота. Такой формат казался оптимальным, так как у нас уже был опыт работы с библиотекой Aiogram, а Telegram обеспечивает удобный интерфейс для пользователей. Кроме того, бот позволяет сразу отправлять готовое резюме в формате PDF, что делает его простым и эффективным инструментом.
Мы используем LLM для определенных задач:
-
Валидиация ответов пользователей
-
Генерация уточняющего вопроса
-
Суммарицазия текста для раздела «Обо мне»
А теперь разберем, как устроен работают наши ИИ‑агенты. В резюме мы имеем несколько необходимых составляющих: опыт работы, образование, навыки и обо мне. Для хорошего резюме эти разделы должны быть правильно заполнены. Разберем на примере с опытом работы, как мы заполняем информацию.
Наша цель собрать JSON со всеми заполненными значения перед тем, как преобразовать эти данные в PDF для резюме
Промпт для обработки:
promt_work_expirience_for_read_data = '''
Тебе необходимо выделить информацию об опыте работы в тексте от пользователя:
позиция в компании, название компании, длительность работы в формате "1 год 4 месяца" в компании и рабочие обязанности.
В тексте могут быть не все блоки. Если информация отсутствует, то оставь пустую строку в значении словаря.
Отвечай на русском, пожалуйста.
Пример оформления ответа:
[
{
"position": "Аналитик",
"company": "Пример",
"duration": "6 месяцев",
"description": [
"Сбор и анализ данных для выявления тенденций и моделей.",
"Подготовка отчетов и презентаций с результатами анализа.",
"Содействие в разработке и оптимизации бизнес-процессов.",
"Взаимодействие с другими отделами для сбора необходимой информации.",
"Мониторинг эффективности реализованных решений и внесение необходимых изменений."
]
}
Пожалуйста, верни только JSON-объект без дополнительных комментариев или текста и в ответе строго должен быть ключ словаря work_experience
'''
Промпт для уточняющего вопроса:
promt_work_expirience_for_ask = '''
Тебе необходимо:
Попроси пользователя рассказать про его опыт работы для того, чтобы узнать информацию об отсутствующем блоки информации.
Нужно спросить про название должностей, компаний, длительность работы в определенной компании и рабочие обязанности.
В ответе напиши только вопрос.
Замени упоминание JSON на "сообщение".
Не используй обращение.
Задавай вопрос только про отсутствующую информацию в json.
Не спрашивай про прошлые места работы.
Спрашивай только про компании, которые упоминал пользователь.
Спрашивай нужную информацию с упоминанием места работы с отсутствующей информацией
Пиши текст более человечно.
Отвечай на русском, пожалуйста.
'''
Функция чтения текста от пользователя:
def read_data(message_usr, system_promt):
result_prompt = rl.promt_context_json(system_promt, message_usr)
result_prompt = json.loads(result_prompt)
return result_prompt
Функция уточняющего вопроса:
def ask(message_usr, system_promt):
result = rl.promt_context_string(system_promt, message_usr)
return result
Функция проверки наличия пустых значений в словаре:
def has_empty_values(data):
if isinstance(data, dict): # Если data - это словарь
for value in data.values():
if has_empty_values(value) == 1: # Рекурсивная проверка для вложенных структур
return 1
elif isinstance(data, list): # Если data - это список
if len(data) == 0: # Явная проверка пустого списка
return 1
for item in data:
if has_empty_values(item) == 1: # Рекурсивная проверка для вложенных структур
return 1
elif data is None or data == "" or data is False: # Проверка на пустое значение (пустая строка, None, False)
return 1
return 0 # Если пустых значений нет
Функция валидации:
def check_data(json_data, system_promt):
if has_empty_values(json_data) == 1:
return ask(json_data, system_promt)
else:
return True
Функция дополнения ответа:
def add_data(message_usr, first_data):
first_data = 'Первый JSON: ' + str(first_data)
promt = first_data + '''
Тебе необходимо заполнить пропуски в первом JSON только на основе сообщения пользователя.
Отвечай на русском, пожалуйста.
Ответы прошу заполнить в пустые поля в исходном json.
Ответ нужен в формате Json.
'''
result_prompt = rl.promt_context_string(promt, message_usr)
return result_prompt
Собираем все в одну функцию:
def classificator_answer(promt_for_read_data, promt_for_ask):
message_usr = input()
while True:
read = read_data(message_usr, promt_for_read_data)
print(read)
check = check_data(read, promt_for_ask)
print(check)
if check == 'Спасибо за ответы на вопросы! Мы начали генерацию вашего резюме. Просим немного подождать':
break
message_usr = input()
message_usr = add_data(message_usr, read)
print(message_usr)
return message_usr
В итоге мы получаем общение с пользователем в формате цикла, пока он правильно не ответит на вопрос про свой опыт работы. Этот метод позволяет разбивать процесс заполнения резюме на небольшие этапы и не нагружает пользователя, что выражается в конверсии 40–50% в созданные резюме. Будем рады обратной связи нашему способу использования ИИ‑агентов для помощи в написании резюме.
В следующих статьях планируем рассказать про построение аналитики для телеграм бота и выборе опенсорсных LLM
Автор: yrschnk