Привет, Хабр! Мой путь в мире IT официально начался относительно недавно: в октябре 2025 года. До этого программирование вообще не выходило за рамки увлечений. Но однажды я решил испытать удачу и выйти на тропу приключений, после которой я уже не вернулся прежним...
Даже при условии, что я до этого воспылал намерением написать одного ТГ-бота как свой проект для личного портфолио, пламя, как известно, горит только при условии наличия горючего — проект я быстренько свернул и закопал в приватном репозитории гитхаба (я планирую к нему вернуться). Еще и поджимал факт того, что я могу с бо́льшей вероятностью загреметь на платное в универ. Так что после этого я совершил наступление на то, что определенно меня бы встряхнуло и дало бы интересное приключение — хакатоны.
Взяв штурмом сайт хакатоны.рус, я пересмотрел все хакатоны, и меня заинтересовал один — AI for Finance Hack 2025 (да, в идеале я должен был писать эту статью в ноябре, только после результатов, провинился. Поэтому и ретроспектива). Условия были выгодные, мне понравилось.
RAG (Retrieval-Augmented Generation - поисковая дополненная генерация) — это технология искусственного интеллекта, которая позволяет большим языковым моделям (LLM) получать доступ к внешним базам знаний, чтобы генерировать более точные, актуальные и обоснованные ответы, не требуя дорогостоящего переобучения.
Выражаясь простым языком, у вас может быть какой-нибудь супер-умный и супер-быстрый сотрудник (т.е. LLM), но у него проблемы с памятью (например, он может сомневаться насчет банковской ставки, и в документе с равной вероятностью проставить 15% (ваша реальная ставка) или 12% (подсмотрел это число абсолютно в другом месте, даже не факт, что в релевантном).
RAG — это папка с документами. С каждой новой задачей сотрудник будет рыться в ней и вытаскивать оттуда необходимые данные. Теперь он точно будет знать, что ставка — 15, и именно 15%.
Когда я зарегистрировался на хакатоне (разумеется, не после небольшой процедуры валидации навыков, чтобы узнать, а мог бы я вообще участвовать. Оказалось, что мог), я сразу же улетел в групповой ТГ-чат искать участников. По правилам хакатона, можно было в команду принимать от 2 до 4 людей. Не нашли? Вам автоматически выберут команду по рулетке. У меня не было желания работать с теми, кого я не знаю (и чей стек мог бы мне просто не подойти), поэтому я создал свою команду под названием RAGnarök.
Тогда всяко клеймивший себя бэкенд-разработчиком, соответствуя своему образу, я мобилизовал к себе в команду фронтендера (он заявлял, что могёт в React, Vue, ТГ-ботов и обучение LM) и ML-инженера (учился в финтехе, тоже много делал на словах). Дело было 24 октября 2025, пока
Вот только эти двое оказались полнейшими тюфяками: после первой итерации ML не стал отвечать вообще. Дело продолжалось до 30 октября, пока я его не выкинул из команды после нескольких предупреждений.
Фронтендера же тоже пришлось выбрасывать, но уже в процессе разработки (и вообще не факт, что он бы нам понадобился: хакатон был по теме DS). Когда сам хакатон начался, он просто залег на дно и только булькал понемногу. Как бы я к нему в ЛС ни стучался, он просто читал и ничего не отвечал. Хоть бы сказал "я не умею". Никогда так не делайте, уважаемые читатели. Только команду подведете.
И все же, 28 октября в мою команду постучался единственный компетентный участник (называть его по имени без его согласия было бы настоящим свинством, поэтому пусть будет Комрад). Комраду 23 года, он работал в сфере DS при университете и по ходу дела баловался ML. Как и я, он был новичком в хакатонах, и надеялся на опыт и портфолио. Он давал мне рекомендации по всей теме, за что огромная ему благодарность. Даже если основную работу делал я, он все еще наставлял меня и помогал придумывать решения.
Только-только я получил ТЗ, я сразу его открыл. Суть в том, что нам выдавали следующие файлы:
train_data.csv — огромный файл на 5.7 МБ. Содержал в себе 350 финансовых статей и представлял с собой сам RAG. Организаторы гарантировали, что в нем есть ответы на все вопросы, просто в некоторых местах они скрываются в формулировках
questions.csv — файл с 500 вопросами, на которые LLM должна ответить, опираясь на данные из train_data
baseline.py — минимальный пример того, как подключить LLM
libraries.txt — разрешенные библиотеки (повторяюсь, хакатон был по DS, и чтобы избежать ляпов при проверке, в этом файле были зафиксированы библиотеки среды выполнения организаторов, и их версии. Что до Python, то на нем была версия 3.12)
Самой же целью хакатона было написать скрипт для RAG-ядра, помогающего LLM отвечать на 500 вопросов из questions.csv, и сохранять ответы в submission.csv.
LLM же нам предоставляли по API ($3 кредитов на день с 1 по 7 ноября, $5 8 и 9 ноября, а в последний день нам увеличили квоту до $7), как и эмбеддеры ($1 кредитов — с 4 ноября нам разрешили подключить еще и реранкер Qwen-4B-Reranker, деля с эмбеддером квоту). Сам же список LLM:
mistral-small-3.2-24b-instruct
llama-3-70b-instruct
grok-3-mini
gemma-3-27b-it
И нам реально нужны были квоты: мы были вынуждены прогонять LLM по кругу каждый день по несколько раз. Видите ли, с 3 ноября нам разрешили по 5 раз в день сдавать решение (чем развернутее и качественнее LLM ответила, тем лучше), а судил нас не человек, а LLM. В решение должны были входить:
main.py — точка входа
submission.csv — конечные результаты
Перед самими прогонами я решил испытать те 4 LLM, и исследование показало такие результаты:
Mistral показал себя с идеальной стороны, понимая российский рынок (мой выбор)
Llama оказалась для меня дороговатой
Grok был тоже дорогим, но еще и самовольным
Gemma был заточен больше под IT, нежели под финансы
Переварив ТЗ и результаты всех своих исследований, мы принялись кодить. Сначала мы построили минимальнейший из алгоритмов. Скажу сразу: он работал и получал ответы, но так, что за него мне было стыдно (хотя, на первый-то день разработки...), не хочу об этом тут рассказывать. Позже я решил подключить легковесную векторную БД FAISS для улучшения отбора. Провозился с ней очень долго (день или два), но зато под конец стало получше.
Хотя в итоге она и стала почти неиспользуемой фичей — после подключения реранкера Комрад скинул мне код алгоритма BM25 (Best-Match25, алгоритм лексического поиска из 90-ых, который в основном используется в поисковиках по типу Google), который оказался бесплатным и к тому же более совместимым с реранкером при правильной настройке. Сам же алгоритм работал так, что он отбирал top_k*3 релевантных документов, чтобы реранкер откинул ⅔ из них, оставив top_k документов для LLM. Сама же FAISS была оставлена на случай, если BM25 каким-то чудом не справится.
Сама же архитектура выглядит примерно так:
|
Вопрос |
|
Эмбеддер |
|
FAISS/BM25 |
|
Реранкер |
|
LLM |
|
Ответ |
(Я создавал эту статью на телефоне, и пока я пытался описать архитектуру с помощью таблицы, у меня глюкнул элемент, я не смог его удалить, поэтому я сделал так. Если кто-то пишет с телефона и знает, как удалить такую таблицу, подскажите, пожалуйста.)
9 ноября ко мне в ЛС постучался Комрад и сказал, что мы все это время отсылали решения не так. Помните состав отправочных файлов на верификацию (main.py + submission.csv)? У нас было все разбито на модули (main.py + embedding_service.py + rag_core.py + full_text_search.py — BM25 + submission.csv). И вообще мы скидывали .rar-файлы, а надо было .zip-файлы. Пришлось, скрипя зубами, склеивать это все в единый монолит. А ведь я был за это ответственным.
Несмотря на то, что наша команда проигрывала по численности (2 человека против большинства команд по 3-4 человека: команд всего было 354, а участников было около 1140), компетенции (Комрад из всего кода написал только один модуль, а я только учился, да и вообще в основном вайбкодил, пока против нас стояли в основном джуны+/миддлы), и технической осведомленности (см. Лажа)...
...мы все равно по качеству настройки вознеслись на 37 место в отборочном из 354 команд. Рейтинг качества ответов у нас был 9.53 (у 1 места, для сравнения, был 27.12). Мы буквально оставили позади около тысячи человек!
Признаться, я был в таком шоке от результата, что мне пришлось подбирать челюсть с пола. Причем, как только я отошел от шока, организаторы ещё анонсировали топу-50 команд из отборочных праздник в московском баре. Мне пришло приглашение на почту, я глазки потупил от удивления, но все же не поехал (денег на дорогу не было, да и дается мне, что тащиться из деревеньки Смоленской области в Москву ради одного праздника на один день удовольствие ниже среднего).
Текст письма выглядел примерно так:
И все же, я примерно догадываюсь, почему так много команд отсеяли. В чате команд было довольно много слепых вайбкодеров, обсуждавших, с какой LLM лучше работать (Claude, ChatGPT). Я же, пусть сам этим промышлял, все же параллельно с этим рыскал по интернету и собирал знания. Для написания кода же использовал DeepSeek v3.1 (не самый лучший выбор, но зато бесплатно). В общем, не стоит лезть в это дело, если вы считаете, что ИИ все сделает за вас. Это ускоритель, а не замена. Так было, так есть, и так будет.
Мне очень понравился этот хакатон. Пусть даже организаторы оттягивали сроки окончания отборочных (с 7 числа перенесли на 10), LLM-судья барахлил, а выдача сертификатов затянулась чуть ли не на добрый месяц, это был незабываемый опыт. Теперь у меня есть кейс в портфолио, контакт Комрада, и жгучее желание пойти в ИИ-инжиниринг. Мне даже страшно представить, сколько денег вбахали организаторы на хакатон, дабы его провести (от подсчета одних только кредитов всем командам отборочных на 10 дней мне уже стало плохо — да, я люблю считать чужие деньги). Хотя, раз уж организатором был Райффайзенбанк, я не удивлен. Но компетенции их организаторов я бы влепил четверочку (из ста).
На этой ноте хотел бы с вами попрощаться до следующей статьи. Желаю, чтобы скрипты не давали сбоев, и чтобы код компилировался с первого раза (если вы предпочитаете компилируемые ЯП). Всего хорошего!
(Уважаемые хабровчане, пожалуйста, скажите, что вам понравилось в этой статье. Я здесь новенький, поэтому экспериментирую со стилями написания. Я выливаю в статьи душу, мне искренне нравится рассказывать про это. Буду признателен за фидбэк.)
Источник


