semcod

← all projects

nlp2dsl

Reusable Python SDK for the NLP2DSL platform

Python updated 1w ago View on GitHub → Homepage

MVP Automation Platform

AI Cost Tracking

PyPI Version Python License
AI Cost Human Time Model

  • 🤖 LLM usage: $13.8505 (64 commits)
  • 👤 Human dev: ~$4015 (40.1h @ $100/h, 30min dedup)

Generated on 2026-07-07 using openrouter/qwen/qwen3-coder-next


System kompilujący intencje biznesowe (język naturalny) do wykonywalnych procesów w kontenerach Docker — z konwersacyjnym AI i dynamicznym UI.

Architektura

Użytkownik (tekst / głos / GUI)
        │
        ▼
┌──────────────────────────┐
│   NLP Service            │
│  ├─ Parser (rules/LLM)   │  ← rozumie język naturalny
│  ├─ Mapper (determ.)     │  ← buduje DSL
│  ├─ Orchestrator         │  ← conversation loop
│  └─ Schema generator     │  ← dynamic UI forms
└──────────┬───────────────┘
           ▼
┌──────────────────┐     ┌──────────────┐
│     Backend      │────▶│    Worker    │
│  (API Gateway)   │     │  (Executors) │
│  DSL Engine      │     └──────────────┘
└──────┬───────────┘
       │
  ┌────┴────┐
  │ Postgres│
  └─────────┘

Zasada: LLM rozumie → Pydantic waliduje → Mapper buduje → Docker wykonuje

Integracja z nlp2cmd

Repozytorium zawiera dwa poziomy:

Warstwa Lokalizacja Rola
Platforma MVP backend/, nlp-service/, worker/ Workflow DSL (faktury, e-mail, raporty) w Docker
SDK (wydzielone) packages/dsl-*, nlp2dsl-*, workflow-export, testql-conversations Kontrakty, walidacja, artefakty, eksport markpact/pactown
Mapa środowiska env2llm (semcod) environment.doql.less, SystemMapIR, registry
Pakiety IR packages/pact-ir, nlp2cmd-* IntentIR / ExecutionPlanIR — wspólny język z nlp2cmd i Propact

Podział odpowiedzialności

Narzędzie Zadanie
nlp2dsl show "query" Struktura zapytania (IntentIR) — bez wykonania
nlp2cmd plan "query" Plan → Propact markdown; --execute → hybrid executor (Propact + nlp2cmd)
nlp2cmd -q "query" -r Legacy runtime nlp2cmd (shell / browser / canvas)
*`examples//scenario.py`** Demo platformy MVP (wymaga docker compose up; main.py = punkt wejścia)

Instalacja pakietów (dev)

./scripts/setup-dev.sh          # pakiety IR + SDK + nlp2cmd[integration]
# lub tylko pakiety:
./packages/install-dev.sh

export NLP2CMD_INTEGRATION=1
nlp2dsl show "znajdz pliki *.py w src"               # IntentIR JSON
nlp2cmd plan "znajdz pliki *.py w src"               # Propact markdown
nlp2cmd plan "znajdz pliki *.py w src" --explain     # + execution_route
nlp2cmd plan "znajdz pliki *.py w src" --execute     # hybrid executor
NLP2CMD_SHOW_STRUCTURE=1 nlp2cmd -q "query"          # analiza na wejściu nlp2cmd

Szczegóły: packages/README.md · walidacja kontraktów: docs/intract-integration.md · walidacja requestu: docs/validation.md

Architektura pakietów IR

flowchart LR
    Q[NL query] --> SHOW[nlp2dsl show]
    Q --> PLAN[nlp2cmd plan]

    subgraph pkgs [packages/]
        IR[IntentIR]
        EPIR[ExecutionPlanIR]
    end

    SHOW --> IR
    SHOW --> EPIR
    PLAN --> IR --> EPIR --> MD[Propact markdown]

    EPIR -.->|NLP2CMD_INTRACT_GATE| GATE[PlanStepGate w nlp2cmd]
