From a2fa9a9e7b043e6f97aa6d11c63c7c7708fb7bb1 Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Tue, 12 May 2026 19:33:11 +1000 Subject: [PATCH] LLM integration - LiteLLM config - UI tweaks (#4134) --- changedetectionio/blueprint/settings/llm.py | 67 ++++++++++++++++-- .../settings/templates/settings_llm_tab.html | 2 +- changedetectionio/forms.py | 1 - .../translations/cs/LC_MESSAGES/messages.po | 6 +- .../translations/de/LC_MESSAGES/messages.po | 6 +- .../en_GB/LC_MESSAGES/messages.po | 6 +- .../en_US/LC_MESSAGES/messages.po | 6 +- .../translations/es/LC_MESSAGES/messages.po | 6 +- .../translations/fr/LC_MESSAGES/messages.po | 6 +- .../translations/it/LC_MESSAGES/messages.po | 6 +- .../translations/ja/LC_MESSAGES/messages.po | 6 +- .../translations/ko/LC_MESSAGES/messages.mo | Bin 102821 -> 102575 bytes .../translations/ko/LC_MESSAGES/messages.po | 8 +-- changedetectionio/translations/messages.pot | 8 +-- .../pt_BR/LC_MESSAGES/messages.po | 6 +- .../translations/tr/LC_MESSAGES/messages.po | 6 +- .../translations/uk/LC_MESSAGES/messages.po | 6 +- .../translations/zh/LC_MESSAGES/messages.po | 6 +- .../zh_Hant_TW/LC_MESSAGES/messages.po | 6 +- 19 files changed, 79 insertions(+), 85 deletions(-) diff --git a/changedetectionio/blueprint/settings/llm.py b/changedetectionio/blueprint/settings/llm.py index 92513a26..a027d751 100644 --- a/changedetectionio/blueprint/settings/llm.py +++ b/changedetectionio/blueprint/settings/llm.py @@ -1,4 +1,7 @@ +import json +import logging import os +import re from flask import Blueprint, jsonify, redirect, url_for, flash from flask_babel import gettext @@ -8,6 +11,44 @@ from changedetectionio.store import ChangeDetectionStore from changedetectionio.auth_decorator import login_optionally_required +class _LiteLLMWarningCapture(logging.Handler): + """Capture warnings emitted on the 'LiteLLM' stdlib logger during a single call. + + litellm.get_valid_models() catches HTTP/auth errors internally, logs a warning, + and returns []. Without capturing that warning we can't tell the user *why* + no models came back (bad key vs. offline vs. genuinely empty model list). + """ + def __init__(self): + super().__init__(level=logging.WARNING) + self.messages = [] + + def emit(self, record): + try: + self.messages.append(record.getMessage()) + except Exception: + pass + + +def _humanize_litellm_error(raw: str) -> str: + # litellm warnings typically look like: + # "Error getting valid models: Failed to get models: { 'error': { 'message': '...' } }" + # Pull the inner provider message when present; otherwise trim the boilerplate. + if not raw: + return raw + m = re.search(r'\{.*\}', raw, re.DOTALL) + if m: + try: + body = json.loads(m.group(0)) + inner = (body.get('error') or {}).get('message') or body.get('message') + if inner: + return inner + except Exception: + pass + cleaned = re.sub(r'^Error getting valid models:\s*', '', raw) + cleaned = re.sub(r'^Failed to get models:\s*', '', cleaned).strip() + return cleaned[:500] + + def construct_llm_blueprint(datastore: ChangeDetectionStore): llm_blueprint = Blueprint('llm', __name__) @@ -41,13 +82,27 @@ def construct_llm_blueprint(datastore: ChangeDetectionStore): try: import litellm logger.debug(f"LLM model list: calling litellm.get_valid_models provider={provider!r} (litellm={litellm_provider!r}) api_base={api_base!r}") - raw = litellm.get_valid_models( - check_provider_endpoint=True, - custom_llm_provider=litellm_provider, - api_key=api_key or None, - api_base=api_base or None, - ) or [] + + capture = _LiteLLMWarningCapture() + litellm_logger = logging.getLogger('LiteLLM') + litellm_logger.addHandler(capture) + try: + raw = litellm.get_valid_models( + check_provider_endpoint=True, + custom_llm_provider=litellm_provider, + api_key=api_key or None, + api_base=api_base or None, + ) or [] + finally: + litellm_logger.removeHandler(capture) + models = sorted({(m if m.startswith(prefix) else prefix + m) for m in raw}) + + if not models and capture.messages: + err = _humanize_litellm_error(capture.messages[-1]) + logger.debug(f"LLM model list: 0 models, surfacing captured litellm warning: {err!r}") + return jsonify({'models': [], 'error': err}), 400 + logger.debug(f"LLM model list: got {len(models)} models for provider={provider!r}") return jsonify({'models': models, 'error': None}) except Exception as e: diff --git a/changedetectionio/blueprint/settings/templates/settings_llm_tab.html b/changedetectionio/blueprint/settings/templates/settings_llm_tab.html index 18233e7f..22a74843 100644 --- a/changedetectionio/blueprint/settings/templates/settings_llm_tab.html +++ b/changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -469,7 +469,7 @@ if (!data.models || data.models.length === 0) { statusEl.style.color = '#e67e22'; - statusEl.textContent = '{{ _("No models returned — check your API key.") }}'; + statusEl.textContent = '{{ _("No models returned by the provider.") }}'; selGroup.style.display = 'none'; return; } diff --git a/changedetectionio/forms.py b/changedetectionio/forms.py index 852ed773..9ea93157 100644 --- a/changedetectionio/forms.py +++ b/changedetectionio/forms.py @@ -1106,7 +1106,6 @@ class globalSettingsLLMForm(Form): _l('API Key'), validators=[validators.Optional()], render_kw={ - "placeholder": _l('Leave blank to use LITELLM_API_KEY env var'), "autocomplete": "off", "style": "width: 24em;", }, diff --git a/changedetectionio/translations/cs/LC_MESSAGES/messages.po b/changedetectionio/translations/cs/LC_MESSAGES/messages.po index 33be85c0..3cfadde0 100644 --- a/changedetectionio/translations/cs/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/cs/LC_MESSAGES/messages.po @@ -1121,7 +1121,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3134,10 +3134,6 @@ msgstr "" msgid "API Key" msgstr "API klíč" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/de/LC_MESSAGES/messages.po b/changedetectionio/translations/de/LC_MESSAGES/messages.po index dd6b5a7e..e29f3f19 100644 --- a/changedetectionio/translations/de/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/de/LC_MESSAGES/messages.po @@ -1137,7 +1137,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3186,10 +3186,6 @@ msgstr "" msgid "API Key" msgstr "API-Schlüssel" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po b/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po index 5b538c7b..7de77a5b 100644 --- a/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/en_GB/LC_MESSAGES/messages.po @@ -1119,7 +1119,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3128,10 +3128,6 @@ msgstr "" msgid "API Key" msgstr "" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/en_US/LC_MESSAGES/messages.po b/changedetectionio/translations/en_US/LC_MESSAGES/messages.po index a3f43c35..8e479203 100644 --- a/changedetectionio/translations/en_US/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/en_US/LC_MESSAGES/messages.po @@ -1119,7 +1119,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3128,10 +3128,6 @@ msgstr "" msgid "API Key" msgstr "" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/es/LC_MESSAGES/messages.po b/changedetectionio/translations/es/LC_MESSAGES/messages.po index 7501e355..faa7e30d 100644 --- a/changedetectionio/translations/es/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/es/LC_MESSAGES/messages.po @@ -1157,7 +1157,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3201,10 +3201,6 @@ msgstr "" msgid "API Key" msgstr "Clave API" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/fr/LC_MESSAGES/messages.po b/changedetectionio/translations/fr/LC_MESSAGES/messages.po index 023e342c..ac1a4d8a 100644 --- a/changedetectionio/translations/fr/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/fr/LC_MESSAGES/messages.po @@ -1125,7 +1125,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3141,10 +3141,6 @@ msgstr "" msgid "API Key" msgstr "Clé API" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/it/LC_MESSAGES/messages.po b/changedetectionio/translations/it/LC_MESSAGES/messages.po index a9b3dd09..e1b03bbf 100644 --- a/changedetectionio/translations/it/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/it/LC_MESSAGES/messages.po @@ -1121,7 +1121,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3130,10 +3130,6 @@ msgstr "" msgid "API Key" msgstr "Chiave API" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/ja/LC_MESSAGES/messages.po b/changedetectionio/translations/ja/LC_MESSAGES/messages.po index f3ccd6e5..1d7f983b 100644 --- a/changedetectionio/translations/ja/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/ja/LC_MESSAGES/messages.po @@ -1126,7 +1126,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3147,10 +3147,6 @@ msgstr "" msgid "API Key" msgstr "APIキー" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/ko/LC_MESSAGES/messages.mo b/changedetectionio/translations/ko/LC_MESSAGES/messages.mo index 3d1727a588e4f9db74bf75c7d7fa3293a822da40..1fba60e4388da29e3f141158411449f78acdcb22 100644 GIT binary patch delta 15888 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 aYp|wf`6{s>+G delta 16120 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 diff --git a/changedetectionio/translations/ko/LC_MESSAGES/messages.po b/changedetectionio/translations/ko/LC_MESSAGES/messages.po index 12b40dd0..8b57cd53 100644 --- a/changedetectionio/translations/ko/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/ko/LC_MESSAGES/messages.po @@ -1127,8 +1127,8 @@ msgid "Loading…" msgstr "불러오는 중..." #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." -msgstr "반환된 모델이 없습니다. API 키를 확인하세요." +msgid "No models returned by the provider." +msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html msgid "— choose a model —" @@ -3138,10 +3138,6 @@ msgstr "모델" msgid "API Key" msgstr "API 키" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "LITELLM_API_KEY 환경 변수를 사용하려면 비워 두세요" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "API 기본 URL" diff --git a/changedetectionio/translations/messages.pot b/changedetectionio/translations/messages.pot index ef817899..cfd0fbea 100644 --- a/changedetectionio/translations/messages.pot +++ b/changedetectionio/translations/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: changedetection.io 0.55.3\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-05-02 18:29+0900\n" +"POT-Creation-Date: 2026-05-12 11:08+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -1118,7 +1118,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3127,10 +3127,6 @@ msgstr "" msgid "API Key" msgstr "" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po b/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po index 99666a0f..0668bfe4 100644 --- a/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/pt_BR/LC_MESSAGES/messages.po @@ -1144,7 +1144,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3178,10 +3178,6 @@ msgstr "" msgid "API Key" msgstr "Chave da API" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/tr/LC_MESSAGES/messages.po b/changedetectionio/translations/tr/LC_MESSAGES/messages.po index 7f2f79c9..feac964d 100644 --- a/changedetectionio/translations/tr/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/tr/LC_MESSAGES/messages.po @@ -1154,7 +1154,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3181,10 +3181,6 @@ msgstr "" msgid "API Key" msgstr "API Anahtarı" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/uk/LC_MESSAGES/messages.po b/changedetectionio/translations/uk/LC_MESSAGES/messages.po index 315466f3..2dd786e3 100644 --- a/changedetectionio/translations/uk/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/uk/LC_MESSAGES/messages.po @@ -1134,7 +1134,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3160,10 +3160,6 @@ msgstr "" msgid "API Key" msgstr "Ключ API" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/zh/LC_MESSAGES/messages.po b/changedetectionio/translations/zh/LC_MESSAGES/messages.po index 31197a54..d2c28a18 100644 --- a/changedetectionio/translations/zh/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/zh/LC_MESSAGES/messages.po @@ -1123,7 +1123,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3133,10 +3133,6 @@ msgstr "" msgid "API Key" msgstr "API密钥" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr "" diff --git a/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po index adbf2e23..93c08bee 100644 --- a/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po +++ b/changedetectionio/translations/zh_Hant_TW/LC_MESSAGES/messages.po @@ -1122,7 +1122,7 @@ msgid "Loading…" msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html -msgid "No models returned — check your API key." +msgid "No models returned by the provider." msgstr "" #: changedetectionio/blueprint/settings/templates/settings_llm_tab.html @@ -3132,10 +3132,6 @@ msgstr "" msgid "API Key" msgstr "API 金鑰" -#: changedetectionio/forms.py -msgid "Leave blank to use LITELLM_API_KEY env var" -msgstr "" - #: changedetectionio/forms.py msgid "API Base URL" msgstr ""