Forwarded from Женя, расскажи про AI
Знакомьтесь, Blok!
Blok — это блочный, визуальный open-source редактор типа Notion.
В основу Blok лёг Editor.js — прекрасный визуальный редактор, который в своём развитии остановился где-то в 2018-м году, где было приемлемо иметь средненький UX, плохую документацию и решение не поддерживающее современные фреймворки.
Blok призван решить все эти проблемы и стать тем самым визуальным редактором, который вы искали.
Уже сейчас в Blok, в отличие от Editor.js, исправлены многие баги и проблемы безопасности, повышена стабильность и тестируемость редактора, а также появилась возможность перетаскивать блоки с помощью drag&drop!
В ближайших обновлениях Blok станет React-first для максимально удобной интеграции с вашими приложениями.
Blok доступен бесплатно прямо сейчас!
Blok — это блочный, визуальный open-source редактор типа Notion.
В основу Blok лёг Editor.js — прекрасный визуальный редактор, который в своём развитии остановился где-то в 2018-м году, где было приемлемо иметь средненький UX, плохую документацию и решение не поддерживающее современные фреймворки.
Blok призван решить все эти проблемы и стать тем самым визуальным редактором, который вы искали.
Уже сейчас в Blok, в отличие от Editor.js, исправлены многие баги и проблемы безопасности, повышена стабильность и тестируемость редактора, а также появилась возможность перетаскивать блоки с помощью drag&drop!
В ближайших обновлениях Blok станет React-first для максимально удобной интеграции с вашими приложениями.
Blok доступен бесплатно прямо сейчас!
🔥5 3✍1❤1
А вот результат, ради чего все это делается! Человек пару недель ночами не спал – делал возможным Notion-like экпириенс для наших редакторов! 🧨
На гифке короткое представление, как было и как стало:
На гифке короткое представление, как было и как стало:
This media is not supported in your browser
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤🔥11 4🔥2
Год назад делали с Серегой Орловым LiveActivities на андроиде.
Это такая штука, как на пояснительном дикпике выше. Выглядит просто.
Но я тогда открыл для себя, что в Андроиде все вещи, которые выглядят простыми скорее всего делать будет тупо сложно!
Короче, в своей статье Серега рассказывает как с помощью новой фичи LiveUpdates можно сделать такую вот штучку с прогресс-баром и как это пока что ограниченно в возможностях.
К примеру на верхней картинке верхний и нижний островок – это тупо разные компоненты, а не один и тот же просто переверстанный👁 👁
Вообще мне всегда было забавно, как у нас ребята на андроиде радуются таким вот штучкам. Мне всегда это было как-то до лампочки, у меня вообще все уведомления выключены. А у них там целая история в этих отключенных оповещениях!
Короче, статья вышла прикольная! Заслуживает плюсика в карму💯
Это такая штука, как на пояснительном дикпике выше. Выглядит просто.
Но я тогда открыл для себя, что в Андроиде все вещи, которые выглядят простыми скорее всего делать будет тупо сложно!
Короче, в своей статье Серега рассказывает как с помощью новой фичи LiveUpdates можно сделать такую вот штучку с прогресс-баром и как это пока что ограниченно в возможностях.
К примеру на верхней картинке верхний и нижний островок – это тупо разные компоненты, а не один и тот же просто переверстанный
Вообще мне всегда было забавно, как у нас ребята на андроиде радуются таким вот штучкам. Мне всегда это было как-то до лампочки, у меня вообще все уведомления выключены. А у них там целая история в этих отключенных оповещениях!
Короче, статья вышла прикольная! Заслуживает плюсика в карму
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5 3👍1
В первый раз за долгое время в практике понадобилось использовать бэкграундную таску.
Нужно было добавить в процесс логина автоприсваивание пользователям определенных доступов. Операция не обязательная и из-за нее не должен падать логин. Тем более процесс логина из-за нее тоже не хочется растягивать.
Можно было сделать fire and forget опустив слово await:
groupAccessService.AssignPredefinedSpacesAsync(existingUser, CancellationToken.None);
То есть пустить таску на самотек. С одной стороны просто и понятно, но хочется как-то понимать, дошла таска до своего финала или нет и как-то все это залогировать. Короче хочется больше контроля над таким.
Вспомнил, что когда-то с IHostedService слышал про BackgroundTaskQueue
Оказалось, что в доке прям есть кусок кода, который мне нужен. По нему решил реализовать вот такой простенький бэкграунд кью воркер
using System.Threading.Channels;
namespace Dodo.KnowledgeBase.Web.Services.BackgroundTasks;
public class BackgroundTaskQueue(IServiceScopeFactory serviceScopeFactory) : IBackgroundTaskQueue
{
private readonly Channel<Func<CancellationToken, ValueTask>> _queue =
Channel.CreateUnbounded<Func<CancellationToken, ValueTask>>();
public async ValueTask QueueAsync(Func<CancellationToken, ValueTask> workItem)
{
ArgumentNullException.ThrowIfNull(workItem);
await _queue.Writer.WriteAsync(workItem);
}
public async ValueTask QueueAsync(Func<IServiceProvider, CancellationToken, ValueTask> workItem)
{
ArgumentNullException.ThrowIfNull(workItem);
await _queue.Writer.WriteAsync(ScopedWorkItem);
return;
async ValueTask ScopedWorkItem(CancellationToken ct)
{
using var scope = serviceScopeFactory.CreateScope();
await workItem(scope.ServiceProvider, ct);
}
}
internal async IAsyncEnumerable<Func<CancellationToken, ValueTask>> DequeueAsync(
[System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken ct)
{
await foreach (var item in _queue.Reader.ReadAllAsync(ct))
{
yield return item;
}
}
}
В котором вы по сути кладете функцию в канальчик, а бэкграундный хостед сервис этот канальчик потихоньку разгребает вот так:
namespace Dodo.KnowledgeBase.Web.Services.BackgroundTasks;
public class QueuedHostedService(
IBackgroundTaskQueue taskQueue,
ILogger<QueuedHostedService> logger) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken ct)
{
logger.LogInformation("Queued Hosted Service is running");
await foreach (var workItem in ((BackgroundTaskQueue)taskQueue).DequeueAsync(ct))
{
try
{
await workItem(ct);
}
catch (Exception ex)
{
logger.LogError(ex, "Error occurred executing task work item");
}
}
}
}
И вот так это можно использовать:
await backgroundTaskQueue.QueueAsync(async (sp, ct) =>
{
var groupAccessService = sp.GetRequiredService<IGroupAccessService>();
await groupAccessService.AssignPredefinedSpacesAsync(existingUser, ct);
});
Вроде несложно, но если что упадет, то всегда можно увидеть в логах в отличие от fire and forget запуска.
В отличие от варианта в доке сделал через IAsyncEnumerable. Так что вышло ну чуть покрасивше и с моей любимой фичей, которую редко когда получается заюзать.
Please open Telegram to view this post
VIEW IN TELEGRAM
Docs
Background tasks with hosted services in ASP.NET Core
Learn how to implement background tasks with hosted services in ASP.NET Core.
Всех с наступающим, чуваки! Пусть следующий год будет круче, чем предыдущий, пусть в нем будет побольше новых знаний и поменьше нейрослопа!
Поглотите столько оливье и крабового салата, чтобы хватило до следующего года, ну и вообще оторвитесь так, чтобы в первый рабочий день глаза смотрели на код чистым и незамутненным взором младенца: "А что это за буквы такие?"
Ну и всем мира и добра! И пусть вот будет для вас фотка из новогодней Местии для создания атмосферы!
Please open Telegram to view this post
VIEW IN TELEGRAM
До того как стать программистом я учился в универе на светотехника. Это такие чуваки, которые по идее разрабатывают всякие лампочки. И одна из прикольных тем, которая мне нравилась, но мозгов не хватало, чтобы в ней разбираться — газоразрядные лампы. Их в быту еще называют люминесцентные.
На самом деле лампы эти довольно прикольные по своей идее – вы создаете молнию и просто постоянно ее поддерживаете, чтобы она давала свет. Первые лампы типа “Свеча Яблочникова” вот буквально светили электродугой. Что конечно жесть еще та. Просто прикиньте охуительность идеи – освещать улицы сварочными аппаратами!
Так вот в какой-то момент люди додумались, что эту молнию можно запихнуть в колбу, а раз можно запихнуть в колбу, то эту колбу можно наполнить каким-то газом, из которого попроще извлечь свет, чем из воздуха. Так и появились сначала прототипы, а потом уже и куча разных ламп.
Процесс зажигания в таких лампах похож на молнию в целом: вам для начала нужно создать довольно серьезное напряжение, дождаться пока лампа разгорится, а потом уже можно напряжение снижать чуть по чуть.
Так вот – это все реально круто. А вот что не круто, так это лабы, в которых чтобы зажечь такую дуру надо было сначала приводить ее в рабочее состояние, а потом надеяться, что она загорится, потом понемногу снижать напряжение и молиться, чтобы она не погасла. Потому что если погасла – то это швах и надо ждать минут 40 пока она снова придет в рабочее состяние. А это значит, что лабу ты не закроешь, и придется пересдавать, что было довольно сложно.
Короче, тема интересная, но мне вот хотелось тогда сначала на какой-то симуляции все покрутить, поломать, а потом уже и за дело браться. И наконец мечта стала явью.
Замутил вот такой вот такой вот симулятор зажигателя газоразрядной лампы!
1) Короче, проходите по ссылке (желательно с компа)
2) Включаете схему и крутите напряжение и все заданные ручки, пока лампа не начнет светиться.
3) Можете менять газ, менять давление в трубке, длину трубки, подогрев электродов – короче все что вы всегда хотели поменять, но не решались.
4) Если получится зажечь лампу (как на пояснительном дикпике) и не взорвать ее, то вы красавчики – можете в награду почитать ДУШНЕЙШУЮ лекцию о том, как это работает на физическом уровне.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11⚡5 3
Из-за появления вайбкодинга постоянно что-то нет-нет, да склепаю за вечерок типа вот этой визуализации газоразрядной лампы. Но приходится делать все на HTML + JS, чтобы не нужно было хостить бэк.
За последнее время скопилась куча идей, которые можно сделать за вечерок, но для всех нужен бэк, а это сразу лень – потому что надо хостить.
Раньше для таких целей я юзал хероку. Не знаю, помните такую штуку или нет, но она позволяла буквально в два клика развернуть бэк где-то на их сервере. То есть буквально – вы в папке проекта делали
git push heroku main и вуаля – все раскатывалось! Там нужно было еще докер файл накидать, но это тоже было делом минутным. Короче, раньше было хорошо.И вот я подумал, а что если навайбкодить альтренативу этой штуке? Просто из микрокубера и пары автоматизаций собрать что-то такое на коленке. Пошел разбираться, как это все собрать и наткнулся на то, что все уже разумеется сделано.
Dokku – это штучка, которую вы ставите на свой сервак и все! С этого момента можете хостить любую бурду за одну консольную команду
git push dokku mainПо сути – это просто докер и куча скриптов, которые за вас могут многое сделать. Даже можно базку для сервиса своего поднять! Ну и еще одну головную боль она с вас снимает – сама обновляет сертификаты для HTTPS через letsencrypt.
Пока что не пробовал поставить, ибо что-то пока лень
Но в общем, если вам нужна какая-то self-hosted альтернатива для быстрого теста всяких бэкэндерских идей, то Dokku должно прокатить. Ну и если кто пользовался, то расскажите тоже, вдруг оно говно и все об этом уже знают)
PS: И вот еще их репа на гитхабе
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7🔥7 3✍2
🧝♀️ Нужен ли еще Entity Framework в 2026 году?
Пытался недавно в очередной раз посмотреть, могу ли я перевести базу знаний на .NET 10. И – нет, все еще не могу. Потому что нужно дождаться когда выйдет совместимая версия библиотеки Pomelo которая отвечает за общение EF с MySQL. И это в очередной раз заставило меня задуматься о пользе которую я вообще получаю от EF.
➕ В теории плюсы:
1) Автоматизированное создание миграций
2) Написал класс и все – можешь работать
3) Писать запросы на LINQ удобнее, пототму что есть автокомплит и проверка компилитором.
4) И самая главная киллер-фича – я в любой момент могу переехать на новую базу данных.
Казалось бы. Но на самом деле в современном мире все эти плюсы довольно сомнительные,
➖ Потому что минусы буквально по каждому пункту:
1) Сейчас миграцию я могу написать агентом, так что на это я потрачу столько же времени сколько на ревью миграции которую сгенерит EF.
2) Мапперы из базы в модель я теперь тоже могу генерить агентами, так что плюс нивелируется
3) Может это конечно не всегда опция, но с TestContainers проще и надежнее написать на сложный запрос интеграционный тест и проверить, что он выполняется. Но вообще это нужно делать и для EF, потому что некоторые запросы в целом могут не смапиться нормально и попросить у вас переписать некоторые операторы на EF функции.
4) Ну и переезд на другую базу – звучит как крутой аргумент. Пожалуй даже единственный, который может сейчас определить нужен вам EF или нет. И в целом он даже выстреливал именно на базе знаний. Вот тут Арсений писал про это дело статью. Но в любом случае переезд базы – это крупная операция, в которой большую долю времени займет перенос данных. Предугадать, что в вашем переезде именно запросы будут бутылочным горлышком – ну это довольно сложно. Мне кажется это можно предугадать только если вы намеренно захотели это сделать.
Но даже из четвертого пункта следуют довольно 🚱 неочевидные минусы:
Если вы выбрали путь джедая и хотите иметь возможность переехать к примеру с MySQL на Postgress по клику. То попрощайтесь со встроенными функциями MySQL. Хотите заюзать INSERT ... ON DUPLICATE KEY UPDATE? Если планируете переезд, то придется отказатся от этой фичи. И EF тут не поможет. Этот запрос в любом случае придется переписывать.
Ну и далее сложности с поддержкой устройства самого EF.
1) Это довольно нетривиальный фреймворк, на его изучение вполне может уйти сравнимое время на изучение особенностей какой-то конкретной БД.
2) В какой-то момент вы поймаете себя на мысли, что пытаетесь не только разобраться, как вам написать запрос чтобы он не сломался, но и как открыть и заинжектить DBContext, чтобы ничего не потекло по памяти из-за неправильно использованного Change Tracker.
3) Разумеется вам постоянно еще нужно будет следить, чтобы не случился N+1. Не сказать, что это сложно, но блин, впопыхах можно и пропустить.
4) Ну и да, вам нужно будет ждать, когда не только нугет EF обновится, но и коннектор. Что потенциально + 1 зависимость
🅰️ Короче, все весомые плюсы, которые были до эпохи агентов у EF закончились, как мне кажется. Так что лично я бы для нового проекта эту штуку не выбрал в 2026 году. Вот такие дела.
Пытался недавно в очередной раз посмотреть, могу ли я перевести базу знаний на .NET 10. И – нет, все еще не могу. Потому что нужно дождаться когда выйдет совместимая версия библиотеки Pomelo которая отвечает за общение EF с MySQL. И это в очередной раз заставило меня задуматься о пользе которую я вообще получаю от EF.
1) Автоматизированное создание миграций
2) Написал класс и все – можешь работать
3) Писать запросы на LINQ удобнее, пототму что есть автокомплит и проверка компилитором.
4) И самая главная киллер-фича – я в любой момент могу переехать на новую базу данных.
Казалось бы. Но на самом деле в современном мире все эти плюсы довольно сомнительные,
1) Сейчас миграцию я могу написать агентом, так что на это я потрачу столько же времени сколько на ревью миграции которую сгенерит EF.
2) Мапперы из базы в модель я теперь тоже могу генерить агентами, так что плюс нивелируется
3) Может это конечно не всегда опция, но с TestContainers проще и надежнее написать на сложный запрос интеграционный тест и проверить, что он выполняется. Но вообще это нужно делать и для EF, потому что некоторые запросы в целом могут не смапиться нормально и попросить у вас переписать некоторые операторы на EF функции.
4) Ну и переезд на другую базу – звучит как крутой аргумент. Пожалуй даже единственный, который может сейчас определить нужен вам EF или нет. И в целом он даже выстреливал именно на базе знаний. Вот тут Арсений писал про это дело статью. Но в любом случае переезд базы – это крупная операция, в которой большую долю времени займет перенос данных. Предугадать, что в вашем переезде именно запросы будут бутылочным горлышком – ну это довольно сложно. Мне кажется это можно предугадать только если вы намеренно захотели это сделать.
Но даже из четвертого пункта следуют довольно 🚱 неочевидные минусы:
Если вы выбрали путь джедая и хотите иметь возможность переехать к примеру с MySQL на Postgress по клику. То попрощайтесь со встроенными функциями MySQL. Хотите заюзать INSERT ... ON DUPLICATE KEY UPDATE? Если планируете переезд, то придется отказатся от этой фичи. И EF тут не поможет. Этот запрос в любом случае придется переписывать.
Ну и далее сложности с поддержкой устройства самого EF.
1) Это довольно нетривиальный фреймворк, на его изучение вполне может уйти сравнимое время на изучение особенностей какой-то конкретной БД.
2) В какой-то момент вы поймаете себя на мысли, что пытаетесь не только разобраться, как вам написать запрос чтобы он не сломался, но и как открыть и заинжектить DBContext, чтобы ничего не потекло по памяти из-за неправильно использованного Change Tracker.
3) Разумеется вам постоянно еще нужно будет следить, чтобы не случился N+1. Не сказать, что это сложно, но блин, впопыхах можно и пропустить.
4) Ну и да, вам нужно будет ждать, когда не только нугет EF обновится, но и коннектор. Что потенциально + 1 зависимость
🅰️ Короче, все весомые плюсы, которые были до эпохи агентов у EF закончились, как мне кажется. Так что лично я бы для нового проекта эту штуку не выбрал в 2026 году. Вот такие дела.
Please open Telegram to view this post
VIEW IN TELEGRAM
Squad Health Check 🌡
Вообще я очень интересуюсь процессами разработки и их налаживанием. Сюда как-то стал писать про это редко, потому что в последнее время особо нет сложностей с этим. Но лет пять назад меня прям поразил метод проверки здоровья команд в Спотифай.
Это такая табличка, как на пояснительном дикпике выше, по которой можно определить, что и в каких командах идет не так, и, наоборот, где у кого все хорошо. Ну и допом, если смотреть по горизонтали, то можно выявить не только локальные но и организационные проблемы.
Получается такой результат путем короткого опроса. Заполняете всей командой вместе на общей встрече. По каждому пункту отвечаете хорошо там все или плохо, и улучшается ли ситуация?
Так вот из всего Додо кажется только у нас в юните FAP есть такая штука. Мне этот формат как части команды помогает к примру лишний раз порефлексировать, а что мы можем улучшить у себя, и где мы расходимся во взглядах с остальной командой. Ну и интересно наблюдать с о временем как наши показатели меняются.
А сегодня вот вскрылась еще одна неочевидная польза уже для нашего нового ЕМа. Он сказал, что составление этой таблички дало прям дофига стартовых данных для начала работы. Больше чем просто хождение по синкам и встречам-знакомствам.
Я приложил на себя его отзыв и подумал, что реально классный формат, если ты только пришел и тебе надо как-то быстро познакомиться с командми и выявить проблемные места. Это получается и не тупая встреча-знакомства без цели, но и не душниловка, с заготовленными вопросами. У вас есть конкретная цель, при этом вы вольны на каждом этапе немного поговорить и накинуть наболевшего контекста. Короче, можете взять себе на заметку формат. Длится встреча минут 40, а пользы на месяцы я думаю
Вообще я очень интересуюсь процессами разработки и их налаживанием. Сюда как-то стал писать про это редко, потому что в последнее время особо нет сложностей с этим. Но лет пять назад меня прям поразил метод проверки здоровья команд в Спотифай.
Это такая табличка, как на пояснительном дикпике выше, по которой можно определить, что и в каких командах идет не так, и, наоборот, где у кого все хорошо. Ну и допом, если смотреть по горизонтали, то можно выявить не только локальные но и организационные проблемы.
Получается такой результат путем короткого опроса. Заполняете всей командой вместе на общей встрече. По каждому пункту отвечаете хорошо там все или плохо, и улучшается ли ситуация?
Так вот из всего Додо кажется только у нас в юните FAP есть такая штука. Мне этот формат как части команды помогает к примру лишний раз порефлексировать, а что мы можем улучшить у себя, и где мы расходимся во взглядах с остальной командой. Ну и интересно наблюдать с о временем как наши показатели меняются.
А сегодня вот вскрылась еще одна неочевидная польза уже для нашего нового ЕМа. Он сказал, что составление этой таблички дало прям дофига стартовых данных для начала работы. Больше чем просто хождение по синкам и встречам-знакомствам.
Я приложил на себя его отзыв и подумал, что реально классный формат, если ты только пришел и тебе надо как-то быстро познакомиться с командми и выявить проблемные места. Это получается и не тупая встреча-знакомства без цели, но и не душниловка, с заготовленными вопросами. У вас есть конкретная цель, при этом вы вольны на каждом этапе немного поговорить и накинуть наболевшего контекста. Короче, можете взять себе на заметку формат. Длится встреча минут 40, а пользы на месяцы я думаю
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍1 1
Ну и я еще навайбкодил формочку, которую можно заполнить вместе с командой и получить общую сводку
🤝4👍2✍1😎1
Вчера рассказал про формочку для хэлсчека, а сегодня вот Женя @that_ai_guy с утра сделал ПР, в котором сделал UX как про! Так что теперь эта формочка еще и с охуенным UXом!
🔥11❤3❤🔥1 1
🤖 Semantic Kernel, часть 1: если ты хочешь написать мини-агента за две строчки кода.
У нас сейчас есть задачка — при открытии стран надо модифицировать несколько проектов: добавить свитч-кейсы, прописать новые значения в нужных местах и сделать ПРы.
Идея – эту задачку выпнуть как-то на LLM. Звучит просто, но как представляешь себе реализацию — сразу ощущение надвигающейся геморройной жести с ифчиками и парсингом ответов от LLM.
А хочется, чтобы LLM сам решал, что делать: прочитать файл, создать ветку, закоммитить изменения, открыть PR. Но в голове сразу картинка: парсишь ответ от LLM, руками вызываешь нужную библиотеку, обрабатываешь результат, снова что-то парсишь. Руки опускались ещё на этапе проектирования.
А потом я наткнулся на Semantic Kernel. Про который много слышал, но не понимал что это.
Так вот! Фактически – это мини-агент который можно дергать через бэк. Типа мини-курсор или мини-копайлот.
Идея простая:
1️⃣ Ты описываешь инструменты — обычные C# методы, которые дергают апишки (к примеру гитхабовские) с атрибутом [KernelFunction] и Description.
2️⃣ SK подпихивает эти методы LLMке. Через рефлексию и вот это все.
3️⃣ Дальше запускается маленький агентный цикл: SK делает вызов, возвращает результат обратно в контекст — и так по кругу пока задача не решена.
И все это за вас! Написать агентный цикл в целом тот еще гемор, а тут все готово.
Вот так регаем инструмент:
Вот так вызываем промпт:
Дальше говоришь агенту: «отредактируй README.md в owner/repo, добавь раздел Installation, создай PR» — и он сам читает файл, создаёт ветку, коммитит изменения и открывает PR. Без единого ифчика с твоей стороны.
Вот тут можете посмотреть как это все работает: https://github.com/Undermove/csharpshortpostsexamples/tree/main/SemanticKernelExample.
🅰️ Итого: Если у вас есть ощущение, что вы хотите на бэке иметь под некоторые задачи мини-агента, который бы взаимодействовал с апишками, то попробуйте Semantic Kernel в качестве обертки.
У нас сейчас есть задачка — при открытии стран надо модифицировать несколько проектов: добавить свитч-кейсы, прописать новые значения в нужных местах и сделать ПРы.
Идея – эту задачку выпнуть как-то на LLM. Звучит просто, но как представляешь себе реализацию — сразу ощущение надвигающейся геморройной жести с ифчиками и парсингом ответов от LLM.
А хочется, чтобы LLM сам решал, что делать: прочитать файл, создать ветку, закоммитить изменения, открыть PR. Но в голове сразу картинка: парсишь ответ от LLM, руками вызываешь нужную библиотеку, обрабатываешь результат, снова что-то парсишь. Руки опускались ещё на этапе проектирования.
А потом я наткнулся на Semantic Kernel. Про который много слышал, но не понимал что это.
Так вот! Фактически – это мини-агент который можно дергать через бэк. Типа мини-курсор или мини-копайлот.
Идея простая:
1️⃣ Ты описываешь инструменты — обычные C# методы, которые дергают апишки (к примеру гитхабовские) с атрибутом [KernelFunction] и Description.
2️⃣ SK подпихивает эти методы LLMке. Через рефлексию и вот это все.
3️⃣ Дальше запускается маленький агентный цикл: SK делает вызов, возвращает результат обратно в контекст — и так по кругу пока задача не решена.
И все это за вас! Написать агентный цикл в целом тот еще гемор, а тут все готово.
Вот так регаем инструмент:
[KernelFunction, Description("Создаёт pull request в репозитории")]
public async Task<string> CreatePullRequest(
[Description("Владелец репозитория")] string owner,
[Description("Название репозитория")] string repo,
[Description("Заголовок pull request")] string title,
[Description("Описание pull request")] string body,
[Description("Ветка с изменениями")] string headBranch,
[Description("Целевая ветка")] string baseBranch = "main")
{
var pr = await _client.PullRequest.Create(owner, repo,
new NewPullRequest(title, headBranch, baseBranch) { Body = body });
return $"PR создан: {pr.HtmlUrl}";
}
Вот так вызываем промпт:
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-4o", openAiKey)
.Build();
kernel.Plugins.AddFromObject(new GitHubPlugin(githubToken), "GitHub");
var settings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
Дальше говоришь агенту: «отредактируй README.md в owner/repo, добавь раздел Installation, создай PR» — и он сам читает файл, создаёт ветку, коммитит изменения и открывает PR. Без единого ифчика с твоей стороны.
Вот тут можете посмотреть как это все работает: https://github.com/Undermove/csharpshortpostsexamples/tree/main/SemanticKernelExample.
🅰️ Итого: Если у вас есть ощущение, что вы хотите на бэке иметь под некоторые задачи мини-агента, который бы взаимодействовал с апишками, то попробуйте Semantic Kernel в качестве обертки.
GitHub
csharpshortpostsexamples/SemanticKernelExample at main · Undermove/csharpshortpostsexamples
Code examples for C# Short Posts Channel. Contribute to Undermove/csharpshortpostsexamples development by creating an account on GitHub.
Хочу показать разницу. Которую я сам не понимал: Function Calling у OpenAI (и других) есть и без SK. Но вот агентный цикл — то есть “вызвал тул, получил результат, спросил LLM снова, повторить“ — ты пишешь руками.
Просто для сравнения:
Без SK:
С SK:
Весь этот while-loop, switch по именам тулов и склейка результатов обратно в messages — это и есть то что SK делает за тебя. И это просто капец как удобно!
Просто для сравнения:
Без SK:
var messages = new List<ChatMessage> { new("user", prompt) };
while (true)
{
var response = await openAiClient.Chat.CreateAsync(
new() { Model = "gpt-4o", Messages = messages, Tools = tools });
if (response.FinishReason == "stop") break; // задача решена
// достаём все запрошенные тул-вызовы
foreach (var toolCall in response.ToolCalls)
{
var result = toolCall.Name switch
{
"CreatePullRequest" => await github.CreatePR(toolCall.Args),
"ReadFile" => await github.ReadFile(toolCall.Args),
"CreateBranch" => await github.CreateBranch(toolCall.Args),
_ => throw new Exception($"Unknown tool: {toolCall.Name}")
};
messages.Add(new("tool", result, toolCall.Id));
}
// и снова идём в LLM — пока он не скажет stop
}
С SK:
kernel.Plugins.AddFromObject(new GitHubPlugin(token), "GitHub");
var settings = new OpenAIPromptExecutionSettings
{
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto()
};
await chat.GetChatMessageContentAsync(prompt, settings, kernel);
Весь этот while-loop, switch по именам тулов и склейка результатов обратно в messages — это и есть то что SK делает за тебя. И это просто капец как удобно!
👍3 2🔥1
🔁 Semantic Kernel, часть 2. Как это работает под капотом и можно ли на него положиться.
Когда я впервые запустил SK и он сам прочитал файл, создал ветку и открыл PR — у меня был вопрос: а как он вообще понял что надо делать именно в такой последовательности? И точно ли он не промахнётся?
Так вот, под капотом там не магия, а как мы посмотрели выше:хуягия петля.
1️⃣ SK сериализует все твои [KernelFunction] методы в JSON-схему — название функции, её Description и описания каждого параметра — и отдаёт всё это LLM вместе с промптом.
2️⃣ LLM смотрит на задачу и список доступных инструментов, выбирает нужный и возвращает не текст, а структурированный вызов функции с параметрами.
3️⃣ SK перехватывает этот вызов, выполняет твой C# метод, результат кладёт обратно в контекст.
4️⃣ LLM смотрит на результат и решает: задача решена или нужно ещё что-то сделать? Если нужно — идёт новый круг.
Написать такой цикл руками — тот ещё гемор, как я уже говорил. SK делает это за вас.
Теперь про надёжность. Можно ли на него положиться? Честный ответ: зависит от того насколько хорошо ты написал Description. LLM выбирает тул не телепатией, а на основе текста описания(хотя рефлексия это тот еще спиритизм!) . Написал «создаёт PR в репозитории» — попадёт точно. Написал «делает штуку с гитхабом» — промахнётся. Это примерно как с промптами: мусор на входе, мусор на выходе.
Короче, качество Description — это единственное место где нужно думать все еще🙁 .
Ещё один момент — если хочешь чтобы агент не снес тебе прод, то SK умеет перехватывать вызовы через фильтры! Можно логировать каждый тул-вызов или попросить подтверждение перед тем как агент что-то реально запишет в репозиторий. Но про его фичи я еще чуть подробнее расскажу думаю
Когда я впервые запустил SK и он сам прочитал файл, создал ветку и открыл PR — у меня был вопрос: а как он вообще понял что надо делать именно в такой последовательности? И точно ли он не промахнётся?
Так вот, под капотом там не магия, а как мы посмотрели выше:
1️⃣ SK сериализует все твои [KernelFunction] методы в JSON-схему — название функции, её Description и описания каждого параметра — и отдаёт всё это LLM вместе с промптом.
2️⃣ LLM смотрит на задачу и список доступных инструментов, выбирает нужный и возвращает не текст, а структурированный вызов функции с параметрами.
3️⃣ SK перехватывает этот вызов, выполняет твой C# метод, результат кладёт обратно в контекст.
4️⃣ LLM смотрит на результат и решает: задача решена или нужно ещё что-то сделать? Если нужно — идёт новый круг.
Написать такой цикл руками — тот ещё гемор, как я уже говорил. SK делает это за вас.
Теперь про надёжность. Можно ли на него положиться? Честный ответ: зависит от того насколько хорошо ты написал Description. LLM выбирает тул не телепатией, а на основе текста описания
Короче, качество Description — это единственное место где нужно думать все еще
Ещё один момент — если хочешь чтобы агент не снес тебе прод, то SK умеет перехватывать вызовы через фильтры! Можно логировать каждый тул-вызов или попросить подтверждение перед тем как агент что-то реально запишет в репозиторий. Но про его фичи я еще чуть подробнее расскажу думаю
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3🤝2 2🤔1
🔬 Проверил .NET скиллы для Copilot CLI
Microsoft на прошлой неделе выкатила dotnet/skills — репу с agent skills для .NET разработчиков. Ставишь через
и агент подгружает специальный контекст перед тем как отвечать. Все это написала команда, которая сама рантайм строит.
Я каждый день работаю с Copilot CLI на рабочем проекте, и первая мысль была "ну это просто промпты в markdown".
Если честно я так ко всем скиллам отношусь) Ну типа скептически. Но тут вроде умные дяди написали.Хуйни не посоветуют… Наверное.
В общем, решил зачекать, а не угадывать.
1️⃣ Взял задачу с кодом из своего репо — написать BenchmarkDotNet-проект для бенчмарка SimpleKeywordEmbeddingGenerator.
2️⃣ Прогнал три раза: Copilot с некорректным скиллом csharp-scripts, Copilot без скилла, Copilot с правильным скиллом.
Выбрал для теста скилл microbenchmarking. Он сам признаётся в своём файле: "у LLM известные паттерны ошибок с BenchmarkDotNet из-за устаревших данных в training data". То есть по умолчанию LLMки подсовывают старую версию и пишут некорректно бенчмарки. Вот и посмотрим как будет, подумал.
Эксперимент 1: Без скилла
Copilot написал вот такой бенчмарк:
--job Dry прошёл без ошибок, аллокации вроде как измерялись. Но в колонке Allocated для SingleString — прочерк, 0 байт. Хотя метод явно что-то создаёт в памяти.
Причина: мы вызываем GenerateAsync, но не возвращаем результат — он просто выбрасывается. JIT видит что результат никуда не идёт, и может оптимизировать вычисление. [MemoryDiagnoser] тоже не видит аллокаций у выброшенного результата. Скилл прямо об этом предупреждает: "Return results from benchmark methods".
Эксперимент 2: Со скиллом
Тут уже агент написал правильно:
И сразу: GenerateSingle: 2.83 KB allocated. Данные корректные.
Ещё два момента. Во-первых, версии без скилла — написали BenchmarkDotNet Version="0.14.0", актуальная 0.15.8. Скилл говорит "используй dotnet add package без версии" — и только с правильным скиллом агент именно так и сделал.
Эксперимент 3: в котором неверный скилл все равно уменьшил потребление токенов.
Во-вторых, самая неожиданная находка: я поставил csharp-scripts скилл (который вообще для one-file скриптов, не для BDN-проектов) — и тоже получил улучшение кода с 3 из 7 до 6 из 7 критериев.
😱 И что приятно удивило — даже с неправильным скиллом message-токены упали с 14.6k до 6.8k!
То есть агент решил задачу в два раза меньшим числом итераций. Любой скилл добавляет режим "поработай аккуратнее". Но специфическую ошибку с аллокациями исправил только правильный.
🅰️ Короче, скиллы работают — НО! Но но но!
Есть момент, что нужно подбирать скиллы каждый раз!
🌭️️️️️️ Им бы написать роутер-скилл, кмк, который бы сам умел выбирать из сета. Думаю, это решило бы проблему. Но вы тоже это можете сделать и даже без коммита в основное репо. Но просто учитывайте это.
В общем, для диагностики, дебага, BDN-бенчмарков — реально помогают, там есть специфика которой нет в training data. Для остального — зависит от задачи и надо подбирать скилл.
Полный эксперимент с кодом, тремя ветками и инструкцией для воспроизведения туть. Можете все сами почекать
Microsoft на прошлой неделе выкатила dotnet/skills — репу с agent skills для .NET разработчиков. Ставишь через
/plugin install dotnet-diag@dotnet-agent-skills
и агент подгружает специальный контекст перед тем как отвечать. Все это написала команда, которая сама рантайм строит.
Я каждый день работаю с Copilot CLI на рабочем проекте, и первая мысль была "ну это просто промпты в markdown".
Если честно я так ко всем скиллам отношусь) Ну типа скептически. Но тут вроде умные дяди написали.
В общем, решил зачекать, а не угадывать.
Выбрал для теста скилл microbenchmarking. Он сам признаётся в своём файле: "у LLM известные паттерны ошибок с BenchmarkDotNet из-за устаревших данных в training data". То есть по умолчанию LLMки подсовывают старую версию и пишут некорректно бенчмарки. Вот и посмотрим как будет, подумал.
Эксперимент 1: Без скилла
Copilot написал вот такой бенчмарк:
[Benchmark(Baseline = true)]
public async Task SingleString()
{
await _generator.GenerateAsync(SingleInput); // результат выброшен
}
--job Dry прошёл без ошибок, аллокации вроде как измерялись. Но в колонке Allocated для SingleString — прочерк, 0 байт. Хотя метод явно что-то создаёт в памяти.
Причина: мы вызываем GenerateAsync, но не возвращаем результат — он просто выбрасывается. JIT видит что результат никуда не идёт, и может оптимизировать вычисление. [MemoryDiagnoser] тоже не видит аллокаций у выброшенного результата. Скилл прямо об этом предупреждает: "Return results from benchmark methods".
Эксперимент 2: Со скиллом
Тут уже агент написал правильно:
[Benchmark(Baseline = true)]
public Task<GeneratedEmbeddings<Embedding<float>>> GenerateSingle()
=> _generator.GenerateAsync(SingleInput); // результат возвращается
И сразу: GenerateSingle: 2.83 KB allocated. Данные корректные.
Ещё два момента. Во-первых, версии без скилла — написали BenchmarkDotNet Version="0.14.0", актуальная 0.15.8. Скилл говорит "используй dotnet add package без версии" — и только с правильным скиллом агент именно так и сделал.
Эксперимент 3: в котором неверный скилл все равно уменьшил потребление токенов.
Во-вторых, самая неожиданная находка: я поставил csharp-scripts скилл (который вообще для one-file скриптов, не для BDN-проектов) — и тоже получил улучшение кода с 3 из 7 до 6 из 7 критериев.
То есть агент решил задачу в два раза меньшим числом итераций. Любой скилл добавляет режим "поработай аккуратнее". Но специфическую ошибку с аллокациями исправил только правильный.
🅰️ Короче, скиллы работают — НО! Но но но!
Есть момент, что нужно подбирать скиллы каждый раз!
🌭️️️️️️ Им бы написать роутер-скилл, кмк, который бы сам умел выбирать из сета. Думаю, это решило бы проблему. Но вы тоже это можете сделать и даже без коммита в основное репо. Но просто учитывайте это.
В общем, для диагностики, дебага, BDN-бенчмарков — реально помогают, там есть специфика которой нет в training data. Для остального — зависит от задачи и надо подбирать скилл.
Полный эксперимент с кодом, тремя ветками и инструкцией для воспроизведения туть. Можете все сами почекать
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - dotnet/skills: Repository for skills to assist AI coding agents with .NET and C#
Repository for skills to assist AI coding agents with .NET and C# - dotnet/skills
❤2 2❤🔥1👍1
Часть 1.
Часть 2.
Окей, с агентным циклом разобрались. Поняли, что SK это не просто обёртка над одним OpenAI. Че они еще умеют:
var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion("gpt-5”, openAiKey, serviceId: "expensive")
.AddOllamaChatCompletion("llama3", serviceId: "cheap")
.Build();
🅰️ Ну и главное — куда я хочу это всё применить. У нас процесс открытия стран описан карточками в Kaiten. Хочется сделать агента, который берёт карточку и сам выполняет её: читает код, добавляет свитч-кейсы, создаёт PR, пишет в мессенджеры, итп. Хз, получится или нет, но пару недель назад смотрелось страшнее, чем сейчас.
Короче, не знаю ещё насколько это будет надёжно на практике. Но теперь хотя бы понятно с чего начать.
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
C# Short Posts 🔞
🤖 Semantic Kernel, часть 1: если ты хочешь написать мини-агента за две строчки кода.
У нас сейчас есть задачка — при открытии стран надо модифицировать несколько проектов: добавить свитч-кейсы, прописать новые значения в нужных местах и сделать ПРы.
Идея…
У нас сейчас есть задачка — при открытии стран надо модифицировать несколько проектов: добавить свитч-кейсы, прописать новые значения в нужных местах и сделать ПРы.
Идея…
🔥2❤🔥1 1
В последние недели реально херачим с Женьком просто как кони! (не то что до этого мы проебывались. просто пахали как лошади, а тут прям разогнались так сказать )
Я когда про это рассказываю, то прилетает ОЧЕНЬ много вопросов о том, как мы с такми подходом не разносим прод.
Не очень понимаю, откуда может прийти пиздец, ну разве что мы агентов в прод базу не запустим)))) Но так мы делать не будем. НО НО!
Если чет разъебется так чтоб прям пиздец. Я обязательно расскажу тут)
Я когда про это рассказываю, то прилетает ОЧЕНЬ много вопросов о том, как мы с такми подходом не разносим прод.
Не очень понимаю, откуда может прийти пиздец, ну разве что мы агентов в прод базу не запустим)))) Но так мы делать не будем. НО НО!
Если чет разъебется так чтоб прям пиздец. Я обязательно расскажу тут)
❤5 4👏1
Forwarded from Женя, расскажи про AI
В продолжение постов об исследованиях от METR
На скриншоте — количество задач, которые мы закрыли в последнем спринте командой из двух человек: 25 задач.
Для нашей команды это много. Очень много. Можете не считать стори-поинты, так как вряд ли эти оценки будут информативны, ибо они учитывают разработку с агентами, и 0.1 для агента спокойно может быть 0.5-1 для человека.
Причём у нас не было цели «закрыть как можно больше задач» или «поднажать в этом спринте» — это самый обычный спринт.
За исключением того, что наш бекендер, Дима, адаптировал под нас систему, придуманную другой командой из Додо, которая позволяет прожаривать карточки с помощью LLM.
Суть простая: мы берём юзер-стори → LLM исследует кодовую базу и все открытые/архивные карточки → на основе юзер-стори LLM пишет описание для карточки с техническими деталями и закидывает её к нам на доску → that's it.
Казалось бы, ничего революционного, но на деле — это офигенный способ использовать LLM в уже устоявшейся кодовой базе, так как она имеет нужный ей контекст и почти без ошибок угадывает, какие паттерны применить, куда положить файлы, как задизайнить API и так далее.
Ниже — то, как новый подход ускорил нас.
1. Даже в нашей небольшой команде прожарка задач была бутылочным горлышком.
Помимо того, что она занимала огромное количество времени, зачастую она была очень муторной, и после неё зачастую не оставалось мыслетоплива для того, чтобы делать ещё что-то в течение дня.
2. Новый подход позволил нам распараллелить работу.
Так как все задачи прожарены наперёд, то я могу взять в работу задачу, для которой нужен бэк, понимая, что API не готово. И мне, в целом, без разницы, когда оно будет готово. Как будет готово — фича полностью заработает, а до этого момента просто будет скрыта от глаз пользователя.
Это особенно классно, учитывая то, что у нас есть много независимых задач, которые нужно делать только на фронте или только на бэке, из-за чего бывает очень сложно синхронизироваться, чтобы сделать/прожарить задачу, которая уже требует работы с обеих сторон. Сейчас эта проблема исчезла, ибо у нас просто отпала необходимость синхронизироваться друг с другом там, где это было необходимо раньше.
3. Мы можем брать задачи из другого домена.
Так на прошлой неделе наш менеджер, Оля, принесла юзер-стори, прожарила её через скилл в Claude Code, а затем на основе прожаренной карточки самостоятельно закрыла задачу.
Задача была на бэке, поэтому Дима, само собой, посмотрел код, немного поправил тесты и слил задачу в мастер. И всё это в рамках одного дня. В такие моменты особенно отчётливо приходит понимание, что эра разработчиков, которые умеют просто превращать прожаренные требования в код, подошла к концу.
Кстати, зацените распределение карточек по типам:
• 14 фичей
• 8 багов
• 2 технические задачи
• 1 исследование
То есть 32% закрытых карточек были багами. Думаю, что кому-то это число может показаться большим, поэтому давайте разберём, что там за баги:
• 4 бага связаны с огромной фичой на 70 тыс. строк (таблицы для Blok), которую я затащил за спринт до этого. Все баги — неучтённые edge-кейсы.
• 3 бага — те самые регрессии, которых все боятся при работе с агентами. Сценарии, в которых они возникали, уже покрыты тестами, так что снова не появятся:)
• 1 баг вообще находился не в нашем сервисе, но так как ребята из другого сервиса пока не могут пофиксить баг у себя, мы сделали изощрённую заплатку в нашем сервисе, до которой не додумались бы сами.
Так что, как видите, даже с учётом возросшей скорости и количества фичей, которые мы шипим, у нас произошло всего 12% регрессии за спринт. И это опять же очень классный результат!
P.S.
Уже в текущем спринте Оля закрыла ещё две задачи. Я их отревьюил и просто слил в мастер, так как доработки не требовались.
Да, пока Оля берёт в работу только небольшие задачи, но думаю, что со временем мы будем экспериментировать с карточками бо́льших размеров. Посмотрим, что из этого получится:)
На скриншоте — количество задач, которые мы закрыли в последнем спринте командой из двух человек: 25 задач.
Для нашей команды это много. Очень много. Можете не считать стори-поинты, так как вряд ли эти оценки будут информативны, ибо они учитывают разработку с агентами, и 0.1 для агента спокойно может быть 0.5-1 для человека.
Причём у нас не было цели «закрыть как можно больше задач» или «поднажать в этом спринте» — это самый обычный спринт.
За исключением того, что наш бекендер, Дима, адаптировал под нас систему, придуманную другой командой из Додо, которая позволяет прожаривать карточки с помощью LLM.
Суть простая: мы берём юзер-стори → LLM исследует кодовую базу и все открытые/архивные карточки → на основе юзер-стори LLM пишет описание для карточки с техническими деталями и закидывает её к нам на доску → that's it.
Казалось бы, ничего революционного, но на деле — это офигенный способ использовать LLM в уже устоявшейся кодовой базе, так как она имеет нужный ей контекст и почти без ошибок угадывает, какие паттерны применить, куда положить файлы, как задизайнить API и так далее.
Ниже — то, как новый подход ускорил нас.
1. Даже в нашей небольшой команде прожарка задач была бутылочным горлышком.
Помимо того, что она занимала огромное количество времени, зачастую она была очень муторной, и после неё зачастую не оставалось мыслетоплива для того, чтобы делать ещё что-то в течение дня.
2. Новый подход позволил нам распараллелить работу.
Так как все задачи прожарены наперёд, то я могу взять в работу задачу, для которой нужен бэк, понимая, что API не готово. И мне, в целом, без разницы, когда оно будет готово. Как будет готово — фича полностью заработает, а до этого момента просто будет скрыта от глаз пользователя.
Это особенно классно, учитывая то, что у нас есть много независимых задач, которые нужно делать только на фронте или только на бэке, из-за чего бывает очень сложно синхронизироваться, чтобы сделать/прожарить задачу, которая уже требует работы с обеих сторон. Сейчас эта проблема исчезла, ибо у нас просто отпала необходимость синхронизироваться друг с другом там, где это было необходимо раньше.
3. Мы можем брать задачи из другого домена.
Так на прошлой неделе наш менеджер, Оля, принесла юзер-стори, прожарила её через скилл в Claude Code, а затем на основе прожаренной карточки самостоятельно закрыла задачу.
Задача была на бэке, поэтому Дима, само собой, посмотрел код, немного поправил тесты и слил задачу в мастер. И всё это в рамках одного дня. В такие моменты особенно отчётливо приходит понимание, что эра разработчиков, которые умеют просто превращать прожаренные требования в код, подошла к концу.
Кстати, зацените распределение карточек по типам:
• 14 фичей
• 8 багов
• 2 технические задачи
• 1 исследование
То есть 32% закрытых карточек были багами. Думаю, что кому-то это число может показаться большим, поэтому давайте разберём, что там за баги:
• 4 бага связаны с огромной фичой на 70 тыс. строк (таблицы для Blok), которую я затащил за спринт до этого. Все баги — неучтённые edge-кейсы.
• 3 бага — те самые регрессии, которых все боятся при работе с агентами. Сценарии, в которых они возникали, уже покрыты тестами, так что снова не появятся:)
• 1 баг вообще находился не в нашем сервисе, но так как ребята из другого сервиса пока не могут пофиксить баг у себя, мы сделали изощрённую заплатку в нашем сервисе, до которой не додумались бы сами.
Так что, как видите, даже с учётом возросшей скорости и количества фичей, которые мы шипим, у нас произошло всего 12% регрессии за спринт. И это опять же очень классный результат!
P.S.
Уже в текущем спринте Оля закрыла ещё две задачи. Я их отревьюил и просто слил в мастер, так как доработки не требовались.
Да, пока Оля берёт в работу только небольшие задачи, но думаю, что со временем мы будем экспериментировать с карточками бо́льших размеров. Посмотрим, что из этого получится:)
❤6🔥4 4
Когда я ковырялся со скиллами для dotnet-агентов, то предположил, что нужно писать свой роутер — «если задача про бенчмарки, вызови microbenchmarking, если про дебаг — вызови clr-debugging»?
Но в комментариях появился аргумент: так оно же уже само все встроено.
Я если честно не знаю, но решил полезть в единственный более менее адекватный опенсорсный агент opencode. Просто хотелось хотя бы у кого-то лично в коде а не на основе предположений посмотреть, как оно там работаетъ.
Но есть множественные нюансы,
Как это работает внутри:
Skills provide specialized instructions and workflows for specif
Use the skill tool to load a skill when a task matches its description.
Available skills:
- microbenchmarking: Writing correct BDN benchmarks...
- csharp-scripts: Running one-file C# programs...
- clr-debugging: Analyzing CLR crash dumps...
То есть роутинг — это просто tool use. LLM читает описания скиллов в системном промпте и сам решает, какой вызвать. Точно так же, как он решает вызвать bash или grep — на основе описания.
Теперь про «а если скиллов 10, не запутается ли?». Тут есть два момента.
1️⃣ В системный промпт попадают только описания, не содержимое. Каждый скилл — это одна строчка: имя + description. 10 скиллов = 10 строк. Это не забивает контекстное окно. Содержимое скилла (инструкции, примеры, референсы) подгружается только когда LLM явно вызвал skill tool. Это ленивая загрузка — сначала агент видит меню, потом заказывает конкретное блюдо.
2️⃣ Качество роутинга зависит от качества description. Если у тебя два скилла с описаниями «helps with .NET» и «helps with C#» — агент будет путаться. Если описания конкретные — «Writing correct BenchmarkDotNet micro-benchmarks with proper allocation tracking» — модель попадает точно. Это та же история что и с описаниями kernel functions в Semantic Kernel: чем точнее Description, тем лучше LLM выбирает инструмент.
Есть ещё один слой — AGENTS.md (аналог CLAUDE.md). Туда можно написать правила, которые помогают в неочевидных случаях. Я у себя именно так делаю — в AGENTS.md описываю доп инфу которая поможет точнее понять, какой скилл вызывать если я употреблю неформальное слово типа “
🅰️ Итого:
В любом случае остается проблема замусоривания. Если вы накидали 100500 скиллов с похожими описаниями, но немного разными значениями, а потом благополучно забыли, что и зачем вы сами там понатыкали. Но это уже кожаномешковая проблема скорее.
А хотя… Может написать скилл, который будет периодически форсить юзера пересматривать список скиллов?
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - anomalyco/opencode: The open source coding agent.
The open source coding agent. Contribute to anomalyco/opencode development by creating an account on GitHub.
🔥4💅2 2
Ну что же. Вот и настала пора прощаться с этой ебанутой библиотекой на проде.
Как вы помните автомаппер после версии 14 стал платным. Я долго морозился чтобы не выпиливать это говно и просто не повышал версию.
Но 16 марта настал час Ч. В автомаппере нашлась критическая уязвимость и билд проекта с TreatWarningAsErrors просто падал и больше не собирался.
Можно было бы по пути ветра, конечно, и просто заигнорить. Но я подумал, что ну его нах.
Чтобы вы понимали в проекте из 100к строк эта зараза опутала ну довольно много функционала.
Агент пыхтел несколько часов. В итоге выдал 137 файлов чейнджей. И таки все выпилил.
Я решил не менять все это на какую-то другую библиотеку, или на какой-то бесплатный форк, а попросил просто все переделать на статические методы.
В итоге зарелизил. Два дня полет нормальный. Один минорный баг с отображением времени апдейта статьи.
Помогли как всегда тесты и покрытие ими. Но в старом коде покрытие конечно так себе. Так что там помогло просто попросить агента проанализировать каждый юзадж и дать отчет в виде текста.
Если тоже оттягивали момент отпила автомаппера. То кажется он настал.
ПС: у нас не было каких-то супер-мега сложных правил маппинга, но в целом какие-то правила все же были и все прошло норм.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10 2💘1