Skip to content

Commit

Permalink
Decouple DME
Browse files Browse the repository at this point in the history
  • Loading branch information
vladmaraev committed Aug 20, 2024
1 parent 7b14053 commit 823d15e
Show file tree
Hide file tree
Showing 5 changed files with 916 additions and 152 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
},
"devDependencies": {
"typescript": "^5.2.2",
"vite": "^5.2.0"
"vite": "^5.2.0",
"vitest": "^2.0.5"
},
"dependencies": {
"@statelyai/inspect": "^0.2.5",
Expand Down
172 changes: 41 additions & 131 deletions src/isu.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,13 @@
import {
assign,
createActor,
setup,
AnyMachineSnapshot,
raise,
AnyTransitionConfig,
} from "xstate";
import { createActor, setup, AnyMachineSnapshot, sendTo } from "xstate";
import { speechstate } from "speechstate";
import { createBrowserInspector } from "@statelyai/inspect";
import { KEY } from "./azure";
import { DMContext, DMEvent } from "./types";
import { rules } from "./rules";
import { DMContext, DMEvent, NextMoveEvent } from "./types";
import { nlg, nlu } from "./nlug";
import { dme } from "./dme";

const inspector = createBrowserInspector();

function isuTransition(
nextState: string,
ruleName: string,
): AnyTransitionConfig {
return {
target: nextState,
guard: { type: "isu", params: { name: ruleName } },
actions: { type: "isu", params: { name: ruleName } },
};
}

const azureCredentials = {
endpoint:
"https://northeurope.api.cognitive.microsoft.com/sts/v1.0/issuetoken",
Expand All @@ -42,41 +24,25 @@ const settings = {
};

const dmMachine = setup({
guards: {
/** preconditions */
isu: ({ context }, params: { name: string }) =>
rules[params.name](context).preconditions,
actors: {
dme: dme,
},
actions: {
/** effects */
isu: assign(({ context }, params: { name: string }) => {
return { is: rules[params.name](context).effects };
}),
/** update latest_move (outside IS!) based on ASR/TTS (SAYS event) */
updateLatestMove: assign(({ event }) => {
console.debug("[DM updateLatestMove]", event);
return {
latest_move: event.value.move,
latest_speaker: event.value.speaker,
};
}),
/** TTS */
speak_next_move: ({ context }) =>
speak_next_move: ({ context, event }) =>
context.ssRef.send({
type: "SPEAK",
value: {
utterance: nlg(context.is.next_move),
utterance: nlg((event as NextMoveEvent).value),
},
}),
/** ASR */
listen: ({ context }) =>
context.ssRef.send({
type: "LISTEN",
}),
},
types: {} as {
context: DMContext;
event: DMEvent;
events: DMEvent;
},
}).createMachine({
context: ({ spawn }) => {
Expand Down Expand Up @@ -135,8 +101,9 @@ const dmMachine = setup({
on: {
RECOGNISED: {
target: "Idle",
actions: raise(({ event }) => ({
actions: sendTo("dmeID", ({ event, self }) => ({
type: "SAYS",
sender: self,
value: {
speaker: "usr",
move: nlu(event.value[0].utterance),
Expand All @@ -146,16 +113,17 @@ const dmMachine = setup({
ASR_NOINPUT: {
target: "Idle",
// FOR TESTING
actions: raise({
actions: sendTo("dmeID", ({ self }) => ({
type: "SAYS",
sender: self,
value: {
speaker: "usr",
move: {
type: "ask",
content: (x: string) => `favorite_food ${x}`,
},
},
}),
})),
},
},
},
Expand All @@ -165,104 +133,41 @@ const dmMachine = setup({
initial: "Idle",
states: {
Idle: {
always: {
target: "Speaking",
guard: ({ context }) => !!context.is.next_move,
on: {
NEXT_MOVE: {
target: "Speaking",
actions: sendTo("dmeID", ({ event, self }) => ({
type: "SAYS",
sender: self,
value: {
speaker: "sys",
move: event.value,
},
})),
},
},
},
Speaking: {
entry: "speak_next_move",
on: {
SPEAK_COMPLETE: {
target: "Idle",
actions: [
raise(({ context }) => ({
type: "SAYS",
value: {
speaker: "sys",
move: context.is.next_move,
},
})),
assign(({ context }) => {
return { is: { ...context.is, next_move: null } };
}),
],
},
},
},
},
},
DME: {
initial: "Select",
states: {
Select: {
entry: ({ context }) =>
console.debug("[DM] ENTERING SELECT", context.is),
initial: "SelectAction",
states: {
SelectAction: {
always: [
isuTransition("SelectMove", "select_respond"),
isuTransition("SelectMove", "select_from_plan"),
{ target: "SelectMove" }, // TODO check it -- needed for greeting
],
},
SelectMove: {
always: [
isuTransition("SelectionDone", "select_ask"),
isuTransition("SelectionDone", "select_answer"),
isuTransition("SelectionDone", "select_other"),
{ target: "SelectionDone" },
],
},
SelectionDone: { type: "final" },
},
onDone: "Update",
},
Update: {
initial: "Init",
states: {
Init: {
always: isuTransition("Grounding", "clear_agenda"),
},
Grounding: {
// TODO: rename to Perception?
on: {
SAYS: {
target: "Integrate",
actions: [
{
type: "updateLatestMove",
},
{ type: "isu", params: { name: "get_latest_move" } },
],
},
},
},
Integrate: {
always: [
isuTransition("DowndateQUD", "integrate_usr_request"),
isuTransition("DowndateQUD", "integrate_sys_ask"),
isuTransition("DowndateQUD", "integrate_usr_ask"),
isuTransition("DowndateQUD", "integrate_greet"),
],
},
DowndateQUD: {
always: [
isuTransition("LoadPlan", "downdate_qud"),
{ target: "LoadPlan" },
],
},
LoadPlan: {
always: { target: "ExecPlan" },
},
ExecPlan: {
type: "final",
},
},
onDone: {
target: "Select",
},
invoke: {
src: "dme",
id: "dmeID",
input: ({ context, self }) => {
return {
parentRef: self,
latest_move: context.latest_move,
latest_speaker: context.latest_speaker,
is: context.is,
};
},
},
},
Expand All @@ -282,7 +187,12 @@ dmActor.subscribe((snapshot: AnyMachineSnapshot) => {
// is !== snapshot.context.is && console.log("[IS]", snapshot.context.is);
is = snapshot.context.is;
// console.log("IS", is);
console.log("%cState value:", "background-color: #056dff", snapshot.value);
console.log(
"%cState value:",
"background-color: #056dff",
snapshot.value,
snapshot.context.is,
);
});

export function setupButton(element: HTMLElement) {
Expand Down
27 changes: 15 additions & 12 deletions src/rules.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {
Question,
DMContext,
TotalInformationState,
InformationState,
Move,
DomainRelation,
} from "./types";

type Rules = {
[index: string]: (context: DMContext) => {
[index: string]: (context: TotalInformationState) => {
preconditions: boolean;
effects: InformationState;
};
Expand All @@ -21,15 +21,15 @@ function resolves(x: DomainRelation): boolean {
}

const plans = {
"create_appointment": [
create_appointment: [
{
"type": "findout",
"content": {
"type": "wh_question",
"predicate": "meeting_person"
}
}
]
type: "findout",
content: {
type: "wh_question",
predicate: "meeting_person",
},
},
],
};

export const rules: Rules = {
Expand Down Expand Up @@ -71,15 +71,18 @@ export const rules: Rules = {
*/
/** rule 5.1 */
integrate_usr_request: ({ is }) => {
if (is.shared.lu!.speaker === "usr" && is.shared.lu!.move.type === "request") {
if (
is.shared.lu!.speaker === "usr" &&
is.shared.lu!.move.type === "request"
) {
let action = is.shared.lu!.move.content;
if (action in plans) {
let plan = plans[action];
const newIS = {
...is,
private: {
...is.private,
agenda: plan.concat(is.private.agenda)
agenda: plan.concat(is.private.agenda),
},
};
console.debug(`[ISU integrate_usr_request]`, newIS);
Expand Down
22 changes: 20 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,15 @@ export interface InformationState {
};
}

export interface DMContext {
export interface DMContext extends TotalInformationState {
ssRef: any;
}

export interface DMEContext extends TotalInformationState {
parentRef: any;
}

export interface TotalInformationState {
/** interface variables */
latest_speaker?: Speaker;
latest_move?: Move;
Expand All @@ -48,8 +54,20 @@ export interface DMContext {
is: InformationState;
}

export type DMEvent = SpeechStateExternalEvent | SaysMoveEvent;
export type DMEvent =
| { type: "CLICK" }
| SpeechStateExternalEvent
| NextMoveEvent;

export type DMEEvent = SaysMoveEvent;

export type SaysMoveEvent = {
type: "SAYS";
sender: any;
value: { speaker: Speaker; move: Move };
};

export type NextMoveEvent = {
type: "NEXT_MOVE";
value: Move;
};
Loading

0 comments on commit 823d15e

Please sign in to comment.