Skip to content

Ivanbsp-coder/hh-agent

Repository files navigation

hh-agent

AI-агент-исследователь вакансий hh.ru. Основные функции:

  1. Сканирование вакансий в браузере Яндекс с версионностью описаний (Playwright + SQLite).
    • 1.2. Проверка архивных вакансий — помечает ушедшие в архив, чтобы не рекомендовать закрытые позиции.
  2. Ранжирование относительно вашего резюме по 10-балльной шкале (LLM, OpenAI-совместимый API).
  3. Советы по улучшению резюме и навыков на основе результатов скрининга (LLM).
  4. Подборка вакансий для отклика — топ-N по баллу + бонусу за свежесть, с опциональной «тёмной лошадкой» от LLM. Сохраняет историю подборок и отметки об откликах (отклики делаются вручную в том же браузере).
  5. Синхронизация откликов и отказов с hh.ru: текущие статусы + журнал отказов по работодателям для cooldown.

Управление — через opencode с slash-командами и скиллами, CLI-скрипты, локальный веб-UI.


Содержание


Архитектура и принципы

  • Повторяющиеся алгоритмы (сканирование, нормализация, диф, сохранение, выборки) написаны на Python.
  • Творческие / исследовательские шаги (понимание соответствия, генерация советов) делегированы LLM через slash-команды .
  • Браузер: установленный у вас Яндекс.Браузер запускается через Playwright в отдельном профиле ~/.hh-agent/browser_profile/ — не конфликтует с вашим обычным сёрфингом, отдельный Chromium качать не нужно.
  • Безопасность: пароль hh.ru вы вводите лично в окне браузера (агент его не видит и не хранит). API-ключ LLM-провайдера берётся из переменной окружения (имя — в config.yaml → llm.api_key_env, по умолчанию YOUR_PROVIDER_API_KEY; добавьте export YOUR_PROVIDER_API_KEY=... в ~/.zshrc).
┌──────────────┐   slash-команды         ┌────────────────────────────┐
│   opencode   │ ─────────────────────▶ │  CLI скрипты (Python)      │
│   (LLM-агент)│                        │  scan / rank / advise / UI │
└──────────────┘                        └──────────┬─────────────────┘
                                                   │
                            ┌──────────────────────┼─────────────────────┐
                            ▼                      ▼                     ▼
                  ┌──────────────────┐   ┌───────────────────┐   ┌──────────────┐
                  │ Playwright +     │   │ OpenAI-совмест.   │   │ SQLite       │
                  │ Яндекс.Браузер   │   │ LLM (DeepSeek и   │   │ (hh.db)      │
                  │ (отд. профиль)   │   │  др., через base_url)│ │ + версии     │
                  └──────────────────┘   └───────────────────┘   └──────┬───────┘
                                                                        │
                                                          FastAPI UI ◄──┘
                                                          (localhost:8765)

Что внутри

hh-agent/
├── README.md                  # этот файл
├── setup.sh                   # установка
├── requirements.txt
├── config.example.yaml        # шаблон конфига
├── hh_agent/                  # Python-пакет
│   ├── config.py              # YAML + интерактивные секреты
│   ├── db.py                  # SQLite-схема и операции с версионностью
│   ├── scraper.py             # Playwright + Яндекс.Браузер
│   ├── llm_client.py          # OpenAI-совместимый клиент
│   ├── scoring.py             # алгоритм 10-балльного ранжирования
│   ├── advisor.py             # генерация советов по резюме
│   ├── recommender.py         # Функция 4: отбор + freshness + llm_pick (учитывает cooldown отказов)
│   ├── delays.py              # human-like log-normal задержки
│   └── notifier.py            # macOS уведомления (osascript)
│   # scraper.py также реализует Функцию 1.2 (архив) и Функцию 5 (/applicant/negotiations)
├── scripts/                   # CLI точки входа
│   ├── init_db.py
│   ├── scan_vacancies.py      # Функция 1
│   ├── check_archived.py      # Функция 1.2: проверка архивных вакансий
│   ├── rank_vacancies.py      # Функция 2 (включая --uid для переоценки конкретной вакансии)
│   ├── advise_resume.py       # Функция 3
│   ├── recommend.py           # Функция 4: подборка на отклик (+ флаги --sync, --no-cooldown)
│   ├── sync_responses.py      # Функция 5: синхронизация откликов и статусов с hh.ru
│   ├── apply_mark.py          # отметка «откликнулся вручную»
│   ├── delete_vacancy.py      # удаление вакансии из БД
│   ├── add_resume.py
│   └── serve_ui.py
├── ui/                        # FastAPI + HTML/JS
│   ├── app.py
│   └── static/
│       ├── index.html
│       ├── styles.css
│       └── app.js
├── .opencode/                 # конфигурация opencode
│   ├── command/               # slash-команды (/scan, /rank, /advise и др.)
│   └── skills/                # скиллы — инструкции для агента (на русском)
│       ├── func1_scan/
│       ├── func1_check_archived/
│       ├── func2_rank/
│       ├── func3_advise/
│       ├── func4_recommend/
│       ├── func4_llm_pick/
│       ├── func5_sync_responses/
│       ├── util_resume_add/
│       ├── util_open_ui/
│       ├── util_adhoc/
│       └── func_adhoc_skills_top/  # ad-hoc: топ востребованных навыков

