243 lines
5.7 KiB
Python
243 lines
5.7 KiB
Python
from enum import Enum
|
|
from typing import Literal
|
|
|
|
from pydantic import UUID4, BaseModel
|
|
|
|
|
|
class ProgramElement(BaseModel):
|
|
"""
|
|
Represents a basic element of our behavior program.
|
|
|
|
:ivar name: The researcher-assigned name of the element.
|
|
:ivar id: Unique identifier.
|
|
"""
|
|
|
|
name: str
|
|
id: UUID4
|
|
|
|
# To make program elements hashable
|
|
model_config = {"frozen": True}
|
|
|
|
|
|
class LogicalOperator(Enum):
|
|
"""
|
|
Logical operators for combining beliefs.
|
|
"""
|
|
|
|
AND = "AND"
|
|
OR = "OR"
|
|
|
|
|
|
type Belief = KeywordBelief | SemanticBelief | InferredBelief | EmotionBelief
|
|
type BasicBelief = KeywordBelief | SemanticBelief | EmotionBelief
|
|
|
|
|
|
class KeywordBelief(ProgramElement):
|
|
"""
|
|
Represents a belief that is activated when a specific keyword is detected in the user's speech.
|
|
|
|
:ivar keyword: The string to look for in the transcription.
|
|
"""
|
|
|
|
name: str = ""
|
|
keyword: str
|
|
|
|
|
|
class SemanticBelief(ProgramElement):
|
|
"""
|
|
Represents a belief whose truth value is determined by an LLM analyzing the conversation
|
|
context.
|
|
|
|
:ivar description: A natural language description of what this belief represents,
|
|
used as a prompt for the LLM.
|
|
"""
|
|
|
|
description: str
|
|
|
|
|
|
class InferredBelief(ProgramElement):
|
|
"""
|
|
Represents a belief derived from other beliefs using logical operators.
|
|
|
|
:ivar operator: The :class:`LogicalOperator` (AND/OR) to apply.
|
|
:ivar left: The left operand (another belief).
|
|
:ivar right: The right operand (another belief).
|
|
"""
|
|
|
|
name: str = ""
|
|
operator: LogicalOperator
|
|
left: Belief
|
|
right: Belief
|
|
|
|
class EmotionBelief(ProgramElement):
|
|
"""
|
|
Represents a belief that is set when a certain emotion is detected.
|
|
|
|
:ivar emotion: The emotion on which this belief gets set.
|
|
"""
|
|
|
|
name: str = ""
|
|
emotion: str
|
|
|
|
class Norm(ProgramElement):
|
|
"""
|
|
Base class for behavioral norms that guide the robot's interactions.
|
|
|
|
:ivar norm: The textual description of the norm.
|
|
:ivar critical: Whether this norm is considered critical and should be strictly enforced.
|
|
"""
|
|
|
|
name: str = ""
|
|
norm: str
|
|
critical: bool = False
|
|
|
|
|
|
class BasicNorm(Norm):
|
|
"""
|
|
A simple behavioral norm that is always considered for activation when its phase is active.
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
class ConditionalNorm(Norm):
|
|
"""
|
|
A behavioral norm that is only active when a specific condition (belief) is met.
|
|
|
|
:ivar condition: The :class:`Belief` that must hold for this norm to be active.
|
|
"""
|
|
|
|
condition: Belief
|
|
|
|
|
|
type PlanElement = Goal | Action
|
|
|
|
|
|
class Plan(ProgramElement):
|
|
"""
|
|
Represents a list of steps to execute. Each of these steps can be a goal (with its own plan)
|
|
or a simple action.
|
|
|
|
:ivar steps: The actions or subgoals to execute, in order.
|
|
"""
|
|
|
|
name: str = ""
|
|
steps: list[PlanElement]
|
|
|
|
|
|
class BaseGoal(ProgramElement):
|
|
"""
|
|
Represents an objective to be achieved. This base version does not include a plan to achieve
|
|
this goal, and is used in semantic belief extraction.
|
|
|
|
:ivar description: A description of the goal, used to determine if it has been achieved.
|
|
:ivar can_fail: Whether we can fail to achieve the goal after executing the plan.
|
|
"""
|
|
|
|
description: str = ""
|
|
can_fail: bool = True
|
|
|
|
|
|
class Goal(BaseGoal):
|
|
"""
|
|
Represents an objective to be achieved. To reach the goal, we should execute the corresponding
|
|
plan. It inherits from the BaseGoal a variable `can_fail`, which if true will cause the
|
|
completion to be determined based on the conversation.
|
|
|
|
Instances of this goal are not hashable because a plan is not hashable.
|
|
|
|
:ivar plan: The plan to execute.
|
|
"""
|
|
|
|
plan: Plan
|
|
|
|
|
|
type Action = SpeechAction | GestureAction | LLMAction
|
|
|
|
|
|
class SpeechAction(ProgramElement):
|
|
"""
|
|
An action where the robot speaks a predefined literal text.
|
|
|
|
:ivar text: The text content to be spoken.
|
|
"""
|
|
|
|
name: str = ""
|
|
text: str
|
|
|
|
|
|
class Gesture(BaseModel):
|
|
"""
|
|
Defines a physical gesture for the robot to perform.
|
|
|
|
:ivar type: Whether to use a specific "single" gesture or a random one from a "tag" category.
|
|
:ivar name: The identifier for the gesture or tag.
|
|
"""
|
|
|
|
type: Literal["tag", "single"]
|
|
name: str
|
|
|
|
|
|
class GestureAction(ProgramElement):
|
|
"""
|
|
An action where the robot performs a physical gesture.
|
|
|
|
:ivar gesture: The :class:`Gesture` definition.
|
|
"""
|
|
|
|
name: str = ""
|
|
gesture: Gesture
|
|
|
|
|
|
class LLMAction(ProgramElement):
|
|
"""
|
|
An action that triggers an LLM-generated conversational response.
|
|
|
|
:ivar goal: A temporary conversational goal to guide the LLM's response generation.
|
|
"""
|
|
|
|
name: str = ""
|
|
goal: str
|
|
|
|
|
|
class Trigger(ProgramElement):
|
|
"""
|
|
Defines a reactive behavior: when the condition (belief) is met, the plan is executed.
|
|
|
|
:ivar condition: The :class:`Belief` that triggers this behavior.
|
|
:ivar plan: The :class:`Plan` to execute upon activation.
|
|
"""
|
|
|
|
condition: Belief
|
|
plan: Plan
|
|
|
|
|
|
class Phase(ProgramElement):
|
|
"""
|
|
A logical stage in the interaction program, grouping norms, goals, and triggers.
|
|
|
|
:ivar norms: List of norms active during this phase.
|
|
:ivar goals: List of goals the robot pursues in this phase.
|
|
:ivar triggers: List of reactive behaviors defined for this phase.
|
|
"""
|
|
|
|
name: str = ""
|
|
norms: list[BasicNorm | ConditionalNorm]
|
|
goals: list[Goal]
|
|
triggers: list[Trigger]
|
|
|
|
|
|
class Program(BaseModel):
|
|
"""
|
|
The top-level container for a complete robot behavior definition.
|
|
|
|
:ivar phases: An ordered list of :class:`Phase` objects defining the interaction flow.
|
|
"""
|
|
|
|
phases: list[Phase]
|
|
|
|
|
|
if __name__ == "__main__":
|
|
input = input("Enter program JSON: ")
|
|
program = Program.model_validate_json(input)
|
|
print(program) |