Иногда кажется, что если попросить какую-то LLM модель проверить информацию, указав при этом, что получил ее от другой модели - она это делает с какой-то особой тщательностью)))
Скорее всего кажется - как проекция взаимоотношений создателей на их модели. Я про OpenAI, Claude, Grok и Gemini.
Но в любом случае это отличный быстрый способ проверки информации из LLM.
И тут хорош Perplexity, т.к. там все перечисленные модели есть.
#ai
Скорее всего кажется - как проекция взаимоотношений создателей на их модели. Я про OpenAI, Claude, Grok и Gemini.
Но в любом случае это отличный быстрый способ проверки информации из LLM.
И тут хорош Perplexity, т.к. там все перечисленные модели есть.
#ai
Как AI интегрируется в существующие программные продукты?
Пример.
Есть такое понятие как API шлюз - прокси, позволяющий согласовать API из разных источников, навесить туда аутентификацию и авторизацию, rate limiting, мониторинг и некоторые другие функции.
Один из самых известных open source шлюзов - Kong Gateway.
Где тут AI?
А вот https://developer.konghq.com/plugins/?category=ai
Что можно навесить на шлюз:
1) AI Proxy - API разных LLM моделей отличается, поэтому актуальной является конвертация API. Если быть точным: на вход OpenAI API, на выходе - другие модели.
Вот список https://developer.konghq.com/plugins/?category=ai
Почему на входе OpenAI формат думаю понятно, так работает большинство AI Proxy.
2) AI Prompt Decorator - добавляет текст в начало и конец промта. Область применения видится для случаев, когда есть некий AI чат-клиент и недостаточно функционала для AI агента (сервера).
Тогда данный компонент может сформировать системный промт или обогатить промт историей.
Еще важный момент - текст в начале и в конце промта (который мы добавляем таким образом) имеет больший вес для модели.
3) AI Request Transformer\AI Response Transformer - обогащение\преобразование промта с использованием ИИшки.
Например, добавить страну к каждому городу в промте.
Тут конечно важен вопрос скорости, прокси не должен тормозить запрос
4) AI Prompt Guard - ограничение доступных запросов по regexp. Не 100% гарантия, но зато быстро.
5) AI Prompt Template - создаем набор типовых запросов к модели, от клиента просим только заполнить {{параметры}}
Есть еще опции, требующие лицензии, среди них я бы отметил:
1) AI LLM as Judge - валидацию ответа LLM другой моделью из коробки
2) AI MCP Proxy - преобразование протокола MCP в HTTP или объединение нескольких MCP серверов в один + возможность навесить на MCP запрос все фичи API шлюза - аутентификацию, rate limiting, мониторинг. Видится полезным для быстрого подключения существующих сервисов компании как тулов для AI агента.
3) AI Prompt Compressor - сжатие пользовательского промта. Цель - снижение стоимости. Интересно, но обязательно надо тестировать качество получаемых ответов.
4) AI Semantic Cache - кэшируем в векторной БД ответы LLM опять же для снижения стоимости
Выводы.
- все вышеперечисленные плагины можно рассматривать как AI паттерны, которые можно реализовать или на отдельном шлюзе, или внутри сервиса
- AI-шка внедряется в традиционные стеки
#ai
Пример.
Есть такое понятие как API шлюз - прокси, позволяющий согласовать API из разных источников, навесить туда аутентификацию и авторизацию, rate limiting, мониторинг и некоторые другие функции.
Один из самых известных open source шлюзов - Kong Gateway.
Где тут AI?
А вот https://developer.konghq.com/plugins/?category=ai
Что можно навесить на шлюз:
1) AI Proxy - API разных LLM моделей отличается, поэтому актуальной является конвертация API. Если быть точным: на вход OpenAI API, на выходе - другие модели.
Вот список https://developer.konghq.com/plugins/?category=ai
Почему на входе OpenAI формат думаю понятно, так работает большинство AI Proxy.
2) AI Prompt Decorator - добавляет текст в начало и конец промта. Область применения видится для случаев, когда есть некий AI чат-клиент и недостаточно функционала для AI агента (сервера).
Тогда данный компонент может сформировать системный промт или обогатить промт историей.
Еще важный момент - текст в начале и в конце промта (который мы добавляем таким образом) имеет больший вес для модели.
3) AI Request Transformer\AI Response Transformer - обогащение\преобразование промта с использованием ИИшки.
Например, добавить страну к каждому городу в промте.
Тут конечно важен вопрос скорости, прокси не должен тормозить запрос
4) AI Prompt Guard - ограничение доступных запросов по regexp. Не 100% гарантия, но зато быстро.
5) AI Prompt Template - создаем набор типовых запросов к модели, от клиента просим только заполнить {{параметры}}
Есть еще опции, требующие лицензии, среди них я бы отметил:
1) AI LLM as Judge - валидацию ответа LLM другой моделью из коробки
2) AI MCP Proxy - преобразование протокола MCP в HTTP или объединение нескольких MCP серверов в один + возможность навесить на MCP запрос все фичи API шлюза - аутентификацию, rate limiting, мониторинг. Видится полезным для быстрого подключения существующих сервисов компании как тулов для AI агента.
3) AI Prompt Compressor - сжатие пользовательского промта. Цель - снижение стоимости. Интересно, но обязательно надо тестировать качество получаемых ответов.
4) AI Semantic Cache - кэшируем в векторной БД ответы LLM опять же для снижения стоимости
Выводы.
- все вышеперечисленные плагины можно рассматривать как AI паттерны, которые можно реализовать или на отдельном шлюзе, или внутри сервиса
- AI-шка внедряется в традиционные стеки
#ai
Kong Docs
Kong Plugin Hub | Kong Docs
Extend Kong Gateway and Kong Konnect with powerful plugins and easy integrations.
Магические 80% покрытия кода тестами.
Часто возникает вопрос - почему 80?
Краткий ответ - почему бы и нет)
А если серьезно: оценка может быть числовой (процент покрытия) или бинарной (достаточно или нет).
Бинарная плоха тем, что не документирована и зависит от мнения эксперта. Это может привести к проблемам на код-ревью.
А тут умные люди из SonarQube придумали метрику покрытия https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition#coverage
и дали её рекомендуемое значение. И это не 100%, т.е. запас есть.
Считаю, что от этой рекомендации стоит отталкиваться.
К тому же JaCoCo, обычно используемый для расчета покрытия, позволяет гибко настраивать сам процесс.
Следующий вопрос, который может возникнуть: "Почему ради достижения 80% я должен писать тесты на элементарный код?" Я про getter, setter и все, все, все https://t.me/javaKotlinDevOps/34
Ответ: "Нет, не нужны эти тесты".
Лишний код можно исключить из покрытия:
1) generated код исключается по умолчанию начиная с JaCoCo 0.8.2
2) generated код Lombok - через lombok.addLombokGeneratedAnnotation = true (жаль, что только для Lombok это можно сделать, но есть еще альтернатива - см. следующий абзац.)
3) тривиальный код - явно исключая классы или пакеты по маске через настройки JaCoCo. Если какой-то код не получается исключить таким образом - это повод задуматься о рефакторинге.
Еще вопрос: "Зачем писать модульные (unit) тесты ради покрытия на интеграционный код: сервисные классы или классы контроллеров, которые представляют линейную цепочку вызовов методов?"
Ответ: "Не обязательно писать unit тесты".
Для простых микросервисов является нормальной перевернутая пирамида тестирования - когда интеграционных тестов разработки больше, чем модульных.
Простой код можно покрыть интеграционными тестами, включив их в общее покрытие. JaCoCo позволяет это настроить. Единственная проблема может быть, если тесты находятся в одном модуле, а код для покрытия - в другом, но и она решается.
И тут может возникнуть самый главный вопрос - а это не читерство? Чем это лучше отсутствия цели по покрытию?
Ответ: лучше тем, что мы четко задаем - вот это код не нужно покрывать тестами, а остальной - нужно.
И смотря на паттерны исключения - на их состав и количество - можно их быстро оценить и при необходимости скорректировать.
Ну и если ничего не помогло - тогда уже стоит задуматься о новом Quality Gate в SonarQube с меньшим процентом покрытия.
Никакой магии нет - https://t.me/javaKotlinDevOps/403.
Но числовой показатель (80% по умолчанию), задокументированные исключения и цель покрыть максимум кода, в котором возможны ошибки, быть должны.
P.S. Еще AI можно попросить тесты написать, у него это неплохо получается)
#unittests #integration_tests #java
Часто возникает вопрос - почему 80?
Краткий ответ - почему бы и нет)
А если серьезно: оценка может быть числовой (процент покрытия) или бинарной (достаточно или нет).
Бинарная плоха тем, что не документирована и зависит от мнения эксперта. Это может привести к проблемам на код-ревью.
А тут умные люди из SonarQube придумали метрику покрытия https://docs.sonarsource.com/sonarqube-server/user-guide/code-metrics/metrics-definition#coverage
и дали её рекомендуемое значение. И это не 100%, т.е. запас есть.
Считаю, что от этой рекомендации стоит отталкиваться.
К тому же JaCoCo, обычно используемый для расчета покрытия, позволяет гибко настраивать сам процесс.
Следующий вопрос, который может возникнуть: "Почему ради достижения 80% я должен писать тесты на элементарный код?" Я про getter, setter и все, все, все https://t.me/javaKotlinDevOps/34
Ответ: "Нет, не нужны эти тесты".
Лишний код можно исключить из покрытия:
1) generated код исключается по умолчанию начиная с JaCoCo 0.8.2
2) generated код Lombok - через lombok.addLombokGeneratedAnnotation = true (жаль, что только для Lombok это можно сделать, но есть еще альтернатива - см. следующий абзац.)
3) тривиальный код - явно исключая классы или пакеты по маске через настройки JaCoCo. Если какой-то код не получается исключить таким образом - это повод задуматься о рефакторинге.
Еще вопрос: "Зачем писать модульные (unit) тесты ради покрытия на интеграционный код: сервисные классы или классы контроллеров, которые представляют линейную цепочку вызовов методов?"
Ответ: "Не обязательно писать unit тесты".
Для простых микросервисов является нормальной перевернутая пирамида тестирования - когда интеграционных тестов разработки больше, чем модульных.
Простой код можно покрыть интеграционными тестами, включив их в общее покрытие. JaCoCo позволяет это настроить. Единственная проблема может быть, если тесты находятся в одном модуле, а код для покрытия - в другом, но и она решается.
И тут может возникнуть самый главный вопрос - а это не читерство? Чем это лучше отсутствия цели по покрытию?
Ответ: лучше тем, что мы четко задаем - вот это код не нужно покрывать тестами, а остальной - нужно.
И смотря на паттерны исключения - на их состав и количество - можно их быстро оценить и при необходимости скорректировать.
Ну и если ничего не помогло - тогда уже стоит задуматься о новом Quality Gate в SonarQube с меньшим процентом покрытия.
Никакой магии нет - https://t.me/javaKotlinDevOps/403.
Но числовой показатель (80% по умолчанию), задокументированные исключения и цель покрыть максимум кода, в котором возможны ошибки, быть должны.
P.S. Еще AI можно попросить тесты написать, у него это неплохо получается)
#unittests #integration_tests #java
Sonarsource
Understanding measures and metrics | SonarQube Server | Sonar Documentation
Measures and metrics used in SonarQube to evaluate your code.
Что такое Agile для разработчика?
Возьмем SCRUM, как наиболее типичный его вариант.
IMHO конечно.
Это не церемонии - Daily, планирование, ретро, демо.
Не наличие Scrum мастера в команде.
Это красивый burn-down chart и velocity.
Не poker planing и оценка в story point.
Не работа с досками.
И даже не работающий инкремент каждую неделю.
База - это две вещи:
1) навык декомпозиции задач.
Который приводит к небольшим инкрементам.
А конечные цели:
- минимум зависимостей от других
- маленькие PR = быстрое ревью и вливание
- инкрементная интеграция кода = возможность вливания в целевую ветку и отправку на тестирование без ожидания других доработок.
2) точность оценки задач.
Не важно в чем - в story point, человеко-днях или в конкретных датах.
Оценка, кстати, зависит от декомпозиции, т.к. мелкие задачи можно оценить точнее, а потом оценки просуммировать.
Конечная цель - совпадение прогнозируемых сроков с реальными.
В данном случае речь про сроки этапа разработки, за соблюдение сроков интеграции со смежниками отвечает PO, DL и команда в целом.
Не всегда эти цели достижимы на 100%, но ставить их нужно. Если их себе ставить, то навык рано или поздно появится.
И традиционные ответы на не заданные вопросы)
Вопрос: "А разве это не навыки сеньоров?"
Ответ: когда-то возможно да, но с учетом последних тенденций (не могу не вставить AI в пост) кажется всем надо повышать уровень "сеньорности".
#agile
Возьмем SCRUM, как наиболее типичный его вариант.
IMHO конечно.
Это не церемонии - Daily, планирование, ретро, демо.
Не наличие Scrum мастера в команде.
Это красивый burn-down chart и velocity.
Не poker planing и оценка в story point.
Не работа с досками.
И даже не работающий инкремент каждую неделю.
База - это две вещи:
1) навык декомпозиции задач.
Который приводит к небольшим инкрементам.
А конечные цели:
- минимум зависимостей от других
- маленькие PR = быстрое ревью и вливание
- инкрементная интеграция кода = возможность вливания в целевую ветку и отправку на тестирование без ожидания других доработок.
2) точность оценки задач.
Не важно в чем - в story point, человеко-днях или в конкретных датах.
Оценка, кстати, зависит от декомпозиции, т.к. мелкие задачи можно оценить точнее, а потом оценки просуммировать.
Конечная цель - совпадение прогнозируемых сроков с реальными.
В данном случае речь про сроки этапа разработки, за соблюдение сроков интеграции со смежниками отвечает PO, DL и команда в целом.
Не всегда эти цели достижимы на 100%, но ставить их нужно. Если их себе ставить, то навык рано или поздно появится.
И традиционные ответы на не заданные вопросы)
Вопрос: "А разве это не навыки сеньоров?"
Ответ: когда-то возможно да, но с учетом последних тенденций (не могу не вставить AI в пост) кажется всем надо повышать уровень "сеньорности".
#agile
👍3
Почему победил компактный стиль форматирования кода?
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
vs
Базовый ответ - потому что он компактнее)
Но я бы накинул еще один аргумент. Рассуждение:
- стиль форматирования нужен человеку, и не нужен машине
- человеку важно понимать, где начало и конец логического блока кода или управляющей конструкции
- "железобетонный" способ это понять - четкие маркеры, хороший пример: begin-end в Delphi, If-End If в VB
- хороший, но не идеальный, т.к. слишком много символов - 8 вместо минимально возможных 2
- скобки на той же строке, что и управляющая конструкция, у Google\Sun - это по сути компактная эмуляция begin-end. Эмуляция потому что они не обязательны. Скобки как бы становятся частью управляющей конструкции - if, for, while, switch, try.
- а вот альтернативный вариант - это что-то странное, т.к. скобки по отступам находятся на уровне управляющей конструкции, но зачем тогда перенос на новую строку?
Тогда логичнее вот так:
Но это еще страннее смотрится.
Ну и напоследок каких целей должно достичь хорошее форматирование кода:
1) разделение логических блоков кода: пробелы, отступы, скобки
2) единообразие
3) улучшение читаемости
4) облегчение правок - возможность быстро понять, какой блок кода нужно перенести или удалить целиком
5) компактность. Причем как раз компактность с увеличением размера монитора становится менее
важна
P.S. Спонсор выпуска - Совершенный код, Стив Макконнелл)
#java #formating
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
public class OrderService {
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority) {
if (order == null) {
...vs
public class OrderService
{
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority)
{
if (order == null)
{
...
Базовый ответ - потому что он компактнее)
Но я бы накинул еще один аргумент. Рассуждение:
- стиль форматирования нужен человеку, и не нужен машине
- человеку важно понимать, где начало и конец логического блока кода или управляющей конструкции
- "железобетонный" способ это понять - четкие маркеры, хороший пример: begin-end в Delphi, If-End If в VB
- хороший, но не идеальный, т.к. слишком много символов - 8 вместо минимально возможных 2
- скобки на той же строке, что и управляющая конструкция, у Google\Sun - это по сути компактная эмуляция begin-end. Эмуляция потому что они не обязательны. Скобки как бы становятся частью управляющей конструкции - if, for, while, switch, try.
- а вот альтернативный вариант - это что-то странное, т.к. скобки по отступам находятся на уровне управляющей конструкции, но зачем тогда перенос на новую строку?
Тогда логичнее вот так:
public class OrderService
{
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority)
{
if (order == null)
{
...
Но это еще страннее смотрится.
Ну и напоследок каких целей должно достичь хорошее форматирование кода:
1) разделение логических блоков кода: пробелы, отступы, скобки
2) единообразие
3) улучшение читаемости
4) облегчение правок - возможность быстро понять, какой блок кода нужно перенести или удалить целиком
5) компактность. Причем как раз компактность с увеличением размера монитора становится менее
важна
P.S. Спонсор выпуска - Совершенный код, Стив Макконнелл)
#java #formating
👍1
Почему LLM может писать хороший код, но плохо генерит JSON?
Может и плохой код писать, к слову, зависит от модели и задачи)
Я уже писал о том, что генерация JSON - не конёк LLM https://t.me/javaKotlinDevOps/484
Сейчас попробую расписать почему.
Возьмем ситуацию до появления паттерна structured output. LLM отвечает текстом, если нам нужно вызвать тулу и передать туда определенный набор параметров - можно описать этот набор JSON схемой.
JSON схема как валидатор объекта параметров.
Получался примерно такой запрос к модели на формирование вызова тулы:
Здесь две проблемы.
1) модель конечно знает что такое JSON, но она генерирует токены, а не текст по формату.
2) у агента\чата есть задача уменьшить контекст, поэтому даже если ему дать полную схему с minimum, minimum, pattern, minItems - он ее может порезать (и режет) для оптимизации.
Поэтому модель могла вернуть и некорректный по структуре JSON, и проигнорировать ряд атрибутов схемы. Первое реже, второе - всегда.
Когда появился structured json - модель же гарантирует корректность возвращаемого JSON (JSON = возвращаемый объект) проблема казалось бы должна уйти в прошлое?
В модель летит такой запрос:
Тут даже "additionalProperties": false есть. И required само собой. И это все даже работает)
Но в целом гарантии точному соответствию схеме нет.
Как в большинстве моделей реализуется structured output?
Схема превращается в набор т.наз. грамматик.
Например
превратится в что-то такое:
А далее по этим грамматикам строится state machine.
И при генерации очередного токена во внимание принимается не только его вероятность (как при обычном выводе), но и идет проверка на разрешенное состояние по этой state machine.
И если не разрешено - выбираем следующий.
Процесс называется constrained decoding, вот пример библиотеки, его реализующей: https://xgrammar.mlc.ai/
И я бы из ее описания обратил внимание на фразу:
Может и плохой код писать, к слову, зависит от модели и задачи)
Я уже писал о том, что генерация JSON - не конёк LLM https://t.me/javaKotlinDevOps/484
Сейчас попробую расписать почему.
Возьмем ситуацию до появления паттерна structured output. LLM отвечает текстом, если нам нужно вызвать тулу и передать туда определенный набор параметров - можно описать этот набор JSON схемой.
JSON схема как валидатор объекта параметров.
Получался примерно такой запрос к модели на формирование вызова тулы:
{
"model": "gpt-4o-mini",
"messages": [
{
"role": "user",
"content": "Создай заказ: 2 товара по цене 10"
}
],
"tools": [
{
"type": "function",
"function": {
"name": "create_order",
"description": "Создание заказа",
"parameters": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"price": { "type": "number" },
"quantity": { "type": "integer" }
},
"required": ["price", "quantity"]
}
}
},
"required": ["items"]
}
}
}
]
}Здесь две проблемы.
1) модель конечно знает что такое JSON, но она генерирует токены, а не текст по формату.
2) у агента\чата есть задача уменьшить контекст, поэтому даже если ему дать полную схему с minimum, minimum, pattern, minItems - он ее может порезать (и режет) для оптимизации.
Поэтому модель могла вернуть и некорректный по структуре JSON, и проигнорировать ряд атрибутов схемы. Первое реже, второе - всегда.
Когда появился structured json - модель же гарантирует корректность возвращаемого JSON (JSON = возвращаемый объект) проблема казалось бы должна уйти в прошлое?
В модель летит такой запрос:
{
"model": "gpt-4.1",
"messages": [
{
"role": "user",
"content": "Создай заказ: 2 товара по цене 10"
}
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "order_response",
"schema": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"price": { "type": "number" },
"quantity": { "type": "integer" }
},
"required": ["price", "quantity"],
"additionalProperties": false
}
},
"total": {
"type": "number",
"description": "Общая стоимость"
}
},
"required": ["items", "total"],
"additionalProperties": false
},
"strict": true
}
}
}Тут даже "additionalProperties": false есть. И required само собой. И это все даже работает)
Но в целом гарантии точному соответствию схеме нет.
Как в большинстве моделей реализуется structured output?
Схема превращается в набор т.наз. грамматик.
Например
"type": "array",
"items": { "type": "integer" }
превратится в что-то такое:
[ INT (, INT)* ]
А далее по этим грамматикам строится state machine.
И при генерации очередного токена во внимание принимается не только его вероятность (как при обычном выводе), но и идет проверка на разрешенное состояние по этой state machine.
И если не разрешено - выбираем следующий.
Процесс называется constrained decoding, вот пример библиотеки, его реализующей: https://xgrammar.mlc.ai/
И я бы из ее описания обратил внимание на фразу:
aiming at bring flexible zero-overhead structure generation everywhere
zero-overhead. Т.е. при генерации state machine под схему из схемы снова выкидывается все лишнее, для скорости. А скорость ответа для LLM критична.
Т.е. constrained decoding работает не так строго, как обычный валидатор JSON Schema в Java или Python.
И minimum, maximum, pattern, format снова не работают.
Зато быстро. Но все равно чуть медленнее, чем без structured output, т.к. и дополнительная валидация появляется, и перебор вариантов.
В теории можно было бы взять open-source движок инференса и прикрутить туда нормальный JSON валидатор. Но подозреваю LLM станет отвечать очень медленно.
Как с этим бороться?
Все уже придумано, паттерн Retry.
Да, и structured output - это все равно шаг вперед. Модель не генерирует как бы json, есть валидатор, проверяющий ну скажем 80-90% схемы.
#ai #llm
Т.е. constrained decoding работает не так строго, как обычный валидатор JSON Schema в Java или Python.
И minimum, maximum, pattern, format снова не работают.
Зато быстро. Но все равно чуть медленнее, чем без structured output, т.к. и дополнительная валидация появляется, и перебор вариантов.
В теории можно было бы взять open-source движок инференса и прикрутить туда нормальный JSON валидатор. Но подозреваю LLM станет отвечать очень медленно.
Как с этим бороться?
Все уже придумано, паттерн Retry.
MAX_RETRIES = 3
def generate_order(user_input: str):
prompt = f"Сформируй заказ в JSON: {user_input}"
last_error = None
for attempt in range(MAX_RETRIES):
raw = call_llm(prompt)
try:
order = Order.model_validate_json(raw)
return order
except ValidationError as e:
last_error = str(e)
# repair prompt
prompt = f"""
Ты вернул невалидный JSON.
Ошибка:
{last_error}
Твой предыдущий ответ:
{raw}
Исправь JSON строго по схеме.
Верни только JSON, без комментариев.
"""
raise Exception(f"Не удалось получить валидный ответ: {last_error}")
Да, и structured output - это все равно шаг вперед. Модель не генерирует как бы json, есть валидатор, проверяющий ну скажем 80-90% схемы.
#ai #llm
Telegram
(java || kotlin) && devOps
LLM как серебряная пуля?
Конечно же нет.
А если серьезно - что не умеет LLM?
1) выдавать актуальную информацию. Фиксится подключением веб-поиска
2) выдавать 100% точные ответы. LLM вероятностна по своей природе, поэтому даже самая мощная модель с огромным…
Конечно же нет.
А если серьезно - что не умеет LLM?
1) выдавать актуальную информацию. Фиксится подключением веб-поиска
2) выдавать 100% точные ответы. LLM вероятностна по своей природе, поэтому даже самая мощная модель с огромным…
Кто же изобрел ноутбуки (Jupiter notebook)?
Ранее уже писал, что это питонисты, а точнее ML инженеры питонисты.
Выяснилось, что это не совсем так.
Дональд Кнут Грамотное программирование, 2001. Тот самый, что написал 3 тома Искусства программирования.
Собственно концепция грамотного программирования - это писать код для людей, а не для машин. Т.е. в формате рассказа, где главный - текст.
Т.е не
а скорее
А код - это переменная, которую можно переиспользовать.
При нужны соответствующие правила форматирования и движок для рендера всего это в удобочитаемый вид.
Кнут предлагал его всем разработчикам, взяли только дата сатанисты) Но с развитием AI может и пошире распространится)
Плюс понятен - читаемость. Минус - сложнее (дольше) писать. Мы же вообще уходим от документации к самодокументирующемуся кода. Но для сложного кода кажется смысл в нем есть.
#python #notebooks
Ранее уже писал, что это питонисты, а точнее ML инженеры питонисты.
Выяснилось, что это не совсем так.
Дональд Кнут Грамотное программирование, 2001. Тот самый, что написал 3 тома Искусства программирования.
Собственно концепция грамотного программирования - это писать код для людей, а не для машин. Т.е. в формате рассказа, где главный - текст.
Т.е не
// Используем метод сортировки пузырьком, суть которого...
// Декларация метода:
void boubleSort(int[] array) {
...
а скорее
Используем метод сортировки пузырьком, суть которого...
Декларация метода:
@sort_method =
void (int[] array) {
...
@
А код - это переменная, которую можно переиспользовать.
При нужны соответствующие правила форматирования и движок для рендера всего это в удобочитаемый вид.
Кнут предлагал его всем разработчикам, взяли только дата сатанисты) Но с развитием AI может и пошире распространится)
Плюс понятен - читаемость. Минус - сложнее (дольше) писать. Мы же вообще уходим от документации к самодокументирующемуся кода. Но для сложного кода кажется смысл в нем есть.
#python #notebooks
Еще о форматировании.
Может показаться, что форматирование уже не критично, ведь весь код скоро будет писать AI, а мы все переквалифицируемся в архитекторы)
Насколько скоро - отдельный холиварный вопрос. Но не буду отвлекаться.
1) Факт номер раз: модель код (текст) превращает в токены. Токен с пробелом, табом, скобкой или переводом строки и без него - это разные токены.
Факт номер два: форматирование должно подчеркивать логическую структуру кода https://t.me/javaKotlinDevOps/559.
Следовательно, единообразное форматирование улучшает понимание кода моделью.
2) модель генерирует код по аналогии. Код проекта имеет больший приоритет, чем код, на котором ее обучали. Следовательно, какое форматирование на входе, такое и на выходе.
Далее повторяем 1) и 2) для каждой новой фичи и в итоге получаем, что хорошее форматирование кода может повысить шансы на выживание сервиса после его рефакторинга AI-шкой.
Да и при ревью человеком AI кода хорошее форматирование сильно поможет. А код-ревью нужно, сейчас так точно. Если смотреть в будущее - как опция, для сложных участков кода.
Итого - как раз таки для LLM, в отличие от компилятора, форматирование кода важно.
И видится плюс: если код пишет AI - форматированием и читаемость кода должны становится лучше при условии хорошей базы.
Модели легче сгенерировать пару лишних токенов, чем человеку поставить нужное число пробелов или скобок.
#ai #formating
Может показаться, что форматирование уже не критично, ведь весь код скоро будет писать AI, а мы все переквалифицируемся в архитекторы)
Насколько скоро - отдельный холиварный вопрос. Но не буду отвлекаться.
1) Факт номер раз: модель код (текст) превращает в токены. Токен с пробелом, табом, скобкой или переводом строки и без него - это разные токены.
Факт номер два: форматирование должно подчеркивать логическую структуру кода https://t.me/javaKotlinDevOps/559.
Следовательно, единообразное форматирование улучшает понимание кода моделью.
2) модель генерирует код по аналогии. Код проекта имеет больший приоритет, чем код, на котором ее обучали. Следовательно, какое форматирование на входе, такое и на выходе.
Далее повторяем 1) и 2) для каждой новой фичи и в итоге получаем, что хорошее форматирование кода может повысить шансы на выживание сервиса после его рефакторинга AI-шкой.
Да и при ревью человеком AI кода хорошее форматирование сильно поможет. А код-ревью нужно, сейчас так точно. Если смотреть в будущее - как опция, для сложных участков кода.
Итого - как раз таки для LLM, в отличие от компилятора, форматирование кода важно.
И видится плюс: если код пишет AI - форматированием и читаемость кода должны становится лучше при условии хорошей базы.
Модели легче сгенерировать пару лишних токенов, чем человеку поставить нужное число пробелов или скобок.
#ai #formating
Telegram
(java || kotlin) && devOps
Почему победил компактный стиль форматирования кода?
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
public class OrderService {
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority) {
…
Я про сталь Oracle\Sun и очень похожий на него стиль Google:
public class OrderService {
private static final int MAX_RETRIES = 3;
public String processOrder(Order order, boolean isPriority) {
…
Что C++ унаследовал от Java?
Внимательный читатель должен сказать - стой, автор, ты ничего не перепутал? Может Java от C++?
Не перепутал)
Да, Java был создан как безопасная и легко портируемая альтернатива C++.
Но кое-что он вернул прародителю.
Как ни странно - это стандарт документирования кода. C++ изначально шел без стандарта документирования. Используйте что хотите. А JavaDoc с Java был изначально. По факту стандартной тулой для документации С++ стал Doxygen. А Doxigen взял за основу JavaDoc.
Такие дела)
#java #c++
Внимательный читатель должен сказать - стой, автор, ты ничего не перепутал? Может Java от C++?
Не перепутал)
Да, Java был создан как безопасная и легко портируемая альтернатива C++.
Но кое-что он вернул прародителю.
Такие дела)
#java #c++
Чем ещё может нам помочь AI?
Есть такая проблема - устаревание любой документации. Причина простая - код в большом числе случаев невозможно забыть исправить. Программа сломается, тесты сломаются. В худшем случае - ПРОМ сломается, но не будем о грустном)
А вот ошибка в документации никак себя не проявит, пока кто-то не начнёт эту документацию читать. И даже тогда ошибка может не бросаться в глаза, наоборот, ввести в заблуждение.
Как "заставить" разработчика всегда поддерживать актуальность документации?
Да никак.
Поэтому и стал популярным самодокументирующий код.
А вот AI как раз таки заставить можно. Одним промтом. Ещё один агент для мультиагентной системы. И опять же - в итоге тот же AI будет лучше понимать получившийся код.
#ai
Есть такая проблема - устаревание любой документации. Причина простая - код в большом числе случаев невозможно забыть исправить. Программа сломается, тесты сломаются. В худшем случае - ПРОМ сломается, но не будем о грустном)
А вот ошибка в документации никак себя не проявит, пока кто-то не начнёт эту документацию читать. И даже тогда ошибка может не бросаться в глаза, наоборот, ввести в заблуждение.
Как "заставить" разработчика всегда поддерживать актуальность документации?
Да никак.
Поэтому и стал популярным самодокументирующий код.
А вот AI как раз таки заставить можно. Одним промтом. Ещё один агент для мультиагентной системы. И опять же - в итоге тот же AI будет лучше понимать получившийся код.
#ai
Иногда лучше молчать, чем говорить - продолжение)
Я про auto complete в dev агентах в IDE, который не должен всегда выдавать хоть что-то. А должен выдавать что-то адекватное)
Чтд ... https://habr.com/ru/companies/tbank/articles/1012196/
Суть. Ребята из Т-банка сделали двойную фильтрацию подсказок с помощью LLM+ML с целью выбросить нерелевантные. И в итоге смогли сдвинуться с мертвой точки и улучшить процент принятых подсказок. Этот показатель у них вышел на плато и не двигался несколько лет.
Интересно, что им бизнес разрешил фильтровать не более 5% подсказок чтобы не ухудшить пользовательский опыт. Но даже в этом случае процент принятия увеличился на 5+%. И доверие к фиче, что более важно!
В статье достаточно много деталей реализации - кому интересно, почитайте.
P.S. Интересно, делают ли так другие агенты?)
P.P.S. часть первая https://t.me/javaKotlinDevOps/539
#ai #ai_agents
Я про auto complete в dev агентах в IDE, который не должен всегда выдавать хоть что-то. А должен выдавать что-то адекватное)
Чтд ... https://habr.com/ru/companies/tbank/articles/1012196/
Суть. Ребята из Т-банка сделали двойную фильтрацию подсказок с помощью LLM+ML с целью выбросить нерелевантные. И в итоге смогли сдвинуться с мертвой точки и улучшить процент принятых подсказок. Этот показатель у них вышел на плато и не двигался несколько лет.
Интересно, что им бизнес разрешил фильтровать не более 5% подсказок чтобы не ухудшить пользовательский опыт. Но даже в этом случае процент принятия увеличился на 5+%. И доверие к фиче, что более важно!
В статье достаточно много деталей реализации - кому интересно, почитайте.
P.S. Интересно, делают ли так другие агенты?)
P.P.S. часть первая https://t.me/javaKotlinDevOps/539
#ai #ai_agents
Хабр
AI Code Completion: как мы добавили умный фильтр и перестали показывать лишнее
Всем привет! На связи Александр и Артем — ML-инженеры из Т-Банка. Мы делаем copilot-инструмент для разработчиков. Статья будет не про агентов. Расскажем, как отрезали лишние и бесполезные подсказки в...
🔥1
Снова нападки на Scala)
Я уже немного писал про Scala когда говорил о выборе новых языков программирования https://t.me/javaKotlinDevOps/251
Но осталось чувство недосказанности. Сложный - да, о ведь функционально крутой. Может стоит набрать команду "спецназа" от разработки, пусть на Scala пишут ядро системы?
Я бы не стал. Сложность это полбеды. Сложность не там, где ей стоит быть - вот проблема.
Большиство предметных областей дают нам бизнесовую сложность. Если бы это было не так - вместо разработки стоило бы купить готовое решение. Или взять готовую библиотеку.
Сложность должна быть в бизнес-логике. А не в конструкциях языка.
Второй момент - основная задача разработчика (чего-то сложнее hello world) - борьба со сложностью. SOLID, DRY. переиспользование кода, микросервисы, уровни приложения, говорящие имена, читаемость кода, DDD, итеративная разработка... - все это помогает уменьшить сложность. А тут язык провоцирует ее увеличение.
И ещё пример. Google. Компания может позволить себе нанять наверное любого программиста. Популяризовать любой язык.
Но что она делает?
Видит проблему на backend.
C++ быстр, но не безопасен и сложен.
Java безопасная, попроще, но не идеал.
И придумывает Go: быстрый и простой. Ещё заточенный на многопоточность, но простую - goroutines.
Мобильная разработка - есть завязка на JDK. Почему так - тема отдельная. Базовый язык для JDK - Java, про Java см. выше. Тут появляется более простой Kotlin - и Google делает его стандартом Android разработки.
Итого - в обоих случаях Google сделал разработку проще. production подход. Хотя где-то у них используется Scala.
#java #kotlin #scala
Я уже немного писал про Scala когда говорил о выборе новых языков программирования https://t.me/javaKotlinDevOps/251
Но осталось чувство недосказанности. Сложный - да, о ведь функционально крутой. Может стоит набрать команду "спецназа" от разработки, пусть на Scala пишут ядро системы?
Я бы не стал. Сложность это полбеды. Сложность не там, где ей стоит быть - вот проблема.
Большиство предметных областей дают нам бизнесовую сложность. Если бы это было не так - вместо разработки стоило бы купить готовое решение. Или взять готовую библиотеку.
Сложность должна быть в бизнес-логике. А не в конструкциях языка.
Второй момент - основная задача разработчика (чего-то сложнее hello world) - борьба со сложностью. SOLID, DRY. переиспользование кода, микросервисы, уровни приложения, говорящие имена, читаемость кода, DDD, итеративная разработка... - все это помогает уменьшить сложность. А тут язык провоцирует ее увеличение.
И ещё пример. Google. Компания может позволить себе нанять наверное любого программиста. Популяризовать любой язык.
Но что она делает?
Видит проблему на backend.
C++ быстр, но не безопасен и сложен.
Java безопасная, попроще, но не идеал.
И придумывает Go: быстрый и простой. Ещё заточенный на многопоточность, но простую - goroutines.
Мобильная разработка - есть завязка на JDK. Почему так - тема отдельная. Базовый язык для JDK - Java, про Java см. выше. Тут появляется более простой Kotlin - и Google делает его стандартом Android разработки.
Итого - в обоих случаях Google сделал разработку проще. production подход. Хотя где-то у них используется Scala.
#java #kotlin #scala
Telegram
(java || kotlin) && devOps
Всем привет!
В развитие прошлого поста предлагаю поговорить про большие компании и новые языки программирования.
Вопросы, на который я постараюсь дать исчерпывающий ответ:
1) какие риски несет внедрение нового языка в enterprise?
2) нужно ли согласовывать…
В развитие прошлого поста предлагаю поговорить про большие компании и новые языки программирования.
Вопросы, на который я постараюсь дать исчерпывающий ответ:
1) какие риски несет внедрение нового языка в enterprise?
2) нужно ли согласовывать…
👍1
AI, везде AI)
Кажется назрел пост-глоссарий терминов. Сам иногда путаюсь)
ML модель - узкоспециализированная небольшая модель, как правило требующая обучения под конкретную задачу: классификация текстов, картинок или видео, определение тональности текста, преобразования Image\Audio в Text и обратно.
Существуют достаточно давно.
LLM - модель общего назначения, базово умеет продолжать текстовые фразы.
С конвертерами и тулами - принимать и генерировать любой контент, недостающие знания запрашивая из внешнего мира.
За универсальность приходится платить - LLM медленнее и требует более мощного железа.
промт - часть запроса к LLM. Почему часть? Как правило исходный запрос пользователя не попадает напрямую в LLM.
Исходный запрос - это пользовательский промт, а еще бывают системный и assistant.
Системный - это промт, "захардкоженный" внутри сервиса, взаимодействующего с LLM, и имеющий более высокий приоритет. Например, чата или агента.
assistant промт - прошлые ответы модели, добавленные в диалог.
tool - метод агента, имеющий четкое API и выполняющий некое действие\возвращающий некие данных.
Должен быть корректно описан, чтобы модель поняла зачем он нужен и вызывала его в случаях, когда сама не может выполнить какой-то запрос.
Как правило tool-ы встроенные, но иногда есть возможность создать пользовательские tool.
MCP - протокол клиент-сервер, позволяющий вынести tool-ы из агента.
Позволяет легко переиспользовать tool в разных агентах и разделить разработку логики агента и бизнесовых инструментов.
skill - навык агента. По сути более сложный tool, скорее сценарий, оркестрирующий вызовы нескольких тулов. Включает промт, документацию, схемы валидации, скрипты.
rule - правила работы, которые должны применяться при любом запросе к LLM.
RAG - статическая база знаний по узкой предметной области, содержащая данные, которых нет в LLM.
Контекст - набор данных, на основании которого LLM генерирует текст. В контекст имеет смысл включать:
а) промты
б) историю диалога и вызовов инструментов
в) полезные данные из RAG
г) список доступных tools, skills и MCP серверов
д) rules
Контекст привязан к клиентской сессии.
Контекстное окно - ограничение на размер контекста в сессии. Контекст хранится в памяти, память дорогая, приходится ограничивать. При достижении предела нужно принять два решения:
а) падать\ не падать (последнее - плавающее окно)
б) удалять \ сжимать старые данные.
Агент - сервис, с помощью AI способный самостоятельно понять и решить поставленную задачу.
В простейшем виде это бесконечный цикл вида:
а) ожидание входных данных
б) формирование данных, которые могут попасть в запрос к LLM
в) фильтрация этих данных
г) вызов LLM
д) получение дополнительных данных с помощью tool
е) валидация ответа
д) возврат ответа
В более сложных случаях - ациклический граф (DAG, не путать с RAG) или стейт-машина. Или даже циклический граф, для обработки ошибочного ответа.
Команды - по сути shortcut вида /execute для быстрого выполнения промта при общении с агентом в чате.
ACP - протокол для общения IDE и агента. Альтернатива MCP для вызова функций IDE из агента.
При использовании MCP агент просто вызывает функции IDE как тулы.
При использовании ACP - взаимодействие двухстороннее. Где это может понадобиться? Разве что для реализации единого окна чата в IDE для разных агентов.
Субагент - агент внутри агента. Ключевые характеристики - свой системный промт, свой набор тулов и свое контекстное окно. Простейший способ реализации мультиагентной системы.
Можно считать, что субагент - это развитый skill, имеющий свой контекст.
Обучение модели - в случае LLM по сути альтернатива RAG. Вместо того, чтобы хранить данные рядом с агентом - добавляем их в модель.
В целом LLM не требуют обучения, но иногда оно полезно.
Обучение дорогое - в случае LLM для него требуется множество GPU. Есть разные виды обучения, но это отдельная тема)
Инференс (inference) - обработка пользовательских запросов моделью. Инференс менее ресурсозатратный процесс, но для больших LLM также требует GPU.
ollama - самый популярный движок для локального инференса.
Кажется назрел пост-глоссарий терминов. Сам иногда путаюсь)
ML модель - узкоспециализированная небольшая модель, как правило требующая обучения под конкретную задачу: классификация текстов, картинок или видео, определение тональности текста, преобразования Image\Audio в Text и обратно.
Существуют достаточно давно.
LLM - модель общего назначения, базово умеет продолжать текстовые фразы.
С конвертерами и тулами - принимать и генерировать любой контент, недостающие знания запрашивая из внешнего мира.
За универсальность приходится платить - LLM медленнее и требует более мощного железа.
промт - часть запроса к LLM. Почему часть? Как правило исходный запрос пользователя не попадает напрямую в LLM.
Исходный запрос - это пользовательский промт, а еще бывают системный и assistant.
Системный - это промт, "захардкоженный" внутри сервиса, взаимодействующего с LLM, и имеющий более высокий приоритет. Например, чата или агента.
assistant промт - прошлые ответы модели, добавленные в диалог.
tool - метод агента, имеющий четкое API и выполняющий некое действие\возвращающий некие данных.
Должен быть корректно описан, чтобы модель поняла зачем он нужен и вызывала его в случаях, когда сама не может выполнить какой-то запрос.
Как правило tool-ы встроенные, но иногда есть возможность создать пользовательские tool.
MCP - протокол клиент-сервер, позволяющий вынести tool-ы из агента.
Позволяет легко переиспользовать tool в разных агентах и разделить разработку логики агента и бизнесовых инструментов.
skill - навык агента. По сути более сложный tool, скорее сценарий, оркестрирующий вызовы нескольких тулов. Включает промт, документацию, схемы валидации, скрипты.
rule - правила работы, которые должны применяться при любом запросе к LLM.
RAG - статическая база знаний по узкой предметной области, содержащая данные, которых нет в LLM.
Контекст - набор данных, на основании которого LLM генерирует текст. В контекст имеет смысл включать:
а) промты
б) историю диалога и вызовов инструментов
в) полезные данные из RAG
г) список доступных tools, skills и MCP серверов
д) rules
Контекст привязан к клиентской сессии.
Контекстное окно - ограничение на размер контекста в сессии. Контекст хранится в памяти, память дорогая, приходится ограничивать. При достижении предела нужно принять два решения:
а) падать\ не падать (последнее - плавающее окно)
б) удалять \ сжимать старые данные.
Агент - сервис, с помощью AI способный самостоятельно понять и решить поставленную задачу.
В простейшем виде это бесконечный цикл вида:
а) ожидание входных данных
б) формирование данных, которые могут попасть в запрос к LLM
в) фильтрация этих данных
г) вызов LLM
д) получение дополнительных данных с помощью tool
е) валидация ответа
д) возврат ответа
В более сложных случаях - ациклический граф (DAG, не путать с RAG) или стейт-машина. Или даже циклический граф, для обработки ошибочного ответа.
Команды - по сути shortcut вида /execute для быстрого выполнения промта при общении с агентом в чате.
ACP - протокол для общения IDE и агента. Альтернатива MCP для вызова функций IDE из агента.
При использовании MCP агент просто вызывает функции IDE как тулы.
При использовании ACP - взаимодействие двухстороннее. Где это может понадобиться? Разве что для реализации единого окна чата в IDE для разных агентов.
Субагент - агент внутри агента. Ключевые характеристики - свой системный промт, свой набор тулов и свое контекстное окно. Простейший способ реализации мультиагентной системы.
Можно считать, что субагент - это развитый skill, имеющий свой контекст.
Обучение модели - в случае LLM по сути альтернатива RAG. Вместо того, чтобы хранить данные рядом с агентом - добавляем их в модель.
В целом LLM не требуют обучения, но иногда оно полезно.
Обучение дорогое - в случае LLM для него требуется множество GPU. Есть разные виды обучения, но это отдельная тема)
Инференс (inference) - обработка пользовательских запросов моделью. Инференс менее ресурсозатратный процесс, но для больших LLM также требует GPU.
ollama - самый популярный движок для локального инференса.
👍3🔥1
embeddings - преобразование текста в вектора (набор чисел). LLM работает с векторами, RAG хранит данные в виде векторов, при поиске по RAG запрос также превращается в векторную форму. Для формирования embeddings есть специальные ML модели, меньшие и более быстрые.
Семантический поиск = векторный поиск. Суть в том, что ищет не похожие по написанию слова, а близкие слова в пространстве векторов.
#ai
Семантический поиск = векторный поиск. Суть в том, что ищет не похожие по написанию слова, а близкие слова в пространстве векторов.
#ai
👍1
Forwarded from Мысли вне кода | Суринов
Не знаю кто автор, но это гениально:
mcp-сервер – это ящик с лобзиками и напильниками
skills – это инструкция как из деревяшки сделать разделочную доску
rules – это «палец себе не отпили»
agents – это пятиклашки
prompt – это «сегодня на уроке все делаем подарок маме на 8 марта»
vibecoder – это трудовик, который дал задачу, а сам ушёл бухать с физруком
🔥1
Еще две мысли о комментариях в коде.
Я как наверное и большинство разработчик - ярый сторонник самодокументирующегося кода.
При этом JavaDoc (KDoc) иногда нужны.
Когда - уже говорил тут https://t.me/javaKotlinDevOps/183
Сейчас хочется добавить еще один позитивный кейс и один признать негативным.
Документация полезна, когда описывает то, чего нет в коде - это понятно.
Но также она полезна, если в нескольких строчках описывает то, что происходит в сложном методе или классе, включающем, скажем, 100-300 строк кода.
В первом случае время прочтения < 1 минуты, во втором прочитать и главное разобраться потребует в разы или на порядок больше времени.
А мы большей частью код читаем, а не пишем. И с учетом потока информации в наше время - код забывается быстро.
И антипаттерн. Ранее я писал, что документирование неочевидных вещей в коде может быть полезно, но это также повод задуматься о рефакторинге.
Сейчас прихожу к мнению, что единственный нормальный комментарий для особого случая - это
И такой TODO - это code smell в терминологии SonarQube. Не все TODO = code smell, это могут быть и планы на будущее, но в данном случае это точно техдолг.
#documentation
Я как наверное и большинство разработчик - ярый сторонник самодокументирующегося кода.
При этом JavaDoc (KDoc) иногда нужны.
Когда - уже говорил тут https://t.me/javaKotlinDevOps/183
Сейчас хочется добавить еще один позитивный кейс и один признать негативным.
Документация полезна, когда описывает то, чего нет в коде - это понятно.
Но также она полезна, если в нескольких строчках описывает то, что происходит в сложном методе или классе, включающем, скажем, 100-300 строк кода.
В первом случае время прочтения < 1 минуты, во втором прочитать и главное разобраться потребует в разы или на порядок больше времени.
А мы большей частью код читаем, а не пишем. И с учетом потока информации в наше время - код забывается быстро.
И антипаттерн. Ранее я писал, что документирование неочевидных вещей в коде может быть полезно, но это также повод задуматься о рефакторинге.
Сейчас прихожу к мнению, что единственный нормальный комментарий для особого случая - это
// TODO исправить ...
И такой TODO - это code smell в терминологии SonarQube. Не все TODO = code smell, это могут быть и планы на будущее, но в данном случае это точно техдолг.
#documentation
Telegram
(java || kotlin) && devOps
Всем привет!
Уже несколько раз упоминал в последних постах JavaDoc\KDoc. Нужен ли он вообще?
Мой ответ: да, но не всегда.
Основной критерий - JavaDoc должен приносить пользу. Т.е. давать дополнительную информацию. Дополнительную к чему?
1) названию модуля…
Уже несколько раз упоминал в последних постах JavaDoc\KDoc. Нужен ли он вообще?
Мой ответ: да, но не всегда.
Основной критерий - JavaDoc должен приносить пользу. Т.е. давать дополнительную информацию. Дополнительную к чему?
1) названию модуля…
Что такое промт-инжиниринг?
Прочитал книжку "Промт-инжиниринг для LLM. Искусство построения приложений на основе больших языковых моделей"
Ясно, что в этой области все быстро устаревает, но в целом рекомендовать могу. Кажется книге не хватает структурированности, это скорее набор мыслей идей, инсайтов как сейчас модно говорить)
Но сейчас хотел бы обратить внимание на другое.
До сих пор я считал, что промт инжиниринг - это написание текстовых пользовательских промтов, no code.
После прочтения этой книги я бы сказал, что это только первый уровень.
Второй уровень - системный промт, который нужно писать с учетом того, что он должен задавать четкую роль для агента и направлять\ограничивать пользовательские промты. Т.е. встает вопрос совместимости.
А третий уровень - это собственно формирование диалога с LLM.
Напомню, запрос к LLM может выглядеть так:
Системный промт - вступление
Пользовательский промт
История диалога
rules
Список тулов, skills, MCP
Результаты вызова тулов, skills, MCP
Релевантные данные из RAG
Любые другие данные из контекста (например, открытые в IDE файлы для dev агента)
Системный промт - окончание.
Это все нужно собрать, приоритезировать, отфильтровать и встроить в шаблон запроса к LLM. А вначале этот шаблон придумать. А потом верифицировать ответ, если надо сделать цикл обратной связи для обработки некорректных ответов. А далее возможно декомпозировать на отдельные задачи для субагентов. Написать тесты для всего этого дела. Придумать метрики для отслеживания релевантности, точности и полноты ответов в ПРОМе. Наверняка еще задачи отладки и логирования станут актуальными, чтобы понять по каким веткам нашего графа идут запросы.
В общем, работы много.
И это уже не no code.
И быть такие промт-инженером уже не обидно для разработчика)
P.S. Авторы книги - бывшие разработчики GitHub Copilot.
#ai #dev
Прочитал книжку "Промт-инжиниринг для LLM. Искусство построения приложений на основе больших языковых моделей"
Ясно, что в этой области все быстро устаревает, но в целом рекомендовать могу. Кажется книге не хватает структурированности, это скорее набор мыслей идей, инсайтов как сейчас модно говорить)
Но сейчас хотел бы обратить внимание на другое.
До сих пор я считал, что промт инжиниринг - это написание текстовых пользовательских промтов, no code.
После прочтения этой книги я бы сказал, что это только первый уровень.
Второй уровень - системный промт, который нужно писать с учетом того, что он должен задавать четкую роль для агента и направлять\ограничивать пользовательские промты. Т.е. встает вопрос совместимости.
А третий уровень - это собственно формирование диалога с LLM.
Напомню, запрос к LLM может выглядеть так:
Системный промт - вступление
Пользовательский промт
История диалога
rules
Список тулов, skills, MCP
Результаты вызова тулов, skills, MCP
Релевантные данные из RAG
Любые другие данные из контекста (например, открытые в IDE файлы для dev агента)
Системный промт - окончание.
Это все нужно собрать, приоритезировать, отфильтровать и встроить в шаблон запроса к LLM. А вначале этот шаблон придумать. А потом верифицировать ответ, если надо сделать цикл обратной связи для обработки некорректных ответов. А далее возможно декомпозировать на отдельные задачи для субагентов. Написать тесты для всего этого дела. Придумать метрики для отслеживания релевантности, точности и полноты ответов в ПРОМе. Наверняка еще задачи отладки и логирования станут актуальными, чтобы понять по каким веткам нашего графа идут запросы.
В общем, работы много.
И это уже не no code.
И быть такие промт-инженером уже не обидно для разработчика)
P.S. Авторы книги - бывшие разработчики GitHub Copilot.
#ai #dev
👍1
В последнее время все более популярными становятся CLI агенты.
Claude Code, Codex CLI, Gemini CLI, Qwen Code, OpenCode. GigaCode недавно подтянулся.
OpenClaw туда же, хотя он не заточен под разработку.
Некоторые из них имеют своего IDE аналога, часто даже двух - для IDEA и VSCode, некоторые нет.
Концепции современной CLI (shell) примерно 55 лет.
В 1969 году появился Unix, 3 стандартных потока - stdin, stdout, stderr и перенаправление > и < в файл (концепция "все есть файл").
Чуть позже в 1973 году - концепция pipe (|), т.е передача stdout одного приложения в stdin другого, и т.об. выстраивание команд в цепочку.
И еще чуть позже - в 1975 году - появился vi - редактор с TUI (Terminal UI).
Курсор можно было перемещать в любое место экрана плюс горячие клавиши.
Кроме vim можно вспомнить файловые менеджеры - mc, Norton Commander, Volkov Commander.
И вот сейчас благодаря AI агентам наблюдается некий ренессанс.
Да, CLI API был всегда. git, kubectl, docker, gradle, maven.
Интересна скорее связка TUI + CLI API, т.к. это два разных сценария работы.
TUI - замена IDE. Для каких задач? Видимо тех, где IDE не сильно нужен или вообще не поможет.
Т.е. не работа с кодовой базой, а скорее написание отдельных скриптов.
Если это shell скрипты - то их можно на месте и отладить.
Это DevOps и Ops.
Или быстрые и простые правки в проекте, когда вся мощь IDE не нужна.
А еще проекты, совсем не связанные с кодом. Например, анализ каких-то данных. Создание презентаций и схем.
Ручной анализ ошибок, результата запуска тестов.
Генерация тестовых данных.
Тут агент с TUI побеждает обычный чат за счет режима планирования, скилов, комманд, сабагентов.
И - тут плавно переходим в CLI режиму - разработка и отладка AI агента.
CLI режим по-другому называется headless, head в данном случае терминал.
Вот какие команды поддерживает OpenCode https://opencode.ai/docs/ru/cli/
А вот какие Gemini: https://google-gemini.github.io/gemini-cli/docs/cli/headless.html
Пару примеров из мануала Gemini:
Здесь у нас есть вся мощь CLI - агенту (почти всем CLI агентам) можно передать чей-то stdout.
И передать дальше их stdout, отформатировав его в json. Или сохранить в файл.
Где можно использовать - да везде.
Предварительно настроив сабагентов и скилы.
prCheck, автоматическое code review, автогенерация кода, тестов, документации, отчетов, анализ логов....
Ну и еще два применения:
1) консоль есть в IDE, можно использовать агента там. Правда интеграция будет хуже, чем у нативного IDE агента.
2) если выстрелит протокол ACP https://www.jetbrains.com/help/ai-assistant/acp.html, не путать с другими ACP,
то в IDEA будет стандартное окно AI чата, из которого можно переключаться\выбирать себе агента сохраняя клиентский опыт.
И еще один очевидный, но важный момент: консоль - это инструмент ИТ-шника.
Разработчик, тестировщик, DevOps, Ops, системный аналитик, ИТ менеджер наконец.
Как минимум нужно понимать, почему это установленному скилу потребовался Python, NodeJS и множество пакетов к ним.
Да и с концепцией venv лучше быть знакомым)
И это инструмент локальный - т.е. нужна возможность скачать и установить агента и его секреты (API ключи).
#ai
Claude Code, Codex CLI, Gemini CLI, Qwen Code, OpenCode. GigaCode недавно подтянулся.
OpenClaw туда же, хотя он не заточен под разработку.
Некоторые из них имеют своего IDE аналога, часто даже двух - для IDEA и VSCode, некоторые нет.
Концепции современной CLI (shell) примерно 55 лет.
В 1969 году появился Unix, 3 стандартных потока - stdin, stdout, stderr и перенаправление > и < в файл (концепция "все есть файл").
Чуть позже в 1973 году - концепция pipe (|), т.е передача stdout одного приложения в stdin другого, и т.об. выстраивание команд в цепочку.
И еще чуть позже - в 1975 году - появился vi - редактор с TUI (Terminal UI).
Курсор можно было перемещать в любое место экрана плюс горячие клавиши.
Кроме vim можно вспомнить файловые менеджеры - mc, Norton Commander, Volkov Commander.
И вот сейчас благодаря AI агентам наблюдается некий ренессанс.
Да, CLI API был всегда. git, kubectl, docker, gradle, maven.
Интересна скорее связка TUI + CLI API, т.к. это два разных сценария работы.
TUI - замена IDE. Для каких задач? Видимо тех, где IDE не сильно нужен или вообще не поможет.
Т.е. не работа с кодовой базой, а скорее написание отдельных скриптов.
Если это shell скрипты - то их можно на месте и отладить.
Это DevOps и Ops.
Или быстрые и простые правки в проекте, когда вся мощь IDE не нужна.
А еще проекты, совсем не связанные с кодом. Например, анализ каких-то данных. Создание презентаций и схем.
Ручной анализ ошибок, результата запуска тестов.
Генерация тестовых данных.
Тут агент с TUI побеждает обычный чат за счет режима планирования, скилов, комманд, сабагентов.
И - тут плавно переходим в CLI режиму - разработка и отладка AI агента.
CLI режим по-другому называется headless, head в данном случае терминал.
Вот какие команды поддерживает OpenCode https://opencode.ai/docs/ru/cli/
А вот какие Gemini: https://google-gemini.github.io/gemini-cli/docs/cli/headless.html
Пару примеров из мануала Gemini:
cat src/auth.py | gemini -p "Review this authentication code for security issues" > security-review.txt
result=$(git diff --cached | gemini -p "Write a concise commit message for these changes" --output-format json)
echo "$result" | jq -r '.response'
Здесь у нас есть вся мощь CLI - агенту (почти всем CLI агентам) можно передать чей-то stdout.
И передать дальше их stdout, отформатировав его в json. Или сохранить в файл.
Где можно использовать - да везде.
Предварительно настроив сабагентов и скилы.
prCheck, автоматическое code review, автогенерация кода, тестов, документации, отчетов, анализ логов....
Ну и еще два применения:
1) консоль есть в IDE, можно использовать агента там. Правда интеграция будет хуже, чем у нативного IDE агента.
2) если выстрелит протокол ACP https://www.jetbrains.com/help/ai-assistant/acp.html, не путать с другими ACP,
то в IDEA будет стандартное окно AI чата, из которого можно переключаться\выбирать себе агента сохраняя клиентский опыт.
И еще один очевидный, но важный момент: консоль - это инструмент ИТ-шника.
Разработчик, тестировщик, DevOps, Ops, системный аналитик, ИТ менеджер наконец.
Как минимум нужно понимать, почему это установленному скилу потребовался Python, NodeJS и множество пакетов к ним.
Да и с концепцией venv лучше быть знакомым)
И это инструмент локальный - т.е. нужна возможность скачать и установить агента и его секреты (API ключи).
#ai
OpenCode
CLI
Параметры и команда opencode CLI.
Мы?)
Но что интересно - AI-шка здорово ускоряет создание таких часто одноразовых инструментов. Особенно если это shell скрипты или любой код не на основном языке разработчика. Так что подозреваю, что таких утилит будет больше, а времени на их создание будет затрачиваться меньше. И одноразовость уже не будет блокером.
P.S. Да, это снова флешбеки от Совершенного кода)
#book_review #ai
Но что интересно - AI-шка здорово ускоряет создание таких часто одноразовых инструментов. Особенно если это shell скрипты или любой код не на основном языке разработчика. Так что подозреваю, что таких утилит будет больше, а времени на их создание будет затрачиваться меньше. И одноразовость уже не будет блокером.
P.S. Да, это снова флешбеки от Совершенного кода)
#book_review #ai
🔥2