332 lines
9.9 KiB
Python
332 lines
9.9 KiB
Python
"""
|
|
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) |