""" This program has been developed by students from the bachelor Computer Science at Utrecht University within the Software Project course. © Copyright Utrecht University (Department of Information and Computing Sciences) """ 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. These operators define how beliefs can be combined to form more complex logical conditions. They are used in inferred beliefs to create compound beliefs from simpler ones. AND: Both operands must be true for the result to be true. OR: At least one operand must be true for the result to be true. """ 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. Keyword beliefs provide a simple but effective way to detect specific topics or intentions in user speech. They are triggered when the exact keyword string appears in the transcribed user input. :ivar keyword: The string to look for in the transcription. Example: A keyword belief with keyword="robot" would be activated when the user says "I like the robot" or "Tell me about robots". """ name: str = "" keyword: str class SemanticBelief(ProgramElement): """ Represents a belief whose truth value is determined by an LLM analyzing the conversation context. Semantic beliefs provide more sophisticated belief detection by using an LLM to analyze the conversation context and determine if the belief should be considered true. This allows for more nuanced and context-aware belief evaluation. :ivar description: A natural language description of what this belief represents, used as a prompt for the LLM. Example: A semantic belief with description="The user is expressing frustration" would be activated when the LLM determines that the user's statements indicate frustration, even if no specific keywords are used. """ description: str class InferredBelief(ProgramElement): """ Represents a belief derived from other beliefs using logical operators. Inferred beliefs allow for the creation of complex belief structures by combining simpler beliefs using logical operators. This enables the representation of sophisticated conditions and relationships between different aspects of the conversation or context. :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. Norms represent guidelines, principles, or rules that should govern the robot's behavior during interactions. They can be either basic (always active in their phase) or conditional (active only when specific beliefs are true). :ivar norm: The textual description of the norm. :ivar critical: Whether this norm is considered critical and should be strictly enforced. Critical norms are currently not supported yet, but are intended for norms that should ABSOLUTELY NOT be violated, possible cheched by additional validator agents. """ 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. Basic norms are the most straightforward type of norms. They are active throughout their assigned phase and provide consistent behavioral guidance without any additional conditions. These norms are suitable for general principles that should always apply during a particular interaction phase. """ pass class ConditionalNorm(Norm): """ A behavioral norm that is only active when a specific condition (belief) is met. Conditional norms provide context-sensitive behavioral guidance. They are only active and considered for activation when their associated condition (belief) is true. This allows for more nuanced and adaptive behavior that responds to the specific context of the interaction. An important note, is that the current implementation of these norms for keyword-based beliefs is that they only hold for 1 turn, as keyword-based conditions often express temporary conditions. :ivar condition: The :class:`Belief` that must hold for this norm to be active. Example: A conditional norm with the condition "user is frustrated" might specify that the robot should use more empathetic language and avoid complex topics. """ 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. Plans define sequences of actions and subgoals that the robot should execute to achieve a particular objective. They form the procedural knowledge of the behavior program, specifying what the robot should do in different situations. :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. The can_fail attribute determines whether goal achievement is binary (success/failure) or whether it can be determined through conversation analysis. """ 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. Goals extend base goals by including a specific plan to achieve the objective. They form the core of the robot's proactive behavior, defining both what should be accomplished and how to accomplish it. 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. The type field determines how the gesture is selected: - "single": Use the specific gesture identified by name - "tag": Select a random gesture from the category identified by name """ 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. The goal parameter provides high-level guidance to the LLM about what the response should aim to achieve, while allowing the LLM flexibility in how to express it. """ 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. The Program class represents the complete specification of a robot's behavioral logic. It contains all the phases, norms, goals, triggers, and actions that define how the robot should behave during interactions. :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)