A natural-language YouTube Music assistant powered by FunctionGemma — a 270M-parameter Gemma 3 model fine-tuned for structured function calling. Type plain English; the model dispatches to the right tool; your browser opens (or a list is printed).
| Layer | File | Purpose |
|---|---|---|
| AI dispatch | ytmusic_assistant.py | REPL, model inference, tool definitions |
| Recommendation engine | recommender.py, labeler.py, preference.py, local_history.py | Candidate gathering, labeling, scoring, preference learning |
| Demo / scratch | main.py | Minimal weather demo showing the basic 4-stage cycle |
Requirements: Python with torch, transformers, huggingface_hub, google-auth-oauthlib, sentence-transformers, questionary
# Create and activate virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/Scripts/activate # Git Bash / WSL
# Install dependencies
pip install torch transformers huggingface_hub google-auth-oauthlib google-api-python-client sentence-transformers questionary
# Authenticate with Hugging Face (one-time, token stored in GemmaToken.txt)
python hf_login.py
YouTube API setup:
client_secrets.jsontoken.json is written and auto-refreshedpython main.py # minimal weather demo (no API keys needed)
python ytmusic_assistant.py # interactive YouTube Music assistant
| Tool | What it does |
|---|---|
open_liked_songs() | Opens music.youtube.com/playlist?list=LM |
list_liked_songs(limit) | Fetches liked songs via API, prints numbered list |
open_history() | Opens music.youtube.com/history |
open_playlist(name) | Fuzzy-matches a playlist by name, opens it |
search_and_open(query) | YouTube search (music category), opens first hit |
open_item(number) | Opens item N from the last printed list |
recommend_videos_from_taste(k) | Taste-only recommendation |
recommend_videos_from_theme(prompt, k) | Themed recommendation from your library |
recommend_videos_with_search_query(query, k) | Artist/entity search + recommendation |
FunctionGemma operates on a fixed 4-stage cycle:
processor.apply_chat_template(messages, tools=[...]) encodes the user prompt with tool schemasmodel.generate() emits a structured function call:
<start_function_call>call:function_name{param:<escape>value<escape>}<end_function_call>
TOOL_MAP, call the Python functionCritical: The
role: "developer"system message"You are a model that can do function calling with the following functions"must be present — it activates function-calling behavior.
Recommendations use a scoring formula combining semantic similarity and learned taste:
score = alpha * cosine_sim(prompt_embedding, title_embedding)
+ beta * mean(preference_profile[dim][label])
| Mode | alpha | beta |
|---|---|---|
| Taste only | 0.0 | 1.0 |
| Themed | 0.55 | 0.45 |
| Search query | 0.8 | 0.2 |
Video titles are labeled across 5 dimensions (content type, genre, mood, use case, language) using all-MiniLM-L6-v2 embeddings. Your preference profile (data/preferences.json) updates via EMA each time you select recommended videos.
| File | Contents |
|---|---|
data/preferences.json | Per-label weights per dimension, updated on every selection |
data/history.json | Every video opened or selected |
data/labels.csv | Label assignment cache (avoids re-computing embeddings) |
labels.json | Master label vocabulary (5 dimensions) |
token.json | OAuth2 token for YouTube Data API (auto-refreshed) |
client_secrets.json | Google Cloud OAuth credentials — not committed |
google/functiongemma-270m-it — 270M parameter Gemma 3 model fine-tuned exclusively for single-turn function calling. It does not produce free-form text answers.
Limitations: single-turn only, no chaining, no multi-step reasoning.
2 commits
Python
100.0%
A natural-language YouTube Music assistant powered by FunctionGemma — a 270M-parameter Gemma 3 model fine-tuned for structured function calling. Type plain English; the model dispatches to the right tool; your browser opens (or a list is printed).
| Layer | File | Purpose |
|---|---|---|
| AI dispatch | ytmusic_assistant.py | REPL, model inference, tool definitions |
| Recommendation engine | recommender.py, labeler.py, preference.py, local_history.py | Candidate gathering, labeling, scoring, preference learning |
| Demo / scratch | main.py | Minimal weather demo showing the basic 4-stage cycle |
Requirements: Python with torch, transformers, huggingface_hub, google-auth-oauthlib, sentence-transformers, questionary
# Create and activate virtual environment
python -m venv .venv
.venv\Scripts\activate # Windows
source .venv/Scripts/activate # Git Bash / WSL
# Install dependencies
pip install torch transformers huggingface_hub google-auth-oauthlib google-api-python-client sentence-transformers questionary
# Authenticate with Hugging Face (one-time, token stored in GemmaToken.txt)
python hf_login.py
YouTube API setup:
client_secrets.jsontoken.json is written and auto-refreshedpython main.py # minimal weather demo (no API keys needed)
python ytmusic_assistant.py # interactive YouTube Music assistant
| Tool | What it does |
|---|---|
open_liked_songs() | Opens music.youtube.com/playlist?list=LM |
list_liked_songs(limit) | Fetches liked songs via API, prints numbered list |
open_history() | Opens music.youtube.com/history |
open_playlist(name) | Fuzzy-matches a playlist by name, opens it |
search_and_open(query) | YouTube search (music category), opens first hit |
open_item(number) | Opens item N from the last printed list |
recommend_videos_from_taste(k) | Taste-only recommendation |
recommend_videos_from_theme(prompt, k) | Themed recommendation from your library |
recommend_videos_with_search_query(query, k) | Artist/entity search + recommendation |
FunctionGemma operates on a fixed 4-stage cycle:
processor.apply_chat_template(messages, tools=[...]) encodes the user prompt with tool schemasmodel.generate() emits a structured function call:
<start_function_call>call:function_name{param:<escape>value<escape>}<end_function_call>
TOOL_MAP, call the Python functionCritical: The
role: "developer"system message"You are a model that can do function calling with the following functions"must be present — it activates function-calling behavior.
Recommendations use a scoring formula combining semantic similarity and learned taste:
score = alpha * cosine_sim(prompt_embedding, title_embedding)
+ beta * mean(preference_profile[dim][label])
| Mode | alpha | beta |
|---|---|---|
| Taste only | 0.0 | 1.0 |
| Themed | 0.55 | 0.45 |
| Search query | 0.8 | 0.2 |
Video titles are labeled across 5 dimensions (content type, genre, mood, use case, language) using all-MiniLM-L6-v2 embeddings. Your preference profile (data/preferences.json) updates via EMA each time you select recommended videos.
| File | Contents |
|---|---|
data/preferences.json | Per-label weights per dimension, updated on every selection |
data/history.json | Every video opened or selected |
data/labels.csv | Label assignment cache (avoids re-computing embeddings) |
labels.json | Master label vocabulary (5 dimensions) |
token.json | OAuth2 token for YouTube Data API (auto-refreshed) |
client_secrets.json | Google Cloud OAuth credentials — not committed |
google/functiongemma-270m-it — 270M parameter Gemma 3 model fine-tuned exclusively for single-turn function calling. It does not produce free-form text answers.
Limitations: single-turn only, no chaining, no multi-step reasoning.
2 commits
Python
100.0%