Все AI dev агенты делятся на 2 категории по тому, как хранят свои правила.
Один файл:
Claude Code — CLAUDE.md
Gemini CLI — GEMINI.md
OpenAI Codex CLI — AGENTS.md
JetBrains Junie — .junie/guidelines.md
Папка с несколькими файлами:
Cursor — .cursor/rules/*.mdc
Windsurf — .windsurf/rules/*.md
Cline — .clinerules/*.md
Roocode — .roo/rules/*.md
GitHub Copilot — .github/instructions/*.instructions.md
JetBrains AI Assistant — .aiassistant/rules/*.md
Continue — .continue/rules/*.md
GigaCode - .gitverse/pr_rules/*.md (для версии на GitVerse)
Cline тут выделяется тем, что вообще говоря позволяет оба варианта - файл .clinerules или одноименный каталог.
Особенность Claude - кастомные команды, хранятся в кастомные команды в ~/.claude/commands/<name>.md. В принципе можно использовать и как аналог rule при явном указании в чате. Но без автозагрузки.
И еще сильнее выделяется OpenCode.
Он вначале пытается быть совместимым с OpenAI (AGENTS.md), если не нашел - с Claude Code (CLAUDE.md). А кроме того позволяет через customInstructions в opencode.json подключать произвольные файлы, включая загрузку по http, что является уникальной фичей.
Какие плюсы\минусы у этих подходов?
Один файл - простота.
Особенно учитывая тот факт, что практически ни один агент не дает менять имя файла\папки - т.е. имеем дело с convention over configuration во всей красе.
Пару слов про смену имени: единственное исключение - Gemini CLI, позволяет задать contextFileName в settings.json.
Еще в теории с этим подходом больше шансов получить непротиворечивые правила, но с ростом размера файла это преимущество нивелируется.
Каталог - а мне этот вариант кажется более удобным - имеет следующие плюсы:
1) если в репо лежит разнородный код, который пишут разные люди: фронт, бэк, devops, автотесты то удобнее, если у каждого будет свой файл с правилами. Да, AI способствует T-shape, но это пока что процесс, а не свершившийся факт.
2) несколько файлов точно легче читать и править человеку. А со слабыми моделями - возможно и LLM.
3) в теории при наличии нескольких файлов LLM исходя из текущей задачи сама могла бы выбрать только нужные, тем самым уменьшив расход токенов и контекстного окна и ускорив работу.
Обходной вариант для single rule агентов - можно указать в промте или rules: "прочитай инструкции из каталога xxx", - и т.об решить проблему. Но это менее надежно.
И главный вопрос - как избежать vendor lock и не нарушать DRY?
Делаем базовую папку с правилами, дале в Windows - создаем ссылку с помощью junction, в Linux - symlink.
И лучше добавить в .gitignore для надежности, чтобы случайно не задублировалось.
Для single rule агентов можно навайбкодить утилиту по склеиванию всех файлов в один, или использовать готовую cursor2claude.
Но вообще говоря эта область прям напрашивается на стандартизацию - либо через convention, либо через использование отдельного компонента.
#ai #ai_agents
Один файл:
Claude Code — CLAUDE.md
Gemini CLI — GEMINI.md
OpenAI Codex CLI — AGENTS.md
JetBrains Junie — .junie/guidelines.md
Папка с несколькими файлами:
Cursor — .cursor/rules/*.mdc
Windsurf — .windsurf/rules/*.md
Cline — .clinerules/*.md
Roocode — .roo/rules/*.md
GitHub Copilot — .github/instructions/*.instructions.md
JetBrains AI Assistant — .aiassistant/rules/*.md
Continue — .continue/rules/*.md
GigaCode - .gitverse/pr_rules/*.md (для версии на GitVerse)
Cline тут выделяется тем, что вообще говоря позволяет оба варианта - файл .clinerules или одноименный каталог.
Особенность Claude - кастомные команды, хранятся в кастомные команды в ~/.claude/commands/<name>.md. В принципе можно использовать и как аналог rule при явном указании в чате. Но без автозагрузки.
И еще сильнее выделяется OpenCode.
Он вначале пытается быть совместимым с OpenAI (AGENTS.md), если не нашел - с Claude Code (CLAUDE.md). А кроме того позволяет через customInstructions в opencode.json подключать произвольные файлы, включая загрузку по http, что является уникальной фичей.
Какие плюсы\минусы у этих подходов?
Один файл - простота.
Особенно учитывая тот факт, что практически ни один агент не дает менять имя файла\папки - т.е. имеем дело с convention over configuration во всей красе.
Пару слов про смену имени: единственное исключение - Gemini CLI, позволяет задать contextFileName в settings.json.
Еще в теории с этим подходом больше шансов получить непротиворечивые правила, но с ростом размера файла это преимущество нивелируется.
Каталог - а мне этот вариант кажется более удобным - имеет следующие плюсы:
1) если в репо лежит разнородный код, который пишут разные люди: фронт, бэк, devops, автотесты то удобнее, если у каждого будет свой файл с правилами. Да, AI способствует T-shape, но это пока что процесс, а не свершившийся факт.
2) несколько файлов точно легче читать и править человеку. А со слабыми моделями - возможно и LLM.
3) в теории при наличии нескольких файлов LLM исходя из текущей задачи сама могла бы выбрать только нужные, тем самым уменьшив расход токенов и контекстного окна и ускорив работу.
Обходной вариант для single rule агентов - можно указать в промте или rules: "прочитай инструкции из каталога xxx", - и т.об решить проблему. Но это менее надежно.
И главный вопрос - как избежать vendor lock и не нарушать DRY?
Делаем базовую папку с правилами, дале в Windows - создаем ссылку с помощью junction, в Linux - symlink.
И лучше добавить в .gitignore для надежности, чтобы случайно не задублировалось.
Для single rule агентов можно навайбкодить утилиту по склеиванию всех файлов в один, или использовать готовую cursor2claude.
Но вообще говоря эта область прям напрашивается на стандартизацию - либо через convention, либо через использование отдельного компонента.
#ai #ai_agents
Agile мир победил, микросервисы оказались сильней)
Вот данные из моей любимой книжки по разработке.
Медиану можно оценить ~9, среднее ~19, но среднее мало информативно из-за сильной правой асимметрии (маленьких команд сильно больше, чем больших).
Я бы из него сделал вывод, что микросервисы были всегда, просто раньше назывались по-другому — например, SOA (Service Oriented Architecture).
Но конечно ситуация меняется(хотел написать «не могла не измениться», но вспомнил свой же пост про двойное отрицание))) .
А вот более современные данные, не такие подробные.
Если сравнить 2003 и 2012 годы — медиана уменьшилась почти в 2 раза: 9 → 5.
Ещё есть данные опроса пользователей JetBrains (2024) https://www.jetbrains.com/lp/devecosystem-2024/
Медиана ≈ 6 человек, среднее ≈ 11. Примерно то же, что в 2012, только как ни странно числа стали чуть больше). Зато видно, что больших команд стало в 2+ раза меньше.
По моему опыту (кровавый enterprise) медианный размер команды на данный момент выше, ближе к 9. Но то, что 80% команд укладываются в 12 человек — сходится.
В 2003 году было ~60%.
Т.е. мы пока одной ногой шагнули в новую эру) enterprise требует жертв. Но тренд понятен.
О причинах — часть уже назвал: Agile и микросервисы. Ещё — улучшившийся инструментарий: IDE и фреймворки/библиотеки под любую потребность. А сейчас ещё и AI.
Так что думаю, что к 6 людям в команде мы все скоро придём. Будет ли меньше? В теории да: ВП, аналитик, 1–2 разработчика, тестировщик.
P.S. Т.к. в таблицах процент команд, а не процент людей - в командах более 12 человек все еще работает более 50% разработчиков. Было - более 80%. Интересно кто это?
P.P.S. Станет ли медианным значением 1 — ВП, который с помощью AI пилит и тестирует сервисы сам? ...Где-то да, уже сейчас. Но массово — может помешать Skynet. Или поспособствовать — сидишь себе в матрице, вайб-кодишь с AI микросервисы.
#book_review #agile #ai #microservices
Вот данные из моей любимой книжки по разработке.
Процентное соотношение проектов по размеру команды:
Размер команды | Доля
----------------|------
1–3 человека | 25%
4–10 человек | 30%
11–25 человек | 20%
26–50 человек | 15%
>50 человек | 10%
Источники: Beck and Perkins (1983), Highsmith (2002), Boehm and Turner (2003)
Медиану можно оценить ~9, среднее ~19, но среднее мало информативно из-за сильной правой асимметрии (маленьких команд сильно больше, чем больших).
Я бы из него сделал вывод, что микросервисы были всегда, просто раньше назывались по-другому — например, SOA (Service Oriented Architecture).
Но конечно ситуация меняется
А вот более современные данные, не такие подробные.
В исследовании Rodriguez et al. (JSS, 2012) на базе 951 проекта — 75% имели команду менее 10 человек. Медиана = 5, среднее ≈ 7.9.
Если сравнить 2003 и 2012 годы — медиана уменьшилась почти в 2 раза: 9 → 5.
Ещё есть данные опроса пользователей JetBrains (2024) https://www.jetbrains.com/lp/devecosystem-2024/
Размер команды | Доля
----------------|------
1 человек | 8%
2–7 человек | 49%
8–12 человек | 22%
13–20 человек | 10%
21–40 человек | 6%
>40 человек | 5%
Медиана ≈ 6 человек, среднее ≈ 11. Примерно то же, что в 2012, только как ни странно числа стали чуть больше). Зато видно, что больших команд стало в 2+ раза меньше.
По моему опыту (кровавый enterprise) медианный размер команды на данный момент выше, ближе к 9. Но то, что 80% команд укладываются в 12 человек — сходится.
В 2003 году было ~60%.
Т.е. мы пока одной ногой шагнули в новую эру) enterprise требует жертв. Но тренд понятен.
О причинах — часть уже назвал: Agile и микросервисы. Ещё — улучшившийся инструментарий: IDE и фреймворки/библиотеки под любую потребность. А сейчас ещё и AI.
Так что думаю, что к 6 людям в команде мы все скоро придём. Будет ли меньше? В теории да: ВП, аналитик, 1–2 разработчика, тестировщик.
P.S. Т.к. в таблицах процент команд, а не процент людей - в командах более 12 человек все еще работает более 50% разработчиков. Было - более 80%. Интересно кто это?
P.P.S. Станет ли медианным значением 1 — ВП, который с помощью AI пилит и тестирует сервисы сам? ...Где-то да, уже сейчас. Но массово — может помешать Skynet. Или поспособствовать — сидишь себе в матрице, вайб-кодишь с AI микросервисы.
#book_review #agile #ai #microservices
JetBrains: Developer Tools for Professionals and Teams
Software Developers Statistics 2024 - State of Developer Ecosystem Report
Explore key software developer statistics for 2024 in the State of Developer Ecosystem Report. Trends, insights, and tools shaping the developer world
👍1
Иногда кажется, что если попросить какую-то 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