ADR: Почему TextFoundry сделан как самостоятельный продукт, а не как решение на базе DSPy

1. Статус и назначение документа

Статус: принят как продуктово-архитектурное объяснение текущего направления.

Назначение: зафиксировать, почему проект был спроектирован как собственный authoring and delivery workbench с библиотекой блоков, композициями, версионированием и desktop UI, а не как тонкая надстройка вокруг DSPy.

2. Контекст

На уровне идеи оба подхода частично пересекаются:

  • и DSPy, и TextFoundry работают с prompt/program abstractions;

  • и там, и там есть интерес к управлению качеством LLM-поведения;

  • и там, и там можно думать о composition, optimization и reuse.

Но фактическая задача TextFoundry с самого начала была другой.

Цель проекта не сводилась к тому, чтобы:

  • программно оптимизировать prompts в Python-рантайме;

  • строить исследовательский pipeline вокруг телеметрии модели;

  • опираться на кодовые abstractions как на основной пользовательский интерфейс.

Реальная задача продукта:

  • сделать библиотеку prompt-блоков как управляемый актив;

  • дать пользователю визуальный authoring workflow;

  • поддержать версии блоков и композиций;

  • отделить deterministic assembly от optional AI assistance;

  • обеспечить inspectable desktop/TUI workbench, а не только программный SDK.

3. Проблема, которую нужно было решить

Нужно было выбрать базовую архитектурную ставку:

  • строить продукт поверх внешнего framework-мышления вроде DSPy;

  • или сделать собственную доменную модель и собственный workbench под задачу управления prompt-артефактами.

Если взять DSPy как центральную основу, возникают вопросы:

  • где будет жить библиотека версионируемых блоков;

  • как представить composition как stable asset, а не просто кодовую цепочку;

  • как дать non-programmatic authoring workflow;

  • как удержать строгую границу между deterministic render и AI-assisted edits;

  • как сделать локальный desktop-first UX с просмотром, сравнением и ручной публикацией.

4. Рассмотренные варианты

Вариант A. Построить продукт как thin layer поверх DSPy

Идея: использовать DSPy как основной каркас и добавить немного своей оболочки для хранения и UI.

Плюсы:

  • можно переиспользовать известный framework;

  • часть терминологии про prompt programs уже существует;

  • меньше своей низкоуровневой логики в начале.

Минусы:

  • центр тяжести смещается в сторону Python/framework runtime, а не в сторону самостоятельной библиотеки артефактов;

  • продукт начинает наследовать чужую модель мира, а не свою;

  • desktop workbench, версионирование блоков и композиции оказываются вторичными или "навешанными сверху";

  • deterministic render path как независимый core перестаёт быть естественным центром архитектуры.

Вердикт:

  • отклонено.

Вариант B. Использовать отдельные идеи DSPy выборочно, но не строить продукт вокруг него

Идея: смотреть на DSPy как на источник отдельных идей про decomposition, evaluation, prompt-program thinking, но не делать его базовым platform layer.

Плюсы:

  • можно заимствовать полезные подходы;

  • продукт сохраняет свою доменную модель;

  • не возникает жёсткой зависимости от чужого runtime.

Минусы:

  • часть удобств framework нужно реализовывать самостоятельно;

  • архитектурные решения и документацию приходится прорабатывать глубже самим.

Вердикт:

  • по сути это и есть принятая траектория.

Вариант C. Построить самостоятельный продукт вокруг domain model TextFoundry

Идея: центром архитектуры сделать не framework, а собственные сущности:

  • Block

  • Composition

  • Renderer

  • versioned storage

  • desktop/TUI authoring surfaces

  • optional AI adapters

Плюсы:

  • архитектура полностью соответствует задаче продукта;

  • UI и storage становятся первичными, а не побочными;

  • deterministic core легко отделяется от AI workflows;

  • можно поддерживать explicit human-in-the-loop publishing;

  • система не зависит от чужой эволюции API и философии.

Минусы:

  • больше своей архитектурной и продуктовой работы;

  • меньше готовых высокоуровневых абстракций "из коробки";

  • нужно самостоятельно строить дисциплину evaluation и documentation.

Вердикт:

  • выбранный вариант.

5. Принятое решение

