All streams
Search
Write a publication
Pull to refresh
39
0
Борис Николаев @devmark

Backend developer

Send message

с вавилонской башней всё плохо кончилось как раз потому, что тогда у строителей не оказалось переводчиков)

Согласен. Но mvp без правильного маркетинга и раньше было обречено на провал.

Ревьюить будет разработчик. Пока что ещё рано из этой цепочки исключать человека, ведь только он знает, что именно нужно делать. А разработчик ещё примерно понимает, как это сделать.

Вообще защита чувствительных данных - это немного другое. MCP - это по сути универсальный протокол интеграции.

Если взять конкретно ваш пример, чтобы напоминания не создавались другому пользователю - это легко обеспечить. Достаточно передавать в метод идентификатор пользователя (чем более сложный, тем лучше). Например, uid. LLM не сможет "выдумать" такой uid. Она должна будет его как-то получить или запросить. А если попытается передать какой-то левый - MCP-сервер просто вернёт ошибку и напоминание не создаст.

Да, порядок в явном виде никак не определяется и отдаётся на откуп модели. Всегда когда мы работаем с LLM, то оперируем некоторой вероятностью. Если тулы будут иметь похожие описания, тогда да, велика вероятность вызова не того метода.

Поэтому я ещё раз хочу подчеркнуть, что описания инструментов MCP - чуть ли не самое главное, на что нужно сделать упор.

Но если описания более-менее подробные, то и 1000 вызовов будут выполнены корректно.

Кстати, сейчас подумал, что если нужно обеспечить 100% последовательность, то можно создать некий прокси MCP-метод, внутри которого этот порядок будет зашит. Тогда и контекст уменьшим. Эдакий паттерн "Фасад" в нейросетях)

50-100 тысяч документов в час... тут явно ведь не про базу знаний речь идёт?)

Проверка быстродействия RAG на объёмах 50-100 тысяч документов - эта тема заслуживает отдельной статьи! Но мне кажется если мы говорим в основном про поиск документов, то RAG действительно не самое оптимальное и далеко не дешёвое решение.

Вы верно подметили про RAG и чат-ботов, потому что порой интересно даже не поиск информации "как есть" в документе, а вывод из существующей информации новых фактов.

Например, где-то среди тысяч документов в описании конкретного процесса всего 1 раз упоминается, что "... согласованием занимается Иванов (начальник отдела документооборота)...", чат-бот нам сможет ответить и кто такой Иванов (в контексте именно данной компании), и кто является начальником отдела документооборота.

В данной статье я делал упор не столько на вопросы производительности и выбор наиболее быстрого векторного хранилища, сколько на то, что Spring AI позволяет нам уже здесь и сейчас с минимальным количеством кода использовать RAG. Поэтому взял pgVector, т.к. большинство проектов на Spring-стеке использует postgres.

Касательно того, что документ может не влезть в контекст, в Spring AI есть такой класс как TokenTextSplitter. Он позволяет разбивать исходный документ на несколько частей. Параметры такого разбиения можно гибко настраивать.

А вы какое векторное хранилище предпочитаете использовать?

Microsoft исторически всегда пытается свои стандарты сделать стандартами индустрии. Иногда ей это удаётся. Иногда - не очень. Захотели свою Java - сделали C#. Захотели свой Flash - сделали Silverlight. Ещё сходу вспоминается обратный слеш в пути до файлов, /r/n вместо /n для перевода строк и кодировка 1251)

"Microsoft" и "стандарт" в одном предложении?)

👋 Привет! Хочу поделиться своим pet-проектом для изучения английского — https://wordcards.ru

Это онлайн-словарь для запоминания слов методом интервальных повторений. Добавлять слова для изучения можно либо через поиск на странице конкретного слова, либо через тематические наборы слов https://wordcards.ru/wordsets. Есть возможность указывать конкретную часть речи при добавлении (например "orange" можно изучать или как существительное "апельсин", или как прилагательное "оранжевый"). Затем сервис автоматически будет напоминать о необходимости повторить то или иное слово.