Narzędzie Walidacja struktury Kontrakty Intract
nlp2dsl show Pydantic + confidence opcjonalnie --plan + INTRACT_GATE
nlp2cmd plan needs_clarification zawsze opcjonalnie INTRACT_GATE
nlp2cmd -q -r ActionRegistry (legacy) opcjonalnie INTRACT_GATE

Kodowanie UTF-8 (polskie znaki)

Nie wymaga ręcznej konfiguracji. Import nlp2dsl_sdk oraz CLI (nlp2dsl, nlp2dsl-demo, nlp2dsl-show) automatycznie ustawiają stdio i locale na UTF-8 (naprawia m.in. znajd?znajdź).

Szczegóły: docs/encoding.md

Wyłączenie: NLP2DSL_UTF8=0

Artefakty przykładów (NLP → DSL → CMD → process)

examples/NN-name/.nlp2dsl/ — DOQL env (env2llm), manifest/pipeline/process (nlp2dsl-artifacts), TestQL (testql-conversations).

Pakiet Pliki
env2llm registry/environment.doql.less
nlp2dsl-artifacts manifest.yaml, pipeline/, process/, commands.testql.toon.yaml
workflow-export generated/markpact/, generated/pactown/ (examples 03, 04, 14)
nlp2dsl-stack generated/docker-compose.stack.yaml, cron (example 13)

Generowanie: bash examples/run-all.sh · docs: docs/artifacts.md · pakiety: packages/README.md

Szybki start

git clone <repo-url> && cd nlp2dsl
cp .env.example .env
# Uzupełnij klucze API (opcjonalne - system działa z parserem reguł)
docker compose up --build
# Poczekaj na health (SDK robi to automatycznie w przykładach):
curl -s http://localhost:8010/health && curl -s http://localhost:8012/health && curl -s http://localhost:8004/health
Serwis URL Opis
Backend API http://localhost:8010/docs Gateway + workflow engine
NLP Service http://localhost:8012/docs NLP + conversation + schema
Worker http://localhost:8004/docs Executory akcji

Port 8012 (nie 8002) — 8002 bywa zajęty przez Mullm Projector. Zmienne: NLP2DSL_BACKEND_HOST_PORT, NLP2DSL_NLP_HOST_PORT, NLP2DSL_WORKER_HOST_PORT w .env.

Walidacja requestu

Struktura zapytania (environment.doql.less / SystemMapIR) determinuje reguły walidacji w każdej fazie (preflight → DSL ready → execute → post-exec). Autonomiczna pętla naprawia brakujące dane i niepoprawne załączniki PDF zanim zapyta użytkownika.

Szczegóły: docs/validation.md · docs/process-agent.md · docs/reflection-model.md

Przykłady i tryb interaktywny

Szczegóły (Intract vs MVP, walidacja, logi, dialog): examples/README.md

# env2llm nie jest na PyPI — najpierw lokalne pakiety (semcod/env2llm + packages/)
bash scripts/install-local-deps.sh && pip install -e .
# lub: ./scripts/setup-dev.sh
docker compose up -d
python3 examples/06-interactive-chat/main.py --interactive   # rozmowa w terminalu
python3 examples/07-email-conversation/main.py               # e-mail + uzupełnianie body
./examples/run-all.sh

Conversation Loop (AI Dialog)

System prowadzi konwersację, dopytuje o brakujące dane i generuje dynamiczny formularz UI.

Rozpocznij rozmowę

# Tekst
curl -X POST http://localhost:8010/workflow/chat/start \
  -H "Content-Type: application/json" \
  -d '{"text": "Chcę wysłać fakturę"}'

# Audio (STT via Deepgram)
curl -X POST http://localhost:8010/workflow/chat/start \
  -F "audio=@nagranie.wav"

Odpowiedź (brakujące dane):

