mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 10:22:08 +00:00
- A health problem of a VM or CT names the guest in its title and in the Quiet Hours summary; a recovery shows its category by name in the reader's language. - AI model lists reviewed against each provider: Gemini adds 3.6/3.7/3.8 Flash, Groq adds gpt-oss-120b, and Groq/OpenRouter models no longer served are removed. - OCI installer proposes the volume choice the recipe declares, so a path meant for a host directory is proposed as one; Duplicati /source is proposed on a host directory.
343 lines
30 KiB
JSON
343 lines
30 KiB
JSON
{
|
||
"meta": {
|
||
"title": "Proxmox AI Assistant — OpenAI, Claude, Gemini, Groq, Ollama | ProxMenux Monitor",
|
||
"description": "The optional AI Assistant rewrites Proxmox VE notifications in plain language. Six providers: OpenAI, Anthropic Claude, Google Gemini, Groq, OpenRouter and Ollama. The UI offers thirteen languages, three detail levels per channel, custom prompts with a community library, and event context including uptime, recurrence and SMART data.",
|
||
"ogTitle": "Proxmox AI Assistant — OpenAI, Claude, Gemini, Groq, Ollama",
|
||
"ogDescription": "Rewrite Proxmox VE notifications in plain language with OpenAI, Anthropic Claude, Google Gemini, Groq, OpenRouter or local Ollama.",
|
||
"twitterTitle": "Proxmox AI Assistant | ProxMenux Monitor",
|
||
"twitterDescription": "Rewrite Proxmox VE notifications in plain language with OpenAI, Anthropic, Gemini, Groq, OpenRouter or local Ollama."
|
||
},
|
||
"header": {
|
||
"title": "AI Assistant",
|
||
"description": "Optional AI rewriting turns eligible notification templates into plain-language messages, with per-channel detail levels, thirteen UI languages, custom prompts, a public community library and context enrichment. Backup reports <code>backup_complete</code> and <code>backup_fail</code> bypass AI entirely.",
|
||
"section": "ProxMenux Monitor"
|
||
},
|
||
"intro": {
|
||
"title": "Off by default, single switch to enable",
|
||
"body": "AI rewriting is off by default. Enable it in <em>Settings → Notifications → Advanced: AI Enhancement</em>. If enrichment or rewriting fails, the dispatcher sends the original template. Rewrites in the event dispatch queue have a 25-second timeout; reaching it sends the template instead of waiting."
|
||
},
|
||
"howItWorks": {
|
||
"heading": "How it works",
|
||
"intro": "Every event the Monitor dispatches goes through the same pipeline. The AI rewriter is one optional stage that sits between the templated body and the channel send. End to end, a single event walks through four steps:",
|
||
"steps": [
|
||
"<strong>Event + template.</strong> An event arrives from one of the six collectors and is rendered into a structured plain-text body by <code>notification_templates.py</code>. This is the body the channel would send if AI rewrite were off.",
|
||
"<strong>Context enrichment.</strong> The dispatcher inspects the event and conditionally appends the relevant extra signals — system uptime (only for critical system failures), event frequency, SMART data (only for disk events), Known Errors database matches and journal log lines.",
|
||
"<strong>Prompt builder.</strong> The system prompt is assembled from the template plus the per-channel settings: target language, detail level, emoji rules from <em>Rich messages</em>, and the AI Suggestions addon if enabled. In Custom prompt mode, your prompt replaces the system prompt entirely. The user message is built from the templated body plus the enriched context blocks.",
|
||
"<strong>Provider call.</strong> The configured provider (Groq, OpenAI, Anthropic, Gemini, Ollama or OpenRouter) returns a rewritten title and body. The dispatcher parses the response, replaces the original title and body for that channel, and hands it off to the channel adapter for delivery."
|
||
],
|
||
"notesIntro": "Three details worth holding on to before reading the rest of this page:",
|
||
"notes": [
|
||
"<strong>The AI does not produce events.</strong> Every event is born from a real signal (Health Monitor scan, journal line, PVE webhook, etc.) and is rendered into a templated body before the AI ever sees it. The AI is a translator and re-formatter, not a watcher.",
|
||
"<strong>The AI runs per-channel.</strong> Telegram and Discord can use a brief rewrite while Email gets a detailed report — same event, different shape, all from one provider call per channel.",
|
||
"<strong>Failure is silent.</strong> If the provider 5xx's, times out, returns malformed output or rejects the request, the dispatcher logs the error and falls back to the original templated body for that channel. You never lose a notification because the LLM had a bad day."
|
||
]
|
||
},
|
||
"enabling": {
|
||
"heading": "Enabling the panel",
|
||
"intro": "The AI configuration lives at the bottom of the Notifications panel inside the Settings tab, as a collapsible <em>Advanced: AI Enhancement</em> block. Click the header to expand:",
|
||
"collapsedAlt": "Collapsed Advanced AI Enhancement header with chevron indicator",
|
||
"collapsedCaption": "Collapsed by default — one click expands the panel.",
|
||
"panelAlt": "Expanded AI Enhancement panel showing AI-Enhanced Messages master toggle, Provider Google Gemini, API Key masked, Model gemini-2.5-flash, Prompt Mode Default, Language English, Detail Level per Channel for Telegram Discord Gotify Email, AI Suggestions toggle and Test Connection button",
|
||
"panelCaption": "The full AI Enhancement panel — every control documented in this page maps to one of the fields above.",
|
||
"outro": "Top to bottom, the panel exposes: the <em>AI-Enhanced Messages</em> master toggle, the provider selector with an information modal next to it, the API key input (or Ollama URL for local mode), the model dropdown (loaded from the provider after entering the key), the prompt mode (<em>Default</em> / <em>Custom</em>), the output language, the per-channel detail level, the <em>AI Suggestions</em> opt-in, and a <em>Test Connection</em> button that sends a probe message to the provider to validate the credentials."
|
||
},
|
||
"context": {
|
||
"heading": "What context the AI receives",
|
||
"intro": "Before the prompt is built, the dispatcher walks a context-enrichment routine that decides which extra signals are relevant to the event at hand. The aim is to give the LLM enough information to produce a useful message, without flooding it (and your wallet) with noise that doesn't apply. Five context blocks can be added to the user message:",
|
||
"headerBlock": "Block",
|
||
"headerWhen": "When it's injected",
|
||
"headerWhat": "What it carries",
|
||
"rows": [
|
||
{
|
||
"block": "System uptime",
|
||
"when": "Only for critical system-level failures: <code>crash</code>, <code>panic</code>, <code>oom</code>, <code>kernel</code>, <code>split_brain</code>, <code>quorum_lost</code>, <code>node_offline</code>, <code>node_fail</code>, <code>system_fail</code>, <code>boot_fail</code>. Skipped for disk errors, warnings and routine operations to keep the prompt tight.",
|
||
"what": "A line such as <code>System uptime: 14 days (stable system)</code>. Lets the LLM distinguish startup issues from long-running failures."
|
||
},
|
||
{
|
||
"block": "Event frequency",
|
||
"when": "Always, when the Monitor has seen the same fingerprint before.",
|
||
"what": "Occurrence count, first-seen timestamp, optional pattern label (recurring / one-off / spike). The LLM uses this to phrase \"recurring issue\" vs \"first time seen\"."
|
||
},
|
||
{
|
||
"block": "SMART data",
|
||
"when": "Only for disk-related events (event type contains <code>disk</code>, <code>smart</code>, <code>storage</code>, <code>io_error</code>, or the body mentions <code>/dev/sd</code>, <code>ata</code>, <code>i/o error</code>).",
|
||
"what": "Output of <code>smartctl</code> for the affected device — overall health (PASSED / FAILED) plus the relevant attributes for the failure mode."
|
||
},
|
||
{
|
||
"block": "Known errors DB",
|
||
"when": "When the body or journal context matches a Proxmox-specific error pattern shipped with the Monitor.",
|
||
"what": "A <code>KNOWN PROXMOX ERROR DETECTED</code> block with the matched cause and a concrete solution. The prompt instructs the LLM to translate this verbatim — no paraphrasing of the recommended fix."
|
||
},
|
||
{
|
||
"block": "Journal logs",
|
||
"when": "Whenever the originating collector captured journal lines for the event (mostly the journal watcher and the task watcher).",
|
||
"what": "Raw <code>journalctl</code> excerpts. The prompt tells the LLM to extract IDs, timestamps and root-cause hints, and to ignore unrelated entries."
|
||
}
|
||
],
|
||
"afterBlocks": "Once these blocks are joined, the user message sent to the LLM has this shape:",
|
||
"calloutTitle": "No telemetry beyond the event itself",
|
||
"calloutBody": "The Monitor only sends what it has on hand for the current event — no system-wide telemetry, no historical metric series, no inventory dumps. The five blocks above are the upper bound of what leaves the host on a single AI rewrite."
|
||
},
|
||
"tokens": {
|
||
"heading": "Tokens — what they are and how they're consumed",
|
||
"intro1": "Every commercial provider charges per <em>token</em>, so it's worth understanding what a token is before picking a plan. A token is roughly four characters of English text or about three quarters of a word. The phrase <em>\"Backup completed on storage local-bak\"</em> is around eight tokens. A short journal excerpt of ten lines can be 200-400 tokens depending on the technical density.",
|
||
"intro2": "Two things are billed on every call:",
|
||
"items": [
|
||
"<strong>Input tokens</strong> cover the system prompt and user message: severity, title, rendered body and enriched context. Their number depends on the actual prompt and event content. Each rewritten channel can incur its own input-token usage; backup-complete and backup-fail reports bypass AI.",
|
||
"<strong>Output tokens</strong> — what the model writes back. The Monitor caps this with <code>max_tokens</code> (see the table below). The cap is a <em>limit</em>, not a charge: if the model produces 250 tokens with a cap of 1500, you pay for 250."
|
||
],
|
||
"capsIntro": "These are the actual caps the dispatcher applies, taken straight from <code>AI_DETAIL_TOKENS</code> in <code>notification_templates.py</code>:",
|
||
"headerLevel": "Detail level",
|
||
"headerCap": "Output cap (tokens)",
|
||
"headerConsumption": "Typical real consumption",
|
||
"capRows": [
|
||
{
|
||
"level": "brief",
|
||
"cap": "500",
|
||
"consumption": "50-200 output tokens for short events."
|
||
},
|
||
{
|
||
"level": "standard",
|
||
"cap": "1500",
|
||
"consumption": "200-700 output tokens for typical events with light context."
|
||
},
|
||
{
|
||
"level": "detailed",
|
||
"cap": "3000",
|
||
"consumption": "500-2000 output tokens for full email reports with logs and SMART tables."
|
||
}
|
||
],
|
||
"customNote": "Custom prompt mode uses a fixed cap of 500 output tokens regardless of detail level — the custom prompt is in your control and the cap protects against runaway responses.",
|
||
"sizingTitle": "Practical sizing",
|
||
"sizingBody": "Estimate usage as rewritten events × AI-enabled channels × input-plus-output tokens per call. For example, 50 events × one channel × (2,000 input + 300 output tokens) is about 115,000 tokens per day, since the default system prompt alone is roughly 1,500 tokens. Actual usage and charges depend on model, context, caching and provider limits. The <link>Detail level per channel</link> section shows how to use <code>brief</code> for chat instead of <code>standard</code>, while keeping detailed email reports."
|
||
},
|
||
"providers": {
|
||
"heading": "AI providers",
|
||
"intro": "Six providers are wired into the Monitor. The provider dropdown in the UI shows them all; an information button next to it opens a modal with a one-line description for each. Below is the full reference, with the URL for getting an API key, the description shown in the UI and the relevant notes from the codebase.",
|
||
"imageAlt": "AI Providers Information modal listing the six supported providers — Groq, OpenAI, Anthropic Claude, Google Gemini, Ollama, OpenRouter — each with its icon and one-line description, and a special OpenAI-Compatible APIs note for OpenAI",
|
||
"imageCaption": "The in-app modal — six cards, one per provider, with the same descriptions documented below.",
|
||
"groq": {
|
||
"heading": "Groq",
|
||
"tagline": "Very fast, generous free tier (30 req/min). Ideal to start.",
|
||
"items": [
|
||
"API key: <a>console.groq.com/keys</a>",
|
||
"Examples from the bundled model list: <code>allam-2-7b</code>, <code>qwen/qwen3.8-27b</code>, <code>openai/gpt-oss-20b</code>, <code>openai/gpt-oss-120b</code>.",
|
||
"Bundled recommendation: <strong><code>openai/gpt-oss-20b</code></strong>. Use the provider selector and connection test to check availability for your account."
|
||
]
|
||
},
|
||
"openai": {
|
||
"heading": "OpenAI",
|
||
"tagline": "Industry standard. Very accurate and widely used.",
|
||
"items": [
|
||
"API key: <a>platform.openai.com/api-keys</a>",
|
||
"Examples from the bundled model list: <code>gpt-4.1-nano</code>, <code>gpt-4.1-mini</code>, <code>gpt-4o-mini</code>, <code>gpt-4.1</code>, <code>gpt-4o</code>, <code>gpt-5-nano</code>.",
|
||
"Bundled recommendation: <strong><code>gpt-4.1-nano</code></strong>. The adapter also handles model-specific requirements for reasoning models; the bundled list includes gpt-5-nano, so reasoning models are not universally excluded."
|
||
],
|
||
"baseUrlTitle": "OpenAI-compatible base URL",
|
||
"baseUrlBody": "The OpenAI provider also accepts a custom <em>Base URL</em>, which lets you point the Monitor at any OpenAI-compatible endpoint. Confirmed to work with <strong>BytePlus / ByteDance (Kimi K2.5)</strong>, <strong>LocalAI</strong>, <strong>LM Studio</strong>, <strong>vLLM</strong>, <strong>Together AI</strong>, <strong>Fireworks AI</strong>, and any other service that speaks the OpenAI <code>/v1/chat/completions</code> dialect. Set the URL in the OpenAI tab next to the API key field."
|
||
},
|
||
"anthropic": {
|
||
"heading": "Anthropic (Claude)",
|
||
"tagline": "Excellent for writing and translation. Fast and economical.",
|
||
"items": [
|
||
"API key: <a>console.anthropic.com/settings/keys</a>",
|
||
"Examples from the bundled model list: <code>claude-haiku-5-5</code>, <code>claude-sonnet-5-5</code>, <code>claude-opus-5-5</code>.",
|
||
"Bundled recommendation: <strong><code>claude-haiku-5-5</code></strong>, the most economical current Claude model."
|
||
]
|
||
},
|
||
"gemini": {
|
||
"heading": "Google Gemini",
|
||
"tagline": "Free tier available, great quality/price ratio.",
|
||
"items": [
|
||
"API key: <a>aistudio.google.com/app/apikey</a>",
|
||
"Examples from the bundled model list: <code>gemini-2.5-flash-lite</code>, <code>gemini-2.5-flash</code>, <code>gemini-3-flash-preview</code>.",
|
||
"Recommended: <strong><code>gemini-2.5-flash-lite</code></strong> — flash and flash-lite pass the verifier consistently. The pro variants reject the <code>thinkingBudget=0</code> setting the Monitor uses and are overkill for this workload."
|
||
]
|
||
},
|
||
"openrouter": {
|
||
"heading": "OpenRouter",
|
||
"tagline": "Aggregator with access to 100+ models using a single API key. Maximum flexibility.",
|
||
"items": [
|
||
"API key: <a>openrouter.ai/keys</a>",
|
||
"Examples from the bundled model list: <code>meta-llama/llama-3.3-70b-instruct</code>, <code>meta-llama/llama-3.1-70b-instruct</code>, <code>meta-llama/llama-3.1-8b-instruct</code>, <code>anthropic/claude-haiku-4.5</code>, <code>google/gemini-2.5-flash-lite</code>, <code>openai/gpt-4o-mini</code>, <code>mistralai/mistral-medium-3</code>.",
|
||
"Recommended: <strong><code>meta-llama/llama-3.3-70b-instruct</code></strong> — same model as the Groq entry but routed through OpenRouter, which means a single key for all the listed models."
|
||
]
|
||
},
|
||
"ollama": {
|
||
"heading": "Ollama (Local)",
|
||
"tagline": "Uses models exposed by your configured Ollama server. Local models execute there; Ollama cloud models forward requests to a cloud provider. Local execution avoids a hosted API charge but still uses your hardware and electricity.",
|
||
"items": [
|
||
"No API key. Set the <em>Ollama URL</em> field to your server (default <code>http://localhost:11434</code> or whatever host runs your Ollama instance).",
|
||
"Models: <strong>not filtered.</strong> The Monitor reads whichever models you have pulled on the Ollama side via <code>ollama pull <model></code>. The dropdown is populated from <code>GET /api/tags</code> on your Ollama server.",
|
||
"Install: <a>ollama.com/download</a> — runs on Linux, macOS, Windows. For best results pick a model that fits in RAM with a large enough context window for the journal blocks the dispatcher injects."
|
||
]
|
||
}
|
||
},
|
||
"models": {
|
||
"heading": "Why these specific models",
|
||
"intro": "Commercial-provider model choices come from the bundled compatibility catalogue <code>verified_ai_models.json</code>, combined with the provider adapter’s availability checks. Adapters map the internal <code>system_prompt + user_message + max_tokens</code> request to each provider’s API. The catalogue contains tested entries and manual additions; it is a snapshot, not a guarantee of current account access or a promise that every entry passed the same verifier.",
|
||
"consequencesIntro": "Two consequences worth being aware of:",
|
||
"consequences": [
|
||
"<strong>The bundled recommendation</strong> is a starting point selected for notification formatting. Assess language quality, latency and cost for your own event content and provider account rather than treating it as a universal model ranking.",
|
||
"<strong>You can choose another listed model</strong> from the dropdown to suit your quota or preferences. Check its availability with the connection test; being listed does not guarantee current access for your account."
|
||
],
|
||
"ollamaTitle": "Ollama is the exception",
|
||
"ollamaBody": "The Ollama dropdown is not filtered by the commercial-provider catalogue; it reflects models exposed by your Ollama server. For local execution choose a local model that fits your RAM and has enough context for the journal blocks. Cloud-tagged models are remote even when accessed through a local Ollama server."
|
||
},
|
||
"defaultPrompt": {
|
||
"heading": "Default prompt",
|
||
"intro": "With prompt mode set to <em>Default</em>, the Monitor uses the system prompt below. The prompt is templated at runtime: <code>'{'language'}'</code>, <code>'{'detail_level'}'</code>, <code>'{'emoji_instructions'}'</code> and <code>'{'suggestions_addon'}'</code> are replaced before the call. The variants for rich vs plain channels and the AI Suggestions addon are shown immediately after.",
|
||
"showFullSummary": "Show full default system prompt",
|
||
"passagesIntro": "Two passages in the prompt above are placeholders that get swapped depending on the per-channel <em>Rich messages</em> toggle:",
|
||
"passages": [
|
||
"<strong>Rich on</strong> → an emoji block is injected listing the icons the LLM may use, plus a hostname rule (the LLM must keep the hostname prefix from the title verbatim) and a handful of formatted examples (backup start, backup complete, updates, VM start, health degraded). This is what produces the emoji-prefixed messages on Telegram and Discord.",
|
||
"<strong>Rich off</strong> → a one-line block tells the LLM to use plain ASCII only — no emojis, no Unicode symbols. Used for email and any channel where formatting noise hurts inbox rules or readability."
|
||
],
|
||
"suggestionsPlaceholder": "And the <code>'{'suggestions_addon'}'</code> placeholder is empty unless you enable AI Suggestions (next section), in which case this block gets injected:",
|
||
"showAddonSummary": "Show AI Suggestions addon"
|
||
},
|
||
"customPrompt": {
|
||
"heading": "Custom prompt mode",
|
||
"intro": "Switching the prompt mode to <em>Custom</em> swaps the entire default system prompt for one you write yourself. The custom prompt is stored in the Monitor's SQLite settings and sent verbatim on every AI rewrite call. It's the right escape hatch when you want a completely different voice, structure or focus than the bundled prompt offers.",
|
||
"imageAlt": "Custom Prompt mode showing a textarea with translation rules and Export Import buttons plus a Community prompts link",
|
||
"imageCaption": "Custom Prompt — large textarea with the user's prompt, plus <em>Export</em>, <em>Import</em> and a link to the community gallery on GitHub.",
|
||
"changesTitle": "What changes when Custom is on",
|
||
"changes": [
|
||
"<strong>The default prompt is replaced entirely.</strong> The Proxmox mappings, the context-handling rules and the emoji instructions are all gone. If you want to keep any of them, paste them into your prompt — the bundled <code>EXAMPLE_CUSTOM_PROMPT</code> shown below is a starting point.",
|
||
"<strong>The Language selector is ignored.</strong> The default prompt has a <code>'{'language'}'</code> placeholder; the custom prompt does not. If you want output in a specific language, declare it inside your prompt (\"Translate to Spanish\", \"Output everything in French\").",
|
||
"<strong>The custom-mode output cap is fixed at 500 tokens</strong>, independent of the stored per-channel detail setting. Default mode uses the 500 / 1500 / 3000 limits. Editing the custom prompt cannot raise the cap; request a shorter answer or use an appropriate Default detail level.",
|
||
"<strong>The output markers remain mandatory.</strong> Include <code>[TITLE]</code> and <code>[BODY]</code> in the response format. The parser extracts their content; if either marker is missing, it returns the original template instead.",
|
||
"<strong>Rich messages emoji rules are not auto-injected.</strong> If you want emojis, tell the prompt to use them. If you want plain text, tell it not to. The toggle only gates the bundled blocks of the default prompt, not your custom string."
|
||
],
|
||
"starterTitle": "Starter prompt",
|
||
"starterIntro": "The <em>Custom Prompt</em> textarea ships pre-filled with a minimal example you can adapt:",
|
||
"showStarterSummary": "Show starter custom prompt",
|
||
"shareTitle": "Sharing prompts with the community",
|
||
"shareIntro": "The <em>Export</em> button writes your current custom prompt to a file (<code>.txt</code> / <code>.md</code>) you can keep as a backup or hand to someone else. <em>Import</em> pulls one back in. The third button next to them links to a public community gallery on GitHub:",
|
||
"shareLinkLabel": "github.com/MacRimi/ProxMenux/discussions — Share custom prompts for AI notifications",
|
||
"shareOutro": "Browse the discussion to see what other users have built — terse pager-style alerts, verbose technical reports, language-specific variants. If you tweak yours and like the result, post it there: even a one-paragraph description of what your prompt optimises for helps people pick a good starting point. Feedback on what works and what doesn't is equally welcome."
|
||
},
|
||
"suggestions": {
|
||
"heading": "AI Suggestions (BETA)",
|
||
"intro": "AI Suggestions is an opt-in addon that lets the LLM append <strong>one</strong> short, actionable tip at the end of the body. It only activates when the prompt mode is <em>Default</em>, the master AI toggle is on, and the <em>AI Suggestions</em> switch is flipped — and even then, the prompt instructs the model to skip the tip whenever the cause or solution is unclear.",
|
||
"formatIntro": "When a tip is added, it follows this exact format:",
|
||
"rulesIntro": "The rules baked into the addon (visible in the collapsible block under the Default prompt section above):",
|
||
"rules": [
|
||
"The tip is included <em>only</em> if the journal context or the Known Errors database clearly points to a specific fix.",
|
||
"The prompt requests a tip under 100 characters; the parser does not independently enforce that length.",
|
||
"The prompt requires a specific command or path and instructs the model to avoid generic advice.",
|
||
"If a Known Error provides a solution, the LLM must use that solution, not invent a new one.",
|
||
"The prompt instructs the model to omit the tip if the input does not support a concrete fix."
|
||
],
|
||
"betaTitle": "Why BETA",
|
||
"betaBody": "Tip quality depends on two things outside of ProxMenux: the model picked, and how rich the journal context for the event was. With a strong model (Claude 3.5 Haiku, GPT-4.1 Mini, Llama 3.3 70B) and a disk error that comes with smartctl + journal lines, the tip is consistently useful. With a tiny local Ollama model and a one-line event, the tip can fall flat or get skipped entirely. Disable the toggle if you find the tips noisy and re-enable it when you want it back."
|
||
},
|
||
"detailLevel": {
|
||
"heading": "Detail level per channel",
|
||
"intro": "Each of the four channels (Telegram, Discord, Gotify, Email) has its own detail-level dropdown. Three values are available, mapped to specific output token caps and to specific instructions in the default prompt:",
|
||
"headerLevel": "Level",
|
||
"headerLabel": "UI label",
|
||
"headerCap": "Output cap",
|
||
"headerProduce": "What the prompt asks the LLM to produce",
|
||
"rows": [
|
||
{
|
||
"level": "brief",
|
||
"label": "2-3 lines, essential only",
|
||
"cap": "500 tokens",
|
||
"produce": "\"What happened + where\". Nothing else."
|
||
},
|
||
{
|
||
"level": "standard",
|
||
"label": "Concise with basic context",
|
||
"cap": "1500 tokens",
|
||
"produce": "3-6 lines: what, where, cause, affected devices."
|
||
},
|
||
{
|
||
"level": "detailed",
|
||
"label": "Complete technical details",
|
||
"cap": "3000 tokens",
|
||
"produce": "Full report: what, where, cause, affected, logs, SMART data, history."
|
||
}
|
||
],
|
||
"defaultsIntro": "Defaults the Monitor applies on first install:",
|
||
"defaults": [
|
||
"<strong>Telegram, Discord, Gotify</strong> — <code>standard</code>.",
|
||
"<strong>Email</strong> — <code>detailed</code>. Email is the channel where you typically want the full picture for archival."
|
||
],
|
||
"emailTitle": "Email detail level appends the original",
|
||
"emailBody": "When the AI formatter returns a result for Email on <code>detailed</code> and the original body is longer than 50 characters, the formatter appends that original text after a 40-dash divider and the label <code>Original message:</code>. This retains the source details for later searches. AI bypasses and failures can instead deliver the original template alone."
|
||
},
|
||
"language": {
|
||
"heading": "Language",
|
||
"intro": "The UI selector offers thirteen languages. It stores <code>ai_language</code>, which the default system prompt uses in <em>\"translate alerts into '{'language'}'\"</em>. The UI list is:",
|
||
"list": "English (<code>en</code>), Slovak (<code>sk</code>), Spanish (<code>es</code>), French (<code>fr</code>), German (<code>de</code>), Portuguese (<code>pt</code>), Italian (<code>it</code>), Russian (<code>ru</code>), Swedish (<code>sv</code>), Norwegian (<code>no</code>), Japanese (<code>ja</code>), Chinese (<code>zh</code>), Dutch (<code>nl</code>).",
|
||
"rulesIntro": "Two important rules taken straight from the prompt:",
|
||
"rules": [
|
||
"<strong>Translate</strong>: labels, descriptions, status words, units (e.g. GB → Go in French).",
|
||
"<strong>Do not translate</strong>: hostnames, IPs, paths, VM/CT IDs, device names like <code>/dev/sdX</code>, technical identifiers. These stay verbatim regardless of language."
|
||
],
|
||
"customNote": "Custom prompt mode <strong>does not use</strong> the Language selector. If you switch to Custom and want a specific output language, declare it inside your prompt."
|
||
},
|
||
"templates": {
|
||
"heading": "A note on templates",
|
||
"body1": "The AI receives a rendered template rather than raw event data. Types such as <code>vm_start</code>, <code>auth_fail</code> and <code>health_degraded</code> have templates in <code>notification_templates.py</code>. The AI rewrites eligible template output; <code>backup_complete</code> and <code>backup_fail</code> retain their deterministic reports and bypass AI.",
|
||
"body2": "Two practical implications: the AI never sees a hostname or VMID it has to invent — those fields are placed by the template before the rewrite. And if AI is disabled, the templated body is what gets dispatched directly. The <link>Notifications</link> page documents the dispatch pipeline in full and is the right cross-reference for everything that happens to an event before it reaches this layer."
|
||
},
|
||
"privacy": {
|
||
"heading": "Privacy & data flow",
|
||
"intro": "With AI rewrite enabled, the Monitor sends the rendered notification body plus the enriched context blocks to the configured provider. That can include hostnames, IPs, usernames, device paths, journal log lines and SMART attributes for the affected device. Whether that leaves the host depends on which provider you chose:",
|
||
"headerProvider": "Provider",
|
||
"headerDestination": "Data destination",
|
||
"rows": [
|
||
{
|
||
"provider": "Ollama",
|
||
"destination": "Local models run on the configured Ollama host. Their requests stay on that host when it is the Proxmox node itself. Ollama cloud models forward requests outside the host, even through a local Ollama server."
|
||
},
|
||
{
|
||
"provider": "OpenAI",
|
||
"destination": "<code>api.openai.com</code> by default, or the configured custom Base URL. The data-handling policy of the actual endpoint operator applies."
|
||
},
|
||
{
|
||
"provider": "Anthropic",
|
||
"destination": "<code>api.anthropic.com</code>."
|
||
},
|
||
{
|
||
"provider": "Google Gemini",
|
||
"destination": "<code>generativelanguage.googleapis.com</code>."
|
||
},
|
||
{
|
||
"provider": "Groq",
|
||
"destination": "<code>api.groq.com</code>."
|
||
},
|
||
{
|
||
"provider": "OpenRouter",
|
||
"destination": "<code>openrouter.ai</code>, which forwards to the underlying model provider chosen in the <code>model</code> field. Two hops instead of one."
|
||
}
|
||
],
|
||
"calloutTitle": "If event content cannot leave the network",
|
||
"calloutBody": "Use a locally hosted endpoint with a local model, such as local Ollama or an OpenAI-compatible server, or disable AI rewriting. Ollama cloud models do not keep processing local. The dispatcher does not redact hostnames or IPs; it builds the prompt from the actual event content."
|
||
},
|
||
"whereNext": {
|
||
"heading": "Where to next",
|
||
"items": [
|
||
{
|
||
"label": "Notifications",
|
||
"href": "/docs/monitor/notifications",
|
||
"tail": " — the dispatch pipeline, channels, per-event toggles and the PVE webhook integration that surrounds this layer."
|
||
},
|
||
{
|
||
"label": "Health Monitor",
|
||
"href": "/docs/monitor/health-monitor",
|
||
"tail": " — the largest single producer of events the AI ends up rewriting, with its own per-category suppression durations."
|
||
},
|
||
{
|
||
"label": "Architecture",
|
||
"href": "/docs/monitor/architecture",
|
||
"tail": " — where the AI Enhancer fits into the wider Monitor process (it's a module, not a separate service)."
|
||
}
|
||
],
|
||
"communityLabel": "Community prompts on GitHub",
|
||
"communityTail": " — browse, share, ask."
|
||
}
|
||
}
|