# Zarządzanie wieloetapowymi dialogami w Pythonie za pomocą konfiguracji JSON
Rozwój ankiet, onboardingów i skomplikowanych wizardów często prowadzi do nagromadzenia logiki warunkowej, którą trudno utrzymywać i skalować. Biblioteka dialog-engine oferuje deklaratywną alternatywę: struktura dialogu, reguły widoczności pól i nawigacja są opisane w JSON lub YAML. Silnik samodzielnie oblicza dostępne kroki na podstawie kontekstu sesji, eliminując konieczność pisania zagnieżdżonych konstrukcji dla każdego scenariusza.
Deklaratywny sposób budowania wizardów
Tradycyjna implementacja formularzy krokowych wymaga jawnego zarządzania stanem. Programista ręcznie śledzi bieżący etap, sprawdza warunki przejścia i formuje interfejs. Przy zmianie logiki biznesowej lub dodaniu nowych gałęzi kod szybko się komplikuje, zamieniając w spaghetti z if i match. dialog-engine odwraca ten proces: dialog staje się zbiorem danych, a nie sekwencją instrukcji.
Plik konfiguracyjny zawiera tablicę kroków. Każdy element definiuje identyfikator, typ wejścia, tekst i opcjonalne parametry walidacji. Silnik nie interpretuje typów pól — text, choice, photo lub niestandardowe wartości pozostają na poziomie konwencji między konfiguracją a warstwą wyświetlania. Dzięki temu ten sam plik można wykorzystać dla bota Telegram, interfejsu webowego lub narzędzia konsolowego.
{
"steps": [
{ "id": "name", "type": "text", "text": "What is your name?" },
{ "id": "plan", "type": "choice", "text": "Choose a plan",
"choices": { "free": "Free", "pro": "Professional" } },
{ "id": "company_inn", "type": "text", "text": "Enter the company tax ID",
"show_when": { "field": "plan", "equals": "pro" } },
{ "id": "confirm", "type": "text", "text": "Is everything correct? Sending!" }
]
}
Instalacja rdzenia nie wymaga zewnętrznych zależności. Dodatkowe moduły podłącza się w miarę potrzeb za pomocą extras, co zachowuje lekką wagę podstawowej dystrybucji.
pip install dialog-engine
pip install dialog-engine[validation,yaml,aiogram]
Mechanizm warunkowej widoczności i nawigacji
Kluczową cechą silnika jest routowanie zależne od kontekstu. Zamiast hardkodowanych przejść używa się słownika z odpowiedziami użytkownika. Na jego podstawie obliczane są indeksy następnego i poprzedniego widocznego kroku. Ukryte etapy są automatycznie pomijane w pasku postępu i logice nawigacji, co gwarantuje poprawny licznik pozycji typu „krok 2 z 3”.
Warunki widoczności określa się za pomocą pól show_when i skip_when. Obsługiwane są podstawowe operatory porównania i sprawdzania istnienia, a także złożone reguły any_of i all_of do realizacji skomplikowanej logiki biznesowej. Reguły można zagnieżdżać bez ograniczeń głębokości.
{
"skip_when": {
"any_of": [
{ "field": "plan", "equals": "free" },
{ "field": "age", "lt": 18 }
]
}
}
Python API dostarcza metody do pracy z indeksami i pozycjami. Pozwala to precyzyjnie kontrolować stan sesji bez ręcznego przeszukiwania warunków.
ctx = {"plan": "free"}
next_idx = engine.next_index(1, ctx)
prev_idx = engine.previous_index(3, ctx)
pos = engine.effective_position(next_idx, ctx)
total = engine.effective_total(ctx)
if engine.is_last_visible(next_idx, ctx):
# Complete dialog
...
Do trwałości sesji przewidziano klasę DialogSessionState, która serializuje bieżący indeks i kontekst do JSON. Ułatwia to przechowywanie stanu w Redis lub relacyjnych bazach danych między żądaniami użytkownika.
Integracja z aiogram 3 i obsługa callbacków
Rdzeń biblioteki jest agnostyczny wobec frameworków, ale dla ekosystemu Telegram przygotowano gotowe pomocniki. Generują one klawiatury inline, automatycznie oznaczają wybrane wartości i tworzą poprawne callback_data. Obsługa kliknięć jest typowana i oddziela logikę wyboru, pominięcia i powrotu.
from dialog_engine.integrations.aiogram import (
build_step_keyboard,
parse_choice_callback,
is_named_callback,
KeyboardCallbacks,
)
step = engine.get_step(current_index)
kb = build_step_keyboard(step, translate, show_back=True, current_value=ctx.get(step.id))
await message.answer(step.text, reply_markup=kb)
Rozbiór przychodzących callbacków odbywa się za pomocą parserów, które zwracają identyfikator kroku i wybrane wartość. Eliminuje to konieczność ręcznego parsowania stringów callback.data i zmniejsza ryzyko kolizji prefiksów.
@router.callback_query()
async def on_callback(callback: CallbackQuery):
cb = KeyboardCallbacks()
pair = parse_choice_callback(callback.data, cb)
if pair:
step_id, choice_key = pair
ctx[step_id] = choice_key
next_idx = engine.next_index(current_index, ctx)
...
Narzędzia CLI i walidacja konfiguracji
Obsługa deklaratywnych konfiguracji wymaga narzędzi analizy statycznej. Dostarczany CLI pozwala sprawdzać strukturę pliku pod kątem duplikatów identyfikatorów, uszkodzony linków i błędów składniowych przed uruchomieniem aplikacji. Tryb ścisły używa Pydantic do pełnej weryfikacji typów.
dialog-engine validate wizard.json— podstawowa weryfikacja struktury.dialog-engine validate --strict wizard.json— walidacja przez Pydantic.dialog-engine mermaid wizard.json— generowanie diagramu przejść do dokumentacji.dialog-engine schema > dialog.schema.json— eksport JSON Schema do autouzupełniania w IDE.dialog-engine init -o my-dialog.json— tworzenie szablonu nowego dialogu.
Wbudowanie walidacji w potok CI/CD gwarantuje, że niepoprawne konfiguracje nie trafią do produkcji. JSON Schema zapewnia podświetlenie składni i podpowiedzi w edytorach kodu, co obniża próg wejścia dla menedżerów produktów i analityków edytujących ankiety.
Co ważne
- Dialog opisuje się deklaratywnie w JSON/YAML, co oddziela logikę biznesową od kodu aplikacji i pozwala edytować scenariusze bez wdrożenia.
- Nawigacja i widoczność kroków obliczane są dynamicznie na podstawie kontekstu sesji, eliminując zagnieżdżone konstrukcje warunkowe.
- Integracja z aiogram 3 dostarcza gotowe generatory klawiatur i typowane parsery callbacków, skracając ilość boilerplate-kodu.
- Narzędzia CLI i JSON Schema zapewniają statyczną weryfikację konfiguracji i wygodną pracę w IDE.
- Biblioteka dystrybuowana jest na licencji source-available: użycie w projektach dozwolone, modyfikacja i redystrybucja kodu źródłowego ograniczona.
— Editorial Team
Brak komentarzy.