Помимо обучающей функции есть также утилита для подбора слов по буквам или по шаблону (для игр типа Wordle) - https://wordcards.ru/wordle

Проект полностью некоммерческий и без рекламы, но буду рад, если окажется полезным и для кого-то ещё 😊

Если вы имеете в виду форматирование исходного кода, то тут как будто нам скорость вообще не критична, ведь это не в райнтайме происходит. Да и если такое форматирование является постоянной практикой (например, перед каждым коммитом), то форматировать нужно будет не 200+ файлов, а намного меньше (ровно тот код, который изменился).

А можете привести примеры, каких инструментов не хватает в Java? В чём именно она отстаёт в плане работы с кодом? Линтеры и форматтеры то везде есть. Да и IntelliJ IDEA, на мой взгляд, одна из лучших IDE, которую я когда-либо встречал.

То, что хотели избавиться от ломбока - это похвально)

Концептуально что record, что data-классы разрабатывались как неизменяемые (т.е. без сеттеров) сущности для хранения данных. Использование var в data-классах - это не совсем в духе котлина. Поэтому если нет каких-то явных технических ограничений (типа Spring Data JPA), рассмотрите возможность ухода от сеттеров в сторону неизменяемых объектов. У таких объектов есть множество преимуществ.

Если вы используете котлин только для dto, а всё остальное пишете на Java, наверное, логичнее использовать record-классы.

Хочу ещё дополнить, что null safety в полной мере работает только для кода, написанного на котлине. Если же у вас интероп между котлином и джавой, тут надо быть аккуратнее, иначе ошибка произойдёт в точке вызова java-кода. Но сама возможность сказать, что "в данном коде не может быть NPE" - это очень круто!

Пустая строка из вашего примера не то же самое, что null, т.к. на пустой строке мы можем спокойно вызывать любой метод из класса String. Тогда как попытка вызова такого метода на переменной, содержащей null, тут же приведёт к NPE. Разница вроде на первый взгляд небольшая, но значительная. Поэтому да, null safety в Kotlin спасает, и ещё как)

Я вам даже больше скажу, иногда хочется разделять строки на подтипы, чтобы не перепутать их при передаче в метод, где несколько параметров и все - строки. Например, строка-логин, строка-пароль, строка-email и т.п. Хотя технически всё это строки. В Kotlin есть решение и для этого - value class.

Как правило, если мы используем стандартные компоненты Spring Boot и что-то не работает, не подавая виду, то там либо сразу выдаётся ошибка (а подчас ещё и решение предлагается прямо в логах), либо мы просто не повесили где-то аннотацию или не добавили какой-то параметр в конфиг.

Что касается бюрократии, то от этого никуда не уйти в сколь-нибудь крупных проектах и командах. Иначе проект очень быстро превращается в зоопарк, который сложно поддерживать. Ценность тут заключается в снижении стоимости разработки: все пишут более-менее одинаково и не начинают очередной холивар на ревью.

По поводу непредсказуемости Java не соглашусь с вами.

В Java всегда можно посмотреть, например, полный стектрейс и найти, в чём именно ошибка. А несовместимость версий в рантайме выясняется легко при первом запуске. Особенно если мы пишем на фреймворке типа Spring.

Что касается написания методов в разном стиле: с точки зрения производительности и бизнес-логики как будто разницы нет, но ведь каждый разработчик, при очередных правках в этом участке кода, будет стараться переписать его в своём стиле. Может даже и неосознанно. Что приводит к повышению вероятности ошибок и усложняет ревью. А ценности для конечного пользователя мы тут не привносим никакой.

Справедливое замечание. Однако если у нас есть id сабтаски и пользователь меняет её статус, то в данном примере мы ему доверяем. Поэтому достаточно просто проверить наличие сабтаски. А привязку к таске (т.е. что сабтаска не сама по себе) может гарантировать foreign key на уровне БД.

Поэтому такой маппинг с использованием taskId я сделал скорее для единообразия API, нежели из практической необходимости.

Information

Rating
6,303-rd
Location
Москва, Москва и Московская обл., Россия
Works in
Registered
Activity