Требования

  • macOS (тестируется на Mac mini M4)
  • conda (Miniconda/Anaconda)
  • Python 3.11 (поставит conda)
  • Яндекс.Браузер, установленный в /Applications/Yandex.app (если у вас другой путь — пропишите в config.yamlbrowser.executable_path)
  • Учётная запись на hh.ru (войти нужно лично, агент пароль не хранит)
  • API-ключ OpenAI-совместимого LLM-провайдера для функций 2 и 3 (DeepSeek, VseGPT, ProxyAPI, OpenRouter, локальная Ollama — любой)

Установка

Проект устанавливается на чистый macOS из репозитория:

git clone <URL-репозитория> hh-agent
cd hh-agent
chmod +x setup.sh
./setup.sh

setup.sh идемпотентен: создаст conda env hh-agent (Python 3.11), установит зависимости, скопирует config.example.yamlconfig.yaml (если того ещё нет), проверит наличие Яндекс.Браузера и инициализирует пустую БД в ~/.hh-agent/hh.db. Отдельный Chromium не качается — используется ваш установленный Яндекс.Браузер.

Подробная пошаговая инструкция (для новичков, с разбором каждого шага и типичных ошибок) — в INSTALL.md. Минимум, что нужно поправить в config.yaml после установки:

browser:
  executable_path: "/Applications/Yandex.app/Contents/MacOS/Yandex"
  headless: false           # лучше false — увидите, как агент работает

hh:
  search_query: ""          # пусто = что предлагает hh; или впишите "python backend"
  search_params: {}         # доп. GET-параметры поиска; {} = ничего не добавлять
  max_pages: 100

llm:
  base_url: "https://api.aitunnel.ru/v1"
  model: "deepseek-v4-flash"  # или другая модель вашего провайдера

Ключ LLM — в env-переменной (имя — из config.yaml → llm.api_key_env; добавьте export YOUR_PROVIDER_API_KEY=... в ~/.zshrc).


Конфигурация

