Skip to content

Limit the length of AI-written smart playlist descriptions - #5458

Merged
marcelveldt merged 3 commits into
devfrom
exciting-dubinsky-9aca00
Aug 7, 2026
Merged

Limit the length of AI-written smart playlist descriptions#5458
marcelveldt merged 3 commits into
devfrom
exciting-dubinsky-9aca00

Conversation

@marcelveldt

Copy link
Copy Markdown
Member

What does this implement/fix?

Smart Playlist can let an AI engine write the playlist description. That reply was used as-is, with no limit on how long it could be. A description is stored in the library database and on disk, and is sent to the apps with every playlist listing, so an AI engine that runs away and produces pages of text would leave that text sitting in the library instead of a short description.

The reply is now discarded when it is unreasonably long, and the normal rules summary is shown instead.

Related issue (if applicable):

  • n/a

Types of changes

  • Bugfix (non-breaking change which fixes an issue) — bugfix
  • New feature (non-breaking change which adds functionality) — new-feature
  • Enhancement to an existing feature — enhancement
  • New music/player/metadata/plugin provider — new-provider
  • Breaking change (fix or feature that would cause existing functionality to not work as expected) — breaking-change
  • Refactor (no behaviour change) — refactor
  • Documentation only — documentation
  • Maintenance / chore — maintenance
  • CI / workflow change — ci
  • Dependencies bump — dependencies

Changes

  • Added a size limit for the AI-generated smart playlist description.
  • An oversized reply is dropped and the playlist keeps its rules summary as description.
  • Added tests covering the limit, including a reply that is only oversized once encoded.

Checklist

  • The code change is tested and works locally.
  • pre-commit run --all-files passes.
  • pytest passes, and tests have been added/updated under tests/ where applicable.
  • For changes to shared models, the companion PR in music-assistant/models is linked.
  • For changes affecting the UI, the companion PR in music-assistant/frontend is linked.
  • I have read and complied with the project's AI Policy for any AI-assisted contributions.
  • I have raised a PR against the documentation repository targeting the main or beta branch as appropriate.

Copilot AI lite review requested due to automatic review settings August 7, 2026 16:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR prevents runaway AI engines from persisting excessively long smart playlist descriptions by enforcing a hard size cap (in UTF-8 bytes). When the AI response exceeds the cap, it is discarded so the playlist continues to use the normal rules summary as its description, avoiding oversized payloads in storage and in playlist listings sent to clients.

Changes:

  • Introduces MAX_AI_DESCRIPTION_BYTES and rejects AI-generated descriptions whose UTF-8 encoded size exceeds this limit.
  • Logs a debug message when an oversized AI description is discarded.
  • Adds tests covering: oversized responses, boundary-at-cap acceptance, and multibyte/UTF-8 byte counting.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
music_assistant/providers/smart_playlist/__init__.py Enforces a UTF-8 byte-size cap on AI-generated smart playlist descriptions and falls back to rules summary when exceeded.
tests/providers/smart_playlist/test_smart_playlist.py Adds unit tests validating oversized rejection, exact-cap acceptance, and byte-based measurement with multibyte characters.

Copilot AI review requested due to automatic review settings August 7, 2026 16:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (1)

music_assistant/providers/smart_playlist/init.py:1444

  • [PROBLEM] _load_rules_from_disk coerces ai_description with str(...), which can turn corrupted/non-string JSON values into user-visible junk (and re-persist it); it also drops oversized descriptions only in-memory, leaving the oversized value on disk until some later flush. Prefer validating that the value is a string, and when you discard it, immediately rewrite the rules file (via _flush_rules_to_disk) so the oversized text is actually removed from disk.
                # a description persisted before the size cap existed is dropped here too
                description = str(entry.get("ai_description") or "")
                if description and len(description.encode("utf-8")) <= MAX_AI_DESCRIPTION_BYTES:
                    self._descriptions_store[playlist_id] = description

Copilot AI review requested due to automatic review settings August 7, 2026 17:26
@marcelveldt
marcelveldt force-pushed the exciting-dubinsky-9aca00 branch from 8cfc001 to 30346e4 Compare August 7, 2026 17:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

music_assistant/providers/smart_playlist/init.py:1446

  • [CRITICAL] _load_rules_from_disk() now encodes persisted ai_description to enforce the size cap, but description.encode("utf-8") can raise UnicodeEncodeError and abort the entire load (dropping even valid entries); catch encode errors and skip just the bad description.
                description = entry.get("ai_description")
                if (
                    isinstance(description, str)
                    and description
                    and len(description.encode("utf-8")) <= MAX_AI_DESCRIPTION_BYTES

music_assistant/providers/smart_playlist/init.py:1419

  • [CRITICAL] Calling description.encode("utf-8") can raise UnicodeEncodeError for strings containing lone surrogates, which would crash AI refresh (and potentially the provider) instead of cleanly falling back to the rules summary; treat un-encodable text as an invalid AI response and return None.

This issue also appears on line 1442 of the same file.

        description = response.strip()
        if len(description.encode("utf-8")) > MAX_AI_DESCRIPTION_BYTES:
            self.logger.debug(

Copilot AI review requested due to automatic review settings August 7, 2026 17:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Suppressed comments (2)

music_assistant/providers/smart_playlist/init.py:1447

  • [PROBLEM] _load_rules_from_disk also encodes persisted descriptions to UTF-8 to enforce the byte cap; adding a len(description) check before encoding avoids allocating large temporary bytes objects when the stored value is already clearly over the cap by character count.
                if (
                    isinstance(description, str)
                    and description
                    and len(description.encode("utf-8")) <= MAX_AI_DESCRIPTION_BYTES
                ):

music_assistant/providers/smart_playlist/init.py:1419

  • [PROBLEM] The size check encodes the entire AI reply to UTF-8; for runaway responses this can allocate a large temporary bytes object and add avoidable CPU/memory overhead. Add a cheap len(description) pre-check (which is always a lower bound for UTF-8 byte size) so oversized responses short-circuit without encoding.

This issue also appears on line 1443 of the same file.

        description = response.strip()
        if len(description.encode("utf-8")) > MAX_AI_DESCRIPTION_BYTES:

@marcelveldt
marcelveldt marked this pull request as ready for review August 7, 2026 17:35
Copilot AI review requested due to automatic review settings August 7, 2026 17:35
@marcelveldt
marcelveldt force-pushed the exciting-dubinsky-9aca00 branch from 30346e4 to 02176f8 Compare August 7, 2026 17:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@marcelveldt
marcelveldt merged commit 5f68e44 into dev Aug 7, 2026
16 checks passed
@marcelveldt
marcelveldt deleted the exciting-dubinsky-9aca00 branch August 7, 2026 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants