From 118232fa1dd1635bb249a15a02286da09407c8d0 Mon Sep 17 00:00:00 2001 From: Oleg Proskurin Date: Sat, 30 May 2026 14:36:51 +0700 Subject: [PATCH] add esse --- .../supabase-ai-tooling-essay-q1-eval-loop.md | 55 +++++++++++++++ ...oling-essay-q2-knowledge-representation.md | 70 +++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 base/reference/supabase-ai-tooling-essay-q1-eval-loop.md create mode 100644 base/reference/supabase-ai-tooling-essay-q2-knowledge-representation.md diff --git a/base/reference/supabase-ai-tooling-essay-q1-eval-loop.md b/base/reference/supabase-ai-tooling-essay-q1-eval-loop.md new file mode 100644 index 0000000..1c71413 --- /dev/null +++ b/base/reference/supabase-ai-tooling-essay-q1-eval-loop.md @@ -0,0 +1,55 @@ +# Supabase — AI Tooling Engineer — Эссе Q1 (Eval system / instrumentation loop) + +## Метаданные + +- **Компания:** Supabase +- **Роль:** AI Tooling Engineer +- **Канал подачи:** ashbyhq, через careers-page Supabase +- **Дата подачи:** 29 мая 2026 +- **CV использовано:** CV-A (cv-2026-05-base.md), pdf-вариант `oleg_proskurin_ai_engineer_fullstack_cv.pdf` +- **Статус:** подано, ожидаем ответа + +## Вопрос (дословно) + +> Tell us about an eval system, instrumentation loop, or quality framework you built for an AI product or workflow. What did you measure, and how did it change the product? + +## Выбранный угол + +**Track A — Reliability loop.** Schema-validation-driven retry как ядро, instrumentation per step, добор по cost/cache как data-driven decision. Прямая связка: measure → tune → ship-ready output. + +## Финальный текст ответа (English, как подано) + +> On PrimeUI (see primeui.com, released Feb 2026) I've built the page generation flow. It takes a project brief and assembles a page from components from a registry where we have more than 200 real React components. The flow should generate content per component, that match the component schema and cohere with entire page content. The hard part is that one page has to satisfy several things at once: coherent content for the page's purpose, a valid component choice from the registry, props matching each component's schema, and a combination of components that holds up against strict design requirements. +> +> I created the per-component selection and content generation via an LLM (Gemini 2.5 Flash via Mastra), one request per step. And I had to build a harness around it. At each step the model picks from a pre-filtered pool of candidates ranked by a UX scoring system that judge how component combinations sit well together. Each step also gets the component registry, the already-generated content, and the page outline. The model returns structured JSON: component name, props object, and reasoning for the choice. The result is validated against the chosen component's schema (AJV with custom fields). On a validation hit the request repeats with an error message in feedback. After N retries it takes a fallback component. Components persist to DB only after they pass. +> +> Each step logs: cache-hit ratio, latency, retry count, and the UX score of the selected components. Running the generation many times with these logs gave me enough data to analyze. I built a Claude Code skill with instructions on how to compare and analyze the logs, used it to detect repeating patterns and weak spots in the generation, and was able to improve the process significantly. +> +> Before tuning, around 5 of 7 steps on a page needed at least one retry, now it's down to 1-2 of 7. Generation time went from 5-7 minutes to 2-3 minutes per page variant. Component schemas were tuned as well to generate semantically better copy. The overall result: generation quality went up, the flow got significantly faster, and token consumption dropped thanks to better cache hits. + +## Источники материала + +- `cv-master-extended.md` — Block 4 (Eval & guardrails facts: AJV, retry triggers, MAX_GENERATION_RETRIES=5, per-step logging) +- Русский harness-текст из Lucky Hunter / XPN-чатов (последняя вычищенная версия, прошла финализацию в апреле 2026) +- Ранний Q1-драфт из этого же Supabase-чата (с TODO про harness/AJV — там же были числа compact notation 5x, reduced rendering 10-12x, retry 15-20→2-4, time 5-7→2-3 min) +- Уточнения от Олега в этой подаче: метрика «5 of 7 → 1-2 of 7» вместо «15-20 → 2-4», причина ухода от RAG («analyzed, not effective for this scenario»), `up to 150K tokens`, UX scoring как «modeled on designers' and frontend folks' expert judgment» + +## Ключевые приёмы (что делает эссе сильным — для будущего реюза) + +1. **Структура «проблема → решение → инструментация → измеримый сдвиг → продуктовое последствие».** Каждый абзац отвечает на отдельную часть вопроса. +2. **Connect measure → change.** Конкретные before/after: 5/7 → 1-2/7 ретраев, 5-7min → 2-3min. Без этого ответ распадается на «вот наш сетап». +3. **Claude Code skill как анализ-петля.** Добавлено в финальной итерации Олегом — это и есть «how did it change the product»: не просто метрики, а *использование* метрик для улучшения. Сильнее, чем «мы логировали». +4. **Voice signatures сохранены:** `that match`, `that judge`, `from components from a registry`, `with entire page content`, длинные цепочки через запятую, drop -s в 3rd person, фраза-заголовок + двоеточие (`The overall result:`). +5. **Что вырезано в цикле редактирования:** + - em-dashes на parentheticals + - триколоны прилагательных (narrow/predictable/typed → narrow/typed) + - «not X but Y» конструкции + - «Worth saying that», «It's important to note» + - `200+` → `more than 200` (N+ нотация как маркер) +6. **Цена за слово высокая.** ~290 слов финальной версии, ни одного абстрактного прилагательного без числа за ним. + +## Что можно адаптировать для других подач + +- **Core spine (problem → harness → instrumentation → measured change)** переносится без изменений на любую AI-инженерную роль с уклоном в production reliability. +- **Claude Code skill как анализ-петля** — уникальный приём, добавляет signal зрелого AI-augmented workflow. Использовать когда target отзывается на AI-augmented dev practices. +- **Числа из этого эссе можно повторять буквально:** 5/7 → 1-2/7, 5-7min → 2-3min, up to 150K tokens, more than 200 components, AJV with custom fields. Это всё проверенные формулировки. diff --git a/base/reference/supabase-ai-tooling-essay-q2-knowledge-representation.md b/base/reference/supabase-ai-tooling-essay-q2-knowledge-representation.md new file mode 100644 index 0000000..2981c56 --- /dev/null +++ b/base/reference/supabase-ai-tooling-essay-q2-knowledge-representation.md @@ -0,0 +1,70 @@ +# Supabase — AI Tooling Engineer — Эссе Q2 (Docs / interfaces / tooling for agents) + +## Метаданные + +- **Компания:** Supabase +- **Роль:** AI Tooling Engineer +- **Канал подачи:** ashbyhq, через careers-page Supabase +- **Дата подачи:** 29 мая 2026 +- **CV использовано:** CV-A (cv-2026-05-base.md), pdf-вариант `oleg_proskurin_ai_engineer_fullstack_cv.pdf` +- **Статус:** подано, ожидаем ответа + +## Вопрос (дословно) + +> How would you design docs, product interfaces, or developer tooling so agents can use them effectively? + +## Выбранный угол + +**Knowledge representation deep-dive.** Сознательно отказались от двухполушарной структуры (MCP interface + knowledge representation), хотя она ровно матчила формулировку JD. Решили: один глубокий разворот сильнее, чем два поверхностных. MCP оставлен на интервью. + +Сердце ответа — компактный реестр компонентов: minified rendering functions (8KB → 700B на компонент), compact notation для пропсов (1.5KB → 300B из Zod-схем), extended schemas с descriptions и стилями (1.5KB на компонент в итоговом виде). + +## Финальный текст ответа (English, как подано) + +> The actual problem I faced in PrimeUI was how to pass our component library to the page generation LLM so it can properly use it. Let me highlight the issues with the original source first: +> +> - each component has React component code, TypeScript props, and an additional Zod schema. On top of that each one has a markdown file with description, functionality, "where to use", style details, etc. +> - dependencies. Many files have imported components. +> - huge length of definition: component code is big plus types, schemas, and description. Consumes a lot of tokens if passed raw. +> - the amount of components started from 100 and grew to 200. +> - even with Zod schemas we can't fully rely on them, because we have a lot of semantic and design-driven requirements. E.g. number of words in titles, discrete number of cards, capitalization styles, etc. +> - component code actually repeats in many components. Has a lot of functionality that isn't useful for an LLM. Too noisy to detect the look and feel of a component, its purpose. +> +> Having that I realized we can't just pass component code to a model. First attempt was a RAG system over component code, but it still faced the problem that component structure isn't visible because of the noise from classes, functionalities, tons of HTML tags etc. While the goal was to select each component wisely. +> +> The solution I proposed and implemented is creating a special components registry. The essential parts of which: +> +> - minified reduced functions instead of real components. It just outputs simplified HTML code with rendered props. This is enough to understand the structure of an actual component and easy to render existing content during the generation loop. Reduced code size from around 8KB per component to around 700B. +> - special compact notation schema describing component props. I created a syntax that allows describing not only formal requirements but also LLM-important relationships and styles. Managed to reduce from around 1.5KB in zod files to around 300B. +> - extended compact schemas also with component descriptions and visual styles. Finally one component definition in the registry takes approx 1.5K and provides LLM-friendly information about component functionality and usage. +> +> The total component registry was compact enough to put into the model's context window. I selected Gemini Flash 2.5 after some tests across Anthropic, OpenAI, and Gemini models, as a good candidate because of good performance, speed, and caching support. The biggest part of the context is our registry, which is always the same across all client projects and pages, so it always gets cached. Up to 77% cache hit, with reasonable generation speed. +> +> The registry generation is our own internal AI flow involving a few AI agents and deterministic code. It lets any engineer on our team add and update components in PrimeUI. For clients, when they export their project, we provide a production-ready Next.js codebase with the selected components and their props: it works like a usual project. + +## Источники материала + +- Драфт Олега в этой подаче (написан с нуля под этот вопрос, не из других чатов) +- `cv-master-extended.md` — Block 1 (RAG / Retrieval facts) для контекста про переход от RAG к cached registry +- Уточнения по числам: 77% cache hit (тут vs 73% в CV — Олег подтвердил 77%), 8KB→700B, 1.5KB→300B, total ~1.5K per component, registry started from 100 grew to 200 + +## Ключевые приёмы (что делает эссе сильным) + +1. **Структура «проблема изнутри → решение через данные».** Список конкретных issues с реальной кодовой базой → реализованное решение с числами. Не теоретизирование «как бы я спроектировал», а «я столкнулся, я решил так». +2. **Числа per-component compression на каждом пункте решения.** 8KB→700B, 1.5KB→300B, итог 1.5K. Это редкий уровень детализации. Любая компания с eval-first культурой считывает зрелость по таким цифрам. +3. **First attempt → solution.** RAG-первая-попытка показана как тупик, после неё — финальное решение. Это сильнее, чем сразу выложить решение. Показывает инженерный путь, а не готовую теорию. +4. **77% cache hit как закрывающий числовой anchor.** Связывает выбор модели (Gemini Flash 2.5) с инструментацией (registry в кэше) и продуктовым следствием (reasonable speed). +5. **Сознательный отказ от MCP-половины.** На этапе финальной редактуры обсуждали: добавлять ли абзац про MCP server, чтобы закрыть второй буллет JD. Решили — нет: глубокий ответ на одну половину сильнее поверхностного на обе. MCP держим на интервью. +6. **Voice signatures сохранены:** `Having that I realized`, `While the goal was to select each component wisely`, постпозиционные `from`, длинные комма-цепочки, фраза-заголовок + двоеточие, drop -s в `that match`, drop article в bullet points. + +## Что вырезано / не делали + +- MCP-абзац (см. п.5 выше) +- pgvector mention (был nice-to-have в JD, но решили не натягивать — реальный реестр в JSON, не в pgvector) +- Промежуточные эксперименты с другими моделями названы не были — оставлено как «after some tests across Anthropic, OpenAI, and Gemini models» + +## Что можно адаптировать для других подач + +- **Spine «issues with original source → first attempt → solution with numbers»** — переносимая структура для любого вопроса вида «как бы вы спроектировали X для агентов». Реальный кейс всегда сильнее гипотетического. +- **Числа compression (8KB→700B, 1.5KB→300B, 77% cache)** — все проверенные, можно реюзать буквально. +- **Если в другой подаче нужен MCP-угол** — он есть в `cv-master-extended.md` Block 2 (25 tools, official SDK, 6 хостов). Можно собрать отдельное эссе или короткий абзац к этому.