Файл / каталог Назначение
config.yaml основной конфиг проекта (в репозитории — игнорируется git'ом)
~/.hh-agent/hh.db SQLite-база со всеми данными
~/.hh-agent/browser_profile/ persistent-профиль Яндекс.Браузера для агента
YOUR_PROVIDER_API_KEY (env) API-ключ LLM (имя переменной — в config.yaml → llm.api_key_env)

Все пути берутся из paths: секции config.yaml — можно поменять.

Веса критериев ранжирования

В config.yamlscoring.weights. По умолчанию:

scoring:
  weights:
    hard_skills: 0.35
    experience_and_role: 0.25
    domain_knowledge: 0.15
    soft_and_format: 0.10
    conditions: 0.15
  algorithm_version: "v1.0"

Важно: если меняете веса или системный промпт скоринга — увеличьте algorithm_version (например v1.1). Тогда старые оценки в БД останутся, но по algorithm_version вы сможете отделить их от новых.


Использование

Все команды запускаются из корня проекта, в активированном env:

cd ~/projects/hh-agent
conda activate hh-agent

Загрузка резюме

Перед Функциями 2 и 3 нужно загрузить ваше резюме (любой .txt / .md):

python scripts/add_resume.py ~/Documents/resume.txt --title "Senior Python v2"

Резюме сохраняется как новая версия и делается активным. Все старые версии остаются в БД.

Функция 1: сканирование вакансий

python scripts/scan_vacancies.py

Что произойдёт:

  1. Откроется окно Яндекс.Браузера с пустым профилем агента.
  2. Первый раз — попросит вас войти в hh.ru вручную в этом окне. Когда увидите свой кабинет — вернитесь в терминал и нажмите Enter. Cookies сохранятся, второй раз логиниться не нужно.
  3. Скрипт обойдёт страницы поиска (по умолчанию из hh.search_query, можно переопределить --query "...").
  4. По каждой вакансии:
    • извлечёт всю текстовую информацию;
    • посчитает sha256 от нормализованного содержимого;
    • сравнит с тем, что уже в БД:
      • новая → запишет первую версию;
      • изменилась → запишет новую версию (старые не трогает);
      • без изменений → обновит только last_seen_at.
  5. В конце — лог + macOS-уведомление.

Опции:

python scripts/scan_vacancies.py --query "data engineer"
python scripts/scan_vacancies.py --limit 20                  # жёсткий потолок обработанных вакансий (быстрый прогон)
python scripts/scan_vacancies.py --recheck-after-days 7      # свежее N дней — не заходить в карточку
python scripts/scan_vacancies.py --consecutive-known-pages 3 # выход при N «скучных» страницах подряд
python scripts/scan_vacancies.py --captcha-wait-minutes 30   # сколько ждать решения капчи

Функция 1.2: проверка архивных вакансий

python scripts/check_archived.py

Проходит по ранее собранным вакансиям и проверяет, не ушли ли они в архив. Для каждой открывает её страницу в браузере и смотрит <title>: если там «вакансия в архиве» — ставит is_archived = 1, чтобы закрытые позиции не попадали в подборки Функции 4.

Опции:

python scripts/check_archived.py --older-than-days 14  # проверять вакансии старше N дней (по умолчанию 14)
python scripts/check_archived.py --limit 50            # потолок проверяемых за прогон (по умолчанию 50)

Использует тот же профиль Яндекс.Браузера, что и Функции 1/5.

Функция 2: ранжирование

python scripts/rank_vacancies.py

Что произойдёт:

  1. Перед запуском убедитесь, что в сессии выставлена env-переменная с ключом (имя — в config.yaml → llm.api_key_env); base_url и модель — из config.yaml → llm.
  2. Возьмёт активное резюме.
  3. Для каждой вакансии, у которой нет оценки по её последней версии и по этому резюме:
    • вызовет LLM с строгим JSON-промптом (см. hh_agent/scoring.py);
    • получит баллы по 5 критериям + текстовые комментарии;
    • пересчитает итог с весами из конфига (для согласованности);
    • сохранит запись в rankings с algorithm_version, model и временем.

Опции:

python scripts/rank_vacancies.py --all           # переоценить всё (например после правки весов)
python scripts/rank_vacancies.py --uid 123456789  # переоценить конкретную вакансию по UID
python scripts/rank_vacancies.py --uid 123456789 --resume-id 3  # ... по конкретному резюме
python scripts/rank_vacancies.py --limit 20       # ограничить пачку для теста
python scripts/rank_vacancies.py --resume-id 3

Функция 3: советы по резюме

python scripts/advise_resume.py
  • Соберёт топ-20 лучших и топ-20 худших оценок по активному резюме.
  • Скормит LLM с промптом из hh_agent/advisor.py.
  • Получит структурированный JSON: что добавить в резюме, какие hard/soft-навыки прокачать, какие домены освоить — с привязкой к UID вакансий-доказательств.
  • Сохранит report_md + полный JSON в advice_reportsresume_id, датой, моделью, skill_version).

Опции:

python scripts/advise_resume.py --top 30 --bottom 30
python scripts/advise_resume.py --resume-id 2

Функция 4: подборка вакансий на отклик

Количество вакансий в подборке вы задаёте при каждом вызове:

# Топ-10 по баллу + бонусу за свежесть:
python scripts/recommend.py -n 10

# Топ-10 + 1 «тёмная лошадка» от LLM:
python scripts/recommend.py -n 10 --llm-pick

# С пометкой и выбором резюме:
python scripts/recommend.py -n 5 --notes "пятница, фокус на удалёнку" --resume-id 2

