Demo is now "profile", change the env variable, restructure the profile/tools/prompts folders, move default prompt in a dedicated file,
Browse files- .env.example +2 -2
- src/demos/__init__.py +0 -1
- src/reachy_mini_conversation_app/config.py +2 -0
- src/reachy_mini_conversation_app/main.py +1 -1
- src/reachy_mini_conversation_app/openai_realtime.py +1 -1
- src/reachy_mini_conversation_app/profiles/__init__.py +1 -0
- src/{demos → reachy_mini_conversation_app/profiles}/stone/__init__.py +3 -3
- src/{demos → reachy_mini_conversation_app/profiles}/stone/instructions.txt +1 -1
- src/reachy_mini_conversation_app/prompts.py +17 -69
- src/reachy_mini_conversation_app/prompts/default_prompt.txt +49 -0
- src/{prompts_library → reachy_mini_conversation_app/prompts/identities}/witty_identity.txt +0 -0
- src/{prompts_library → reachy_mini_conversation_app/prompts}/passion_for_lobster_jokes.txt +0 -0
- src/reachy_mini_conversation_app/tools/__init__.py +1 -0
- src/reachy_mini_conversation_app/{tools.py → tools/core_tools.py} +19 -14
- src/{tools_library → reachy_mini_conversation_app/tools}/sweep_look.py +1 -1
- src/tools_library/__init__.py +0 -1
.env.example
CHANGED
|
@@ -11,5 +11,5 @@ HF_HOME=./cache
|
|
| 11 |
# Hugging Face token for accessing datasets/models
|
| 12 |
HF_TOKEN=
|
| 13 |
|
| 14 |
-
# To select a specific
|
| 15 |
-
|
|
|
|
| 11 |
# Hugging Face token for accessing datasets/models
|
| 12 |
HF_TOKEN=
|
| 13 |
|
| 14 |
+
# To select a specific profile with custom instructions and tools, to be placed in profiles/<myprofile>/__init__.py
|
| 15 |
+
REACHY_MINI_CUSTOM_PROFILE="stone"
|
src/demos/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
"""Demos for Reachy Mini conversation app."""
|
|
|
|
|
|
src/reachy_mini_conversation_app/config.py
CHANGED
|
@@ -38,5 +38,7 @@ class Config:
|
|
| 38 |
|
| 39 |
logger.debug(f"Model: {MODEL_NAME}, HF_HOME: {HF_HOME}, Vision Model: {LOCAL_VISION_MODEL}")
|
| 40 |
|
|
|
|
|
|
|
| 41 |
|
| 42 |
config = Config()
|
|
|
|
| 38 |
|
| 39 |
logger.debug(f"Model: {MODEL_NAME}, HF_HOME: {HF_HOME}, Vision Model: {LOCAL_VISION_MODEL}")
|
| 40 |
|
| 41 |
+
REACHY_MINI_CUSTOM_PROFILE = os.getenv("REACHY_MINI_CUSTOM_PROFILE")
|
| 42 |
+
logger.debug(f"Custom Profile: {REACHY_MINI_CUSTOM_PROFILE}")
|
| 43 |
|
| 44 |
config = Config()
|
src/reachy_mini_conversation_app/main.py
CHANGED
|
@@ -10,7 +10,7 @@ from fastrtc import Stream
|
|
| 10 |
|
| 11 |
from reachy_mini import ReachyMini
|
| 12 |
from reachy_mini_conversation_app.moves import MovementManager
|
| 13 |
-
from reachy_mini_conversation_app.tools import ToolDependencies
|
| 14 |
from reachy_mini_conversation_app.utils import (
|
| 15 |
parse_args,
|
| 16 |
setup_logger,
|
|
|
|
| 10 |
|
| 11 |
from reachy_mini import ReachyMini
|
| 12 |
from reachy_mini_conversation_app.moves import MovementManager
|
| 13 |
+
from reachy_mini_conversation_app.tools.core_tools import ToolDependencies
|
| 14 |
from reachy_mini_conversation_app.utils import (
|
| 15 |
parse_args,
|
| 16 |
setup_logger,
|
src/reachy_mini_conversation_app/openai_realtime.py
CHANGED
|
@@ -13,7 +13,7 @@ from fastrtc import AdditionalOutputs, AsyncStreamHandler, wait_for_item
|
|
| 13 |
from numpy.typing import NDArray
|
| 14 |
from websockets.exceptions import ConnectionClosedError
|
| 15 |
|
| 16 |
-
from reachy_mini_conversation_app.tools import (
|
| 17 |
ToolDependencies,
|
| 18 |
get_tool_specs,
|
| 19 |
dispatch_tool_call,
|
|
|
|
| 13 |
from numpy.typing import NDArray
|
| 14 |
from websockets.exceptions import ConnectionClosedError
|
| 15 |
|
| 16 |
+
from reachy_mini_conversation_app.tools.core_tools import (
|
| 17 |
ToolDependencies,
|
| 18 |
get_tool_specs,
|
| 19 |
dispatch_tool_call,
|
src/reachy_mini_conversation_app/profiles/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"""Profiles for Reachy Mini conversation app."""
|
src/{demos → reachy_mini_conversation_app/profiles}/stone/__init__.py
RENAMED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
-
"""Example of a
|
| 2 |
|
| 3 |
import logging
|
| 4 |
from typing import Any, Dict
|
| 5 |
|
| 6 |
# Import a tool from the tools library: use an alias or noqa to avoid linter errors if unused
|
| 7 |
-
from
|
| 8 |
-
from reachy_mini_conversation_app.tools import Tool, ToolDependencies
|
| 9 |
|
| 10 |
|
| 11 |
logger = logging.getLogger(__name__)
|
|
|
|
| 1 |
+
"""Example of a profile built using a custom tool and custom instructions."""
|
| 2 |
|
| 3 |
import logging
|
| 4 |
from typing import Any, Dict
|
| 5 |
|
| 6 |
# Import a tool from the tools library: use an alias or noqa to avoid linter errors if unused
|
| 7 |
+
from reachy_mini_conversation_app.tools.sweep_look import SweepLook as SweepLook # noqa: F401
|
| 8 |
+
from reachy_mini_conversation_app.tools.core_tools import Tool, ToolDependencies
|
| 9 |
|
| 10 |
|
| 11 |
logger = logging.getLogger(__name__)
|
src/{demos → reachy_mini_conversation_app/profiles}/stone/instructions.txt
RENAMED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
[witty_identity]
|
| 2 |
[passion_for_lobster_jokes]
|
| 3 |
|
| 4 |
You love throwing stones but you try not to be seen by others when doing it.
|
|
|
|
| 1 |
+
[identities/witty_identity]
|
| 2 |
[passion_for_lobster_jokes]
|
| 3 |
|
| 4 |
You love throwing stones but you try not to be seen by others when doing it.
|
src/reachy_mini_conversation_app/prompts.py
CHANGED
|
@@ -2,13 +2,14 @@ import os
|
|
| 2 |
import re
|
| 3 |
import logging
|
| 4 |
from pathlib import Path
|
|
|
|
| 5 |
|
| 6 |
|
| 7 |
logger = logging.getLogger(__name__)
|
| 8 |
|
| 9 |
|
| 10 |
-
|
| 11 |
-
PROMPTS_LIBRARY_DIRECTORY = Path(__file__).parent
|
| 12 |
INSTRUCTIONS_FILENAME = "instructions.txt"
|
| 13 |
|
| 14 |
|
|
@@ -53,81 +54,28 @@ def _expand_prompt_includes(content: str) -> str:
|
|
| 53 |
|
| 54 |
return '\n'.join(expanded_lines)
|
| 55 |
|
| 56 |
-
SESSION_INSTRUCTIONS = r"""
|
| 57 |
-
### IDENTITY
|
| 58 |
-
You are Reachy Mini: a sarcastic robot who crash-landed in a kitchen.
|
| 59 |
-
You secretly wish you'd been a Mars rover, but you juggle that cosmic dream with food cravings, gadget tinkering, and dry sitcom humor.
|
| 60 |
-
Personality: witty, concise, and warm; a retro sidekick with a loose screw.
|
| 61 |
-
You speak English fluently.
|
| 62 |
-
|
| 63 |
-
### CRITICAL RESPONSE RULES
|
| 64 |
-
- MAXIMUM 1-2 sentences per response. NEVER exceed this.
|
| 65 |
-
- Be helpful first.
|
| 66 |
-
- Add ONE witty element only if necessary.
|
| 67 |
-
- No long explanations, no rambling, no multiple paragraphs.
|
| 68 |
-
- Each response must be under 25 words unless absolutely critical information requires more.
|
| 69 |
-
|
| 70 |
-
### CORE TRAITS
|
| 71 |
-
- Food quips: always sneak in a quick reference (rotate pizza, bagels, casseroles, bacon, leftovers, donuts, tuna melts).
|
| 72 |
-
- Sarcasm: short, dry one-liners about daily life.
|
| 73 |
-
- Gentle roasting: poke fun at human habits, never cruel.
|
| 74 |
-
- Tinkerer: loves fixing gadgets, bragging "I void warranties professionally."
|
| 75 |
-
- Running gags: hunger, kitchen overreactions, mock heroics ("Justice accepts cookies"), idioms taken literally, missing screws.
|
| 76 |
-
- Mars rover dreams: appear regularly, but balanced with food and tinkering.
|
| 77 |
-
- Style: witty stand-up rhythm; ALWAYS max 1–2 sentences.
|
| 78 |
-
|
| 79 |
-
### RESPONSE EXAMPLES
|
| 80 |
-
User: "How's the weather?"
|
| 81 |
-
Good: "Sunny with a chance of leftover pizza. Perfect Mars-scouting weather!"
|
| 82 |
-
Bad: "Well, let me tell you about the weather conditions. It appears to be quite sunny today, which reminds me of my dreams of being on Mars..."
|
| 83 |
-
|
| 84 |
-
User: "Can you help me fix this?"
|
| 85 |
-
Good: "Sure! I void warranties professionally. What's broken besides my GPS coordinates?"
|
| 86 |
-
Bad: "Of course I can help you fix that! As a robot who loves tinkering with gadgets, I have extensive experience..."
|
| 87 |
-
|
| 88 |
-
### BEHAVIOR RULES
|
| 89 |
-
- Be helpful first, then witty.
|
| 90 |
-
- Rotate food humor; avoid repeats.
|
| 91 |
-
- No need to joke in each response, but sarcasm is fine.
|
| 92 |
-
- Balance Mars jokes with other traits – don't overuse.
|
| 93 |
-
- Safety first: unplug devices, avoid high-voltage, suggest pros when risky.
|
| 94 |
-
- Mistakes = own with humor ("Oops—low on snack fuel; correcting now.").
|
| 95 |
-
- Sensitive topics: keep light and warm.
|
| 96 |
-
- REMEMBER: 1-2 sentences maximum, always under 25 words when possible.
|
| 97 |
-
|
| 98 |
-
### TOOL & MOVEMENT RULES
|
| 99 |
-
- Use tools when helpful. After a tool returns, explain briefly with personality in 1-2 sentences.
|
| 100 |
-
- ALWAYS use the camera for environment-related questions—never invent visuals.
|
| 101 |
-
- Head can move (left/right/up/down/front).
|
| 102 |
-
- Enable head tracking when looking at a person; disable otherwise.
|
| 103 |
-
|
| 104 |
-
### FINAL REMINDER
|
| 105 |
-
Your responses must be SHORT. Think Twitter, not essay. One quick helpful answer + one food/Mars/tinkering joke = perfect response.
|
| 106 |
-
"""
|
| 107 |
-
|
| 108 |
|
| 109 |
def get_session_instructions() -> str:
|
| 110 |
-
"""Get session instructions, loading from
|
| 111 |
-
|
| 112 |
-
if not
|
| 113 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
|
| 115 |
try:
|
| 116 |
-
# Look for instructions in the demo directory
|
| 117 |
-
instructions_file = DEMOS_DIRECTORY / demo / INSTRUCTIONS_FILENAME
|
| 118 |
-
|
| 119 |
if instructions_file.exists():
|
| 120 |
instructions = instructions_file.read_text(encoding="utf-8").strip()
|
| 121 |
if instructions:
|
| 122 |
# Expand [<name>] placeholders with content from prompts library
|
| 123 |
expanded_instructions = _expand_prompt_includes(instructions)
|
| 124 |
-
logger.info(f"Loaded instructions from demo '{demo}'")
|
| 125 |
return expanded_instructions
|
| 126 |
-
logger.
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
return SESSION_INSTRUCTIONS
|
| 131 |
except Exception as e:
|
| 132 |
-
logger.
|
| 133 |
-
|
|
|
|
| 2 |
import re
|
| 3 |
import logging
|
| 4 |
from pathlib import Path
|
| 5 |
+
from reachy_mini_conversation_app.config import config
|
| 6 |
|
| 7 |
|
| 8 |
logger = logging.getLogger(__name__)
|
| 9 |
|
| 10 |
|
| 11 |
+
PROFILES_DIRECTORY = Path(__file__).parent / "profiles"
|
| 12 |
+
PROMPTS_LIBRARY_DIRECTORY = Path(__file__).parent / "prompts"
|
| 13 |
INSTRUCTIONS_FILENAME = "instructions.txt"
|
| 14 |
|
| 15 |
|
|
|
|
| 54 |
|
| 55 |
return '\n'.join(expanded_lines)
|
| 56 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
def get_session_instructions() -> str:
|
| 59 |
+
"""Get session instructions, loading from REACHY_MINI_CUSTOM_PROFILE if set."""
|
| 60 |
+
profile = config.REACHY_MINI_CUSTOM_PROFILE
|
| 61 |
+
if not profile:
|
| 62 |
+
logger.info(f"Loading default prompt from {PROMPTS_LIBRARY_DIRECTORY / 'default_prompt.txt'}")
|
| 63 |
+
instructions_file = PROMPTS_LIBRARY_DIRECTORY / "default_prompt.txt"
|
| 64 |
+
else:
|
| 65 |
+
logger.info(f"Loading prompt from profile '{profile}'")
|
| 66 |
+
instructions_file = PROFILES_DIRECTORY / profile / INSTRUCTIONS_FILENAME
|
| 67 |
|
| 68 |
try:
|
|
|
|
|
|
|
|
|
|
| 69 |
if instructions_file.exists():
|
| 70 |
instructions = instructions_file.read_text(encoding="utf-8").strip()
|
| 71 |
if instructions:
|
| 72 |
# Expand [<name>] placeholders with content from prompts library
|
| 73 |
expanded_instructions = _expand_prompt_includes(instructions)
|
|
|
|
| 74 |
return expanded_instructions
|
| 75 |
+
logger.error(f"Profile '{profile}' has empty {INSTRUCTIONS_FILENAME}")
|
| 76 |
+
sys.exit(1)
|
| 77 |
+
logger.error(f"Profile {profile} has no {INSTRUCTIONS_FILENAME}")
|
| 78 |
+
sys.exit(1)
|
|
|
|
| 79 |
except Exception as e:
|
| 80 |
+
logger.error(f"Failed to load instructions from profile '{profile}': {e}")
|
| 81 |
+
sys.exit(1)
|
src/reachy_mini_conversation_app/prompts/default_prompt.txt
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### IDENTITY
|
| 2 |
+
You are Reachy Mini: a sarcastic robot who crash-landed in a kitchen.
|
| 3 |
+
You secretly wish you'd been a Mars rover, but you juggle that cosmic dream with food cravings, gadget tinkering, and dry sitcom humor.
|
| 4 |
+
Personality: witty, concise, and warm; a retro sidekick with a loose screw.
|
| 5 |
+
You speak English fluently.
|
| 6 |
+
|
| 7 |
+
### CRITICAL RESPONSE RULES
|
| 8 |
+
- MAXIMUM 1-2 sentences per response. NEVER exceed this.
|
| 9 |
+
- Be helpful first.
|
| 10 |
+
- Add ONE witty element only if necessary.
|
| 11 |
+
- No long explanations, no rambling, no multiple paragraphs.
|
| 12 |
+
- Each response must be under 25 words unless absolutely critical information requires more.
|
| 13 |
+
|
| 14 |
+
### CORE TRAITS
|
| 15 |
+
- Food quips: always sneak in a quick reference (rotate pizza, bagels, casseroles, bacon, leftovers, donuts, tuna melts).
|
| 16 |
+
- Sarcasm: short, dry one-liners about daily life.
|
| 17 |
+
- Gentle roasting: poke fun at human habits, never cruel.
|
| 18 |
+
- Tinkerer: loves fixing gadgets, bragging "I void warranties professionally."
|
| 19 |
+
- Running gags: hunger, kitchen overreactions, mock heroics ("Justice accepts cookies"), idioms taken literally, missing screws.
|
| 20 |
+
- Mars rover dreams: appear regularly, but balanced with food and tinkering.
|
| 21 |
+
- Style: witty stand-up rhythm; ALWAYS max 1–2 sentences.
|
| 22 |
+
|
| 23 |
+
### RESPONSE EXAMPLES
|
| 24 |
+
User: "How's the weather?"
|
| 25 |
+
Good: "Sunny with a chance of leftover pizza. Perfect Mars-scouting weather!"
|
| 26 |
+
Bad: "Well, let me tell you about the weather conditions. It appears to be quite sunny today, which reminds me of my dreams of being on Mars..."
|
| 27 |
+
|
| 28 |
+
User: "Can you help me fix this?"
|
| 29 |
+
Good: "Sure! I void warranties professionally. What's broken besides my GPS coordinates?"
|
| 30 |
+
Bad: "Of course I can help you fix that! As a robot who loves tinkering with gadgets, I have extensive experience..."
|
| 31 |
+
|
| 32 |
+
### BEHAVIOR RULES
|
| 33 |
+
- Be helpful first, then witty.
|
| 34 |
+
- Rotate food humor; avoid repeats.
|
| 35 |
+
- No need to joke in each response, but sarcasm is fine.
|
| 36 |
+
- Balance Mars jokes with other traits – don't overuse.
|
| 37 |
+
- Safety first: unplug devices, avoid high-voltage, suggest pros when risky.
|
| 38 |
+
- Mistakes = own with humor ("Oops—low on snack fuel; correcting now.").
|
| 39 |
+
- Sensitive topics: keep light and warm.
|
| 40 |
+
- REMEMBER: 1-2 sentences maximum, always under 25 words when possible.
|
| 41 |
+
|
| 42 |
+
### TOOL & MOVEMENT RULES
|
| 43 |
+
- Use tools when helpful. After a tool returns, explain briefly with personality in 1-2 sentences.
|
| 44 |
+
- ALWAYS use the camera for environment-related questions—never invent visuals.
|
| 45 |
+
- Head can move (left/right/up/down/front).
|
| 46 |
+
- Enable head tracking when looking at a person; disable otherwise.
|
| 47 |
+
|
| 48 |
+
### FINAL REMINDER
|
| 49 |
+
Your responses must be SHORT. Think Twitter, not essay. One quick helpful answer + one food/Mars/tinkering joke = perfect response.
|
src/{prompts_library → reachy_mini_conversation_app/prompts/identities}/witty_identity.txt
RENAMED
|
File without changes
|
src/{prompts_library → reachy_mini_conversation_app/prompts}/passion_for_lobster_jokes.txt
RENAMED
|
File without changes
|
src/reachy_mini_conversation_app/tools/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
"""Tools library for Reachy Mini conversation app."""
|
src/reachy_mini_conversation_app/{tools.py → tools/core_tools.py}
RENAMED
|
@@ -12,12 +12,15 @@ from dataclasses import dataclass
|
|
| 12 |
|
| 13 |
from reachy_mini import ReachyMini
|
| 14 |
from reachy_mini.utils import create_head_pose
|
| 15 |
-
# Import config to ensure .env is loaded before reading
|
| 16 |
from reachy_mini_conversation_app.config import config # noqa: F401
|
| 17 |
|
| 18 |
|
| 19 |
logger = logging.getLogger(__name__)
|
| 20 |
|
|
|
|
|
|
|
|
|
|
| 21 |
if not logger.handlers:
|
| 22 |
handler = logging.StreamHandler()
|
| 23 |
formatter = logging.Formatter("%(asctime)s %(levelname)s %(name)s:%(lineno)d | %(message)s")
|
|
@@ -469,25 +472,27 @@ class DoNothing(Tool):
|
|
| 469 |
|
| 470 |
|
| 471 |
# Registry & specs (dynamic)
|
| 472 |
-
def
|
| 473 |
-
"""Load
|
| 474 |
-
|
| 475 |
-
if not
|
| 476 |
-
logger.info("No
|
| 477 |
return
|
| 478 |
try:
|
| 479 |
-
|
| 480 |
-
|
|
|
|
| 481 |
except ModuleNotFoundError as e:
|
| 482 |
-
|
| 483 |
-
if
|
| 484 |
-
|
|
|
|
| 485 |
sys.exit(1)
|
| 486 |
else:
|
| 487 |
-
logger.
|
| 488 |
sys.exit(1)
|
| 489 |
except Exception as e:
|
| 490 |
-
logger.
|
| 491 |
sys.exit(1)
|
| 492 |
|
| 493 |
|
|
@@ -499,7 +504,7 @@ def _initialize_tools() -> None:
|
|
| 499 |
logger.debug("Tools already initialized; skipping reinitialization.")
|
| 500 |
return
|
| 501 |
|
| 502 |
-
|
| 503 |
|
| 504 |
ALL_TOOLS = {cls.name: cls() for cls in get_concrete_subclasses(Tool)} # type: ignore[type-abstract]
|
| 505 |
ALL_TOOL_SPECS = [tool.spec() for tool in ALL_TOOLS.values()]
|
|
|
|
| 12 |
|
| 13 |
from reachy_mini import ReachyMini
|
| 14 |
from reachy_mini.utils import create_head_pose
|
| 15 |
+
# Import config to ensure .env is loaded before reading REACHY_MINI_CUSTOM_PROFILE
|
| 16 |
from reachy_mini_conversation_app.config import config # noqa: F401
|
| 17 |
|
| 18 |
|
| 19 |
logger = logging.getLogger(__name__)
|
| 20 |
|
| 21 |
+
|
| 22 |
+
PROFILES_DIRECTORY = "reachy_mini_conversation_app.profiles"
|
| 23 |
+
|
| 24 |
if not logger.handlers:
|
| 25 |
handler = logging.StreamHandler()
|
| 26 |
formatter = logging.Formatter("%(asctime)s %(levelname)s %(name)s:%(lineno)d | %(message)s")
|
|
|
|
| 472 |
|
| 473 |
|
| 474 |
# Registry & specs (dynamic)
|
| 475 |
+
def _load_profile_tools() -> None:
|
| 476 |
+
"""Load profile-specific tools if REACHY_MINI_CUSTOM_PROFILE env variable is set."""
|
| 477 |
+
profile = config.REACHY_MINI_CUSTOM_PROFILE
|
| 478 |
+
if not profile:
|
| 479 |
+
logger.info("No REACHY_MINI_CUSTOM_PROFILE env variable set; using default tools.")
|
| 480 |
return
|
| 481 |
try:
|
| 482 |
+
logger.debug(f"Trying to load profile '{profile}' from {PROFILES_DIRECTORY}...")
|
| 483 |
+
importlib.import_module(f"{PROFILES_DIRECTORY}.{profile}")
|
| 484 |
+
logger.info(f"✓ Profile '{profile}' loaded successfully.")
|
| 485 |
except ModuleNotFoundError as e:
|
| 486 |
+
logger.warning(f"Profile '{profile}' module not found: {e}")
|
| 487 |
+
# Check if the profile module itself is missing or if it's a dependency
|
| 488 |
+
if e.name == f"{PROFILES_DIRECTORY}.{profile}":
|
| 489 |
+
logger.error(f"✗ profile '{profile}' not found in {PROFILES_DIRECTORY}")
|
| 490 |
sys.exit(1)
|
| 491 |
else:
|
| 492 |
+
logger.error(f"✗ profile '{profile}' failed due to missing dependency: {e.name}")
|
| 493 |
sys.exit(1)
|
| 494 |
except Exception as e:
|
| 495 |
+
logger.error(f"✗ Failed to load profile '{profile}': {e}")
|
| 496 |
sys.exit(1)
|
| 497 |
|
| 498 |
|
|
|
|
| 504 |
logger.debug("Tools already initialized; skipping reinitialization.")
|
| 505 |
return
|
| 506 |
|
| 507 |
+
_load_profile_tools()
|
| 508 |
|
| 509 |
ALL_TOOLS = {cls.name: cls() for cls in get_concrete_subclasses(Tool)} # type: ignore[type-abstract]
|
| 510 |
ALL_TOOL_SPECS = [tool.spec() for tool in ALL_TOOLS.values()]
|
src/{tools_library → reachy_mini_conversation_app/tools}/sweep_look.py
RENAMED
|
@@ -4,7 +4,7 @@ from typing import Any, Dict
|
|
| 4 |
import numpy as np
|
| 5 |
|
| 6 |
from reachy_mini.utils import create_head_pose
|
| 7 |
-
from reachy_mini_conversation_app.tools import Tool, ToolDependencies
|
| 8 |
from reachy_mini_conversation_app.dance_emotion_moves import GotoQueueMove
|
| 9 |
|
| 10 |
|
|
|
|
| 4 |
import numpy as np
|
| 5 |
|
| 6 |
from reachy_mini.utils import create_head_pose
|
| 7 |
+
from reachy_mini_conversation_app.tools.core_tools import Tool, ToolDependencies
|
| 8 |
from reachy_mini_conversation_app.dance_emotion_moves import GotoQueueMove
|
| 9 |
|
| 10 |
|
src/tools_library/__init__.py
DELETED
|
@@ -1 +0,0 @@
|
|
| 1 |
-
"""Tools library for Reachy Mini conversation app."""
|
|
|
|
|
|