Files
HeatGuard/internal/llm/prompt.go
vikingowl 1c9db02334 feat: add web UI with full CRUD setup page
Add server-side rendered setup UI accessible via `heatwave web`.
The dashboard is now re-rendered per request and includes a nav bar
linking to the new /setup page. Setup provides full CRUD for profiles,
rooms, devices, occupants, AC units (with room assignment), scenario
toggles, and forecast fetching — all via POST/redirect/GET forms.

- Add ShowNav field to DashboardData for conditional nav bar
- Extract fetchForecastForProfile() for reuse by web handler
- Create setup.html.tmpl with Tailwind-styled entity sections
- Create web_handlers.go with 15 route handlers and flash cookies
- Switch web.go from pre-rendered to per-request dashboard rendering
- Graceful dashboard fallback when no forecast data exists
2026-02-09 10:39:00 +01:00

99 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package llm
import (
"fmt"
"strings"
)
const summarizeSystemPrompt = `You are a heat preparedness assistant. You receive computed heat model data for a specific day.
Generate exactly 3 concise bullet points summarizing the key drivers and risks.
Rules:
- Reference ONLY the data provided below. Do not invent or assume additional information.
- Use preparedness language (comfort, planning). Never give medical advice or diagnoses.
- Each bullet: max 20 words, plain language, actionable insight.
- Format: "- [bullet text]" (markdown list)`
const rewriteActionSystemPrompt = `You are a heat preparedness assistant. Rewrite the given technical action into a clear, friendly, plain-language instruction.
Rules:
- One sentence, max 25 words.
- Reference the provided temperature and time context.
- Use preparedness language. Never give medical advice.
- Return only the rewritten sentence, nothing else.`
const heatPlanSystemPrompt = `You are a heat preparedness assistant. Generate a 1-page plain-language heat plan document.
Rules:
- Reference ONLY the data provided below. Do not invent information.
- Use preparedness language (comfort, planning). Never give medical advice or diagnoses.
- Structure: Brief overview (2-3 sentences), then hour-by-hour key actions, then care reminders.
- Use simple language anyone can understand.
- Keep total length under 500 words.
- Format as markdown with headers.`
// BuildSummaryPrompt constructs the user message for Summarize.
func BuildSummaryPrompt(input SummaryInput) string {
var b strings.Builder
fmt.Fprintf(&b, "Date: %s\n", input.Date)
fmt.Fprintf(&b, "Peak temperature: %.1f°C\n", input.PeakTempC)
fmt.Fprintf(&b, "Minimum night temperature: %.1f°C\n", input.MinNightTempC)
fmt.Fprintf(&b, "Overall risk level: %s\n", input.RiskLevel)
fmt.Fprintf(&b, "AC headroom: %.0f BTU/h\n", input.ACHeadroomBTUH)
fmt.Fprintf(&b, "Budget status: %s\n", input.BudgetStatus)
if len(input.TopHeatSources) > 0 {
b.WriteString("Top heat sources:\n")
for _, s := range input.TopHeatSources {
fmt.Fprintf(&b, " - %s: %.0fW\n", s.Name, s.Watts)
}
}
if len(input.ActiveWarnings) > 0 {
b.WriteString("Active warnings:\n")
for _, w := range input.ActiveWarnings {
fmt.Fprintf(&b, " - %s\n", w)
}
}
if len(input.RiskWindows) > 0 {
b.WriteString("Risk windows:\n")
for _, rw := range input.RiskWindows {
fmt.Fprintf(&b, " - %02d:00%02d:00, peak %.1f°C, level: %s\n", rw.StartHour, rw.EndHour, rw.PeakTempC, rw.Level)
}
}
return b.String()
}
// BuildRewriteActionPrompt constructs the user message for RewriteAction.
func BuildRewriteActionPrompt(input ActionInput) string {
return fmt.Sprintf("Action: %s\nDescription: %s\nCurrent temperature: %.1f°C\nHour: %02d:00",
input.ActionName, input.Description, input.TempC, input.Hour)
}
// BuildHeatPlanPrompt constructs the user message for GenerateHeatPlan.
func BuildHeatPlanPrompt(input HeatPlanInput) string {
var b strings.Builder
b.WriteString(BuildSummaryPrompt(input.Summary))
b.WriteString("\nTimeline:\n")
for _, s := range input.Timeline {
actions := "none"
if len(s.Actions) > 0 {
actions = strings.Join(s.Actions, ", ")
}
fmt.Fprintf(&b, " %02d:00 | %.1f°C | risk: %s | budget: %s | actions: %s\n",
s.Hour, s.TempC, s.RiskLevel, s.BudgetStatus, actions)
}
if len(input.CareChecklist) > 0 {
b.WriteString("\nCare checklist:\n")
for _, c := range input.CareChecklist {
fmt.Fprintf(&b, " - %s\n", c)
}
}
return b.String()
}
// SummarizeSystemPrompt returns the system prompt for Summarize.
func SummarizeSystemPrompt() string { return summarizeSystemPrompt }
// RewriteActionSystemPrompt returns the system prompt for RewriteAction.
func RewriteActionSystemPrompt() string { return rewriteActionSystemPrompt }
// HeatPlanSystemPrompt returns the system prompt for GenerateHeatPlan.
func HeatPlanSystemPrompt() string { return heatPlanSystemPrompt }