惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
H
Help Net Security
小众软件
小众软件
N
Netflix TechBlog - Medium
C
Check Point Blog
量子位
Last Week in AI
Last Week in AI
GbyAI
GbyAI
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
D
DataBreaches.Net
Project Zero
Project Zero
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Security Latest
Security Latest
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
I
Intezer
L
Lohrmann on Cybersecurity
Cyberwarzone
Cyberwarzone
博客园_首页
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog
P
Palo Alto Networks Blog
V
V2EX
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
G
GRAHAM CLULEY
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
F
Full Disclosure
博客园 - 司徒正美
Recent Announcements
Recent Announcements
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
Cloudbric
Cloudbric
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
RAG на кончиках пальцев
IgMamont · 2026-06-22 · via Все публикации подряд на Хабре

Средний

6 мин

4

Хочу поделиться своим опытом создания системы контекстного поиска. Плотно занялся LLM год назад, можно сказать, что я «молодой специалист».

И так, появился первый заказчик. Осознал идею, разбил на этапы и приступил к работе.

Одна из задач — по свободному запросу пользователя находить в базе знаний релевантный термин. От точности поиска зависела вся остальная логика системы и успех проекта.

Выбор модели RAG

Я изначально «интуитивно» смотрел в сторону локальных моделей RAG: во‑первых, чтобы не платить за токены, но самое главное — обеспечить безопасность данных, таково было условие проекта. Почитал форумы, провёл тесты и остановился на «multilingual‑e5-large», несмотря на её мультиязычность. Как ни странно, она показывает лучшие результаты по сравнению с моделями, заточенными под родную кириллицу.

Префиксы

По заверениям авторов, E5 нужны префиксы для корректной работы. Хотя на этапе выбора и тестирования она и без них довольно точно находила нужное значение.

Для запроса ставим префикс: f"query: {problem_text} "

Для записей в базе знаний: f"passage: {p['name']}. {desc} "

Структура базы знаний

Путём экспериментов и тестов, пришёл к следующей структуре. Пример JSON:

Пример корневого свойства, структура дочернего аналогична.
{
    "id": "00",
    "name": "Наименование свойства",
    "aspects": [
        {"type": "1", "text": "Описание 1"},
        {"type": "2", "text": "Описание 2"},
        {"type": "3", "text": "Наименование свойства"}
    ],
    "root_id": "00",
    "parent_name": null,
    "matrix_property": true,
    "categories": [],
    "synonyms": [],
    "negative_synonyms": []
}

Корневые и дочерние свойства

Если пытаться впихнуть в одно свойство все возможные варианты его описания, у модели размывается фокус. Я разбавил структуру. У каждого свойства, по умолчанию есть корневая запись с наименованием и описанием, синонимами. При необходимости добавляем дочерние варианты с аналогичной структурой. Так модель с большей вероятностью подберет подходящий вариант. Даже если их будет несколько, это не критично — скриптом (Python) поднимаем до root ID и получаем искомое свойство.

Главное не переборщить с вариантами — их описание требует много усилий и времени, а их чрезмерное количество для одного свойства в итоге может вытеснить из рейтинга другие свойства, близкие по смыслу и полезные для последующей аналитики и использования.

Композитные свойства

Специфика задачи — в базе знаний оказалось много свойств, которые сочетают в себе несколько смыслов.

Пример: «Индекс ценности фичи» = Бизнес‑ценность + Сложность реализации.

Аспект 1 — бизнес ценность, Аспект 2 — сложность реализации

Использовать «корневые и дочерние» не вариант — при поиске должны «сыграть все смыслы». Поэтому декомпозируем описание свойства на аспекты.

Эмбеддим их отдельно и получаем score каждого, а затем используем функцию meanпри агрегации общего score. Можно использовать более жесткий вариант — Min.

Агрегация происходит по ID свойства. Для его извлечения нужен «лишний» запрос в исходную базу знаний, что не очень хорошо. Поэтому я решил все метаданные, включая ID, хранить непосредственно в базе эмбеддингов. Место они занимают немного, и нет риска рассинхронизации, т.к все загружается из единого источника.

Negative_synonyms

То чем свойство не является. "negative_synonyms": [].Полезная фича для тонкого тюнинга. Использую в исключительных случаях.

Например «Чёрный ящик» имеет два смысла: физический объект и непрозрачность процесса.

Ембеддинг каждого антисинонима выполняется отдельно. Здесь использую функцию Max,то есть беру максимальное значение из всех возможных. Штрафую попавшие в основной рейтинг свойства.

penalty = 2.0 if n_score >= NEG_THRESHOLD else 1.0

В моем случае с E5, опытным путём — NEG_THRESHOLD = 0.83. Т.е. если score негативного синонима больше порогового значения — начисляем штраф.

Я пробовал заполнять это поле поголовно для всех свойств базы знаний, но в итоге отказался, так как под штраф попадали близкие по смыслу свойства, важные для дальнейшей логики работы системы.

С чем модель E5 не справилась

Даже после применённых выше приёмов, модель по прежнему не могла различать «отрицание».