{
  "conversation_id": "a1b2c3d4e5f6",
  "status": "in_progress",
  "message": "Podaj: kwotę, adres e-mail odbiorcy",
  "missing": ["send_invoice.amount", "send_invoice.to"],
  "form": {
    "action": "send_invoice",
    "fields": [
      {"name": "amount", "type": "number", "label": "Kwota", "required": true},
      {"name": "to", "type": "email", "label": "Adres e-mail odbiorcy", "required": true},
      {"name": "currency", "type": "select", "label": "Waluta", "required": false, "options": ["PLN","EUR","USD","GBP"]}
    ]
  }
}

Uzupełnij dane

# Tekst
curl -X POST http://localhost:8010/workflow/chat/message \
  -H "Content-Type: application/json" \
  -d '{"conversation_id": "a1b2c3d4e5f6", "text": "1500 PLN na klient@firma.pl"}'

# Audio (STT via Deepgram)
curl -X POST http://localhost:8010/workflow/chat/message \
  -F "conversation_id=a1b2c3d4e5f6" \
  -F "audio=@odpowiedz.wav"

Uruchom workflow

curl -X POST http://localhost:8010/workflow/chat/message \
  -H "Content-Type: application/json" \
  -d '{"conversation_id": "a1b2c3d4e5f6", "text": "uruchom"}'

Schema-driven UI

Backend generuje schematy formularzy dynamicznie z rejestru akcji:

# Wszystkie akcje
curl http://localhost:8010/workflow/actions/schema

# Konkretna akcja
curl http://localhost:8010/workflow/actions/schema/send_invoice

Frontend renderuje formularze automatycznie z tych schematów — zero ręcznych formularzy.

One-shot Pipeline (bez dialogu)

# Generuj DSL
curl -X POST http://localhost:8010/workflow/from-text \
  -H "Content-Type: application/json" \
  -d '{"text": "Co tydzień generuj raport sprzedaży w PDF i wyślij email do manager@firma.pl"}'

# Generuj + wykonaj
curl -X POST http://localhost:8010/workflow/from-text \
  -H "Content-Type: application/json" \
  -d '{"text": "Wyślij fakturę na 1500 PLN do klient@firma.pl", "execute": true}'

Bezpośrednie uruchomienie DSL (JSON)

curl -X POST http://localhost:8010/workflow/run \
  -H "Content-Type: application/json" \
  -d '{
    "name": "invoice_and_email",
    "steps": [
      {"action": "send_invoice", "config": {"amount": 1500, "to": "klient@firma.pl", "currency": "PLN"}},
      {"action": "send_email", "config": {"to": "klient@firma.pl", "subject": "Faktura wystawiona"}}
    ]
  }'

Dostępne akcje

Akcja Wymagane Aliasy PL
send_invoice amount, to faktura, rachunek
send_email to email, maila, napisz
generate_report report_type raport, zestawienie
crm_update entity aktualizuj crm
notify_slack channel powiadom, slack

Composite intents (auto-wykrywane)

invoice_and_notify · invoice_and_email · report_and_email · full_invoice_flow · full_report_flow

Tryby NLP

Mode Opis
rules Offline, regex + aliasy (domyślny)
llm LLM API (OpenAI / Anthropic / Ollama)
auto Rules first, LLM fallback

Speech-to-Text (Deepgram)

System obsługuje wejście głosowe w Conversation Loop:

# Konfiguracja w .env
DEEPGRAM_API_KEY=

# Użycie
curl -X POST http://localhost:8010/workflow/chat/start \
  -F "audio=@nagranie.wav"

Obsługiwane formaty audio:

  • WAV, MP3, M4A, OGG, FLAC
  • Język: polski (domyślny), konfigurowalny
  • Model: nova-3-general (Deepgram)

Streaming STT:

Dla konwersacji w czasie rzeczywistym użyj WebSocket:

from audio_parser import StreamingSTT

stt = StreamingSTT(language="pl")
await stt.start()
await stt.send_audio(chunk)
transcript = await stt.get_transcript()

Voice Chat UI (PWA)

System zawiera gotowy interfejs webowy z obsługą głosową:

# Otwórz w przeglądarce
http://localhost:8012/chat

Funkcje:

  • 🎤 Voice input - kliknij Start Voice i mów
  • 📝 Text input - wpisz wiadomość ręcznie
  • 🔄 Real-time - WebSocket streaming
  • 📱 PWA - instaluj jako aplikację mobilną/desktopową

Automatyczny start:

<!-- Auto-connect i auto-voice na onload -->
<body onload="initVoice()">

Kiosk mode (desktop/embedded):

# Chrome kiosk
chrome --kiosk --autoplay-policy=no-user-gesture-required http://localhost:8012/chat

# Electron app
npm install electron
# main.js: win.loadURL('http://localhost:8012/chat')

Tauri desktop wrapper

Jeśli chcesz desktopową powłokę zamiast samej przeglądarki, użyj wrappera w tauri-wrapper/.
Ten projekt otwiera istniejący backendowy ekran /chat, więc nie duplikuje logiki STT/TTS.
W trybie dev wrapper uruchamia lokalny launcher na http://127.0.0.1:1420, a potem przechodzi do backendowego czatu, gdy /health odpowie OK.

Jeśli na Twoim Linuxie Tauri blokują brakujące biblioteki WebKitGTK/GTK, użyj browserowego fallbacku:
cd tauri-wrapper && npm run desktop albo bash ./desktop.sh.
Otwiera on ten sam /chat w Chrome/Chromium w trybie --app.

Linux prerequisites

Na Linuxie Tauri v1 wymaga systemowych bibliotek WebKitGTK/GTK. Jeśli npm run dev kończy się błędem z brakującymi libsoup-2.4 albo javascriptcoregtk-4.0, doinstaluj:

sudo apt install build-essential curl wget file libssl-dev libgtk-3-dev \
  libwebkit2gtk-4.0-dev libsoup2.4-dev libjavascriptcoregtk-4.0-dev \
  libayatana-appindicator3-dev librsvg2-dev

Jeśli używasz innej dystrybucji, zainstaluj odpowiednie odpowiedniki pakietów deweloperskich WebKitGTK/GTK.

Uruchomienie

cd tauri-wrapper
npm install
npm run dev

Jeśli nie chcesz instalować bibliotek systemowych albo Tauri nie startuje, użyj:

cd tauri-wrapper
npm run desktop

Launcher sprawdza backend pod http://127.0.0.1:8012 i dopiero potem przełącza do http://127.0.0.1:8012/chat.

Build

cd tauri-wrapper
npm run build

Desktop fallback launcher

Jeśli chcesz ominąć Tauri na danym systemie, użyj tauri-wrapper/desktop.sh.
Skrypt czeka na backend, a potem otwiera voice chat w Chrome/Chromium w trybie --app.
To dobre rozwiązanie, gdy środowisko nie ma wymaganych bibliotek WebKitGTK dla Tauri.

Konfiguracja LLM:

  1. Skopiuj .env.example.env
  2. Uzupełnij klucz API wybranego providera:
# OpenRouter (domyślny)
OPENROUTER_API_KEY=
LLM_MODEL=openrouter/openai/gpt-5-mini

# Speech-to-Text (Deepgram)
DEEPGRAM_API_KEY=

# Lub OpenAI
OPENAI_API_KEY=
LLM_MODEL=gpt-4o-mini

# Lub Anthropic
ANTHROPIC_API_KEY=
LLM_MODEL=claude-sonnet-4-...

# Lub Ollama (lokalny)
OLLAMA_API_BASE=http://localhost:11434
LLM_MODEL=ollama/llama3

Zmienne są automatycznie przekazywane do kontenerów w docker-compose.yml.

Struktura projektu