Что происходит:

  1. Скрипт берёт последние оценки из Функции 2 (по текущей версии каждой вакансии и выбранному резюме).

  2. Исключаются вакансии, помеченные как «откликнулся вручную».

  3. К базовому баллу добавляется бонус за свежесть:

    final_score = score + freshness_bonus_max * exp(-age_days / freshness_halflife_days)

    (по умолчанию: freshness_bonus_max = 1.5, период полураспада 7 дней).

  4. Отбираются топ-N и сохраняются в новую «партию» (recommendation_batches, recommendation_items) с датой/временем — история неизменяема.

  5. При флаге --llm-pick дополнительно LLM получает оставшиеся кандидаты (без тех, что уже в python_pick) и выбирает 1 вакансию‐«тёмную лошадку» с обоснованием в поле reason. Подробности — в .opencode/skills/func4_llm_pick/SKILL.md.

Отметка об отклике

Сами отклики вы делаете вручную в Яндекс.Браузере на hh.ru. Чтобы вакансия перестала появляться в будущих подборках — отметьте это:

python scripts/apply_mark.py <vacancy_uid> --note "по совету LLM"
python scripts/apply_mark.py <vacancy_uid> --unmark
python scripts/apply_mark.py --list

Или в UI: вкладка «Вакансии» → карточка вакансии → кнопка «Откликнулся».

Настройки в config.yaml

recommend:
  freshness_bonus_max: 1.5      # максимальная прибавка к баллу
  freshness_halflife_days: 7    # период полураспада бонуса (дни)
  min_score: 5                  # слабые вакансии не предлагаем

Функция 5: синхронизация откликов и отказов с hh.ru

Заходит на https://hh.ru/applicant/negotiations, собирает все ваши отклики и их текущие статусы (приглашение, отказ, в работе, просмотрено, без ответа), сохраняет в БД с историей переходов между статусами. Отдельно ведётся журнал отказов по работодателям — он используется Функцией 4: компании, которые отказали в последние responses.rejection_cooldown_days дней (по умолчанию 270 = ~9 месяцев), исключаются из подборок Python-алгоритма. LLM (--llm-pick) может в виде исключения предложить такую компанию, но обязан явно пометить это в reason фразой «несмотря на прошлый отказ».

# Полная синхронизация (до responses.sync_max_pages страниц):
python scripts/sync_responses.py

# Ограничить число страниц (для быстрого прогона):
python scripts/sync_responses.py --pages 5

# Сначала синхронизировать, потом сразу сформировать подборку:
python scripts/recommend.py -n 10 --sync
python scripts/recommend.py -n 10 --sync --llm-pick

# Полностью отключить cooldown отказов (диагностика):
python scripts/recommend.py -n 10 --no-cooldown

Что происходит:

  1. Скрипт открывает Яндекс.Браузер с тем же профилем, что и Функции 1/2, и листает страницы откликов с задержкой responses.page_delay_ms.
  2. По каждому отклику определяется статус по русским ключевым словам («приглаш», «отказ»/«не подош»/«к сожалению», «тестов»/«собеседов», «просмотр» и т. д.).
  3. Делается UPSERT в responses по vacancy_uid. Если статус изменился — в response_status_history добавляется строка.
  4. Для статуса rejection добавляется/обновляется запись в employer_rejections (ключ — нормализованное имя работодателя
    • vacancy_uid). Нормализация: lowercase, схлопывание пробелов, очистка кавычек/тире.
  5. В runs записывается прогон function='sync_responses' со статистикой.

Настройки в config.yaml

responses:
  sync_max_pages: 20            # сколько страниц /applicant/negotiations листать
  page_delay_ms: 1500           # задержка между страницами (анти-бан)
  rejection_cooldown_days: 270  # сколько дней работодатель «на карантине»

Веб-UI

python scripts/serve_ui.py

Откройте http://localhost:8765. Доступно:

  • Вакансии — таблица с фильтрами (поиск, работодатель, минимальный балл, выбор резюме). Фильтр min_score учитывает последнюю оценку (не лучшую из всех) — корректно работает с переоценками. Клик по строке → карточка с историей версий, всеми оценками и кнопкой «Откликнулся».
  • Резюме — список версий, активация одной кнопкой.
  • Советы — отчёты Функции 3.
  • Отклики — история подборок (факт + LLM) и список вакансий, на которые вы уже откликнулись вручную.
  • Отклики на hh.ru — собранные Функцией 5 отклики с цветовыми бейджами статусов, фильтр по статусу, а также журнал отказов по работодателям для прозрачности cooldown.
  • Журнал — последние запуски Функций 1/2/3/4/5.

