nardial 0.2.2__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nardial-0.2.2/src/nardial.egg-info → nardial-0.3.2}/PKG-INFO +130 -27
- nardial-0.2.2/PKG-INFO → nardial-0.3.2/README.md +123 -48
- {nardial-0.2.2 → nardial-0.3.2}/pyproject.toml +11 -3
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/factory.py +14 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/conversation_agent.py +104 -14
- nardial-0.3.2/src/nardial/events/__init__.py +11 -0
- nardial-0.3.2/src/nardial/events/bus.py +182 -0
- nardial-0.3.2/src/nardial/events/types.py +68 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/interaction_orchestrator.py +86 -52
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/mini_dialogs.py +249 -49
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/moves.py +210 -1
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/__init__.py +2 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/__init__.py +1 -1
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/__init__.py +9 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/dialogflow.py +3 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/nlu/written_keyword.py +3 -0
- nardial-0.3.2/src/nardial/providers/screen/__init__.py +126 -0
- nardial-0.3.2/src/nardial/providers/screen/null.py +46 -0
- nardial-0.3.2/src/nardial/providers/screen/pepper_tablet.py +155 -0
- nardial-0.3.2/src/nardial/providers/screen/sic_adapter.py +272 -0
- nardial-0.3.2/src/nardial/providers/screen/web/static/screen.css +190 -0
- nardial-0.3.2/src/nardial/providers/screen/web/static/screen.js +215 -0
- nardial-0.3.2/src/nardial/providers/screen/web/static/socket.io.min.js +7 -0
- nardial-0.3.2/src/nardial/providers/screen/web/templates/index.html +32 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/__init__.py +9 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/elevenlabs.py +3 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/google.py +3 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/naoqi.py +3 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/null.py +3 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/session_manager.py +61 -11
- nardial-0.2.2/README.md → nardial-0.3.2/src/nardial.egg-info/PKG-INFO +151 -25
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/SOURCES.txt +12 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/requires.txt +8 -1
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_conversation_agent.py +43 -21
- nardial-0.3.2/tests/test_event_bus.py +60 -0
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_llm.py +35 -22
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_mini_dialogs_extra.py +39 -26
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_moves.py +28 -19
- {nardial-0.2.2 → nardial-0.3.2}/LICENSE +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/setup.cfg +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/__init__.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/__init__.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/export_html.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/authoring/loader.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/conversation_state.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/dialog_logic.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/alphamini.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/desktop.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/nao.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/device/pepper.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/__init__.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/echo.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/llm/openai_gpt.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/tts/cacher.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/__init__.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/null.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/providers/vector_store/redis_store.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial/user_model.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/dependency_links.txt +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/src/nardial.egg-info/top_level.txt +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_authoring_factory.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_conversation_state.py +0 -0
- {nardial-0.2.2 → nardial-0.3.2}/tests/test_providers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nardial
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Nardial Dialog System
|
|
5
5
|
Author-email: Mike Ligthart <m.e.u.ligthart@vu.nl>
|
|
6
6
|
Maintainer: Clara Fayyad, Landon Brown, Evelyne Prodescu
|
|
@@ -17,15 +17,20 @@ Provides-Extra: dialogflow
|
|
|
17
17
|
Requires-Dist: social-interaction-cloud[dialogflow]; extra == "dialogflow"
|
|
18
18
|
Provides-Extra: openai
|
|
19
19
|
Requires-Dist: social-interaction-cloud[openai-gpt]; extra == "openai"
|
|
20
|
+
Provides-Extra: webserver
|
|
21
|
+
Requires-Dist: social-interaction-cloud[webserver]; extra == "webserver"
|
|
20
22
|
Provides-Extra: all
|
|
21
|
-
Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai]; extra == "all"
|
|
23
|
+
Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai,webserver]; extra == "all"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
22
27
|
Dynamic: license-file
|
|
23
28
|
|
|
24
29
|
# NarDialPy
|
|
25
30
|
|
|
26
31
|
**NarDialPy** is a Python package for building and running **narrative-driven, structured dialog systems** — designed for social robots and conversational agents.
|
|
27
32
|
|
|
28
|
-
It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, and
|
|
33
|
+
It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, LLM, and browser-based screen services. The package handles session flow, branching logic, topic tracking, personalization, and screen output so you can focus on what the robot says and how conversations unfold.
|
|
29
34
|
|
|
30
35
|
---
|
|
31
36
|
|
|
@@ -53,6 +58,7 @@ The `nardial` package provides the building blocks for authoring and executing m
|
|
|
53
58
|
| **Dialog JSON** | Conversations are written as structured JSON files. Each file holds one or more *dialogs*, each containing a sequence of *moves* that the robot performs. |
|
|
54
59
|
| **Session Manager** | Loads your dialog JSON, resolves a session agenda, and runs dialogs in order — checking dependencies and tracking state. |
|
|
55
60
|
| **ConversationAgent** | The runtime bridge to the hardware: it calls TTS, STT, LLM, and motion services on your chosen device. |
|
|
61
|
+
| **Screen Provider** | Optional browser-based display layer for transcripts, images, videos, HTML, buttons, and web input. |
|
|
56
62
|
| **Dialog Logic** | Checks eligibility rules (dependencies, variable requirements) before executing each dialog. |
|
|
57
63
|
|
|
58
64
|
Typical use case:
|
|
@@ -165,6 +171,7 @@ NarDialPy is built around a set of provider protocols. Each protocol defines a r
|
|
|
165
171
|
| | `WrittenKeywordNLUProvider` | `nardial.providers.nlu.written_keyword` | base (keyboard input) |
|
|
166
172
|
| **LLM** | `OpenAIGPTProvider` | `nardial.providers.llm.openai_gpt` | `nardial[openai]` |
|
|
167
173
|
| | `EchoLLMProvider` | `nardial.providers.llm.echo` | base (echoes user input) |
|
|
174
|
+
| **Screen** | `ScreenProvider` / `SICScreenAdapter` / `PepperTabletScreenAdapter` | `nardial.providers.screen` | browser display via SIC webserver |
|
|
168
175
|
| **Vector store** | `RedisVectorStoreProvider` | `nardial.providers.vector_store.redis_store` | base + running Redis |
|
|
169
176
|
| | `NullVectorStoreProvider` | `nardial.providers.vector_store.null` | base |
|
|
170
177
|
|
|
@@ -351,7 +358,7 @@ Utility dialogs for session management — greetings, farewells, and structural
|
|
|
351
358
|
{
|
|
352
359
|
"type": "ask_open",
|
|
353
360
|
"text": "Please tell me your name.",
|
|
354
|
-
"set_variable": "first_name"
|
|
361
|
+
"set_variable": "first_name"
|
|
355
362
|
}
|
|
356
363
|
]
|
|
357
364
|
}
|
|
@@ -366,7 +373,7 @@ Short, theme-based conversations on everyday topics. Chitchat dialogs can be see
|
|
|
366
373
|
| Extra field | Type | Required | Description |
|
|
367
374
|
|---|---|---|---|
|
|
368
375
|
| `theme` | string | ✅ | Broad category (e.g. `"nature"`, `"animals"`, `"robots"`) |
|
|
369
|
-
| `topics` | array of strings | | Specific keywords used
|
|
376
|
+
| `topics` | array of strings | | Specific keywords used to drive relevance matching |
|
|
370
377
|
|
|
371
378
|
```json
|
|
372
379
|
{
|
|
@@ -501,7 +508,7 @@ Asks a free-text question and listens for any spoken reply. The answer can be st
|
|
|
501
508
|
"type": "ask_open",
|
|
502
509
|
"text": "What is your favorite color?",
|
|
503
510
|
"set_variable": "favorite_color",
|
|
504
|
-
"add_interest_from_answer": true
|
|
511
|
+
"add_interest_from_answer": true
|
|
505
512
|
}
|
|
506
513
|
```
|
|
507
514
|
|
|
@@ -675,29 +682,125 @@ Triggers a named animation behavior on the robot.
|
|
|
675
682
|
|
|
676
683
|
---
|
|
677
684
|
|
|
685
|
+
#### `timed_wait`
|
|
686
|
+
|
|
687
|
+
Pause execution for a fixed duration before proceeding to the next move. Useful to add natural pauses or give the user time to look at the screen.
|
|
688
|
+
|
|
689
|
+
| Field | Type | Required | Description |
|
|
690
|
+
|---|---|---|---|
|
|
691
|
+
| `type` | string | ✅ | `"timed_wait"` |
|
|
692
|
+
| `duration_seconds` | number | ✅ | Seconds to wait. (Alias: `duration` is also accepted.) |
|
|
693
|
+
|
|
694
|
+
```json
|
|
695
|
+
{ "type": "timed_wait", "duration_seconds": 2.5 }
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
---
|
|
699
|
+
|
|
700
|
+
#### `wait_for_web_input`
|
|
701
|
+
|
|
702
|
+
Suspend dialog execution until a matching web input event arrives or until a timeout elapses. The web UI can present buttons or a short input and emit `web_input` events which this move listens for.
|
|
703
|
+
|
|
704
|
+
| Field | Type | Required | Description |
|
|
705
|
+
|---|---|---|---|
|
|
706
|
+
| `type` | string | ✅ | `"wait_for_web_input"` |
|
|
707
|
+
| `prompt` | string | | Hint text shown in the web UI (not spoken) |
|
|
708
|
+
| `options` | array of strings | | Accepted `value` strings from the web event (if omitted, any value is accepted) |
|
|
709
|
+
| `timeout` | number | | Seconds to wait before falling back (omit for indefinite wait) |
|
|
710
|
+
| `outcomes` | object | | Maps option value → outcome label for branching |
|
|
711
|
+
| `default_outcome` | string | | Outcome used on timeout or when no event matches |
|
|
712
|
+
|
|
713
|
+
```json
|
|
714
|
+
{
|
|
715
|
+
"type": "wait_for_web_input",
|
|
716
|
+
"prompt": "Choose a sticker to show",
|
|
717
|
+
"options": ["smile","thumbs","surprised"],
|
|
718
|
+
"timeout": 15,
|
|
719
|
+
"outcomes": {"smile": "picked_smile"},
|
|
720
|
+
"default_outcome": "no_choice"
|
|
721
|
+
}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
---
|
|
725
|
+
|
|
726
|
+
#### `show_image`
|
|
727
|
+
|
|
728
|
+
Display an image on the connected screen (browser / tablet). Accepts a local path relative to the static assets directory or a full URL.
|
|
729
|
+
|
|
730
|
+
| Field | Type | Required | Description |
|
|
731
|
+
|---|---|---|---|
|
|
732
|
+
| `type` | string | ✅ | `"show_image"` |
|
|
733
|
+
| `src` | string | ✅ | Path or URL to the image (aliases: `image`, `path`) |
|
|
734
|
+
|
|
735
|
+
```json
|
|
736
|
+
{ "type": "show_image", "src": "assets/images/robot_pet.png" }
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
#### `show_video`
|
|
742
|
+
|
|
743
|
+
Display a video on the screen. Can accept a local file path or an embeddable URL (e.g. a YouTube embed link).
|
|
744
|
+
|
|
745
|
+
| Field | Type | Required | Description |
|
|
746
|
+
|---|---|---|---|
|
|
747
|
+
| `type` | string | ✅ | `"show_video"` |
|
|
748
|
+
| `src` | string | ✅ | Video file path or embeddable URL (aliases: `video`, `path`) |
|
|
749
|
+
|
|
750
|
+
```json
|
|
751
|
+
{ "type": "show_video", "src": "https://www.youtube.com/embed/VIDEO_ID" }
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
#### `show_iframe`
|
|
757
|
+
|
|
758
|
+
Embed an external web page inside an iframe on the screen. Use this for interactive web content served from a trusted origin.
|
|
759
|
+
|
|
760
|
+
| Field | Type | Required | Description |
|
|
761
|
+
|---|---|---|---|
|
|
762
|
+
| `type` | string | ✅ | `"show_iframe"` |
|
|
763
|
+
| `url` | string | ✅ | URL to embed (aliases: `src`, `iframe_url`) |
|
|
764
|
+
|
|
765
|
+
```json
|
|
766
|
+
{ "type": "show_iframe", "url": "https://example.com/mini-game" }
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
#### `show_html`
|
|
772
|
+
|
|
773
|
+
Render a raw HTML snippet directly into the display area. The frontend inserts this via innerHTML — treat content as trusted and avoid injecting untrusted user data.
|
|
774
|
+
|
|
775
|
+
| Field | Type | Required | Description |
|
|
776
|
+
|---|---|---|---|
|
|
777
|
+
| `type` | string | ✅ | `"show_html"` |
|
|
778
|
+
| `html` | string | ✅ | HTML snippet to render |
|
|
779
|
+
|
|
780
|
+
```json
|
|
781
|
+
{ "type": "show_html", "html": "<div class=\"card\">Hi there!</div>" }
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
---
|
|
785
|
+
|
|
786
|
+
#### `black_screen`
|
|
787
|
+
|
|
788
|
+
Clear the display (show a blank/black screen). No parameters — the next display move will restore content.
|
|
789
|
+
|
|
790
|
+
| Field | Type | Required | Description |
|
|
791
|
+
|---|---|---|---|
|
|
792
|
+
| `type` | string | ✅ | `"black_screen"` |
|
|
793
|
+
|
|
794
|
+
```json
|
|
795
|
+
{ "type": "black_screen" }
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
---
|
|
799
|
+
|
|
678
800
|
### Key JSON Attributes
|
|
679
801
|
|
|
680
802
|
| Attribute | Where used | Description |
|
|
681
803
|
|---|---|---|
|
|
682
|
-
| `id` | dialog | Unique dialog identifier |
|
|
683
|
-
| `type` | dialog | Dialog type: `functional`, `chitchat`, `narrative`, `llm_based` |
|
|
684
|
-
| `functional_type` | functional dialog | `"greeting"` or `"farewell"` |
|
|
685
|
-
| `thread` | narrative dialog | Story thread name |
|
|
686
|
-
| `position` | narrative dialog | Order within the thread |
|
|
687
|
-
| `theme` | chitchat dialog | Broad topic category |
|
|
688
|
-
| `topics` | chitchat dialog | Keywords for relevance matching |
|
|
689
|
-
| `prompt` | llm_based dialog / `ask_llm` | LLM system prompt |
|
|
690
|
-
| `moves` | dialog | Ordered list of move objects |
|
|
691
|
-
| `dependencies` | dialog | Dialog IDs that must be completed first |
|
|
692
|
-
| `variable_dependencies` | dialog | Variables that must exist in the user model |
|
|
693
|
-
| `set_variable` | move | Saves the user's answer into the user model |
|
|
694
|
-
| `outcomes` | move | Maps answers/intents to outcome labels for branching |
|
|
695
|
-
| `default_outcome` | move | Fallback outcome when no match is found |
|
|
696
|
-
| `add_interest` | `ask_yesno` move | Adds a fixed topic when user says yes |
|
|
697
|
-
| `add_interest_from_answer` | `ask_open` move | Adds the spoken answer as a topic of interest |
|
|
698
|
-
| `add_interest_from_variable` | `ask_open` / `ask_options` move | Adds the stored variable's value as a topic |
|
|
699
|
-
| `llm_followup` | ask moves | System prompt for an inline LLM follow-up response |
|
|
700
|
-
| `%variable%` | `text` values | Placeholder replaced at runtime with the stored variable value |
|
|
701
804
|
|
|
702
805
|
---
|
|
703
806
|
|
|
@@ -708,6 +811,8 @@ All you need is a minimal Python script that wires up the device, loads the dial
|
|
|
708
811
|
Two ready-to-run demos are included in the `examples/` directory:
|
|
709
812
|
* Demo 1 — General Conversation (`demo_general_conversation.py`): A simple four-step conversation using a mix of narrative and functional dialogs
|
|
710
813
|
* Demo 2 — Structured Conversation (`demo_structured_conversation.py`): A more complete example that demonstrates all dialog types and move types, including `ask_llm`, `play`, `motion_sequence`, and `animation`
|
|
814
|
+
* Demo 3 — Screen Display (`demo_screen_provider.py`): Shows the browser-based screen UI with transcripts, images, iframes, HTML snippets, buttons, and text input
|
|
815
|
+
* Demo 4 — Pepper Tablet (`demo_pepper_tablet.py`): Uses the same screen UI on Pepper's tablet through the SIC webserver
|
|
711
816
|
|
|
712
817
|
You can find additional demos in the [SIC Applications repository](https://github.com/Social-AI-VU/sic_applications/tree/main/demos/nardial)
|
|
713
818
|
|
|
@@ -720,5 +825,3 @@ Run tests from the repository root:
|
|
|
720
825
|
```bash
|
|
721
826
|
python -m pytest -q
|
|
722
827
|
```
|
|
723
|
-
|
|
724
|
-
---
|
|
@@ -1,31 +1,8 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: nardial
|
|
3
|
-
Version: 0.2.2
|
|
4
|
-
Summary: Nardial Dialog System
|
|
5
|
-
Author-email: Mike Ligthart <m.e.u.ligthart@vu.nl>
|
|
6
|
-
Maintainer: Clara Fayyad, Landon Brown, Evelyne Prodescu
|
|
7
|
-
License-Expression: AGPL-3.0-only
|
|
8
|
-
Requires-Python: >=3.12
|
|
9
|
-
Description-Content-Type: text/markdown
|
|
10
|
-
License-File: LICENSE
|
|
11
|
-
Requires-Dist: social-interaction-cloud
|
|
12
|
-
Provides-Extra: google-tts
|
|
13
|
-
Requires-Dist: social-interaction-cloud[google-tts]; extra == "google-tts"
|
|
14
|
-
Provides-Extra: elevenlabs
|
|
15
|
-
Requires-Dist: social-interaction-cloud[elevenlabs-tts]; extra == "elevenlabs"
|
|
16
|
-
Provides-Extra: dialogflow
|
|
17
|
-
Requires-Dist: social-interaction-cloud[dialogflow]; extra == "dialogflow"
|
|
18
|
-
Provides-Extra: openai
|
|
19
|
-
Requires-Dist: social-interaction-cloud[openai-gpt]; extra == "openai"
|
|
20
|
-
Provides-Extra: all
|
|
21
|
-
Requires-Dist: nardial[dialogflow,elevenlabs,google-tts,openai]; extra == "all"
|
|
22
|
-
Dynamic: license-file
|
|
23
|
-
|
|
24
1
|
# NarDialPy
|
|
25
2
|
|
|
26
3
|
**NarDialPy** is a Python package for building and running **narrative-driven, structured dialog systems** — designed for social robots and conversational agents.
|
|
27
4
|
|
|
28
|
-
It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, and
|
|
5
|
+
It lets you author complete conversations declaratively in JSON, then drive them from Python using voice, NLU, LLM, and browser-based screen services. The package handles session flow, branching logic, topic tracking, personalization, and screen output so you can focus on what the robot says and how conversations unfold.
|
|
29
6
|
|
|
30
7
|
---
|
|
31
8
|
|
|
@@ -53,6 +30,7 @@ The `nardial` package provides the building blocks for authoring and executing m
|
|
|
53
30
|
| **Dialog JSON** | Conversations are written as structured JSON files. Each file holds one or more *dialogs*, each containing a sequence of *moves* that the robot performs. |
|
|
54
31
|
| **Session Manager** | Loads your dialog JSON, resolves a session agenda, and runs dialogs in order — checking dependencies and tracking state. |
|
|
55
32
|
| **ConversationAgent** | The runtime bridge to the hardware: it calls TTS, STT, LLM, and motion services on your chosen device. |
|
|
33
|
+
| **Screen Provider** | Optional browser-based display layer for transcripts, images, videos, HTML, buttons, and web input. |
|
|
56
34
|
| **Dialog Logic** | Checks eligibility rules (dependencies, variable requirements) before executing each dialog. |
|
|
57
35
|
|
|
58
36
|
Typical use case:
|
|
@@ -165,6 +143,7 @@ NarDialPy is built around a set of provider protocols. Each protocol defines a r
|
|
|
165
143
|
| | `WrittenKeywordNLUProvider` | `nardial.providers.nlu.written_keyword` | base (keyboard input) |
|
|
166
144
|
| **LLM** | `OpenAIGPTProvider` | `nardial.providers.llm.openai_gpt` | `nardial[openai]` |
|
|
167
145
|
| | `EchoLLMProvider` | `nardial.providers.llm.echo` | base (echoes user input) |
|
|
146
|
+
| **Screen** | `ScreenProvider` / `SICScreenAdapter` / `PepperTabletScreenAdapter` | `nardial.providers.screen` | browser display via SIC webserver |
|
|
168
147
|
| **Vector store** | `RedisVectorStoreProvider` | `nardial.providers.vector_store.redis_store` | base + running Redis |
|
|
169
148
|
| | `NullVectorStoreProvider` | `nardial.providers.vector_store.null` | base |
|
|
170
149
|
|
|
@@ -351,7 +330,7 @@ Utility dialogs for session management — greetings, farewells, and structural
|
|
|
351
330
|
{
|
|
352
331
|
"type": "ask_open",
|
|
353
332
|
"text": "Please tell me your name.",
|
|
354
|
-
"set_variable": "first_name"
|
|
333
|
+
"set_variable": "first_name"
|
|
355
334
|
}
|
|
356
335
|
]
|
|
357
336
|
}
|
|
@@ -366,7 +345,7 @@ Short, theme-based conversations on everyday topics. Chitchat dialogs can be see
|
|
|
366
345
|
| Extra field | Type | Required | Description |
|
|
367
346
|
|---|---|---|---|
|
|
368
347
|
| `theme` | string | ✅ | Broad category (e.g. `"nature"`, `"animals"`, `"robots"`) |
|
|
369
|
-
| `topics` | array of strings | | Specific keywords used
|
|
348
|
+
| `topics` | array of strings | | Specific keywords used to drive relevance matching |
|
|
370
349
|
|
|
371
350
|
```json
|
|
372
351
|
{
|
|
@@ -501,7 +480,7 @@ Asks a free-text question and listens for any spoken reply. The answer can be st
|
|
|
501
480
|
"type": "ask_open",
|
|
502
481
|
"text": "What is your favorite color?",
|
|
503
482
|
"set_variable": "favorite_color",
|
|
504
|
-
"add_interest_from_answer": true
|
|
483
|
+
"add_interest_from_answer": true
|
|
505
484
|
}
|
|
506
485
|
```
|
|
507
486
|
|
|
@@ -675,29 +654,125 @@ Triggers a named animation behavior on the robot.
|
|
|
675
654
|
|
|
676
655
|
---
|
|
677
656
|
|
|
657
|
+
#### `timed_wait`
|
|
658
|
+
|
|
659
|
+
Pause execution for a fixed duration before proceeding to the next move. Useful to add natural pauses or give the user time to look at the screen.
|
|
660
|
+
|
|
661
|
+
| Field | Type | Required | Description |
|
|
662
|
+
|---|---|---|---|
|
|
663
|
+
| `type` | string | ✅ | `"timed_wait"` |
|
|
664
|
+
| `duration_seconds` | number | ✅ | Seconds to wait. (Alias: `duration` is also accepted.) |
|
|
665
|
+
|
|
666
|
+
```json
|
|
667
|
+
{ "type": "timed_wait", "duration_seconds": 2.5 }
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
---
|
|
671
|
+
|
|
672
|
+
#### `wait_for_web_input`
|
|
673
|
+
|
|
674
|
+
Suspend dialog execution until a matching web input event arrives or until a timeout elapses. The web UI can present buttons or a short input and emit `web_input` events which this move listens for.
|
|
675
|
+
|
|
676
|
+
| Field | Type | Required | Description |
|
|
677
|
+
|---|---|---|---|
|
|
678
|
+
| `type` | string | ✅ | `"wait_for_web_input"` |
|
|
679
|
+
| `prompt` | string | | Hint text shown in the web UI (not spoken) |
|
|
680
|
+
| `options` | array of strings | | Accepted `value` strings from the web event (if omitted, any value is accepted) |
|
|
681
|
+
| `timeout` | number | | Seconds to wait before falling back (omit for indefinite wait) |
|
|
682
|
+
| `outcomes` | object | | Maps option value → outcome label for branching |
|
|
683
|
+
| `default_outcome` | string | | Outcome used on timeout or when no event matches |
|
|
684
|
+
|
|
685
|
+
```json
|
|
686
|
+
{
|
|
687
|
+
"type": "wait_for_web_input",
|
|
688
|
+
"prompt": "Choose a sticker to show",
|
|
689
|
+
"options": ["smile","thumbs","surprised"],
|
|
690
|
+
"timeout": 15,
|
|
691
|
+
"outcomes": {"smile": "picked_smile"},
|
|
692
|
+
"default_outcome": "no_choice"
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
---
|
|
697
|
+
|
|
698
|
+
#### `show_image`
|
|
699
|
+
|
|
700
|
+
Display an image on the connected screen (browser / tablet). Accepts a local path relative to the static assets directory or a full URL.
|
|
701
|
+
|
|
702
|
+
| Field | Type | Required | Description |
|
|
703
|
+
|---|---|---|---|
|
|
704
|
+
| `type` | string | ✅ | `"show_image"` |
|
|
705
|
+
| `src` | string | ✅ | Path or URL to the image (aliases: `image`, `path`) |
|
|
706
|
+
|
|
707
|
+
```json
|
|
708
|
+
{ "type": "show_image", "src": "assets/images/robot_pet.png" }
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
#### `show_video`
|
|
714
|
+
|
|
715
|
+
Display a video on the screen. Can accept a local file path or an embeddable URL (e.g. a YouTube embed link).
|
|
716
|
+
|
|
717
|
+
| Field | Type | Required | Description |
|
|
718
|
+
|---|---|---|---|
|
|
719
|
+
| `type` | string | ✅ | `"show_video"` |
|
|
720
|
+
| `src` | string | ✅ | Video file path or embeddable URL (aliases: `video`, `path`) |
|
|
721
|
+
|
|
722
|
+
```json
|
|
723
|
+
{ "type": "show_video", "src": "https://www.youtube.com/embed/VIDEO_ID" }
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
---
|
|
727
|
+
|
|
728
|
+
#### `show_iframe`
|
|
729
|
+
|
|
730
|
+
Embed an external web page inside an iframe on the screen. Use this for interactive web content served from a trusted origin.
|
|
731
|
+
|
|
732
|
+
| Field | Type | Required | Description |
|
|
733
|
+
|---|---|---|---|
|
|
734
|
+
| `type` | string | ✅ | `"show_iframe"` |
|
|
735
|
+
| `url` | string | ✅ | URL to embed (aliases: `src`, `iframe_url`) |
|
|
736
|
+
|
|
737
|
+
```json
|
|
738
|
+
{ "type": "show_iframe", "url": "https://example.com/mini-game" }
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
#### `show_html`
|
|
744
|
+
|
|
745
|
+
Render a raw HTML snippet directly into the display area. The frontend inserts this via innerHTML — treat content as trusted and avoid injecting untrusted user data.
|
|
746
|
+
|
|
747
|
+
| Field | Type | Required | Description |
|
|
748
|
+
|---|---|---|---|
|
|
749
|
+
| `type` | string | ✅ | `"show_html"` |
|
|
750
|
+
| `html` | string | ✅ | HTML snippet to render |
|
|
751
|
+
|
|
752
|
+
```json
|
|
753
|
+
{ "type": "show_html", "html": "<div class=\"card\">Hi there!</div>" }
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
---
|
|
757
|
+
|
|
758
|
+
#### `black_screen`
|
|
759
|
+
|
|
760
|
+
Clear the display (show a blank/black screen). No parameters — the next display move will restore content.
|
|
761
|
+
|
|
762
|
+
| Field | Type | Required | Description |
|
|
763
|
+
|---|---|---|---|
|
|
764
|
+
| `type` | string | ✅ | `"black_screen"` |
|
|
765
|
+
|
|
766
|
+
```json
|
|
767
|
+
{ "type": "black_screen" }
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
---
|
|
771
|
+
|
|
678
772
|
### Key JSON Attributes
|
|
679
773
|
|
|
680
774
|
| Attribute | Where used | Description |
|
|
681
775
|
|---|---|---|
|
|
682
|
-
| `id` | dialog | Unique dialog identifier |
|
|
683
|
-
| `type` | dialog | Dialog type: `functional`, `chitchat`, `narrative`, `llm_based` |
|
|
684
|
-
| `functional_type` | functional dialog | `"greeting"` or `"farewell"` |
|
|
685
|
-
| `thread` | narrative dialog | Story thread name |
|
|
686
|
-
| `position` | narrative dialog | Order within the thread |
|
|
687
|
-
| `theme` | chitchat dialog | Broad topic category |
|
|
688
|
-
| `topics` | chitchat dialog | Keywords for relevance matching |
|
|
689
|
-
| `prompt` | llm_based dialog / `ask_llm` | LLM system prompt |
|
|
690
|
-
| `moves` | dialog | Ordered list of move objects |
|
|
691
|
-
| `dependencies` | dialog | Dialog IDs that must be completed first |
|
|
692
|
-
| `variable_dependencies` | dialog | Variables that must exist in the user model |
|
|
693
|
-
| `set_variable` | move | Saves the user's answer into the user model |
|
|
694
|
-
| `outcomes` | move | Maps answers/intents to outcome labels for branching |
|
|
695
|
-
| `default_outcome` | move | Fallback outcome when no match is found |
|
|
696
|
-
| `add_interest` | `ask_yesno` move | Adds a fixed topic when user says yes |
|
|
697
|
-
| `add_interest_from_answer` | `ask_open` move | Adds the spoken answer as a topic of interest |
|
|
698
|
-
| `add_interest_from_variable` | `ask_open` / `ask_options` move | Adds the stored variable's value as a topic |
|
|
699
|
-
| `llm_followup` | ask moves | System prompt for an inline LLM follow-up response |
|
|
700
|
-
| `%variable%` | `text` values | Placeholder replaced at runtime with the stored variable value |
|
|
701
776
|
|
|
702
777
|
---
|
|
703
778
|
|
|
@@ -708,6 +783,8 @@ All you need is a minimal Python script that wires up the device, loads the dial
|
|
|
708
783
|
Two ready-to-run demos are included in the `examples/` directory:
|
|
709
784
|
* Demo 1 — General Conversation (`demo_general_conversation.py`): A simple four-step conversation using a mix of narrative and functional dialogs
|
|
710
785
|
* Demo 2 — Structured Conversation (`demo_structured_conversation.py`): A more complete example that demonstrates all dialog types and move types, including `ask_llm`, `play`, `motion_sequence`, and `animation`
|
|
786
|
+
* Demo 3 — Screen Display (`demo_screen_provider.py`): Shows the browser-based screen UI with transcripts, images, iframes, HTML snippets, buttons, and text input
|
|
787
|
+
* Demo 4 — Pepper Tablet (`demo_pepper_tablet.py`): Uses the same screen UI on Pepper's tablet through the SIC webserver
|
|
711
788
|
|
|
712
789
|
You can find additional demos in the [SIC Applications repository](https://github.com/Social-AI-VU/sic_applications/tree/main/demos/nardial)
|
|
713
790
|
|
|
@@ -720,5 +797,3 @@ Run tests from the repository root:
|
|
|
720
797
|
```bash
|
|
721
798
|
python -m pytest -q
|
|
722
799
|
```
|
|
723
|
-
|
|
724
|
-
---
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nardial"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Nardial Dialog System"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.12"
|
|
@@ -28,8 +28,13 @@ dependencies = [
|
|
|
28
28
|
google-tts = ["social-interaction-cloud[google-tts]"]
|
|
29
29
|
elevenlabs = ["social-interaction-cloud[elevenlabs-tts]"]
|
|
30
30
|
dialogflow = ["social-interaction-cloud[dialogflow]"]
|
|
31
|
-
openai
|
|
32
|
-
|
|
31
|
+
openai = ["social-interaction-cloud[openai-gpt]"]
|
|
32
|
+
webserver = ["social-interaction-cloud[webserver]"]
|
|
33
|
+
all = ["nardial[google-tts,elevenlabs,dialogflow,openai,webserver]"]
|
|
34
|
+
dev = ["pytest", "pytest-asyncio"]
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
asyncio_mode = "auto"
|
|
33
38
|
|
|
34
39
|
[tool.setuptools]
|
|
35
40
|
package-dir = {"" = "src"}
|
|
@@ -37,3 +42,6 @@ license-files = ["LICENSE"]
|
|
|
37
42
|
|
|
38
43
|
[tool.setuptools.packages.find]
|
|
39
44
|
where = ["src"]
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.package-data]
|
|
47
|
+
"nardial.providers.screen" = ["web/templates/*.html", "web/static/*.css", "web/static/*.js"]
|
|
@@ -11,6 +11,13 @@ from nardial.moves import (
|
|
|
11
11
|
MOVE_MOTION_SEQUENCE,
|
|
12
12
|
MOVE_ANIMATION,
|
|
13
13
|
MOVE_BRANCH,
|
|
14
|
+
MOVE_TIMED_WAIT,
|
|
15
|
+
MOVE_WAIT_FOR_WEB_INPUT,
|
|
16
|
+
MOVE_SHOW_IMAGE,
|
|
17
|
+
MOVE_SHOW_VIDEO,
|
|
18
|
+
MOVE_SHOW_IFRAME,
|
|
19
|
+
MOVE_SHOW_HTML,
|
|
20
|
+
MOVE_BLACK_SCREEN,
|
|
14
21
|
)
|
|
15
22
|
|
|
16
23
|
|
|
@@ -24,6 +31,13 @@ ALLOWED_MOVE_TYPES = {
|
|
|
24
31
|
MOVE_MOTION_SEQUENCE,
|
|
25
32
|
MOVE_ANIMATION,
|
|
26
33
|
MOVE_BRANCH,
|
|
34
|
+
MOVE_TIMED_WAIT,
|
|
35
|
+
MOVE_WAIT_FOR_WEB_INPUT,
|
|
36
|
+
MOVE_SHOW_IMAGE,
|
|
37
|
+
MOVE_SHOW_VIDEO,
|
|
38
|
+
MOVE_SHOW_IFRAME,
|
|
39
|
+
MOVE_SHOW_HTML,
|
|
40
|
+
MOVE_BLACK_SCREEN,
|
|
27
41
|
}
|
|
28
42
|
|
|
29
43
|
|