nlp2dsl/
├── docker-compose.yml
├── .env.example                 # Konfiguracja LLM i serwisów (porty 8010/8012/8004)
├── nlp2dsl_sdk/                 # SDK klienta, DOQL, walidacja, reflection
├── docs/                        # Dokumentacja (indeks: docs/README.md)
├── examples/                    # Przykłady użycia
│   ├── 01-invoice/
│   ├── 02-email/
│   ├── 03-report-and-notify/
│   ├── 04-scheduled-report/
│   ├── 05-conversation-flow/
│   ├── README.md
│   ├── EXECUTION_REPORT.md
│   └── MISSING_CONFIGURATION.md
├── backend/                     # API Gateway + Workflow Engine
│   └── app/
│       ├── main.py
│       ├── engine.py            # Workflow execution + pre-step validation
│       └── routers/chat.py      # Chat proxy + auto_execute
├── nlp-service/                 # NLP → DSL Pipeline
│   └── app/
│       ├── conversation/        # orchestrator, autonomous_loop, process_agent
│       ├── validation/          # step_validator, attachment, path_policy
│       ├── registry.py          # Actions registry (migracja → DOQL)
│       └── ...
├── worker/                      # Imperatywne executory + invoice_pdf
│   └── worker.py
├── tauri-wrapper/               # Desktop wrapper Tauri dla `/chat`
└── README.md

Pełna dokumentacja: docs/README.md

Przykłady użycia

Zobacz examples/README.md dla pełnej listy przykładów:

Jeśli chcesz od razu uruchomić gotowy scenariusz bez tworzenia wrappera, użyj pakietowego CLI:

nlp2dsl-demo --list
nlp2dsl-demo gallery
# Uruchom wszystkie przykłady
cd examples
for dir in */; do
    echo "Testing $dir"
    cd "$dir"
    python3 main.py
    cd - > /dev/null
done

Dostępne przykłady:

Przykład Link Opis Koncepcje
01-invoice 📁 examples/01-invoice/ Faktura autonomiczna + PDF + walidacja strict DOQL autofill, attachment_validation, reflection
02-email 📁 examples/02-email/ Różne sposoby wysyłania e-maili Aliasy komend, parametry
03-report-and-notify 📁 examples/03-report-and-notify/ Raporty + powiadomienia na wiele kanałów Composite intents, multi-step
04-scheduled-report 📁 examples/04-scheduled-report/ Zaplanowane raporty (daily/weekly/monthly) Triggers, schedule
05-conversation-flow 📁 examples/05-conversation-flow/ Pełny cykl konwersacyjny od startu do wykonania Chat API, state management

Szybki start z przykładami:

bash scripts/install-local-deps.sh && pip install -e .
docker compose up -d                        # backend + nlp-service + worker
python3 examples/01-invoice/main.py       # czeka na /health (do 120 s)

./examples/run-all.sh                       # wszystkie przykłady
# lub pojedynczo:
cd examples/01-invoice && python3 main.py

SDK (ensure_services) sprawdza http://localhost:8010, :8012, :8004 — nie uruchamiaj main.py w tej samej linii co compose up bez oczekiwania (race przy starcie uvicorn).

Logi serwisu NLP (z roota repo, nie examples/docker-compose.yml):

docker compose logs -f nlp-service

Obsługa błędów i fallback

System jest odporny na brakującą konfigurację:

  • Brak kluczy LLM: Automatycznie używa parsera reguł
  • Brak Redis: In-memory storage (utrata danych przy restarcie)
  • Brak bazy: Ograniczone funkcje (brak historii)
  • Mock integracje: Worker zwraca symulowane odpowiedzi

Szczegóły w examples/MISSING_CONFIGURATION.md.

Docker i .env

Każdy przykład zawiera:

  • Dockerfile - konteneryzacja
  • requirements.txt - zależności Python
  • .env.example - szablon konfiguracji

Opcjonalne serwisy pomocnicze:

docker compose -f examples/docker-compose.yml --profile email up -d smtp-mock
docker compose -f examples/docker-compose.yml --profile storage up -d minio

Dodanie nowej akcji

  1. nlp-service/app/registry.py — dodaj do ACTIONS_REGISTRY
  2. worker/worker.py — dodaj handler @action("nazwa")
  3. docker compose up --build

License

Licensed under Apache-2.0.