German Tutor started as an AI-powered German language learning assistant that helps users improve their German vocabulary, sentence structure, and grammar.
Now it is a multi-lingual language learning assistant that can also be used as a general assistant. It uses speech recognition, large language models (LLMs), text-to-speech (TTS), and RAG (retrieval-augmented generation) to provide corrections, explanations, and up-to-date answers.
German Tutor V3.1 is rebuilt around a LangGraph ReAct pipeline with full session memory.
V3.1 updates:
- Text mode: the assistant can now be used entirely from the terminal, no microphone, no wake word required. Toggle between text and audio mode with
toggle_text_modeinconfig.yaml. - LangGraph ReAct pipeline: the LLM now runs as a proper ReAct agent, it reasons, decides whether to call a tool, receives the result, and loops until it's ready to respond.
- ReAct pipeline: separated into a
react_agentnode (LLM reasoning) and aretriever_agentnode (tool execution), connected via LangGraph's conditional edges. - Session memory: conversation history is persisted across turns using LangGraph's
MemorySavercheckpointer, the model remembers everything said earlier in the session. - TTS interruption: TTS now runs in a background thread and can be interrupted mid-speech by pressing the enter key (in both text and audio modes).
German Tutor V3 introduced multi-language support and general assistant capabilities.
V3.0 updates:
- RAG integration for up-to-date answers using live web search.
- Modular and organized codebase for easier maintenance and customization.
- All options, including language settings, can be modified in the
config.yamlfile.
V3.0 major improvements:
- Faster and more accurate STT: now using
faster-whisperwith configurable model sizes (replacingsound_recognition). - Real-time TTS:
mpv+edge-ttsfor faster synthesis without temporary files (previous method still available if needed). - LLM upgrade:
openai/gpt-oss-120bfrom Groq (default and recommended), offering more free daily API calls. Users can choose any other Groq LLM by changing themodelin theconfig.yamlfile. - Improved TUI for a smoother user experience.
German Tutor V3 now supports two RAG modes (retrieval-augmented generation):
- Online RAG (
tavily_rag.py): live web search via Tavily AI, good for current events, up-to-date grammar references, and anything not in your local books. - Offline RAG (
offline_rag.py): searches a local vector database built from your own books/documents, works without internet and is faster for static reference material.
The ReAct agent decides which tool to use (or neither) based on the question.
Here's a visual comparison of RAG vs no RAG:
NOTE: Anything with an asterisk* can be customized in the
.yamlfile.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β USER INPUT β
β (German, any other language, or any question) β
ββββββββββββββββ¬βββββββββββββββββββββββββββ¬ββββββββββββββββββββ
β β
toggle_text_mode: False toggle_text_mode: True
β β
β β
ββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββ
β AUDIO MODE β β TEXT MODE β
β - Wake word*: "Jarvis" β β - Type directly in terminal β
β - Record until silence β β - Press Enter to send β
β - Whisper STT β β - Press Enter to stop TTS β
ββββββββββββββββ¬ββββββββββββ βββββββββββββββββ¬ββββββββββββββββ
β β
β β
ββββββββββββββββββββββββββββ β
β SPEECH-TO-TEXT β β
β (Faster-Whisper) β β
β - Model*: tiny β large β β
β - Language*: auto/manualβ β
β - Output: USER TEXT β β
ββββββββββββββββ¬ββββββββββββ β
β β
ββββββββββββββββ¬ββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANGGRAPH ReAct PIPELINE (with session memory) β
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β react_agent node (LLM) β β
β β - Receives full conversation history (MemorySaver) β β
β β - Reasons about the input β β
β β - Decides: answer directly OR call a tool β β
β βββββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββββββββ β
β tool call? β β no β final answer β
β β β β
β βββββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββ β
β β retriever_agent node β β END β response to user β β
β β Tool options: β βββββββββββββββββββββββββββββββ β
β β - Tavily web search β β
β β - Offline book search β β
β ββββββββββββ¬βββββββββββββββββ β
β β tool result loops back to react_agent β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TEXT-TO-SPEECH (Edge-TTS + mpv) β
β - Runs in background thread (non-blocking) β
β - Interruptible mid-speech β
βββββββββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AUDIO PLAYBACK β Loop or Exit β
β (using end phrases like: close, bye) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
German-Tutor/
β
βββ german_tutor_V3.py # main entry point
β
βββ MODEL_3/
β βββ graph.py # LangGraph pipeline (ReAct loop + memory)
β βββ config.yaml
β β
β βββ audio/
β β βββ wake_word.py
β β βββ audio_io.py
β β βββ stt.py
β β βββ tts.py
β β βββ end_phrase.py
β β
β βββ LLM/
β β βββ react_agent.py # ReAct agent node + AgentState
β β βββ response_formatter.py
β β βββ prompt_templates.py
β β
β βββ RAG/
β β βββ tavily_rag.py # live web search tool
β β βββ offline_rag.py # local book search tool
β β
β βββ experiments/
β
βββ README.md
β
βββ Archived Models/ # contains versions 1 and 2- faster-whisper
- edge-tts
- groq
- langchain-groq
- langgraph
- rich
- tavily
- chromadb
- pvporcupine
- pyaudio
- mpv (if not possible, then ffmpeg, but it will be slower)
- groq β
GROQ_API_KEY - pvporcupine β
PORCUPINE_ACCESS_KEY - tavily ->
TAVILY_API_KEY
Add them to a .env file.
MIT License See LICENSE for details.