Например: «Подвижный» и «Неподвижный». Отличие всего на две буквы выдаёт почти одинаковые score.

Я пробовал различные варианты описаний — не помогло. Позже выяснил, Е5 не умеет это делать от слова совсем.

Пришлось задействовать силы LLM. Выбралqwen2.5:7b-instruct-q5_K_M.

  1. Перед эмбеддингом LLM классифицирует запрос. Например, на всё тот же «Подвижный» или «Неподвижный».

  2. От Е5, получаем список кандидатов, сравниваем их "categories": [] из метаданных с результатами классификации запроса от LLM и штрафуем тех, чья категория не совпала.

  3. Если запрос не относится к категории — ставлю None без штрафа, то есть шаг классификации пропускается.

  4. Score свойств, которые выиграли в номинации «категория», я не стал искусственно завышать, чтобы они имели одинаковые условия конкуренции в рейтинге с остальными свойствами, к которым номинация «категория» вообще не относится.

Есть риск, что LLM ошибётся, но тесты показали, что хороший промпт + few‑shot JSON, заполненный качественными примерами, выдаёт стабильно корректный результат.

Reranking

Несмотря на то, что удалось добиться высокой точности поиска с минимальным Loss, я решил в завершение цикла добавить Reranking. На топ 5–10 кандидатов он отнимает мизерную долю времени. Выбрал jina‑reranker‑v3.

  1. Jina я отдаю точно такие же данные, что и E5, для сохранения консистентности.

  2. Сырой логит использую как детектор сигнала: в случае если он меньше нуля — откатываюсь обратно на рейтинг E5. Значит Jina бессильна.

  3. Далее нормализую сырой логит через функцию sigmoid, агрегирую результаты композитных свойств (аналогично Е5) и получаю итоговый рейтинг.

Итоговый Pipeline

  1. Загружаем библиотеки и модели с весами.

  2. Загружаем предварительно созданные эмбеддинги по базе знаний вместе с метаданными (ID свойств, категории, и данные для Jina). Чтобы не тратить драгоценные секунды во время поиска.

  3. LLM квалифицирует запрос и возращает признак — подвижный/неподвижный.

  4. E5 по запросу возвращает релевантных кандидатов через фильтрPOS_THRESHOLD. Сравниваем метаданные кандидатов с признаком, полученным от LLM. Через штраф отсеиваем тех, кто не попадает в «категорию» и сработали «антисинонимы». Рассчитываем итоговый pure_score кандидата.

  5. Формула расчета результирующего score перед отправкой в Jina: pure_score = (p_score / penalty) * cat_factor

    • pure_score — итоговый рейтинг;

    • p_score — score который вернул E5;

    • penalty — штраф за негативный синоним;

    • cat_factor — штраф за неправильную категорию.

  6. Отдаем топ отобранных кандидатов в Jina, получаем сырые логиты. Если логиты ВСЕХ аспектов кандидата отрицательные, возращаемся к score Е5. Тут возможны варианты: «все», «хотя бы один положительный», «хотя бы один отрицательный».

  7. Преобразуем сырые логиты через sigmoid, агрегируем по Mean, получаем итоговый рейтинг.

  8. Поднимаем по Root_Id до корневого свойства, получаем искомый результат.

Мелочи и нюансы

  • Все значения фильтров, порогов и штрафов — это настраиваемые параметры, что очень удобно при отладке и тестировании и можно вывести в интерфейс пользователя.

  • Синонимы не должны дублировать слова из описания, излишняя плотность одинаковых слов только вредит поиску, а отличные от описания синонимы дают бОльший охват при поиске.

  • Желательно чтобы все свойства в базе знаний имели полноценное описание (наименование, описание, синонимы) и примерно одинаковое количество символов. Если часть свойств оставить короткими, например только «Наименование» они иногда начинают ошибочно доминировать в рейтинге над свойством с полноценным описанием, создавая лишний шум.

  • С другой стороны, если оставить в базе знаний только «Наименования» свойств, обе модели точно выдают правильный результат, НО НЕ ВСЕГДА!

  • В итоге, я пришел к компромиссному варианту — «Название свойства» (без описания и синонимов) я ставлю как отдельный, дополнительный аспект — даю шанс моделям проявить себя без подсказок, «из коробки». Все всплески нивелируются через фильтрmean. Е5 перестает доминировать, а у Jina пропадают отрицательные логиты, так как в батче идут сразу несколько аспектов вместе, представляя общий контекст свойства.

"aspects": [
        {"type": "1", "text": "Описание 1"},
        {"type": "2", "text": "Описание 2"},
        {"type": "3", "text": "Наименование свойства"}
  • В большинстве случаев score Е5 у правильного ответа становится чуть выше (иногда на десятые доли, а это ощутимый прирост), если синонимы идут через запятую с маленькой буквы. Пробовал точку с запятой, кавычки и другие варианты. Запятая работает если количество синонимов не больше 5 шт, а больше и не стоит иначе размывается фокус.

Надеюсь, что кому‑то я помог. Хочу услышать ваше мнение и советы!