nodes-ui-flow / README.md
markitzeroo
Restore Hugging Face Space metadata
87118dc
---
title: Nodes UI Flow
emoji: 🤖
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
---
# Nodes UI Flow
Визуальный редактор интерактивных AI-сценариев: сценарий собирается из нод, запускается пошагово, задает вопросы пользователю, сохраняет ответы в память, ветвится по смыслу и может отвечать по knowledge-файлам.
Проект сейчас содержит пример для RosUpack 2026, но ноды сделаны универсальными: такой же граф можно собрать для другого стенда, продукта или процесса.
## Что внутри
- React + React Flow интерфейс для сборки графов.
- FastAPI backend для LLM-запросов, классификации, извлечения памяти и ответов по файлам.
- Выбор LLM provider в настройках: Ollama или DeepInfra.
- Перефразирование реплик ассистента при запуске нод, чтобы сценарий не звучал одинаково каждый раз.
- `LLM Test` режим: LLM сама проходит сценарий, а evaluator проверяет вопросы и ответы ассистента.
- Сохранение workflow в JSON.
- Knowledge-файлы, привязанные к конкретной `Knowledge Answer` ноде.
## Быстрый запуск на Windows
Ollama запускается отдельно вручную.
```bat
start_interface.bat
```
Скрипт откроет два окна:
- backend: `http://localhost:8000`
- frontend: `http://localhost:5173`
Остановить интерфейс можно закрытием этих двух окон.
## Ручной запуск
Backend:
```powershell
cd backend
python -m venv .venv
.\.venv\Scripts\activate
pip install -r requirements.txt
python main.py
```
Frontend:
```powershell
npm install
npm run dev
```
Production build:
```powershell
npm run build
```
## Структура проекта
```text
backend/ FastAPI backend
public/ frontend config and presets
scenarios/
dialog/ markdown versions of scenario scripts
knowledge/ curated knowledge bases for Knowledge Answer nodes
source/ original source documents
src/ React app, nodes and workflow runtime
workflows/ saved workflow JSON graphs
archive/ old or experimental workflow snapshots
start_interface.bat one-click Windows launcher
```
Runtime/generated folders are intentionally ignored by git:
```text
dist/
node_modules/
backend/.venv/
knowledge_contexts/
test_logs/
transcript_logs/
```
## Основной workflow
Главный пример:
```text
workflows/full_workflow.json
```
Knowledge base для него:
```text
scenarios/knowledge/rosupack_2026_knowledge_base.md
```
В `Knowledge Answer` ноде путь к файлу сохраняется прямо в JSON workflow, поэтому граф можно открыть после clone и продолжить использовать без повторного upload, если файл лежит в репозитории.
## Как устроен интерактивный сценарий
Типичный поток:
```text
Question -> Save Memory -> Assistant Message -> Semantic Branch -> Question/Message/... -> Knowledge Answer -> Restart
```
Runtime идет до первой `Question`, показывает вопрос в нижней панели и ждет ответ пользователя. Ответ можно:
- ввести руками;
- сгенерировать кнопкой `LLM answer`;
- включить `Auto LLM answer`, чтобы LLM отвечала сама на каждый новый вопрос.
Если у ноды включена галочка `Перефразировать при запуске`, backend перед показом реплики отправит текст в выбранный LLM provider и вернет новую формулировку с тем же смыслом. В transcript и дальше по графу попадет именно показанная пользователю версия.
## LLM provider
Provider выбирается в `Настройки`:
- `Ollama` — локальный режим, backend обращается к `http://localhost:11434`.
- `DeepInfra` — облачный OpenAI-compatible endpoint.
Для DeepInfra в настройках появляется поле API key. Ключ сохраняется локально в `backend/.deepinfra_api_key`, этот файл игнорируется git. Если ключ уже сохранен, поле можно оставить пустым, чтобы не менять его.
Thinking/reasoning в LLM-вызовах отключен: для Ollama backend отправляет `think: false`, для DeepInfra используется `reasoning_effort: none`.
## Основные типы портов
Порты окрашиваются по типу/смыслу, а не по цвету ноды.
- `turn` — объект одного шага диалога: вопрос, ответ и накопленный dialog.
- `dialog` / `dialog-in` — история сообщений.
- `question` — текст вопроса.
- `answer` — текст ответа пользователя.
- `string` — обычный текст.
- `object` — структурированные данные.
Один input может принимать несколько входящих связей. Это используется, когда несколько веток сходятся в общий блок, например в общий `Еще вопросы?`.
## Ключевые ноды
### Question
Задает вопрос ассистента и ставит workflow на паузу до ответа пользователя.
Используйте `turn` output, если дальше нужна вся пара вопрос/ответ. Используйте `dialog` или `dialog-in`, если важно сохранить историю реплик.
Опция `Перефразировать при запуске` заставляет LLM переписать вопрос перед показом пользователю.
### Assistant Message
Показывает реплику ассистента без ожидания пользовательского ответа.
Подходит для коротких объяснений, переходов между ветками и финальных историй.
Опция `Перефразировать при запуске` работает так же, как в `Question`: смысл сохраняется, формулировка может меняться.
### Save Memory
Извлекает значение из ответа пользователя и сохраняет его в память прогона.
Пример ключей:
```text
name
role
industry
scale
```
Значения доступны в шаблонах через фигурные скобки:
```text
{name}, хотели бы узнать что-то еще?
```
Если перед `Save Memory` был retry-переспрос, нода берет последний ответ пользователя из `dialog-in`, а не старый первый ответ из `turn`. Это важно для сценариев вроде проверки имени: пользователь может сначала ответить бессмыслицу, затем назвать имя, и в `{name}` сохранится именно последний корректный ответ.
### Semantic Branch
LLM выбирает один выход по смыслу ответа пользователя.
Один choice = один output. Альтернативы внутри одного choice пишутся через точку с запятой:
```text
да; хочу еще; давай; есть вопрос
нет; хватит; вернуться в начало
```
Точка с запятой означает альтернативные формулировки, а не условие, что все фразы должны встретиться одновременно.
Если ответ непонятен, `retry on unclear` может сразу переспросить пользователя на этой же точке сценария.
У retry-вопроса есть отдельная галочка `Перефразировать unclear-вопрос`, чтобы повторный вопрос звучал живее при нескольких неудачных ответах подряд.
### Knowledge Answer
Отвечает на вопрос пользователя по файлу, привязанному к конкретной ноде.
Поддерживаются:
- `.md`
- `.txt`
- `.docx`
- `.doc` как best-effort text extraction
При upload backend сохраняет оригинал и extracted text. Для репозиторных сценариев лучше хранить curated `.md` knowledge base в `scenarios/knowledge/` и указывать этот относительный путь в `contextPath`.
### Restart
Перезапускает интерактивный сценарий с начала.
Удобно для выставочного сценария: если пользователь больше не хочет задавать вопросы, можно вернуть ассистента в стартовое состояние.
### Request to LLM
Отправляет `system` и `user` prompt на backend.
Используйте для универсальных LLM-операций, которые не покрыты готовыми специализированными нодами.
### Component
Сворачивает часть графа во вложенный компонент.
Подходит для повторяющихся блоков, когда сценарий начинает разрастаться.
## Как соединять ноды
### Сохранить имя
```text
Question(turn) -> Semantic Branch(turn)
Question(turn) -> Save Memory(turn)
Semantic Branch(has-name) -> Save Memory(dialog-in)
Save Memory(dialog) -> Assistant Message(dialog-in)
```
`Semantic Branch` проверяет, есть ли в ответе имя. Если ответа недостаточно, `retry on unclear` сразу переспросит. `Save Memory` получает старый `turn` и свежий `dialog-in`; приоритет отдается последнему ответу пользователя из `dialog-in`, поэтому после переспроса сохраняется корректное имя.
### Ветвление по смыслу
```text
Question(turn) -> Semantic Branch(turn)
Semantic Branch(choice A) -> Node A(dialog-in)
Semantic Branch(choice B) -> Node B(dialog-in)
Semantic Branch(unclear) -> retry или fallback
```
### Общий финальный блок
```text
Branch A final message(dialog) -> Shared Question(dialog-in)
Branch B final message(dialog) -> Shared Question(dialog-in)
Branch C final message(dialog) -> Shared Question(dialog-in)
```
Так несколько веток сходятся в один общий вопрос без дублирования нод.
### Зацикливание knowledge-вопросов
```text
Question "Что узнать?"(turn) -> Knowledge Answer(turn)
Knowledge Answer(dialog) -> Question "Еще вопросы?"(dialog-in)
```
Так пользователь может задавать вопросы по файлу, пока не ответит, что больше вопросов нет.
## LLM answer и LLM Test
### LLM answer
Разово генерирует ответ пользователя на текущий вопрос.
### Auto LLM answer
Автоматически отвечает на каждый новый вопрос тем же prompt-ом тестового пользователя.
Prompt хранится в workflow JSON:
```json
{
"settings": {
"llmRolePrompt": "..."
}
}
```
### LLM Test
Отдельный режим тестирования сценария:
1. LLM проходит сценарий как пользователь.
2. После вопросов/ответов ассистента evaluator проверяет адекватность.
3. Если evaluator видит проблему, в JSONL-лог первым событием пишется причина.
4. Полный trace LLM-запросов сохраняется в `test_logs/`.
`LLM Test` можно остановить кнопкой `Stop LLM Test`.
## Логи
### UI logs
Правая панель показывает служебные события, ошибки, проверки evaluator и пути к файлам логов.
При `Auto LLM answer` и `LLM Test` обычные реплики не дублируются в правый служебный log, потому что они уже видны в transcript.
### Write logs
Галочка `Write logs` пишет простой текстовый transcript:
```text
ASSISTANT: ...
USER: ...
```
Файлы создаются в:
```text
transcript_logs/<workflow-name>/
```
Эта папка не коммитится.
### Test logs
`LLM Test` пишет подробные JSONL trace-файлы:
```text
test_logs/<workflow-name>/
```
Если evaluator считает вопрос или ответ плохим, первая строка файла будет `evaluation_failure_summary` с причиной.
## Скриншоты
Скриншоты UI лучше хранить отдельно от runtime-логов, например:
```text
scenarios/screenshots/
```
Рекомендуемые скрины для README:
- общий вид canvas с RosUpack workflow;
- нижняя interactive panel во время прогона;
- пример `Knowledge Answer` ноды с привязанным файлом;
- пример `Semantic Branch` с альтернативами через `;`.
## Git hygiene
В репозиторий должны попадать:
- `src/`
- `backend/main.py`
- `backend/requirements.txt`
- `public/`
- `workflows/`
- `scenarios/`
- конфиги приложения
В репозиторий не должны попадать:
- `node_modules/`
- `dist/`
- `backend/.venv/`
- `knowledge_contexts/`
- `test_logs/`
- `transcript_logs/`
## GitHub
Repository:
```text
https://github.com/markitzeroo/nodes-ui-flow
```
Repository is private.