feat(ai): massive architecture overhaul, new providers, and generation tuning#2371
Open
VoidX3D wants to merge 30 commits into
Open
feat(ai): massive architecture overhaul, new providers, and generation tuning#2371VoidX3D wants to merge 30 commits into
VoidX3D wants to merge 30 commits into
Conversation
Renamed the central AI orchestration class from AiOrchestrator to AiHandler and updated all references across the codebase.
…s all providers - Create UnifiedModelFilter utility that filters out embedding, image, TTS, speech, moderation, vision-only, and other non-chat models - Update GeminiAiClient to use UnifiedModelFilter instead of hardcoded markers - Update GenericOpenAiClient to use UnifiedModelFilter instead of inline filter
These providers all use OpenAI-compatible APIs. Switching from dedicated client classes to GenericOpenAiClient eliminates duplicate code. The old class files are kept on disk but no longer referenced.
Add CUSTOM provider with hasConfigurableUrl=true and requiresApiKey=true for user-configured self-hosted/custom API endpoints.
CUSTOM provider uses GenericOpenAiClient with an empty default URL (user configures it via settings). createClientWithUrl allows creating a client with a custom base URL for configurable-URL providers.
…ncesRepository Add getBaseUrl/setBaseUrl generic accessors for configurable-URL providers. Add customApiKey, customModel, customSystemPrompt, customBaseUrl convenience flows for the CUSTOM provider.
Ollama is a cloud API-based provider (requires API key, fixed URL), separate from the CUSTOM provider which allows custom endpoints.
A new composable that opens a ModalBottomSheet with a searchable LazyColumn of AI models. Includes search filtering, model count display, and visual selection state.
… and base URL config field
…(unified into GenericOpenAiClient)
…y to AiClient interface
…enericOpenAiClient ChatRequest
…y to GeminiAiClient
…ences Adds DataStore-backed preferences for temperature, topP, topK, maxTokens, presencePenalty, frequencyPenalty, sample size, digest mode (safe/full), and extended fields toggle.
…ot examples, and quality guide rails
…able from preferences
…ons to AI settings
- Move provider val to AI_INTEGRATION scope for accessibility - Remove duplicate base URL AiApiKeyItem block - Add missing imports: CircleShape, ModalBottomSheet, IconButton, OutlinedTextFieldDefaults, GeminiModel, Search, Clear, CheckCircle
… response parsing - Add AiResponseCleaner utility for cleaning JSON/text AI responses - Fix usage tracking to record actual model name instead of provider enum - Update AiPlaylistGenerator and AiMetadataGenerator to use cleaner
- Delete AiMetadataGenerator.kt (AI metadata generation feature) - Remove all references from AiStateHolder, PlayerViewModel, PlayerUiState - Remove generateAiMetadata callback from SongInfoBottomSheet - Strip calls from 10+ screens - Fix AiHandler callWithModel suspend modifier - Fix SettingsCategoryScreen customBaseUrl StateFlow to String - Remove encodeDefaults from GeminiAiClient Json config
- Restructure prompt with <task>, <rules>, <format>, <lyrics> sections - Clarify timestamp preservation and ALREADY_IN_TARGET_LANGUAGE behavior
- Add AiUiSnapshot data class (showAiPlaylistSheet, isGeneratingAiPlaylist, aiStatus, aiError) - Re-add combine in PlayerViewModel init to collect AiStateHolder flows into PlayerUiState - Add showAiPlaylistSheet, isGeneratingAiPlaylist, aiStatus, aiError fields to PlayerUiState
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Removes the unused
AiMetadataGeneratorfeature, adds generation parameters (temperature, topP, topK, maxTokens, presence/frequency penalty) and song data configuration to the AI settings UI, adds OLLAMA and CUSTOM provider support, overhauls all AI prompts with chain-of-thought reasoning and few-shot examples, and fixes two CI compilation errors.Breaking Changes
AiMetadataGeneratordeleted — the AI metadata enhancement feature is removed entirely. All 25+ call sites across screens, holders, and view models have been stripped.What's New
AI Provider Support
AiProviderenum,AiClientFactory, provider fallback chain, preferences, and settings UISearchableModelSelectorcomposable — searchable model dropdown for providers with dynamic model listsAI Settings UI
Generation Parameters (Client API)
topP,topK,maxTokens,presencePenalty,frequencyPenaltyto:AiClientinterfaceGenericOpenAiClient.ChatRequest(serialized to JSON)GeminiAiClient.GenerationConfig(serialized to JSON)AiHandlerfetches gen params from preferences and passes them through togenerateWithRecoveryresult.modelUsed) instead of provider namePrompt Engineering
AiSystemPromptEngineoverhauled with:translateLyricsprompt restructured with XML-bounded<task>,<rules>,<format>,<lyrics>sectionsAiResponseCleanerutility added for robust JSON/text response cleaning (strip markdown fences, trim whitespace, normalize newlines)AiPlaylistGeneratorandUserProfileDigestGeneratorupdated to useAiResponseCleanerWhat's Removed
DeepSeekAiClient.kt,GroqAiClient.kt,MistralAiClient.kt— unified intoGenericOpenAiClient(these are all OpenAI-compatible APIs with identical request/response shapes)AiMetadataGenerator.kt— full file deletiongenerateAiMetadatacalls removed from:AiStateHolder,PlayerViewModel,PlayerUiState,SongInfoBottomSheet,DailyMixSection,UnifiedPlayerOverlaysLayer,DailyMixScreen,AlbumDetailScreen,ArtistDetailScreen,GenreDetailScreen,LibraryScreen,PlaylistDetailScreen,RecentlyPlayedScreen,SearchScreen,PlayerViewModelTestBug Fixes
AiHandler.kt— local functioncallWithModelnot markedsuspend(CI compilation error)SettingsCategoryScreen.kt—customBaseUrlStateFlow passed where String expected; now collected viacollectAsStateWithLifecycle()GeminiAiClient— removedencodeDefaults = truefromJsonconfig to prevent serializing null fieldsAiWorker— digest generator now usesAiResponseCleanerfor robust parsingFiles Changed (37 files, +1054 / −1016)
Added
data/ai/AiResponseCleaner.ktdata/ai/provider/UnifiedModelFilter.ktpresentation/screens/SettingsComponents.ktSearchableModelSelectorcomposableDeleted
data/ai/AiMetadataGenerator.ktdata/ai/provider/DeepSeekAiClient.ktdata/ai/provider/GroqAiClient.ktdata/ai/provider/MistralAiClient.ktModified (key files)
data/ai/AiHandler.ktdata/ai/AiSystemPromptEngine.ktdata/ai/AiPlaylistGenerator.ktdata/ai/UserProfileDigestGenerator.ktdata/ai/provider/AiClient.ktdata/ai/provider/AiClientFactory.ktdata/ai/provider/AiProvider.ktdata/ai/provider/GeminiAiClient.ktdata/ai/provider/GenericOpenAiClient.ktdata/preferences/AiPreferencesRepository.ktdata/worker/AiWorker.ktpresentation/screens/SettingsCategoryScreen.ktpresentation/viewmodel/SettingsViewModel.ktpresentation/viewmodel/AiStateHolder.ktpresentation/viewmodel/PlayerViewModel.ktpresentation/viewmodel/PlayerUiState.ktpresentation/components/SongInfoBottomSheet.ktgenerateAiMetadatacallspresentation/viewmodel/PlayerViewModelTest.ktTesting
PlayerViewModelTest.ktupdated — metadata test references removed