Остановить: Ctrl+C.


Интеграция с opencode

Оркестратор агента — opencode. Всё поведение задаётся тремя компонентами:

  • AGENTS.md — системные правила (язык, архитектура, edit=ask, «один fork»).
  • .opencode/command/*.md — slash-команды для запуска функций (/scan, /rank, /advise, /recommend, /sync, /db, /ui, /resume_add, /adhoc).
  • .opencode/skills/ — подробные инструкции в формате SKILL.md, которые агент читает перед запуском.

В opencode.json выставлен edit=ask: любые правки файлов проходят через подтверждение. Главные функции (1–5) запускаете вы явной командой — никаких авто-запусков и cron.

Примеры команд:

  • /scan --limit 20 — быстрый прогон сбора (Функция 1).
  • /rank --limit 5 — оценить 5 вакансий (Функция 2).
  • /advise --top 30 --bottom 30 — советы по резюме (Функция 3).
  • /recommend -n 10 --llm-pick — топ-10 на отклик + «тёмная лошадка» (Функция 4).
  • /sync — синхронизация откликов и отказов с hh.ru (Функция 5).
  • /db "SELECT ..." — быстрый SQL-запрос к БД.
  • /ui — поднять локальную панель.
  • /resume_add <путь> --title "..." — добавить новую версию резюме.
  • /adhoc <задача> — разовые исследования без записи в БД.

Разовые задания (без funcN)

Помимо пяти основных функций агенту можно поручать разовые исследовательские задачи — те, что не должны попадать в БД и журнал runs:

  • «Найди вакансии по LLM-ops в Москве за неделю, топ-15 по моему резюме»
  • «Посмотри отзывы про компанию X на dreamjob.ru»
  • «Сравни моё резюме с топ-10 высокооценёнными вакансиями в БД»
  • «Какие компании активно ищут Drools/Kogito? Сделай SQL-запрос к базе»
  • «Возьми последние 50 отказов, найди общие признаки вакансий»
  • «Покажи топ-20 самых востребованных навыков в вакансиях»

Для таких задач есть скилл-памятка .opencode/skills/util_adhoc/SKILL.md (вызывается через /adhoc).

Для анализа востребованных навыков — отдельный скилл .opencode/skills/func_adhoc_skills_top/SKILL.md: топ-N навыков из vacancy_versions.key_skills с исключением обобщённых и объединением дубликатов. Агенту доступны:

  1. БД SQLite~/.hh-agent/hh.db, читается через sqlite3 в shell.
  2. REST APIhttp://localhost:8765/api/... (все эндпоинты UI).
  3. Яндекс.Браузер с залогиненным hh.ru в ~/.hh-agent/browser_profile/.
  4. LLM с тем же base_url/ключом, что и функции 2/3/4.

Главные правила (в скилле подробнее):

  • Разовая задача — без запуска funcN_*.py. Они пишут в БД новые версии/партии/записи в runs и зашумят историю.
  • Сначала — данные из БД, потом браузер (1–2 страницы, без записи).
  • Результат в чат; в БД не сохранять, если явно не просили.
  • Источник каждого числа в ответе обязателен («из локальной БД», «свежий поиск hh.ru, страница 1»).

Схема БД и версионность

vacancies                              vacancy_versions
─────────                              ────────────────
uid              PK                    id              PK
url                                    vacancy_uid     FK → vacancies.uid
title                                  version_num
employer_name                          content_hash
current_hash     ← sha256(actual)      title, employer_name, salary,
first_seen_at                          experience, employment,
last_seen_at                           schedule, area, description,
last_changed_at                        key_skills (JSON), raw_json,
versions_count                         captured_at

resumes                                rankings
───────                                ────────
id          PK                         id                  PK
version                                vacancy_uid         FK
title                                  vacancy_version_id  FK
text                                   resume_id           FK
content_hash                           score               1..10
is_active                              breakdown_json      JSON
created_at                             summary
notes                                  model
                                       algorithm_version
                                       scored_at

recommendation_batches                 recommendation_items
──────────────────────                 ────────────────────
id           PK                        id                  PK
created_at                             batch_id            FK
resume_id    FK                        vacancy_uid         FK
requested_n                            vacancy_version_id  FK
llm_pick_used (bool)                   ranking_id          FK
notes                                  rank_in_batch       1..N+1
stats_json                             source              python|llm_pick
                                       base_score          из ranking
                                       freshness_bonus     bonus_max*exp(-age/halflife)
                                       final_score         base + bonus
                                       reason              текст (для llm_pick)

applications                           advice_reports                         runs
────────────                           ──────────────                         ────
id           PK                        id           PK                        id          PK
vacancy_uid  UNIQUE                    resume_id    FK                        function    scan|rank|advise|recommend|sync_responses
resume_id    FK (nullable)             report_md                              status      started|finished|failed
batch_id     FK (nullable)             payload_json JSON                      started_at
applied_at                             model                                  finished_at
note                                   skill_version                          stats_json
                                       created_at                             error
                                       sample_size

responses                              response_status_history                employer_rejections
─────────                              ───────────────────────                ───────────────────
id                PK                   id              PK                     id              PK
vacancy_uid       UNIQUE               response_id     FK → responses.id      employer_name   (нормализовано)
employer_name                          status                                 vacancy_uid
applied_at                             status_at                              rejected_at
current_status    invitation|rejection captured_at                            UNIQUE(employer_name, vacancy_uid)
                  |viewed|in_progress
                  |no_response
last_status_at
last_message_text
last_seen_at

Ключевые принципы:

  • Версионируем содержимое, не запись. В vacancies всегда одна строка на uid; новые версии описания — в vacancy_versions.
  • Дифф по хешу. Сравнение нормализованного JSON через sha256 — быстро и стабильно.
  • Оценки не перезаписываются. Каждый запуск Функции 2 пишет новые строки в rankings. Можно сравнить эффект правок весов / промпта / резюме.
  • Резюме версионируется. Все правки сохраняются; «активное» — то, по которому идёт скрининг сейчас.
  • Отклики и отказы версионируются. В responses одна строка на vacancy_uid; каждое изменение статуса фиксируется в response_status_history. Журнал отказов по работодателям (employer_rejections) используется для cooldown Функцией 4.

FAQ / Решение проблем

Не находит Яндекс.Браузер

Проверьте путь:

ls -la /Applications/Yandex.app/Contents/MacOS/Yandex

Если нет — установите browser.yandex.ru или поправьте config.yamlbrowser.executable_path.

Executable doesn't exist при запуске Playwright

Это значит, что Playwright всё-таки пытается использовать свой Chromium вместо Яндекса. Убедитесь, что в config.yaml указан корректный executable_path — скрипт его передаёт в launch_persistent_context(executable_path=...).

hh.ru показывает капчу / просит подтверждение

  • Увеличьте верхние границы в hh.delays.between_pages.bands и between_vacancies.bands.
  • Запускайте реже.
  • Включите browser.headless: false — на реальном окне капча решается легче.
  • Скрипт сам ждёт решения капчи до hh.captcha_wait_minutes минут.

LLM падает с 401 / 403

Проверьте, что ключ выставлен в текущей сессии:

echo $YOUR_PROVIDER_API_KEY

Если пусто — добавьте в ~/.zshrc:

export YOUR_PROVIDER_API_KEY="sk-..."

и откройте новый терминал (или source ~/.zshrc). base_url и модель — из config.yaml → llm.

Хочу переоценить вакансии после правки промпта/весов

python scripts/rank_vacancies.py --all

Если меняли веса в config.yamlобязательно увеличьте algorithm_version, чтобы старые и новые оценки можно было отличить.

Хочу удалить всё и начать заново

rm -rf ~/.hh-agent/
python scripts/init_db.py

(Останется только config.yaml в корне проекта.)

Локальная Ollama вместо облачной LLM

В config.yaml:

llm:
  base_url: "http://localhost:11434/v1"
  model: "qwen2.5:9b"

Ключ можно ввести любой не пустой (Ollama его не проверяет). Качество ранжирования будет заметно хуже, чем у DeepSeek/Claude/GPT, особенно на длинных описаниях — учтите при интерпретации баллов.


Лицензия

Проект распространяется по лицензии MIT — см. файл LICENSE. Можно свободно использовать, изменять и распространять при сохранении текста лицензии и указания авторства.

About

персональный ассистент соискателя для hh.ru, который автоматизирует рутинную часть поиска работы и оставляет за человеком и за LLM только содержательные решения

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors