feat: add AI cover letter CLI option and update README
- Add CLI toggle for AI-generated cover letters - Update README with cover letter documentation and examples - Display cover letter status in launch summary - Independent control from AI vacancy filtering
This commit is contained in:
parent
5973d0f70e
commit
c2971645ad
39
README.md
39
README.md
|
@ -11,6 +11,7 @@
|
||||||
- **🔍 Умный поиск** - Находит релевантные вакансии по ключевым словам
|
- **🔍 Умный поиск** - Находит релевантные вакансии по ключевым словам
|
||||||
- **🤖 ИИ-анализ** - Gemini AI оценивает соответствие резюме требованиям
|
- **🤖 ИИ-анализ** - Gemini AI оценивает соответствие резюме требованиям
|
||||||
- **📝 Автоматические отклики** - Отправляет заявки на подходящие вакансии
|
- **📝 Автоматические отклики** - Отправляет заявки на подходящие вакансии
|
||||||
|
- **✉️ ИИ-сопроводительные письма** - Автоматически генерирует персональные письма для каждой вакансии
|
||||||
- **⚙️ Гибкая настройка** - Настраиваемые критерии поиска и фильтрации
|
- **⚙️ Гибкая настройка** - Настраиваемые критерии поиска и фильтрации
|
||||||
- **📊 Детальная статистика** - Отчёты о проделанной работе
|
- **📊 Детальная статистика** - Отчёты о проделанной работе
|
||||||
- **🛡️ Безопасность** - Имитация человеческого поведения, паузы между действиями
|
- **🛡️ Безопасность** - Имитация человеческого поведения, паузы между действиями
|
||||||
|
@ -81,6 +82,7 @@ python main.py
|
||||||
🎯 НАСТРОЙКА ПОИСКА:
|
🎯 НАСТРОЙКА ПОИСКА:
|
||||||
Ключевые слова [python junior]: python разработчик
|
Ключевые слова [python junior]: python разработчик
|
||||||
Использовать AI фильтрацию? [y/n]: y
|
Использовать AI фильтрацию? [y/n]: y
|
||||||
|
Использовать ИИ-сопроводительные письма? [y/n]: y
|
||||||
Максимум заявок [40]: 25
|
Максимум заявок [40]: 25
|
||||||
|
|
||||||
Начать автоматизацию? [y/n]: y
|
Начать автоматизацию? [y/n]: y
|
||||||
|
@ -132,6 +134,9 @@ class AppConstants:
|
||||||
# ИИ анализ
|
# ИИ анализ
|
||||||
DEFAULT_AI_THRESHOLD = 0.7
|
DEFAULT_AI_THRESHOLD = 0.7
|
||||||
|
|
||||||
|
# Сопроводительные письма
|
||||||
|
USE_AI_COVER_LETTERS = True
|
||||||
|
|
||||||
# Таймауты
|
# Таймауты
|
||||||
DEFAULT_TIMEOUT = 30
|
DEFAULT_TIMEOUT = 30
|
||||||
API_PAUSE_SECONDS = 0.5
|
API_PAUSE_SECONDS = 0.5
|
||||||
|
@ -159,6 +164,40 @@ class AppConstants:
|
||||||
📈 % одобрения: 53.3%
|
📈 % одобрения: 53.3%
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## ✉️ ИИ-сопроводительные письма
|
||||||
|
|
||||||
|
### Как работает автоматическая генерация писем
|
||||||
|
|
||||||
|
1. **Обнаружение возможности** - Ищет кнопку "Добавить сопроводительное письмо"
|
||||||
|
2. **Анализ вакансии** - Извлекает требования, обязанности, название и компанию
|
||||||
|
3. **Персонализация** - Использует ваши реальные данные из файлов резюме
|
||||||
|
4. **Генерация письма** - Gemini AI создает уникальное письмо для каждой вакансии
|
||||||
|
5. **Автозаполнение** - Вставляет письмо в поле и отправляет заявку
|
||||||
|
|
||||||
|
### Особенности ИИ-писем
|
||||||
|
|
||||||
|
- **Персональные** - Каждое письмо уникально для конкретной вакансии
|
||||||
|
- **Честные** - Не придумывает несуществующий опыт
|
||||||
|
- **Человечные** - Дружелюбный тон без официоза
|
||||||
|
- **Контактные** - Всегда включает контакт "Telegram — @itqen"
|
||||||
|
- **Адаптивные** - Работает с любыми типами вакансий
|
||||||
|
|
||||||
|
### Пример сгенерированного письма
|
||||||
|
|
||||||
|
```
|
||||||
|
Добрый день!
|
||||||
|
|
||||||
|
Заинтересовался вашей вакансией Python-разработчика.
|
||||||
|
У меня есть опыт работы с Python, Django и базами данных,
|
||||||
|
что соответствует вашим требованиям.
|
||||||
|
|
||||||
|
Готов обсудить возможности сотрудничества и рассказать
|
||||||
|
подробнее о своем опыте.
|
||||||
|
|
||||||
|
С уважением,
|
||||||
|
Telegram — @itqen
|
||||||
|
```
|
||||||
|
|
||||||
## 📊 Статистика работы
|
## 📊 Статистика работы
|
||||||
|
|
||||||
После завершения работы бот предоставляет подробную статистику:
|
После завершения работы бот предоставляет подробную статистику:
|
||||||
|
|
|
@ -39,6 +39,14 @@ class CLIInterface:
|
||||||
print("⚠️ AI фильтрация недоступна (нет GEMINI_API_KEY)")
|
print("⚠️ AI фильтрация недоступна (нет GEMINI_API_KEY)")
|
||||||
use_ai = False
|
use_ai = False
|
||||||
|
|
||||||
|
use_ai_cover_letters = True
|
||||||
|
if settings.enable_ai_matching():
|
||||||
|
cover_letter_choice = input("Использовать ИИ-сопроводительные письма? [y/n]: ").lower()
|
||||||
|
use_ai_cover_letters = cover_letter_choice != "n"
|
||||||
|
else:
|
||||||
|
print("⚠️ ИИ-сопроводительные письма недоступны (нет GEMINI_API_KEY)")
|
||||||
|
use_ai_cover_letters = False
|
||||||
|
|
||||||
excludes = ", ".join(settings.get_exclude_keywords()[:5])
|
excludes = ", ".join(settings.get_exclude_keywords()[:5])
|
||||||
print(f"\n🚫 Текущие исключения: {excludes}...")
|
print(f"\n🚫 Текущие исключения: {excludes}...")
|
||||||
exclude_choice = input("Изменить список исключений? [y/n]: ").lower()
|
exclude_choice = input("Изменить список исключений? [y/n]: ").lower()
|
||||||
|
@ -56,7 +64,7 @@ class CLIInterface:
|
||||||
except ValueError:
|
except ValueError:
|
||||||
max_apps = settings.application.max_applications
|
max_apps = settings.application.max_applications
|
||||||
|
|
||||||
return keywords, use_ai, max_apps
|
return keywords, use_ai, use_ai_cover_letters, max_apps
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _configure_exclude_keywords():
|
def _configure_exclude_keywords():
|
||||||
|
@ -104,14 +112,16 @@ class CLIInterface:
|
||||||
cli.print_welcome()
|
cli.print_welcome()
|
||||||
ResumeFileManager.create_sample_files()
|
ResumeFileManager.create_sample_files()
|
||||||
cli.print_settings_info()
|
cli.print_settings_info()
|
||||||
keywords, use_ai, max_apps = cli.get_user_preferences()
|
keywords, use_ai, use_ai_cover_letters, max_apps = cli.get_user_preferences()
|
||||||
|
|
||||||
settings.update_search_keywords(keywords)
|
settings.update_search_keywords(keywords)
|
||||||
settings.application.max_applications = max_apps
|
settings.application.max_applications = max_apps
|
||||||
|
settings.application.use_ai_cover_letters = use_ai_cover_letters
|
||||||
|
|
||||||
print("\n🎯 ЗАПУСК С ПАРАМЕТРАМИ:")
|
print("\n🎯 ЗАПУСК С ПАРАМЕТРАМИ:")
|
||||||
print(f"🔍 Поиск: {keywords}")
|
print(f"🔍 Поиск: {keywords}")
|
||||||
print(f"🤖 AI: {'Включен' if use_ai else 'Отключен'}")
|
print(f"🤖 AI: {'Включен' if use_ai else 'Отключен'}")
|
||||||
|
print(f"📝 ИИ-письма: {'Включены' if use_ai_cover_letters else 'Отключены'}")
|
||||||
print(f"📊 Максимум заявок: {max_apps}")
|
print(f"📊 Максимум заявок: {max_apps}")
|
||||||
|
|
||||||
confirm = input("\nНачать автоматизацию? [y/n]: ").lower()
|
confirm = input("\nНачать автоматизацию? [y/n]: ").lower()
|
||||||
|
|
|
@ -65,6 +65,7 @@ class ApplicationConfig:
|
||||||
pause_min: float = 3.0
|
pause_min: float = 3.0
|
||||||
pause_max: float = 6.0
|
pause_max: float = 6.0
|
||||||
manual_login: bool = True
|
manual_login: bool = True
|
||||||
|
use_ai_cover_letters: bool = True
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
|
@ -435,6 +435,9 @@ class VacancyApplicator:
|
||||||
def _add_cover_letter_if_possible(self, vacancy: Vacancy) -> None:
|
def _add_cover_letter_if_possible(self, vacancy: Vacancy) -> None:
|
||||||
"""Добавление сопроводительного письма если возможно"""
|
"""Добавление сопроводительного письма если возможно"""
|
||||||
try:
|
try:
|
||||||
|
if not settings.application.use_ai_cover_letters:
|
||||||
|
logger.info("ИИ-сопроводительные письма отключены в настройках")
|
||||||
|
return
|
||||||
cover_letter_button_selectors = [
|
cover_letter_button_selectors = [
|
||||||
'[data-qa="add-cover-letter"]',
|
'[data-qa="add-cover-letter"]',
|
||||||
'button[data-qa*="cover-letter"]',
|
'button[data-qa*="cover-letter"]',
|
||||||
|
|
Loading…
Reference in New Issue