uv set all modules loaded
This commit is contained in:
parent
9f552148f1
commit
a9d23d15f8
5 changed files with 2823 additions and 0 deletions
1
README.md
Normal file
1
README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# 141 Spanish Assistant
|
||||
798
doc/notes.md
798
doc/notes.md
|
|
@ -0,0 +1,798 @@
|
|||
- [1. Executive Overview](#1-executive-overview)
|
||||
- [2. System Architecture \& Data Flow](#2-system-architecture--data-flow)
|
||||
- [2.1. Input Stage:](#21-input-stage)
|
||||
- [2.2. Inference Stage:](#22-inference-stage)
|
||||
- [2.3. Synthesis Stage:](#23-synthesis-stage)
|
||||
- [2.4. Output \& Evaluation Stage:](#24-output--evaluation-stage)
|
||||
- [3. Key Tech Stack \& Components](#3-key-tech-stack--components)
|
||||
- [4. User Interface Layout (PySide6)](#4-user-interface-layout-pyside6)
|
||||
- [5. Core Advantages of This Design](#5-core-advantages-of-this-design)
|
||||
- [6. Layout Explanation](#6-layout-explanation)
|
||||
- [7. Code Structure](#7-code-structure)
|
||||
- [8. Key Technical Recommendations for app/modules/](#8-key-technical-recommendations-for-appmodules)
|
||||
- [9. Structure Review \& Observations](#9-structure-review--observations)
|
||||
- [10. Recommended .gitignore](#10-recommended-gitignore)
|
||||
- [11. Tree Commands](#11-tree-commands)
|
||||
- [11.1. Excluding noisy hidden folders](#111-excluding-noisy-hidden-folders)
|
||||
- [11.2. Setting up Git](#112-setting-up-git)
|
||||
- [11.3. Step-by-Step Commands](#113-step-by-step-commands)
|
||||
- [12. Can you help me write the pyproject.toml file for uv including PySide6, mlx-whisper, and Kokoro?](#12-can-you-help-me-write-the-pyprojecttoml-file-for-uv-including-pyside6-mlx-whisper-and-kokoro)
|
||||
- [13. How to Initialize \& Install using uv](#13-how-to-initialize--install-using-uv)
|
||||
- [13.0.1. Note on Python Version:](#1301-note-on-python-version)
|
||||
- [13.1. Errors and Fixes](#131-errors-and-fixes)
|
||||
- [13.1.1. Step-by-Step Resolution Commands](#1311-step-by-step-resolution-commands)
|
||||
- [13.1.2. I got the following errors uv sync](#1312-i-got-the-following-errors-uv-sync)
|
||||
- [Create basic PySide6 boilerplate for main.py, main\_window.py, and the tab modules](#create--basic-pyside6-boilerplate-for-mainpy-main_windowpy-and-the-tab-modules)
|
||||
|
||||
|
||||
# 1. Executive Overview
|
||||
|
||||
The project is a 100% offline, privacy-first Spanish speech practice assistant running natively on an Apple MacBook Pro M3. It creates a low-latency conversational feedback loop where you speak in Spanish, receive a generated audio response from a local LLM, and get automated feedback comparing your spoken pronunciation against the expected text.
|
||||
|
||||
# 2. System Architecture & Data Flow
|
||||
|
||||
```zsh
|
||||
┌────────────────┐ ┌─────────────────────┐ ┌──────────────────────┐
|
||||
│ Mic Input │ ──> │ mlx-whisper (STT) │ ──> │ PySide6 GUI │
|
||||
└────────────────┘ └─────────────────────┘ └──────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌────────────────┐ ┌─────────────────────┐ ┌──────────────────────┐
|
||||
│ Mac Speakers │ <── │ Kokoro-82M (TTS) │ <── │ Gemma 4 (llama.cpp) │
|
||||
└────────────────┘ └─────────────────────┘ └──────────┬───────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Feedback & SQLite DB │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
## 2.1. Input Stage:
|
||||
Your speech is recorded through the MacBook Pro's built-in microphone array and transcribed to Spanish text using mlx-whisper.
|
||||
|
||||
## 2.2. Inference Stage:
|
||||
Transcribed text (along with recent session history from SQLite) is sent via HTTP to a local llama.cpp server running Gemma 4.
|
||||
|
||||
## 2.3. Synthesis Stage:
|
||||
Gemma’s response is passed to Kokoro-82M, generating high-quality Spanish speech audio offline.
|
||||
|
||||
## 2.4. Output & Evaluation Stage:
|
||||
Audio plays directly through your MacBook speakers via sounddevice. Concurrently, a feedback engine compares your spoken text against target phrases to highlight pronunciation accuracy and tracks your progress in SQLite.
|
||||
|
||||
# 3. Key Tech Stack & Components
|
||||
|
||||
|Component|Selected Technology|Role & Key Features|
|
||||
|---------|-------------------|-------------------|
|
||||
|Package Management|uv|"Fast Python environment setup, dependency management, and script execution (uv run main.py)."|
|
||||
|GUI Framework|PySide6|Multi-tab desktop application using QtAsyncio to keep network and audio processes non-blocking.|
|
||||
|LLM Server|Gemma 4 via llama.cpp|Local LLM inference server hosted on localhost:8080 with Metal GPU acceleration.|
|
||||
|Speech-to-Text (STT)|mlx-whisper|"Apple Silicon-optimized Whisper engine utilizing the MLX framework for fast, accurate Spanish transcription."|
|
||||
|Text-to-Speech (TTS)|Kokoro-82M|"Open-weight (Apache 2.0)| 82M parameter offline TTS engine generating 24kHz Spanish audio."|
|
||||
|Feedback Engine,feedback_engine.py|"Calculates word error rates (WER), sequence similarity, and mispronounced/dropped words."|
|
||||
|Data Storage|SQLite3|"Local relational database storing chat sessions| transcripts, system logs, and pronunciation scores."|
|
||||
|Dev Environment|VS Code + Forgejo|Managed locally with self-hosted Git on Forgejo.|
|
||||
|
||||
# 4. User Interface Layout (PySide6)
|
||||
|
||||
The GUI consists of two main tabs:
|
||||
|
||||
* Tab 1: Conversación (Live Chat & Practice)
|
||||
|
||||
* Displays the streaming conversation transcript between you and the Assistant.
|
||||
|
||||
* Shows visual feedback cards after each spoken turn (e.g., Pronunciation Accuracy Score %, highlighted missing words, and accent notes).
|
||||
|
||||
* Tab 2: Control & Logs
|
||||
|
||||
* Displays system status (llama.cpp server state, latency metrics).
|
||||
|
||||
* Includes an embedded SQLite table viewer to inspect past conversation history and track language progress over time.
|
||||
|
||||
# 5. Core Advantages of This Design
|
||||
|
||||
* Zero Cloud Dependencies: Completely offline—no API costs, no network latency, and total privacy for your audio data.
|
||||
|
||||
* Hardware Optimized: Leverages your M3 Mac's Unified Memory, Metal GPU, and Neural Engine for sub-second pipeline processing.
|
||||
|
||||
* Clean Open-Source Licensing: Replaces proprietary components (like edge-tts) with permissive open-weight/open-source alternatives (Apache 2.0 / LGPL / MIT).
|
||||
|
||||
|
||||
```zsh
|
||||
+-------------------------------------------------------------------------------------------------------+
|
||||
| SPANISH VOICE PRACTICE AI [PySide6] [ _ ] [ X ] |
|
||||
+-------------------------------------------------------------------------------------------------------+
|
||||
| [ CONVERSACIÓN (Practice) ] [ CONTROL & LOGS (Settings) ] |
|
||||
+-------------------------------------------------------------------------------------------------------+
|
||||
| |
|
||||
| [TAB 1: CONVERSACIÓN] |
|
||||
| |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| | [CHAT DISPLAY - QTextEdit (Read-Only)] | |
|
||||
| | | |
|
||||
| | [User (Whisper)]: Hola Gemma, ¿cómo puedo mejorar mi acento español? | |
|
||||
| | | |
|
||||
| | [Assistant (Kokoro)]: ¡Hola! La mejor forma de mejorar es practicar en voz alta todos los días. | |
|
||||
| | Intenta imitar mi entonación. | |
|
||||
| | | |
|
||||
| | [User (Whisper)]: ¿Puedes darme una frase para practica? | |
|
||||
| | | |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| | [FEEDBACK PANEL - QFrame (Visible after speaking)] | |
|
||||
| | | |
|
||||
| | Pronunciation Score: [ 88% ] [|||||||||| ] (Good) | |
|
||||
| | -------------------------------------------------- | |
|
||||
| | Target Text: "¿Puedes darme una frase para practica<font color='red'>r</font>?" | |
|
||||
| | Spoken Text: "¿Puedes darme una frase para practica<font color='gray'>_</font>?" | |
|
||||
| | -------------------------------------------------- | |
|
||||
| | [i] Notes: Watch your word endings (verb infinitives like 'practicar'). | |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| | [INPUT AREA] | |
|
||||
| | | |
|
||||
| | [ HOLD SPACE TO SPEAK / Type your prompt... ] [ RECORD (O) ] [ SEND (->) ] | |
|
||||
| | | |
|
||||
| +-------------------------------------------------------------------------------------------------+ |
|
||||
| |
|
||||
+-------------------------------------------------------------------------------------------------------+
|
||||
| System Status: Assistant Speaking... [DB Session: 104] |
|
||||
+-------------------------------------------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
# 6. Layout Explanation
|
||||
1. Main Window Structure
|
||||
* Frameless/Standard QMainWindow: A clean modern window titled "Spanish Voice Practice AI."
|
||||
|
||||
* QTabWidget: The core navigation anchor.
|
||||
|
||||
* Tab 1 (Conversación): The main interaction zone shown above.
|
||||
|
||||
* Tab 2 (Control & Logs): (Not pictured) Would contain database viewing, LLM parameter sliders (temperature, max tokens), and system performance logs (latency checks).
|
||||
|
||||
2. Chat Display (QTextEdit)
|
||||
* Displays a scrolling log of the conversation.
|
||||
|
||||
* Uses rich text formatting to differentiate between User, Assistant, and any system alerts.
|
||||
|
||||
* Transcripts from mlx-whisper are inserted here automatically.
|
||||
|
||||
3. Feedback Panel (QFrame)
|
||||
* This panel appears (or updates) dynamically after the user finishes speaking and Whisper transcribes the audio.
|
||||
|
||||
* It displays the results generated by the PronunciationFeedbackEngine:
|
||||
|
||||
* Visual Score Bar: A colored bar/meter showing accuracy.
|
||||
|
||||
* Diff View: Uses HTML color coding (e.g., Red for omissions, Green for correct words) to visually compare Gemma's target text against the actual spoken transcription.
|
||||
|
||||
4. Input Area (QHBoxLayout)
|
||||
* Combined Input: Primarily focused on voice, but includes a text fallback.
|
||||
|
||||
* Voice Trigger: A prominent visual button (RECORD (O)) and a keyboard shortcut (e.g., holding Spacebar) to initiate recording via the STTEngine.
|
||||
|
||||
* Send Button: A classic arrow icon for sending text input or manually submitting a recorded chunk.
|
||||
|
||||
5. Status Bar (QStatusBar)
|
||||
* Provides real-time feedback on what the background systems are doing (e.g., "Whisper Transcribing...", "Gemma Generating...", "Kokoro Speaking...", "Ready").
|
||||
|
||||
* Displays the current active SQLite database session ID.
|
||||
|
||||
# 7. Code Structure
|
||||
|
||||
1. GUI Framework Alignment: You’ve migrated this project to PySide6 (as noted in your comment), but double-check that your UI imports and sub-classes across main.py, main_window.py, chat_tab.py, and control_tab.py are strictly using PySide6.QtWidgets rather than PyQt6.
|
||||
|
||||
2. Local macOS Optimization Opportunities: Since you are running locally on Apple Silicon (M3), using standard cloud/hybrid pipelines (edge-tts) or baseline CPU bindings might introduce unnecessary network latency or underutilize your Unified Memory.
|
||||
|
||||
## Tree Structure
|
||||
|
||||
```zsh
|
||||
spanish-assistant/
|
||||
├── pyproject.toml # UV dependency management (PySide6, mlx-whisper, etc.)
|
||||
├── app/
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py # PySide6 App entrypoint (QApplication)
|
||||
│ ├── db.py # SQLite3 Context Manager & Repository pattern
|
||||
│ ├── modules/
|
||||
│ │ ├── llm_controller.py # Subprocess / HTTP client for local llama.cpp server
|
||||
│ │ ├── stt_engine.py # Speech-to-Text (mlx-whisper / PyAudio capture)
|
||||
│ │ └── tts_engine.py # Text-to-Speech (Local Kokoro-TTS or edge-tts fallback)
|
||||
│ └── ui/
|
||||
│ ├── main_window.py # Main PySide6 QMainWindow / QTabWidget
|
||||
│ ├── chat_tab.py # Tab 1: Interactive Spanish audio/text interface
|
||||
│ └── control_tab.py # Tab 2: Logs, DB Inspector, and local LLM parameter controls
|
||||
└── data/
|
||||
└── conversation_history.db # Local SQLite database storage
|
||||
|
||||
```
|
||||
|
||||
# 8. Key Technical Recommendations for app/modules/
|
||||
1. Speech-to-Text (stt_engine.py)
|
||||
* Apple Silicon Edge: If you are currently using standard openai-whisper or whisper.cpp Python bindings, consider using mlx-whisper. It leverages Apple's MLX framework to run Whisper directly on the M3 Neural Engine/GPU with significantly lower latency and minimal CPU impact.
|
||||
2. Text-to-Speech (tts_engine.py)
|
||||
* Offline Native TTS: edge-tts is simple and fast, but it requires an active internet connection to stream Microsoft's cloud endpoints.
|
||||
* If you want a 100% offline local setup for Spanish voice practice, look into Kokoro-82M (e.g., via kokoro or kokoro-onnx). It supports high-quality, natural Spanish pronunciation locally on macOS without needing cloud requests.
|
||||
3. Database Layer (db.py)
|
||||
* Make sure your db.py exposes thread-safe connection handling (or a repository pattern) so background Qt threads (QThread) handling STT/TTS don't crash SQLite when logging conversations while the UI is rendering tables.
|
||||
|
||||
```Plaitext
|
||||
spanish-assistant/
|
||||
├── pyproject.toml # Managed with UV (PySide6, mlx-whisper, kokoro, sounddevice, etc.)
|
||||
├── app/
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py # Launches Spanish Assistant (QApplication + QtAsyncio)
|
||||
│ ├── db.py # SQLite3 conversation history & progress tracker
|
||||
│ ├── modules/
|
||||
│ │ ├── llm_controller.py # Background process manager for llama.cpp (Gemma 4)
|
||||
│ │ ├── stt_engine.py # Speech-to-Text via mlx-whisper
|
||||
│ │ ├── tts_engine.py # Local 100% offline Spanish TTS via Kokoro-82M
|
||||
│ │ └── feedback_engine.py # Pronunciation & WER accuracy comparison module
|
||||
│ └── ui/
|
||||
│ ├── main_window.py # Main QMainWindow shell
|
||||
│ ├── chat_tab.py # Tab 1: Live conversation & real-time feedback card
|
||||
│ └── control_tab.py # Tab 2: System logs, DB inspector, and LLM controls
|
||||
└── data/
|
||||
└── conversation_history.db # Session logs & speech analytics storage
|
||||
```
|
||||
|
||||
```zsh
|
||||
141_Spanish_Assistant % tree
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ ├── modules
|
||||
│ │ ├── feedback_engine.py
|
||||
│ │ ├── llm_controller.py
|
||||
│ │ ├── stt_engine.py
|
||||
│ │ └── tts_engine.py
|
||||
│ └── ui
|
||||
│ ├── chat_tab.py
|
||||
│ ├── control_tab.py
|
||||
│ └── main_window.py
|
||||
├── data
|
||||
└── doc
|
||||
├── images
|
||||
└── notes.md
|
||||
```
|
||||
# 9. Structure Review & Observations
|
||||
* Python Packages: You have app/__init__.py, which turns app into a package. If you plan to import modules within chat_tab.py using absolute imports like from app.modules.llm_controller import LLMController, ensure you run your entry point (main.py) from the repository root (e.g., python -m app.main). Alternatively, consider adding an empty __init__.py inside app/modules and app/ui if you run into any relative import issues down the road.
|
||||
|
||||
* Data Directory: Keeping data/ at the root is ideal for local database storage (like SQLite/PostgreSQL dumps), audio cache files, or user session states.
|
||||
|
||||
* Docs & Assets: Placing screenshots or UI reference mockups in doc/images/ and markdown notes in doc/notes.md keeps the repository root tidy.
|
||||
|
||||
# 10. Recommended .gitignore
|
||||
|
||||
```zsh
|
||||
# ==========================================
|
||||
# macOS System Files
|
||||
# ==========================================
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon?
|
||||
._*
|
||||
|
||||
# ==========================================
|
||||
# Python & Bytecode
|
||||
# ==========================================
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
|
||||
# ==========================================
|
||||
# Virtual Environments
|
||||
# ==========================================
|
||||
.venv/
|
||||
venv/
|
||||
ENV/
|
||||
env/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# ==========================================
|
||||
# Application Data & Cache
|
||||
# ==========================================
|
||||
# Keep the data/ directory structure, but ignore dynamic files inside it
|
||||
data/*
|
||||
!data/.gitkeep
|
||||
|
||||
# Local log files and audio caches
|
||||
*.log
|
||||
*.wav
|
||||
*.mp3
|
||||
*.ogg
|
||||
|
||||
# ==========================================
|
||||
# Environment & Secrets
|
||||
# ==========================================
|
||||
.env
|
||||
.env.local
|
||||
*.pem
|
||||
|
||||
# ==========================================
|
||||
# IDEs & Editors
|
||||
# ==========================================
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
```
|
||||
|
||||
# 11. Tree Commands
|
||||
|
||||
To tell tree to display hidden files, pass the -a (all) flag:
|
||||
|
||||
```zsh
|
||||
tree -a
|
||||
```
|
||||
## 11.1. Excluding noisy hidden folders
|
||||
|
||||
If you run tree -a, it will also crawl into the .git directory, which prints a massive, messy wall of internal Git objects.
|
||||
|
||||
To see your .gitkeep and .gitignore without cluttering the output with .git/, use the -I (ignore) flag:
|
||||
|
||||
```zsh
|
||||
tree -a -I '.git'
|
||||
```
|
||||
|
||||
```zsh
|
||||
.
|
||||
├── .gitignore
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ ├── modules
|
||||
│ │ ├── feedback_engine.py
|
||||
│ │ ├── llm_controller.py
|
||||
│ │ ├── stt_engine.py
|
||||
│ │ └── tts_engine.py
|
||||
│ └── ui
|
||||
│ ├── chat_tab.py
|
||||
│ ├── control_tab.py
|
||||
│ └── main_window.py
|
||||
├── data
|
||||
│ └── .gitkeep
|
||||
└── doc
|
||||
├── images
|
||||
└── notes.md
|
||||
```
|
||||
|
||||
```zsh
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % tree -a
|
||||
|
||||
.
|
||||
├── .git
|
||||
│ ├── HEAD
|
||||
│ ├── config
|
||||
│ ├── description
|
||||
│ ├── hooks
|
||||
│ │ ├── applypatch-msg.sample
|
||||
│ │ ├── commit-msg.sample
|
||||
│ │ ├── fsmonitor-watchman.sample
|
||||
│ │ ├── post-update.sample
|
||||
│ │ ├── pre-applypatch.sample
|
||||
│ │ ├── pre-commit.sample
|
||||
│ │ ├── pre-merge-commit.sample
|
||||
│ │ ├── pre-push.sample
|
||||
│ │ ├── pre-rebase.sample
|
||||
│ │ ├── pre-receive.sample
|
||||
│ │ ├── prepare-commit-msg.sample
|
||||
│ │ ├── push-to-checkout.sample
|
||||
│ │ ├── sendemail-validate.sample
|
||||
│ │ └── update.sample
|
||||
│ ├── info
|
||||
│ │ └── exclude
|
||||
│ ├── objects
|
||||
│ │ ├── info
|
||||
│ │ └── pack
|
||||
│ └── refs
|
||||
│ ├── heads
|
||||
│ └── tags
|
||||
├── app
|
||||
│ ├── __init__.py
|
||||
│ ├── main.py
|
||||
│ ├── modules
|
||||
│ │ ├── feedback_engine.py
|
||||
│ │ ├── llm_controller.py
|
||||
│ │ ├── stt_engine.py
|
||||
│ │ └── tts_engine.py
|
||||
│ └── ui
|
||||
│ ├── chat_tab.py
|
||||
│ ├── control_tab.py
|
||||
│ └── main_window.py
|
||||
├── data
|
||||
│ └── .gitkeeper
|
||||
└── doc
|
||||
├── images
|
||||
└── notes.md
|
||||
16 directories, 29 files
|
||||
stephenlohning@Scotty 141_Spanish_Assistant %
|
||||
```
|
||||
|
||||
## 11.2. Setting up Git
|
||||
|
||||
* Setting __push.followTags = true__ changes default behavior so that whenever you run git push, Git automatically pushes annotated tags that point to commits reachable from the branch you are pushing.
|
||||
|
||||
## 11.3. Step-by-Step Commands
|
||||
Run these commands in order in your terminal:
|
||||
|
||||
```zsh
|
||||
# 1. Stage all your initial project files and .gitignore
|
||||
git add .
|
||||
|
||||
# 2. Make your first commit (this resolves HEAD and creates your branch)
|
||||
git commit -m "Initial project structure and config"
|
||||
|
||||
# 3. Ensure your active branch is named 'main'
|
||||
git branch -M main
|
||||
|
||||
# 4. Now create your annotated tag on the new commit
|
||||
git tag -a v0.1.0 -m "Initial project structure and config"
|
||||
|
||||
# 5. Push your branch and tag up to Forgejo
|
||||
git push -u origin main
|
||||
```
|
||||
After running git commit, git branch will display * main, and your git tag command will succeed!
|
||||
|
||||
# 12. Can you help me write the pyproject.toml file for uv including PySide6, mlx-whisper, and Kokoro?
|
||||
|
||||
Here is a complete, production-ready pyproject.toml file tailored specifically for 141_Spanish_Assistant using uv.
|
||||
It includes:
|
||||
* PySide6 for the GUI.
|
||||
* mlx-whisper for Apple Silicon GPU/Neural Engine accelerated speech-to-text.
|
||||
* kokoro-onnx (and soundfile) for fast, local, 100% offline Kokoro-82M TTS.
|
||||
* sounddevice and numpy for real-time audio capture and playback.
|
||||
* requests to communicate with your local llama.cpp server hosting Gemma 4.
|
||||
* editdistance / jiwer for pronunciation accuracy and Word Error Rate (WER) evaluations in feedback_engine.py.pyproject.toml
|
||||
*
|
||||
Create or overwrite pyproject.toml in the root of 141_Spanish_Assistant:
|
||||
|
||||
```zsh
|
||||
[project]
|
||||
name = "spanish-assistant"
|
||||
version = "0.1.0"
|
||||
description = "Local, offline Spanish speech practice assistant running on Apple Silicon"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
authors = [
|
||||
{ name = "Stephen", email = "stephen.lohning@oxnee.com" }
|
||||
]
|
||||
dependencies = [
|
||||
# GUI Framework
|
||||
"pyside6>=6.6.0",
|
||||
|
||||
# Local Speech-to-Text (Apple MLX Engine)
|
||||
"mlx-whisper>=0.2.0",
|
||||
|
||||
# Local Text-to-Speech (Kokoro 82M via ONNX Runtime)
|
||||
"kokoro-onnx>=0.5.0",
|
||||
"soundfile>=0.12.1",
|
||||
|
||||
# Audio Recording & Playback
|
||||
"sounddevice>=0.4.6",
|
||||
"numpy>=1.24.0,<2.0.0",
|
||||
|
||||
# HTTP Client for local llama.cpp server
|
||||
"requests>=2.31.0",
|
||||
|
||||
# Pronunciation Feedback & Text Analytics
|
||||
"editdistance>=0.8.0",
|
||||
"jiwer>=3.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.uv]
|
||||
# Ensures dependencies stay isolated and locked cleanly on macOS
|
||||
dev-dependencies = [
|
||||
"pytest>=8.0.0",
|
||||
"black>=24.0.0",
|
||||
]
|
||||
```
|
||||
|
||||
# 13. How to Initialize & Install using uv
|
||||
|
||||
Run these commands in your terminal from the root directory:
|
||||
|
||||
```zsh
|
||||
# 1. Create a Python 3.12 virtual environment managed by uv
|
||||
uv venv --python 3.12
|
||||
|
||||
# 2. Sync and install all dependencies defined in pyproject.toml
|
||||
uv sync
|
||||
|
||||
# 3. Test that the environment loads cleanly
|
||||
uv run python -c "import PySide6, mlx_whisper, kokoro_onnx; print('All core modules imported successfully!')"
|
||||
```
|
||||
### 13.0.1. Note on Python Version:
|
||||
* requires-python is set to <3.13 because several core MLX and ONNX bindings used on Apple Silicon run most reliably on Python 3.10–3.12.
|
||||
```zsh
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % uv venv --python 3.12
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
Using CPython 3.12.12 interpreter at: /opt/homebrew/opt/python@3.12/bin/python3.12
|
||||
Creating virtual environment at: .venv
|
||||
Activate with: source .venv/bin/activate
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % uv sync
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
× No solution found when resolving dependencies:
|
||||
╰─▶ Because only kokoro-onnx<=0.5.0 is available and kokoro-onnx==0.5.0 depends on numpy>=2.0.2, we can conclude that kokoro-onnx>=0.5.0 depends on numpy>=2.0.2.
|
||||
And because your project depends on kokoro-onnx>=0.5.0 and numpy>=1.24.0,<2.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % source .venv/bin/activate
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant %
|
||||
|
||||
```
|
||||
|
||||
## 13.1. Errors and Fixes
|
||||
|
||||
```zsh
|
||||
I got the following comments
|
||||
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % uv venv --python 3.12
|
||||
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
|
||||
Using CPython 3.12.12 interpreter at: /opt/homebrew/opt/python@3.12/bin/python3.12
|
||||
|
||||
Creating virtual environment at: .venv
|
||||
|
||||
Activate with: source .venv/bin/activate
|
||||
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % uv sync
|
||||
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
|
||||
× No solution found when resolving dependencies:
|
||||
|
||||
╰─▶ Because only kokoro-onnx<=0.5.0 is available and kokoro-onnx==0.5.0 depends on numpy>=2.0.2, we can conclude that kokoro-onnx>=0.5.0 depends on numpy>=2.0.2.
|
||||
|
||||
And because your project depends on kokoro-onnx>=0.5.0 and numpy>=1.24.0,<2.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % source .venv/bin/activate
|
||||
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant % uv run python -c "import PySide6, mlx_whisper, kokoro_onnx; print('All core modules imported successfully!')"
|
||||
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
|
||||
× No solution found when resolving dependencies:
|
||||
|
||||
╰─▶ Because only kokoro-onnx<=0.5.0 is available and kokoro-onnx==0.5.0 depends on numpy>=2.0.2, we can conclude that kokoro-onnx>=0.5.0 depends on numpy>=2.0.2.
|
||||
|
||||
And because your project depends on kokoro-onnx>=0.5.0 and numpy>=1.24.0,<2.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant %
|
||||
|
||||
```
|
||||
This is a dependency conflict between kokoro-onnx and numpy, combined with an updated syntax rule in modern uv.
|
||||
|
||||
Here is why it failed and how to fix it:
|
||||
|
||||
1. numpy Conflict: kokoro-onnx>=0.5.0 explicitly requires numpy>=2.0.2. The pyproject.toml constrained numpy to <2.0.0, creating an impossible set of rules for uv to resolve.
|
||||
|
||||
2. uv Deprecation Warning: In recent uv versions, dev dependencies belong under [dependency-groups] rather than [tool.uv.dev-dependencies].
|
||||
|
||||
The Fixed pyproject.toml
|
||||
Replace your root pyproject.toml with this updated version:
|
||||
|
||||
```zsh
|
||||
[project]
|
||||
name = "spanish-assistant"
|
||||
version = "0.1.0"
|
||||
description = "Local, offline Spanish speech practice assistant running on Apple Silicon"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
authors = [
|
||||
{ name = "Stephen", email = "stephen.lohning@oxnee.com" }
|
||||
]
|
||||
dependencies = [
|
||||
# GUI Framework
|
||||
"pyside6>=6.6.0",
|
||||
|
||||
# Local Speech-to-Text (Apple MLX Engine)
|
||||
"mlx-whisper>=0.2.0",
|
||||
|
||||
# Local Text-to-Speech (Kokoro 82M via ONNX Runtime)
|
||||
"kokoro-onnx>=0.5.0",
|
||||
"soundfile>=0.12.1",
|
||||
|
||||
# Audio Recording & Playback (Compatible with NumPy 2.x)
|
||||
"sounddevice>=0.4.6",
|
||||
"numpy>=2.0.2",
|
||||
|
||||
# HTTP Client for local llama.cpp server
|
||||
"requests>=2.31.0",
|
||||
|
||||
# Pronunciation Feedback & Text Analytics
|
||||
"editdistance>=0.8.0",
|
||||
"jiwer>=3.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# Updated syntax for dev dependencies in modern uv
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"black>=24.0.0",
|
||||
]
|
||||
```
|
||||
### 13.1.1. Step-by-Step Resolution Commands
|
||||
Run these steps in your terminal to clear out the old resolution state and sync cleanly:
|
||||
|
||||
```zsh
|
||||
# 1. Sync dependencies with the updated pyproject.toml
|
||||
uv sync
|
||||
|
||||
# 2. Test the core module imports
|
||||
uv run python -c "import PySide6, mlx_whisper, kokoro_onnx; print('All core modules imported successfully!')"
|
||||
|
||||
```
|
||||
Once uv sync finishes, you will see All core modules imported successfully! and your .venv will be ready for development.
|
||||
|
||||
### 13.1.2. I got the following errors uv sync
|
||||
|
||||
```zsh
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % uv sync
|
||||
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
|
||||
× No solution found when resolving dependencies:
|
||||
|
||||
╰─▶ Because only kokoro-onnx<=0.5.0 is available and kokoro-onnx==0.5.0 depends on numpy>=2.0.2, we can conclude that kokoro-onnx>=0.5.0 depends on numpy>=2.0.2.
|
||||
|
||||
And because your project depends on kokoro-onnx>=0.5.0 and numpy>=1.24.0,<2.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||
|
||||
stephenlohning@Scotty 141_Spanish_Assistant % source .venv/bin/activate
|
||||
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant % uv run python -c "import PySide6, mlx_whisper, kokoro_onnx; print('All core modules imported successfully!')"
|
||||
|
||||
warning: The `tool.uv.dev-dependencies` field (used in `pyproject.toml`) is deprecated and will be removed in a future release; use `dependency-groups.dev` instead
|
||||
|
||||
× No solution found when resolving dependencies:
|
||||
|
||||
╰─▶ Because only kokoro-onnx<=0.5.0 is available and kokoro-onnx==0.5.0 depends on numpy>=2.0.2, we can conclude that kokoro-onnx>=0.5.0 depends on numpy>=2.0.2.
|
||||
|
||||
And because your project depends on kokoro-onnx>=0.5.0 and numpy>=1.24.0,<2.0.0, we can conclude that your project's requirements are unsatisfiable.
|
||||
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant % uv sync
|
||||
|
||||
Resolved 109 packages in 1.52s
|
||||
|
||||
× Failed to build `spanish-assistant @ file:///Users/stephenlohning/Documents/01_Projects/141_Spanish_Assistant`
|
||||
|
||||
├─▶ The build backend returned an error
|
||||
|
||||
╰─▶ Call to `hatchling.build.build_editable` failed (exit status: 1)
|
||||
|
||||
|
||||
|
||||
[stderr]
|
||||
|
||||
Traceback (most recent call last):
|
||||
|
||||
File "<string>", line 11, in <module>
|
||||
|
||||
File "/Users/stephenlohning/.cache/uv/builds-v0/.tmpOvMudK/lib/python3.12/site-packages/hatchling/build.py", line 83, in build_editable
|
||||
|
||||
return os.path.basename(next(builder.build(directory=wheel_directory, versions=["editable"])))
|
||||
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
File "/Users/stephenlohning/.cache/uv/builds-v0/.tmpOvMudK/lib/python3.12/site-packages/hatchling/builders/plugin/interface.py", line 92, in build
|
||||
|
||||
self.metadata.validate_fields()
|
||||
|
||||
File "/Users/stephenlohning/.cache/uv/builds-v0/.tmpOvMudK/lib/python3.12/site-packages/hatchling/metadata/core.py", line 266, in validate_fields
|
||||
|
||||
self.core.validate_fields()
|
||||
|
||||
File "/Users/stephenlohning/.cache/uv/builds-v0/.tmpOvMudK/lib/python3.12/site-packages/hatchling/metadata/core.py", line 1437, in validate_fields
|
||||
|
||||
getattr(self, attribute)
|
||||
|
||||
File "/Users/stephenlohning/.cache/uv/builds-v0/.tmpOvMudK/lib/python3.12/site-packages/hatchling/metadata/core.py", line 533, in readme
|
||||
|
||||
raise OSError(message)
|
||||
|
||||
OSError: Readme file does not exist: README.md
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
hint: Build failures usually indicate a problem with the package or the build environment%
|
||||
|
||||
(141_Spanish_Assistant) stephenlohning@Scotty 141_Spanish_Assistant %
|
||||
```
|
||||
There were two independent issues happening in your terminal output:
|
||||
|
||||
Resolution Failure (Fixed): The first run failed because of the numpy constraint conflict.
|
||||
|
||||
Build Failure (README.md Missing): The second run succeeded in resolving all 109 packages, but failed at the build step because pyproject.toml declared readme = "README.md", but no README.md file existed in your project root yet.
|
||||
|
||||
Additionally, because your Python code lives inside an app/ folder rather than a src/ or spanish_assistant/ package folder, Hatchling (the build backend) needs a small configuration hint to know what to include in editable mode (uv sync).
|
||||
|
||||
Step 1: Create a placeholder README.md
|
||||
Run this in your terminal from the project root:
|
||||
|
||||
``zsh
|
||||
touch README.md
|
||||
echo "# 141 Spanish Assistant" > README.md
|
||||
```
|
||||
Step 2: Use the Updated pyproject.tomlUpdate your root pyproject.toml with this version. It configures [tool.hatch.build.targets.wheel] so Hatchling cleanly packages the app/ directory without throwing editable build errors:
|
||||
|
||||
```zsh
|
||||
[project]
|
||||
name = "spanish-assistant"
|
||||
version = "0.1.0"
|
||||
description = "Local, offline Spanish speech practice assistant running on Apple Silicon"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
authors = [
|
||||
{ name = "Stephen", email = "stephen.lohning@oxnee.com" }
|
||||
]
|
||||
dependencies = [
|
||||
# GUI Framework
|
||||
"pyside6>=6.6.0",
|
||||
|
||||
# Local Speech-to-Text (Apple MLX Engine)
|
||||
"mlx-whisper>=0.2.0",
|
||||
|
||||
# Local Text-to-Speech (Kokoro 82M via ONNX Runtime)
|
||||
"kokoro-onnx>=0.5.0",
|
||||
"soundfile>=0.12.1",
|
||||
|
||||
# Audio Recording & Playback
|
||||
"sounddevice>=0.4.6",
|
||||
"numpy>=2.0.2",
|
||||
|
||||
# HTTP Client for local llama.cpp server
|
||||
"requests>=2.31.0",
|
||||
|
||||
# Pronunciation Feedback & Text Analytics
|
||||
"editdistance>=0.8.0",
|
||||
"jiwer>=3.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# Configures Hatchling to recognise the app/ directory
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["app"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"black>=24.0.0",
|
||||
]
|
||||
```
|
||||
Step 3: Run uv sync and Test
|
||||
Now sync and verify:
|
||||
```zsh
|
||||
uv sync
|
||||
```
|
||||
```zsh
|
||||
uv run python -c "import PySide6, mlx_whisper, kokoro_onnx; print('All core modules imported successfully!')"
|
||||
```
|
||||
You should see All core modules imported successfully!, with zero warnings or errors. Which we did
|
||||
|
||||
git tag -a v0.1.1 -m "uv set all modules loaded "
|
||||
|
||||
# Create basic PySide6 boilerplate for main.py, main_window.py, and the tab modules
|
||||
|
||||
Here is a complete set of boilerplate code tailored specifically for 141_Spanish_Assistant.
|
||||
|
||||
It uses PySide6.QtAsyncio for non-blocking execution (allowing STT, TTS, and LLM calls to run seamlessly in the background without freezing the GUI).
|
||||
|
||||
1. Entry Point: app/main.py
|
||||
This file initializes the PySide6 application, creates the MainWindow, and delegates execution to QtAsyncio.
|
||||
BIN
doc/notes.pdf
Normal file
BIN
doc/notes.pdf
Normal file
Binary file not shown.
45
pyproject.toml
Normal file
45
pyproject.toml
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
[project]
|
||||
name = "spanish-assistant"
|
||||
version = "0.1.0"
|
||||
description = "Local, offline Spanish speech practice assistant running on Apple Silicon"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10,<3.13"
|
||||
authors = [
|
||||
{ name = "Stephen", email = "stephen.lohning@oxnee.com" }
|
||||
]
|
||||
dependencies = [
|
||||
# GUI Framework
|
||||
"pyside6>=6.6.0",
|
||||
|
||||
# Local Speech-to-Text (Apple MLX Engine)
|
||||
"mlx-whisper>=0.2.0",
|
||||
|
||||
# Local Text-to-Speech (Kokoro 82M via ONNX Runtime)
|
||||
"kokoro-onnx>=0.5.0",
|
||||
"soundfile>=0.12.1",
|
||||
|
||||
# Audio Recording & Playback
|
||||
"sounddevice>=0.4.6",
|
||||
"numpy>=2.0.2",
|
||||
|
||||
# HTTP Client for local llama.cpp server
|
||||
"requests>=2.31.0",
|
||||
|
||||
# Pronunciation Feedback & Text Analytics
|
||||
"editdistance>=0.8.0",
|
||||
"jiwer>=3.0.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
# Configures Hatchling to recognise the app/ directory
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["app"]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pytest>=8.0.0",
|
||||
"black>=24.0.0",
|
||||
]
|
||||
Loading…
Reference in a new issue