From 73be0ecedfa5bbb102f6468bc8192ab84c969b6f Mon Sep 17 00:00:00 2001 From: long <452591453@qq.com> Date: Fri, 9 Oct 2026 18:09:12 +0800 Subject: [PATCH] fix: honor configured followup extraction model preference --- .../FollowupAudioProviderConfig.php | 6 +++++- .../tests/FollowupAudioProviderConfigTest.php | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/server/app/common/service/followupaudio/FollowupAudioProviderConfig.php b/server/app/common/service/followupaudio/FollowupAudioProviderConfig.php index 33f4e38c0..7d64b0d0b 100644 --- a/server/app/common/service/followupaudio/FollowupAudioProviderConfig.php +++ b/server/app/common/service/followupaudio/FollowupAudioProviderConfig.php @@ -99,7 +99,11 @@ final class FollowupAudioProviderConfig public static function readyModels(): array { $models = []; - foreach (['qwen', 'openai'] as $profile) { + $profiles = ['qwen', 'openai']; + $preferred = config('followup_audio.profile', 'qwen'); + // Preference is presentation only: existing tasks retain their bound provider identity. + if (in_array($preferred, $profiles, true)) { $profiles = array_values(array_unique(array_merge([$preferred], $profiles))); } + foreach ($profiles as $profile) { if (FollowupAudioGate::ready($profile)) { $models[] = ['value' => $profile, 'label' => self::resolve($profile)['label']]; } } return $models; diff --git a/server/tests/FollowupAudioProviderConfigTest.php b/server/tests/FollowupAudioProviderConfigTest.php index 19ea6c301..7dfae3333 100644 --- a/server/tests/FollowupAudioProviderConfigTest.php +++ b/server/tests/FollowupAudioProviderConfigTest.php @@ -58,4 +58,22 @@ $expectError(static fn () => Provider::resolve('qwen', $changed, []), 'CONFIG_IN $changed = $settings; $changed['providers']['qwen']['verified_fingerprint'] = ''; $expect(!Provider::verified('qwen', $changed, $legacy), 'old unbound flags do not enable audio'); $expect(Provider::status('invalid', $settings, $legacy)['code'] === 'INVALID_PROFILE', 'logical slot allowlist retained'); +// The configured default controls new-upload choices without rebinding historical slots. +$ordering = $settings; +$ordering['verified_profiles'] = ['qwen', 'openai']; +$ordering['providers']['openai'] = $slot; +$ordering['providers']['openai']['label'] = 'GPT extraction'; +$ordering['providers']['openai']['verified_fingerprint'] = Provider::resolve('openai', $ordering, [])['fingerprint']; +$ordering['profile'] = 'openai'; +$config->set($ordering, 'followup_audio'); +$expect(array_column(Provider::readyModels(), 'value') === ['openai', 'qwen'], 'configured GPT default comes first while historical Qwen remains ready'); +$expect(Provider::resolve('qwen')['fingerprint'] === $resolved['fingerprint'], 'default selection does not rebind the historical provider identity'); +$ordering['profile'] = 'qwen'; $config->set($ordering, 'followup_audio'); +$expect(array_column(Provider::readyModels(), 'value') === ['qwen', 'openai'], 'configured Qwen priority remains supported'); +$ordering['profile'] = 'unknown'; $config->set($ordering, 'followup_audio'); +$expect(array_column(Provider::readyModels(), 'value') === ['qwen', 'openai'], 'invalid default never inserts an unrecognized profile'); +$ordering['profile'] = 'openai'; $ordering['providers']['openai']['verified_fingerprint'] = ''; +$config->set($ordering, 'followup_audio'); +$expect(array_column(Provider::readyModels(), 'value') === ['qwen'], 'sorting does not manufacture readiness for an unverified profile'); +$config->set($settings, 'followup_audio'); echo 'FOLLOWUP_AUDIO_PROVIDER_CONFIG assertions=' . $checks . ' PASS explicit_driver=1 model_configurable=1 exact_fingerprint=1 https_verified=1 secrets_hidden=1' . PHP_EOL;