mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-09-24 14:25:53 +00:00
LLM - UI & Ollama tweaks (#4148)
Build and push containers / metadata (push) Has been cancelled
Build and push containers / build-push-containers (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / lint-translations (push) Has been cancelled
ChangeDetection.io App Test / lint-template-i18n (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-14 (push) Has been cancelled
Build and push containers / metadata (push) Has been cancelled
Build and push containers / build-push-containers (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Build distribution 📦 (push) Has been cancelled
ChangeDetection.io App Test / lint-code (push) Has been cancelled
ChangeDetection.io App Test / lint-translations (push) Has been cancelled
ChangeDetection.io App Test / lint-template-i18n (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Test the built package works basically. (push) Has been cancelled
Publish Python 🐍distribution 📦 to PyPI and TestPyPI / Publish Python 🐍 distribution 📦 to PyPI (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-10 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-11 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-12 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-13 (push) Has been cancelled
ChangeDetection.io App Test / test-application-3-14 (push) Has been cancelled
This commit is contained in:
@@ -41,6 +41,7 @@ def construct_blueprint(datastore: ChangeDetectionStore):
|
||||
'llm_change_summary_default': datastore.data['settings']['application'].get('llm_change_summary_default', ''),
|
||||
'llm_override_diff_with_summary': datastore.data['settings']['application'].get('llm_override_diff_with_summary', True),
|
||||
'llm_restock_use_fallback_extract': datastore.data['settings']['application'].get('llm_restock_use_fallback_extract', True),
|
||||
'llm_debug': datastore.data['settings']['application'].get('llm_debug', False),
|
||||
'llm_budget_action': datastore.data['settings']['application'].get('llm_budget_action', 'skip_llm'),
|
||||
'llm_thinking_budget': str(datastore.data['settings']['application'].get('llm_thinking_budget', 0)),
|
||||
'llm_max_summary_tokens': str(datastore.data['settings']['application'].get('llm_max_summary_tokens', 3000)),
|
||||
@@ -125,6 +126,9 @@ def construct_blueprint(datastore: ChangeDetectionStore):
|
||||
datastore.data['settings']['application']['llm_restock_use_fallback_extract'] = (
|
||||
bool(llm_data.get('llm_restock_use_fallback_extract', True))
|
||||
)
|
||||
datastore.data['settings']['application']['llm_debug'] = (
|
||||
bool(llm_data.get('llm_debug', False))
|
||||
)
|
||||
datastore.data['settings']['application']['llm_budget_action'] = (
|
||||
llm_data.get('llm_budget_action') or 'skip_llm'
|
||||
)
|
||||
|
||||
@@ -113,23 +113,43 @@ def construct_llm_blueprint(datastore: ChangeDetectionStore):
|
||||
@llm_blueprint.route("/test", methods=['GET'])
|
||||
@login_optionally_required
|
||||
def llm_test():
|
||||
from flask import request
|
||||
from changedetectionio.llm.client import completion
|
||||
|
||||
llm_cfg = datastore.data['settings']['application'].get('llm') or {}
|
||||
model = llm_cfg.get('model', '').strip()
|
||||
api_base = llm_cfg.get('api_base', '') or ''
|
||||
# Pull stored config as the fallback, then override with anything the
|
||||
# form-driven JS sent as query params. Lets users test config changes
|
||||
# without first hitting Save (matching how /settings/llm/models works).
|
||||
stored = datastore.data['settings']['application'].get('llm') or {}
|
||||
llm_cfg = {
|
||||
'model': (request.args.get('model') or stored.get('model', '')).strip(),
|
||||
'api_key': (request.args.get('api_key') or stored.get('api_key', '')).strip(),
|
||||
'api_base': (request.args.get('api_base') or stored.get('api_base', '')).strip(),
|
||||
'provider_kind': (request.args.get('provider_kind') or stored.get('provider_kind', '')).strip(),
|
||||
'local_token_multiplier': request.args.get('local_token_multiplier') or stored.get('local_token_multiplier'),
|
||||
}
|
||||
model = llm_cfg['model']
|
||||
api_base = llm_cfg['api_base']
|
||||
|
||||
logger.debug(f"LLM connection test requested: model={model!r} api_base={api_base!r}")
|
||||
logger.debug(
|
||||
f"LLM connection test requested: model={model!r} api_base={api_base!r} "
|
||||
f"provider_kind={llm_cfg['provider_kind']!r} "
|
||||
f"source={'form' if request.args.get('model') else 'datastore'}"
|
||||
)
|
||||
|
||||
if not model:
|
||||
logger.error("LLM connection test failed: no model configured in datastore")
|
||||
logger.error("LLM connection test failed: no model configured")
|
||||
return jsonify({'ok': False, 'error': 'No model configured.'}), 400
|
||||
|
||||
try:
|
||||
logger.debug(f"LLM connection test: sending test prompt to model={model!r}")
|
||||
# Reuse the same multiplier path the production calls use, so cloud providers
|
||||
# stay on a small base cap (matching upstream's pre-existing behavior) and only
|
||||
# 'openai_compatible' endpoints opt into the reasoning-friendly headroom.
|
||||
# reasoning-capable endpoints (Ollama, openai_compatible) opt into the extra
|
||||
# headroom needed for chain-of-thought to complete.
|
||||
# Timeout: omit the override so the test inherits DEFAULT_TIMEOUT (60s, tunable
|
||||
# via LLM_TIMEOUT). A shorter test-only timeout falsely fails on cold-starting
|
||||
# cloud reasoning models (e.g. ollama.com hosting qwen3.5:397b takes ~60s on
|
||||
# first hit) even though the same call succeeds in production.
|
||||
from changedetectionio.llm.evaluator import apply_local_token_multiplier
|
||||
text, total_tokens, input_tokens, output_tokens = completion(
|
||||
model=model,
|
||||
@@ -137,8 +157,8 @@ def construct_llm_blueprint(datastore: ChangeDetectionStore):
|
||||
'Respond with just the word: ready'}],
|
||||
api_key=llm_cfg.get('api_key') or None,
|
||||
api_base=api_base or None,
|
||||
timeout=30,
|
||||
max_tokens=apply_local_token_multiplier(200, llm_cfg),
|
||||
debug=bool(datastore.data['settings']['application'].get('llm_debug', False)),
|
||||
)
|
||||
reply = text.strip()
|
||||
if not reply:
|
||||
|
||||
@@ -123,14 +123,15 @@
|
||||
</div>
|
||||
|
||||
{# Hidden field carrying the dropdown selection so the backend knows when to apply
|
||||
reasoning-friendly token caps (only for self-hosted OpenAI-compatible endpoints). #}
|
||||
reasoning-friendly token caps (Ollama and OpenAI-compatible endpoints, which commonly
|
||||
serve reasoning models that need headroom for chain-of-thought to complete). #}
|
||||
{{ form.llm.form.llm_provider_kind() }}
|
||||
|
||||
<div class="pure-control-group" id="llm-local-advanced-group" style="display:none">
|
||||
<label for="{{ form.llm.form.llm_local_token_multiplier.id }}">{{ form.llm.form.llm_local_token_multiplier.label.text }}</label>
|
||||
{{ form.llm.form.llm_local_token_multiplier() }}
|
||||
<span class="pure-form-message-inline">
|
||||
{{ _('Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps.', default='5x') | safe }}
|
||||
{{ _('Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps.', default='5x') | safe }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -201,6 +202,17 @@
|
||||
</a>
|
||||
<span class="pure-form-message-inline">{{ _('Removes all cached AI change summaries across all watches. They will be regenerated on the next check.') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="pure-control-group">
|
||||
<label></label>
|
||||
{{ form.llm.form.llm_debug() }}
|
||||
<label for="{{ form.llm.form.llm_debug.id }}" style="display:inline; font-weight:normal;">
|
||||
{{ form.llm.form.llm_debug.label.text }}
|
||||
</label>
|
||||
<span class="pure-form-message-inline">
|
||||
{{ _('Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. Leave off in production — generates a lot of log volume.') }}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}{# llm_env_configured #}
|
||||
|
||||
{% if not llm_env_configured and not (llm_config and llm_config.get('model')) %}
|
||||
@@ -417,13 +429,14 @@
|
||||
}
|
||||
|
||||
// Persist the dropdown selection so the backend can branch on provider kind
|
||||
// (currently only 'openai_compatible' triggers the local-multiplier code path).
|
||||
// (self-hosted endpoints — 'ollama' and 'openai_compatible' — trigger the
|
||||
// local-multiplier code path; cloud providers do not).
|
||||
if (kindField) kindField.value = provider || '';
|
||||
|
||||
// Show the local-endpoint advanced settings (token multiplier) only for the
|
||||
// OpenAI-compatible self-hosted option. Cloud providers and Ollama get the
|
||||
// original tight caps and don't see this section at all.
|
||||
if (localAdvGrp) localAdvGrp.style.display = (provider === 'openai_compatible') ? '' : 'none';
|
||||
// Show the local-endpoint advanced settings (token multiplier) for self-hosted
|
||||
// endpoints. Cloud providers get the original tight caps and don't see this
|
||||
// section at all.
|
||||
if (localAdvGrp) localAdvGrp.style.display = (provider === 'ollama' || provider === 'openai_compatible') ? '' : 'none';
|
||||
|
||||
hint.textContent = KEY_HINTS[provider] || '';
|
||||
modelSelGrp.style.display = 'none';
|
||||
@@ -502,8 +515,23 @@
|
||||
btn.textContent = '⏳ {{ _("Testing…") }}';
|
||||
result.style.display = 'none';
|
||||
|
||||
// Send the form's current values so the user doesn't have to hit Save before
|
||||
// testing a config change. Endpoint falls back to the stored datastore values
|
||||
// for any field we don't send.
|
||||
const params = new URLSearchParams();
|
||||
const model = (document.querySelector('[name="llm-llm_model"]') || {}).value || '';
|
||||
const apiKey = (document.querySelector('[name="llm-llm_api_key"]') || {}).value || '';
|
||||
const apiBase = (document.querySelector('[name="llm-llm_api_base"]') || {}).value || '';
|
||||
const kind = (document.querySelector('[name="llm-llm_provider_kind"]') || {}).value || '';
|
||||
const mult = (document.querySelector('[name="llm-llm_local_token_multiplier"]') || {}).value || '';
|
||||
if (model.trim()) params.set('model', model.trim());
|
||||
if (apiKey.trim()) params.set('api_key', apiKey.trim());
|
||||
if (apiBase.trim()) params.set('api_base', apiBase.trim());
|
||||
if (kind.trim()) params.set('provider_kind', kind.trim());
|
||||
if (mult.trim()) params.set('local_token_multiplier', mult.trim());
|
||||
|
||||
try {
|
||||
const resp = await fetch('{{ url_for("settings.llm.llm_test") }}');
|
||||
const resp = await fetch('{{ url_for("settings.llm.llm_test") }}?' + params);
|
||||
const data = await resp.json();
|
||||
if (data.ok) {
|
||||
result.style.cssText = 'display:block; background:rgba(39,174,96,0.08); border:1px solid rgba(39,174,96,0.3); border-radius:5px; padding:0.6em 0.85em; font-size:0.88em; line-height:1.45;';
|
||||
@@ -519,7 +547,7 @@
|
||||
result.innerHTML = '<span style="color:#c0392b; font-weight:600;">✗ {{ _("Request failed") }}</span>: ' + e.message.replace(/</g,'<');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
btn.textContent = '▶ {{ _("Test connection") }}';
|
||||
btn.textContent = '▶ {{ _("Test connection") }}';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -270,12 +270,15 @@ def construct_blueprint(datastore: ChangeDetectionStore):
|
||||
LLMInputTooLargeError,
|
||||
)
|
||||
|
||||
# Diff-pref flags + system prompt are part of the cache key so prompt changes bust the cache.
|
||||
# Diff-pref flags + system prompt + active model are part of the cache key
|
||||
# so prompt or model changes bust the cache.
|
||||
_max_summary_tokens = datastore.data['settings']['application'].get('llm_max_summary_tokens', 3000)
|
||||
_llm_model = (datastore.data['settings']['application'].get('llm') or {}).get('model', '')
|
||||
cache_prompt = build_summary_cache_prompt(
|
||||
effective_prompt=get_effective_summary_prompt(watch, datastore),
|
||||
max_summary_tokens=_max_summary_tokens,
|
||||
prefs=prefs,
|
||||
model=_llm_model,
|
||||
)
|
||||
|
||||
# Check cache — keyed by version pair + prompt hash (invalidates if prompt changes)
|
||||
|
||||
@@ -1125,11 +1125,14 @@ class globalSettingsLLMForm(Form):
|
||||
validators=[validators.Optional()],
|
||||
default='',
|
||||
)
|
||||
# Multiplier applied to LLM max_tokens caps when provider_kind == 'openai_compatible'.
|
||||
# Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought into
|
||||
# Multiplier applied to LLM max_tokens caps when provider_kind is 'ollama' or
|
||||
# 'openai_compatible' — endpoints that commonly serve reasoning models (Qwen3,
|
||||
# DeepSeek-R1, Gemma 3, etc.) which emit chain-of-thought into
|
||||
# message.reasoning_content before the final answer lands in message.content.
|
||||
# Local self-hosted models cost no per-token money, so giving them headroom is cheap;
|
||||
# cloud providers stay on the original tight caps so existing users see no cost change.
|
||||
# Cloud providers with non-reasoning defaults (OpenAI, Anthropic, Gemini,
|
||||
# OpenRouter) stay on the original tight caps so existing users see no
|
||||
# behavior or cost change. Users on paid Ollama / openai_compatible endpoints
|
||||
# who care about cost can dial this down to 1x.
|
||||
llm_local_token_multiplier = IntegerField(
|
||||
_l('Token multiplier for local reasoning models'),
|
||||
validators=[validators.Optional(), validators.NumberRange(min=1, max=20)],
|
||||
@@ -1187,6 +1190,10 @@ class globalSettingsLLMForm(Form):
|
||||
_l('Use LLM as a fallback for extracting price and restock info'),
|
||||
default=True,
|
||||
)
|
||||
llm_debug = BooleanField(
|
||||
_l('Enable LLM debug logging'),
|
||||
default=False,
|
||||
)
|
||||
llm_thinking_budget = SelectField(
|
||||
_l('AI thinking budget (tokens)'),
|
||||
choices=[
|
||||
|
||||
@@ -4,6 +4,7 @@ Keeps litellm import isolated so the rest of the codebase doesn't depend on it d
|
||||
and makes the call easy to mock in tests.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from loguru import logger
|
||||
|
||||
@@ -17,9 +18,46 @@ DEFAULT_TIMEOUT = int(os.getenv('LLM_TIMEOUT', 60))
|
||||
DEFAULT_RETRIES = 3
|
||||
|
||||
|
||||
class _LoguruInterceptHandler(logging.Handler):
|
||||
# Routes litellm's stdlib log records through loguru so debug output
|
||||
# uses the same format/sink as the rest of the app.
|
||||
def emit(self, record):
|
||||
try:
|
||||
level = logger.level(record.levelname).name
|
||||
except (ValueError, AttributeError):
|
||||
level = record.levelno
|
||||
logger.opt(exception=record.exc_info).log(level, record.getMessage())
|
||||
|
||||
|
||||
_debug_installed = False
|
||||
|
||||
|
||||
def _install_litellm_debug():
|
||||
# Attach our loguru intercept and clear any pre-existing handlers so litellm's
|
||||
# own stdout StreamHandler (installed by _turn_on_debug / set_verbose) doesn't
|
||||
# double-emit. Setting the logger level to DEBUG is enough to make litellm
|
||||
# produce debug records — we don't call _turn_on_debug() for that reason.
|
||||
global _debug_installed
|
||||
if _debug_installed:
|
||||
return
|
||||
|
||||
handler = _LoguruInterceptHandler()
|
||||
handler.setLevel(logging.DEBUG)
|
||||
for _name in ('LiteLLM', 'litellm', 'litellm.utils', 'litellm.router'):
|
||||
_lg = logging.getLogger(_name)
|
||||
_lg.handlers = []
|
||||
_lg.setLevel(logging.DEBUG)
|
||||
_lg.addHandler(handler)
|
||||
_lg.propagate = False
|
||||
|
||||
_debug_installed = True
|
||||
logger.info("LLM client: litellm debug logging routed through loguru")
|
||||
|
||||
|
||||
def completion(model: str, messages: list, api_key: str = None,
|
||||
api_base: str = None, timeout: int = DEFAULT_TIMEOUT,
|
||||
max_tokens: int = None, extra_body: dict = None) -> tuple[str, int, int, int]:
|
||||
max_tokens: int = None, extra_body: dict = None,
|
||||
debug: bool = False) -> tuple[str, int, int, int]:
|
||||
"""
|
||||
Call the LLM and return (response_text, total_tokens, input_tokens, output_tokens).
|
||||
Retries up to DEFAULT_RETRIES times on timeout or connection errors.
|
||||
@@ -31,6 +69,9 @@ def completion(model: str, messages: list, api_key: str = None,
|
||||
except ImportError:
|
||||
raise RuntimeError("litellm is not installed. Add it to requirements.txt.")
|
||||
|
||||
if debug:
|
||||
_install_litellm_debug()
|
||||
|
||||
_timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
|
||||
|
||||
kwargs = {
|
||||
@@ -49,7 +90,10 @@ def completion(model: str, messages: list, api_key: str = None,
|
||||
|
||||
_retryable = (litellm.Timeout, litellm.APIConnectionError)
|
||||
|
||||
logger.trace("Sending payload to LLM.. ")
|
||||
logger.debug(
|
||||
f"LLM client: calling model={model!r} api_base={api_base!r} "
|
||||
f"timeout={_timeout}s max_tokens={kwargs['max_tokens']}"
|
||||
)
|
||||
logger.trace(messages)
|
||||
|
||||
for attempt in range(1, DEFAULT_RETRIES + 1):
|
||||
|
||||
@@ -120,22 +120,25 @@ def _summary_max_tokens(diff: str, max_cap: int = LLM_DEFAULT_MAX_SUMMARY_TOKENS
|
||||
|
||||
def apply_local_token_multiplier(base_max_tokens: int, llm_cfg: dict) -> int:
|
||||
"""
|
||||
Scale max_tokens for self-hosted OpenAI-compatible endpoints (vLLM, LM Studio, llama.cpp).
|
||||
Scale max_tokens for endpoints that commonly serve reasoning models
|
||||
(Ollama — self-hosted or ollama.com cloud — and OpenAI-compatible servers like
|
||||
vLLM, LM Studio, llama.cpp).
|
||||
|
||||
Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought into
|
||||
`message.reasoning_content` BEFORE the final answer lands in `message.content`.
|
||||
Without enough headroom the request truncates mid-thought (`finish_reason='length'`)
|
||||
and the answer never lands — callers see an empty string and silently fall through
|
||||
to safe defaults, hiding the problem.
|
||||
Without enough headroom the request truncates mid-thought (`finish_reason='length'`
|
||||
or `'stop'` with empty content) and the answer never lands — callers see an empty
|
||||
string and silently fall through to safe defaults, hiding the problem.
|
||||
|
||||
Local self-hosted models cost no per-token money, so headroom is cheap; cloud
|
||||
providers (OpenAI, Anthropic, Gemini, OpenRouter) keep their original tight caps
|
||||
so existing users see no cost change.
|
||||
Cloud providers with stable, non-reasoning defaults (OpenAI, Anthropic, Gemini,
|
||||
OpenRouter) keep their original tight caps so existing users see no behavior or
|
||||
cost change. Ollama / OpenAI-compatible users can dial the multiplier down to 1x
|
||||
in Settings → AI → Provider if they want to keep costs tight on a paid endpoint.
|
||||
|
||||
Activated only when `llm_cfg['provider_kind'] == 'openai_compatible'`.
|
||||
Activated when `llm_cfg['provider_kind']` is `'ollama'` or `'openai_compatible'`.
|
||||
Multiplier defaults to 5x and is user-configurable in Settings → AI → Provider.
|
||||
"""
|
||||
if (llm_cfg or {}).get('provider_kind') != 'openai_compatible':
|
||||
if (llm_cfg or {}).get('provider_kind') not in ('ollama', 'openai_compatible'):
|
||||
return base_max_tokens
|
||||
try:
|
||||
multiplier = int(llm_cfg.get('local_token_multiplier') or 5)
|
||||
@@ -399,6 +402,7 @@ def run_setup(watch, datastore, snapshot_text: str) -> None:
|
||||
api_base=cfg.get('api_base'),
|
||||
max_tokens=apply_local_token_multiplier(JSON_RESPONSE_MAX_TOKENS, cfg),
|
||||
extra_body=_thinking_extra_body(cfg['model'], int(datastore.data['settings']['application'].get('llm_thinking_budget', LLM_DEFAULT_THINKING_BUDGET) or 0)),
|
||||
debug=bool(datastore.data['settings']['application'].get('llm_debug', False)),
|
||||
)
|
||||
_check_token_budget(watch, cfg, tokens)
|
||||
accumulate_global_tokens(datastore, tokens, model=cfg['model'])
|
||||
@@ -472,7 +476,7 @@ class DiffPrefs:
|
||||
|
||||
|
||||
def build_summary_cache_prompt(effective_prompt: str, max_summary_tokens: int,
|
||||
prefs: DiffPrefs = None) -> str:
|
||||
prefs: DiffPrefs = None, model: str = '') -> str:
|
||||
"""
|
||||
Compose the full cache-key string passed to save/get_llm_diff_summary.
|
||||
|
||||
@@ -480,6 +484,10 @@ def build_summary_cache_prompt(effective_prompt: str, max_summary_tokens: int,
|
||||
worker-side pre-cache is hit by an unmodified UI request. Same helper must
|
||||
be used by both the worker pre-cache write and the UI diff route read,
|
||||
otherwise the prompt hashes diverge and the cache file isn't found.
|
||||
|
||||
The active model name is folded into the key so switching models
|
||||
(e.g. qwen3 → gpt-4o) invalidates stale summaries that were generated
|
||||
by a different model with potentially different phrasing/quality.
|
||||
"""
|
||||
if prefs is None:
|
||||
prefs = DiffPrefs()
|
||||
@@ -488,6 +496,7 @@ def build_summary_cache_prompt(effective_prompt: str, max_summary_tokens: int,
|
||||
+ prefs.cache_key_suffix()
|
||||
+ f'\x00sys:{build_change_summary_system_prompt()}'
|
||||
+ f'\x00max_tokens:{max_summary_tokens}'
|
||||
+ f'\x00model:{model}'
|
||||
)
|
||||
|
||||
|
||||
@@ -551,6 +560,7 @@ def summarise_change(watch, datastore, diff: str, current_snapshot: str = '') ->
|
||||
cfg,
|
||||
),
|
||||
extra_body=_extra_body,
|
||||
debug=bool(datastore.data['settings']['application'].get('llm_debug', False)),
|
||||
)
|
||||
raw, tokens = _resp[0], _resp[1]
|
||||
input_tokens = _resp[2] if len(_resp) > 2 else 0
|
||||
@@ -613,6 +623,7 @@ def preview_extract(watch, datastore, content: str) -> dict | None:
|
||||
api_base=cfg.get('api_base'),
|
||||
max_tokens=apply_local_token_multiplier(JSON_RESPONSE_MAX_TOKENS, cfg),
|
||||
extra_body=_thinking_extra_body(cfg['model'], int(datastore.data['settings']['application'].get('llm_thinking_budget', LLM_DEFAULT_THINKING_BUDGET) or 0)),
|
||||
debug=bool(datastore.data['settings']['application'].get('llm_debug', False)),
|
||||
)
|
||||
accumulate_global_tokens(datastore, tokens, model=cfg['model'])
|
||||
result = parse_preview_response(raw)
|
||||
@@ -697,6 +708,7 @@ def evaluate_change(watch, datastore, diff: str, current_snapshot: str = '') ->
|
||||
api_base=cfg.get('api_base'),
|
||||
max_tokens=apply_local_token_multiplier(JSON_RESPONSE_MAX_TOKENS, cfg),
|
||||
extra_body=_thinking_extra_body(cfg['model'], int(datastore.data['settings']['application'].get('llm_thinking_budget', LLM_DEFAULT_THINKING_BUDGET) or 0)),
|
||||
debug=bool(datastore.data['settings']['application'].get('llm_debug', False)),
|
||||
)
|
||||
raw, tokens = _resp[0], _resp[1]
|
||||
input_tokens = _resp[2] if len(_resp) > 2 else 0
|
||||
|
||||
@@ -218,9 +218,11 @@ def render(watch, datastore, request, url_for, render_template, flash, redirect,
|
||||
# Must match the cache_prompt the worker writes and the UI ajax route reads —
|
||||
# using UI default diff prefs so the initial render finds the worker's pre-cache.
|
||||
_max_summary_tokens = datastore.data['settings']['application'].get('llm_max_summary_tokens', 3000)
|
||||
_llm_model = (datastore.data['settings']['application'].get('llm') or {}).get('model', '')
|
||||
_cache_prompt = build_summary_cache_prompt(
|
||||
effective_prompt=_prompt,
|
||||
max_summary_tokens=_max_summary_tokens,
|
||||
model=_llm_model,
|
||||
)
|
||||
llm_diff_summary = watch.get_llm_diff_summary(from_version, to_version, prompt=_cache_prompt)
|
||||
except Exception as e:
|
||||
|
||||
@@ -906,10 +906,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -983,6 +984,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3173,6 +3180,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr "AI pracovní rozpočet (tokeny)"
|
||||
|
||||
@@ -922,10 +922,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -999,6 +1000,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3225,6 +3232,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -904,10 +904,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -981,6 +982,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3167,6 +3174,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -904,10 +904,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -981,6 +982,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3167,6 +3174,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -942,10 +942,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -1019,6 +1020,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3240,6 +3247,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -910,10 +910,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -987,6 +988,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3180,6 +3187,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -906,10 +906,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -983,6 +984,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3169,6 +3176,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -911,10 +911,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -988,6 +989,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3186,6 +3193,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -912,10 +912,11 @@ msgstr "Ollama 또는 사용자 지정/자체 호스팅 엔드포인트에만
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -989,6 +990,12 @@ msgstr "모든 요약 캐시 지우기"
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr "모든 모니터링에 저장된 AI 변경 요약 캐시를 제거합니다. 다음 확인 시 다시 생성됩니다."
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr "기본 AI 변경 요약"
|
||||
@@ -3177,6 +3184,10 @@ msgstr "{{diff}} 알림 토큰을 AI 요약으로 대체"
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr "가격 및 재입고 정보 추출의 대체 수단으로 LLM 사용"
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr "AI 추론 예산 (토큰)"
|
||||
|
||||
@@ -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-15 15:44+0200\n"
|
||||
"POT-Creation-Date: 2026-05-15 18:31+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -903,10 +903,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -980,6 +981,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3166,6 +3173,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -929,10 +929,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -1006,6 +1007,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3217,6 +3224,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -939,10 +939,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -1016,6 +1017,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3220,6 +3227,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -919,10 +919,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -996,6 +997,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3199,6 +3206,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -908,10 +908,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -985,6 +986,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3172,6 +3179,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -907,10 +907,11 @@ msgstr ""
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Local reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This "
|
||||
"multiplier scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to "
|
||||
"%(default)s; raise it if responses come back truncated, lower it if you want tighter limits. Only applied to self-"
|
||||
"hosted OpenAI-compatible endpoints — cloud providers (OpenAI, Anthropic, Gemini) keep their original tight caps."
|
||||
"Reasoning models (Qwen3, DeepSeek-R1, Gemma 3, etc.) emit chain-of-thought before the final answer. This multiplier "
|
||||
"scales every <code>max_tokens</code> cap for this endpoint to leave reasoning room. Defaults to %(default)s; raise it"
|
||||
" if responses come back truncated or empty, lower it (down to 1x) if you want tighter limits on a paid endpoint. "
|
||||
"Applied to Ollama and OpenAI-compatible endpoints — other cloud providers (OpenAI, Anthropic, Gemini) keep their "
|
||||
"original tight caps."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
@@ -984,6 +985,12 @@ msgstr ""
|
||||
msgid "Removes all cached AI change summaries across all watches. They will be regenerated on the next check."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid ""
|
||||
"Enables litellm verbose output (routed through loguru). Useful when diagnosing provider errors or empty responses. "
|
||||
"Leave off in production — generates a lot of log volume."
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/blueprint/settings/templates/settings_llm_tab.html
|
||||
msgid "Default AI Change Summary"
|
||||
msgstr ""
|
||||
@@ -3171,6 +3178,10 @@ msgstr ""
|
||||
msgid "Use LLM as a fallback for extracting price and restock info"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "Enable LLM debug logging"
|
||||
msgstr ""
|
||||
|
||||
#: changedetectionio/forms.py
|
||||
msgid "AI thinking budget (tokens)"
|
||||
msgstr ""
|
||||
|
||||
@@ -539,9 +539,11 @@ async def async_update_worker(worker_id, q, notification_q, app, datastore, exec
|
||||
)
|
||||
_llm_to_version = list(watch.history.keys())[-1]
|
||||
_llm_max_summary_tokens = datastore.data['settings']['application'].get('llm_max_summary_tokens', 3000)
|
||||
_llm_model = (datastore.data['settings']['application'].get('llm') or {}).get('model', '')
|
||||
_llm_cache_prompt = build_summary_cache_prompt(
|
||||
effective_prompt=get_effective_summary_prompt(watch, datastore),
|
||||
max_summary_tokens=_llm_max_summary_tokens,
|
||||
model=_llm_model,
|
||||
)
|
||||
watch.save_llm_diff_summary(
|
||||
update_obj['_llm_change_summary'],
|
||||
|
||||
Reference in New Issue
Block a user