Alina Lozovskaya
commited on
Commit
·
d2e69a3
1
Parent(s):
14afe2b
Add runtime toggles
Browse files- .env.example +1 -15
- README.md +7 -0
- pyproject.toml +1 -1
- src/reachy_mini_conversation_demo/config.py +3 -6
- src/reachy_mini_conversation_demo/main.py +39 -18
.env.example
CHANGED
|
@@ -1,19 +1,5 @@
|
|
| 1 |
OPENAI_API_KEY=
|
| 2 |
MODEL_NAME="gpt-4o-realtime-preview-2025-06-03"
|
| 3 |
|
| 4 |
-
# Please, change to "false" when you test on a real robot
|
| 5 |
-
SIM=true
|
| 6 |
-
LOG_LEVEL=INFO
|
| 7 |
-
|
| 8 |
-
# Keep it as is, but it's to replace inside main later
|
| 9 |
-
SAMPLE_RATE=24000
|
| 10 |
-
|
| 11 |
-
# "true" to enable vision
|
| 12 |
-
VISION_ENABLED=true
|
| 13 |
-
|
| 14 |
-
# If "SIM=true" head tracking is disabled
|
| 15 |
-
# Change to "true" when SIM is "false"
|
| 16 |
-
HEAD_TRACKING=false
|
| 17 |
-
|
| 18 |
# Cache for local VLM
|
| 19 |
-
HF_HOME=./cache
|
|
|
|
| 1 |
OPENAI_API_KEY=
|
| 2 |
MODEL_NAME="gpt-4o-realtime-preview-2025-06-03"
|
| 3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
# Cache for local VLM
|
| 5 |
+
HF_HOME=./cache
|
README.md
CHANGED
|
@@ -13,3 +13,10 @@ pip install -e .
|
|
| 13 |
```bash
|
| 14 |
reachy-mini-conversation-demo
|
| 15 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
```bash
|
| 14 |
reachy-mini-conversation-demo
|
| 15 |
```
|
| 16 |
+
|
| 17 |
+
## Runtime toggles
|
| 18 |
+
You can pass flags to control runtime behavior:
|
| 19 |
+
- `--sim` - run in simulation mode (no real robot needed).
|
| 20 |
+
- `--vision` - enable vision system.
|
| 21 |
+
- `--head-tracking` - enable head tracking (ignored if `--sim` is active).
|
| 22 |
+
- `--debug` - enable debug logging (default is INFO).
|
pyproject.toml
CHANGED
|
@@ -8,7 +8,7 @@ version = "0.1.0"
|
|
| 8 |
authors = [{ name = "Pollen Robotics", email = "contact@pollen-robotics.com" }]
|
| 9 |
description = ""
|
| 10 |
readme = "README.md"
|
| 11 |
-
requires-python = ">=3.
|
| 12 |
dependencies = [
|
| 13 |
"reachy_mini@git+ssh://git@github.com/pollen-robotics/reachy_mini@develop",
|
| 14 |
"openai",
|
|
|
|
| 8 |
authors = [{ name = "Pollen Robotics", email = "contact@pollen-robotics.com" }]
|
| 9 |
description = ""
|
| 10 |
readme = "README.md"
|
| 11 |
+
requires-python = ">=3.10"
|
| 12 |
dependencies = [
|
| 13 |
"reachy_mini@git+ssh://git@github.com/pollen-robotics/reachy_mini@develop",
|
| 14 |
"openai",
|
src/reachy_mini_conversation_demo/config.py
CHANGED
|
@@ -20,10 +20,7 @@ class Config:
|
|
| 20 |
|
| 21 |
# Optional
|
| 22 |
MODEL_NAME = os.getenv("MODEL_NAME", "gpt-4o-realtime-preview")
|
| 23 |
-
|
| 24 |
-
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
|
| 25 |
-
SAMPLE_RATE = int(os.getenv("SAMPLE_RATE", "24000"))
|
| 26 |
-
VISION_ENABLED = getenv_bool("VISION_ENABLED", False)
|
| 27 |
-
HEAD_TRACKING = getenv_bool("HEAD_TRACKING", False)
|
| 28 |
|
| 29 |
-
|
|
|
|
|
|
| 20 |
|
| 21 |
# Optional
|
| 22 |
MODEL_NAME = os.getenv("MODEL_NAME", "gpt-4o-realtime-preview")
|
| 23 |
+
HF_HOME = os.getenv("HF_HOME", "./cache")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
|
| 25 |
+
|
| 26 |
+
config = Config()
|
src/reachy_mini_conversation_demo/main.py
CHANGED
|
@@ -4,7 +4,7 @@ import asyncio
|
|
| 4 |
import json
|
| 5 |
import logging
|
| 6 |
import random
|
| 7 |
-
import
|
| 8 |
import time
|
| 9 |
import warnings
|
| 10 |
import threading
|
|
@@ -31,30 +31,47 @@ from reachy_mini_conversation_demo.movement import MovementManager
|
|
| 31 |
from reachy_mini_conversation_demo.gstreamer import GstPlayer, GstRecorder
|
| 32 |
from reachy_mini_conversation_demo.vision import VisionManager, init_vision, init_camera
|
| 33 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
# logging
|
| 35 |
-
LOG_LEVEL = config.LOG_LEVEL
|
| 36 |
logging.basicConfig(
|
| 37 |
level=getattr(logging, LOG_LEVEL, logging.INFO),
|
| 38 |
format="%(asctime)s %(levelname)s %(name)s:%(lineno)d | %(message)s",
|
| 39 |
)
|
| 40 |
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
| 41 |
|
| 42 |
# Suppress WebRTC warnings
|
| 43 |
warnings.filterwarnings("ignore", message=".*AVCaptureDeviceTypeExternal.*")
|
| 44 |
warnings.filterwarnings("ignore", category=UserWarning, module="aiortc")
|
| 45 |
|
| 46 |
-
#
|
| 47 |
-
|
| 48 |
-
logging.getLogger("
|
| 49 |
-
logging.getLogger("
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
MODEL_NAME = config.MODEL_NAME
|
| 56 |
-
HEAD_TRACKING = config.HEAD_TRACKING
|
| 57 |
-
API_KEY = config.OPENAI_API_KEY
|
| 58 |
|
| 59 |
# Key preview in logs
|
| 60 |
masked = (API_KEY[:6] + "..." + API_KEY[-4:]) if len(API_KEY) >= 12 else "<short>"
|
|
@@ -395,10 +412,10 @@ async def control_mic_loop():
|
|
| 395 |
await asyncio.sleep(block_time)
|
| 396 |
|
| 397 |
|
| 398 |
-
stop_event = threading.Event()
|
|
|
|
| 399 |
|
| 400 |
-
|
| 401 |
-
async def main():
|
| 402 |
openai = OpenAIRealtimeHandler()
|
| 403 |
recorder = GstRecorder(sample_rate=SAMPLE_RATE)
|
| 404 |
recorder.record()
|
|
@@ -443,5 +460,9 @@ async def main():
|
|
| 443 |
logger.info("Stopped, robot disconected")
|
| 444 |
|
| 445 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
if __name__ == "__main__":
|
| 447 |
-
|
|
|
|
| 4 |
import json
|
| 5 |
import logging
|
| 6 |
import random
|
| 7 |
+
import argparse
|
| 8 |
import time
|
| 9 |
import warnings
|
| 10 |
import threading
|
|
|
|
| 31 |
from reachy_mini_conversation_demo.gstreamer import GstPlayer, GstRecorder
|
| 32 |
from reachy_mini_conversation_demo.vision import VisionManager, init_vision, init_camera
|
| 33 |
|
| 34 |
+
# Command-line arguments
|
| 35 |
+
parser = argparse.ArgumentParser(description="Reachy Mini Conversation Demo")
|
| 36 |
+
parser.add_argument("--sim", action="store_true", help="Run in simulation mode")
|
| 37 |
+
parser.add_argument("--vision", action="store_true", help="Enable vision")
|
| 38 |
+
parser.add_argument("--head-tracking", action="store_true", help="Enable head tracking")
|
| 39 |
+
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
|
| 40 |
+
args = parser.parse_args()
|
| 41 |
+
|
| 42 |
+
# Config values
|
| 43 |
+
SAMPLE_RATE = 24000 # TODO: hardcoded, should it stay like this?
|
| 44 |
+
MODEL_NAME = config.MODEL_NAME
|
| 45 |
+
API_KEY = config.OPENAI_API_KEY
|
| 46 |
+
|
| 47 |
+
# Defaults are all False unless CLI flags are passed
|
| 48 |
+
SIM = args.sim
|
| 49 |
+
VISION_ENABLED = args.vision
|
| 50 |
+
HEAD_TRACKING = args.head_tracking
|
| 51 |
+
LOG_LEVEL = "DEBUG" if args.debug else "INFO"
|
| 52 |
+
|
| 53 |
# logging
|
|
|
|
| 54 |
logging.basicConfig(
|
| 55 |
level=getattr(logging, LOG_LEVEL, logging.INFO),
|
| 56 |
format="%(asctime)s %(levelname)s %(name)s:%(lineno)d | %(message)s",
|
| 57 |
)
|
| 58 |
logger = logging.getLogger(__name__)
|
| 59 |
+
logger.info("Runtime toggles: SIM=%s VISION_ENABLED=%s HEAD_TRACKING=%s LOG_LEVEL=%s",
|
| 60 |
+
SIM, VISION_ENABLED, HEAD_TRACKING, LOG_LEVEL)
|
| 61 |
|
| 62 |
# Suppress WebRTC warnings
|
| 63 |
warnings.filterwarnings("ignore", message=".*AVCaptureDeviceTypeExternal.*")
|
| 64 |
warnings.filterwarnings("ignore", category=UserWarning, module="aiortc")
|
| 65 |
|
| 66 |
+
# Tame third-party noise (looser in DEBUG)
|
| 67 |
+
if LOG_LEVEL == "DEBUG":
|
| 68 |
+
logging.getLogger("aiortc").setLevel(logging.INFO)
|
| 69 |
+
logging.getLogger("fastrtc").setLevel(logging.INFO)
|
| 70 |
+
logging.getLogger("aioice").setLevel(logging.INFO)
|
| 71 |
+
else:
|
| 72 |
+
logging.getLogger("aiortc").setLevel(logging.ERROR)
|
| 73 |
+
logging.getLogger("fastrtc").setLevel(logging.ERROR)
|
| 74 |
+
logging.getLogger("aioice").setLevel(logging.WARNING)
|
|
|
|
|
|
|
|
|
|
| 75 |
|
| 76 |
# Key preview in logs
|
| 77 |
masked = (API_KEY[:6] + "..." + API_KEY[-4:]) if len(API_KEY) >= 12 else "<short>"
|
|
|
|
| 412 |
await asyncio.sleep(block_time)
|
| 413 |
|
| 414 |
|
| 415 |
+
# stop_event = threading.Event()
|
| 416 |
+
stop_event = asyncio.Event()
|
| 417 |
|
| 418 |
+
async def loop():
|
|
|
|
| 419 |
openai = OpenAIRealtimeHandler()
|
| 420 |
recorder = GstRecorder(sample_rate=SAMPLE_RATE)
|
| 421 |
recorder.record()
|
|
|
|
| 460 |
logger.info("Stopped, robot disconected")
|
| 461 |
|
| 462 |
|
| 463 |
+
def main():
|
| 464 |
+
asyncio.run(loop())
|
| 465 |
+
|
| 466 |
+
|
| 467 |
if __name__ == "__main__":
|
| 468 |
+
main()
|