Merge pull request #594 from jcastro/fix/provider-model-availability

fix(ai): refresh Groq ordering and unavailable OpenRouter models
This commit is contained in:
MacRimi
2026-11-05 18:20:32 +01:00
committed by GitHub
4 changed files with 80 additions and 8 deletions
+19 -2
View File
@@ -7,7 +7,9 @@ on:
- 'AppImage/scripts/notification_manager.py'
- 'AppImage/scripts/notification_templates.py'
- 'AppImage/scripts/ai_context_enrichment.py'
- 'AppImage/scripts/ai_providers/base.py'
- 'AppImage/scripts/ai_providers/**'
- 'AppImage/config/verified_ai_models.json'
- 'AppImage/scripts/tests/test_groq_model_recommendations.py'
- 'AppImage/scripts/tests/test_backup_ai_diagnostics.py'
- 'AppImage/scripts/notification_channels.py'
- 'AppImage/components/apprise-service-help.tsx'
@@ -72,7 +74,9 @@ on:
- 'AppImage/scripts/notification_manager.py'
- 'AppImage/scripts/notification_templates.py'
- 'AppImage/scripts/ai_context_enrichment.py'
- 'AppImage/scripts/ai_providers/base.py'
- 'AppImage/scripts/ai_providers/**'
- 'AppImage/config/verified_ai_models.json'
- 'AppImage/scripts/tests/test_groq_model_recommendations.py'
- 'AppImage/scripts/tests/test_backup_ai_diagnostics.py'
- 'AppImage/scripts/notification_channels.py'
- 'AppImage/components/apprise-service-help.tsx'
@@ -190,6 +194,19 @@ jobs:
bash -n scripts/gpu_tpu/nvidia_installer.sh
python3 -B -m unittest discover -s tests -p 'test_nvidia*.py' -v
ai-model-availability:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Test model ordering and curated availability without network or credentials
run: python -B -m unittest discover -s AppImage/scripts/tests -p test_groq_model_recommendations.py -v
installer-and-release:
runs-on: ubuntu-latest
timeout-minutes: 10
+2 -4
View File
@@ -110,12 +110,10 @@
"openai/gpt-oss-120b",
"meta-llama/llama-3.1-8b-instruct",
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",
"nvidia/nemotron-3-super-120b-a12b:free",
"google/gemma-4-26b-a4b-it:free",
"poolside/laguna-s-2.1:free"
"google/gemma-4-26b-a4b-it:free"
],
"recommended": "meta-llama/llama-3.3-70b-instruct",
"_note": "Curated manually from the 249+ models OpenRouter serves — the auto-verifier passes ~200 today but only a subset are practical for notification translation. Includes the 11 previously-curated paid models plus 22 new mainstream additions (gpt-5.1, claude-opus-4.8, sonnet-5, grok-4.3/4.20, kimi-k2, deepseek-v3.2, nova, cohere-a, sonar, ...) and 6 `:free` variants re-added manually — the free tier is intentionally supported per user request even though today's rate limits blocked some of them from passing the test. Reviewed 2026-10-26: three `:free` variants no longer served by OpenRouter were dropped."
"_note": "Curated manually from the 249+ models OpenRouter serves — the auto-verifier passes ~200 today but only a subset are practical for notification translation. Includes the 11 previously-curated paid models plus 22 new mainstream additions (gpt-5.1, claude-opus-4.8, sonnet-5, grok-4.3/4.20, kimi-k2, deepseek-v3.2, nova, cohere-a, sonar, ...) and 6 `:free` variants re-added manually — the free tier is intentionally supported per user request even though today's rate limits blocked some of them from passing the test. Reviewed 2026-10-26: three `:free` variants no longer served by OpenRouter were dropped. Availability reviewed 2026-11-04 against the public models endpoint: expired poolside/laguna-s-2.1:free and unlisted nvidia/nemotron-3-super-120b-a12b:free removed. This availability check is not a new inference verification; no untested models were added."
},
"ollama": {
"_note": "Ollama models are local, we don't filter them. User manages their own models.",
@@ -21,8 +21,13 @@ class GroqProvider(AIProvider):
# Exclude non-chat models
EXCLUDED_PATTERNS = ['whisper', 'tts', 'guard', 'tool-use']
# Recommended models (in priority order - versatile/large models first)
RECOMMENDED_PREFIXES = ['llama-3.3', 'llama-3.1-70b', 'llama-3.1-8b', 'mixtral', 'gemma']
# Prefer the verified default and current GPT-OSS models. Llama remains
# available for accounts with access; retired Mixtral/Gemma families have
# no recommendation priority. Sorting never adds IDs to the API response.
RECOMMENDED_PREFIXES = [
'openai/gpt-oss-20b', 'openai/gpt-oss-120b', 'qwen/qwen3.8-27b',
'llama-3.3', 'llama-3.1-8b',
]
def list_models(self) -> List[str]:
"""List available Groq models for chat completions.
@@ -0,0 +1,52 @@
"""Provider model ordering and curated availability, without credentials/network."""
import io
import json
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from ai_providers.groq_provider import GroqProvider
class GroqModelRecommendationsTests(unittest.TestCase):
def fetch(self, ids):
response = io.BytesIO(json.dumps({'data': [{'id': model} for model in ids]}).encode())
with patch('ai_providers.groq_provider.urllib.request.urlopen', return_value=response) as request:
models = GroqProvider(api_key='fixture-only').list_models()
self.assertEqual(request.call_args.kwargs['timeout'], 10)
return models
def test_current_verified_models_precede_legacy_and_unknown_families(self):
listed = ['mixtral-fixture', 'allam-2-7b', 'llama-3.3-70b-versatile',
'openai/gpt-oss-120b', 'qwen/qwen3.8-27b', 'openai/gpt-oss-20b']
self.assertEqual(self.fetch(listed)[:3],
['openai/gpt-oss-20b', 'openai/gpt-oss-120b', 'qwen/qwen3.8-27b'])
self.assertCountEqual(self.fetch(listed), listed)
def test_recommendations_never_invent_models_or_remove_arabic_model(self):
self.assertEqual(self.fetch(['allam-2-7b']), ['allam-2-7b'])
self.assertEqual(self.fetch([]), [])
def test_non_chat_models_still_excluded(self):
self.assertEqual(self.fetch(['whisper-large-v3', 'llama-prompt-guard-2-22m',
'openai/gpt-oss-20b']), ['openai/gpt-oss-20b'])
def test_missing_credentials_do_not_fetch_models(self):
with patch('ai_providers.groq_provider.urllib.request.urlopen') as request:
self.assertEqual(GroqProvider().list_models(), [])
request.assert_not_called()
def test_curated_catalog_keeps_verified_default_and_removes_unavailable_free_ids(self):
catalog = json.loads((Path(__file__).resolve().parents[2] / 'config/verified_ai_models.json').read_text())
self.assertEqual(GroqProvider.RECOMMENDED_PREFIXES[0], catalog['groq']['recommended'])
for provider in ('groq', 'openrouter'):
self.assertIn(catalog[provider]['recommended'], catalog[provider]['models'])
self.assertNotIn('poolside/laguna-s-2.1:free', catalog['openrouter']['models'])
self.assertNotIn('nvidia/nemotron-3-super-120b-a12b:free', catalog['openrouter']['models'])
self.assertIn('allam-2-7b', catalog['groq']['models'])
if __name__ == '__main__':
unittest.main()