Принято решение строить TextFoundry как самостоятельный продукт и собственный prompt authoring/delivery workbench, а не как приложение, ядром которого является DSPy.

Это означает:

  • доменная модель проекта первична и формулируется в терминах блоков, композиций, версий и render contracts;

  • AI-функции подключаются через adapter interfaces и explicit workflows;

  • GUI/TUI являются частью архитектуры продукта, а не вспомогательной обвязкой;

  • продукт ориентирован на управление prompt assets, а не только на programmatic orchestration в коде.

6. Почему DSPy не стал основой продукта

6.1. У продукта другой центр тяжести

DSPy естественно мыслится через программируемые модули, оптимизацию и framework-driven execution.

TextFoundry мыслится через:

  • библиотеку контентных артефактов;

  • их визуальное редактирование;

  • их versioned lifecycle;

  • воспроизводимую сборку и доставку.

То есть главный объект здесь не "программируемый пайплайн модели", а "управляемый набор prompt assets".

6.2. Нужен был deterministic core, не зависящий от framework runtime

В TextFoundry есть сознательная граница:

  • Renderer и versioned repositories образуют deterministic ядро;

  • AI работает поверх ядра только по явному запросу.

Такую модель удобнее строить от своего engine, чем от framework, который изначально фокусируется на LLM-program behavior.

6.3. Продукт требовал desktop-first authoring surfaces

Система строится не только для разработчика, пишущего Python-код, но для оператора, который:

  • просматривает блоки;

  • редактирует композиции;

  • сравнивает версии;

  • нажимает generate / normalize / rewrite;

  • вручную публикует изменения.

Это не похоже на тонкий слой над библиотекой оптимизации prompt-programs.

6.4. Нужна была строгая human-in-the-loop модель

Во всех AI-функциях проекта зафиксировано:

  • AI предлагает draft;

  • человек делает review;

  • публикация остаётся отдельным действием.

Такая операционная философия лучше ложится на собственный asset-centric workbench, чем на framework-centric execution model.

6.5. Версионирование блоков и композиций является базовой функцией, а не дополнением

Если блоки и композиции являются первичными сущностями, то:

  • нужна история версий;

  • нужны explicit publish/update/deprecate flows;

  • composition должна ссылаться на конкретные версии блоков;

  • derivation workflows должны быть трассируемыми.

Это не похоже на "обвязку" вокруг чужого framework. Это и есть ядро продукта.

6.6. Требовалась свобода в развитии интеграций и runtime boundaries

Проекту нужны свои границы:

  • OpenAI-compatible transport;

  • ObjectBox storage;

  • Qt GUI/TUI;

  • planned prompt-server;

  • возможные будущие provider strategies.

Если поставить в центр DSPy, то часть этих решений будет постоянно сопоставляться с его моделью вместо собственной.

7. Что при этом можно брать из DSPy-мира

Этот ADR не утверждает, что DSPy бесполезен или концептуально чужд.

Из него можно и дальше заимствовать идеи:

  • decomposition mindset;

  • evaluation discipline;

  • интерес к качественным метрикам prompt behavior;

  • представление о prompt logic как о системно управляемой конструкции.

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

8. Последствия решения

Положительные:

  • продуктовая архитектура лучше соответствует реальной задаче;

  • код и документация формулируются в собственных доменных терминах;

  • проще удерживать границу deterministic core vs explicit AI workflows;

  • легче развивать GUI/TUI как first-class surface.

Компромиссы:

  • больше своей платформенной ответственности;

  • меньше готовых framework abstractions;

  • архитектурные решения приходится проговаривать и документировать самим.

Отрицательные:

  • выше стоимость проектирования и сопровождения;

  • часть возможностей, похожих на framework tooling, нужно строить вручную.

9. Что важно не исказить в будущем

Даже если позже проект заимствует больше идей или интеграций из DSPy-экосистемы, не следует размывать следующие принципы:

  • TextFoundry остаётся asset-centric продуктом;

  • blocks and compositions остаются первичными сущностями;

  • deterministic render остаётся отдельным базовым контрактом;

  • AI остаётся explicit assistive layer, а не неявной основой всей системы;

  • authoring surfaces остаются частью архитектуры, а не побочным интерфейсом.