orchard
mirrorEvery site I host, in one repo, along with the Cloudflare Tunnel and Caddy that front them. It's all Go, Vite, and SQLite, and it runs on a desktop at home with nothing listening on an inbound port.
blogbuncaddycloudflare-tunneldockergogolanghomelabhtml-templatemonorepoself-hostedseosqlitestatic-sitetypstuptime-monitoringviteweb-analytics
1package main
2
3import (
4 "fmt"
5 "strings"
6 "time"
7)
8
9// Ambient is what the model would know if it were a person sitting here, and
10// has no way of knowing otherwise. Without the date it cannot tell what
11// "recent" means; without the place it answers a question about the weather or
12// what is open as though it were nowhere.
13//
14// Location is a constant for the same reason it is in dash: it is where Isaac
15// is, and a lookup would be a network call to learn something that does not
16// change.
17const (
18 placeName = "Yadkin Valley, North Carolina, United States"
19 timeZone = "America/New_York"
20)
21
22// AmbientContext is the block at the top of every system prompt: the facts plus
23// the instruction for using them.
24func AmbientContext() string {
25 return AmbientFacts() + " " + strings.Join([]string{
26 "Use this only when the question depends on it, such as anything asking what is recent, current, nearby, in season, or open.",
27 "Never state it as a fact from a source, and never repeat it back in an answer.",
28 "The location in particular is for questions about here, and has no place in an answer about anything else.",
29 }, " ")
30}
31
32// AmbientFacts is the same block without the instructions, for showing a person
33// what the model has been told.
34func AmbientFacts() string {
35 now := localNow()
36 parts := []string{
37 fmt.Sprintf("Today is %s.", now.Format("Monday, 2 January 2006")),
38 // To the hour, not the minute. llama-server caches the prompt prefix
39 // it has already processed and every system prompt here opens with
40 // this block, so a clock that changes every minute means no call ever
41 // reuses another's work. Nothing asked here turns on the minute.
42 fmt.Sprintf("The local time is around %s.", now.Format("3 PM MST")),
43 fmt.Sprintf("The user is in %s.", placeName),
44 fmt.Sprintf("It is %s.", season(now)),
45 }
46 if h := holiday(now); h != "" {
47 parts = append(parts, fmt.Sprintf("Today is %s.", h))
48 } else if h, days := nextHoliday(now); h != "" && days <= 14 {
49 parts = append(parts, fmt.Sprintf("%s is in %d days.", h, days))
50 }
51 return strings.Join(parts, " ")
52}
53
54func localNow() time.Time {
55 loc, err := time.LoadLocation(timeZone)
56 if err != nil {
57 return time.Now()
58 }
59 return time.Now().In(loc)
60}
61
62func season(t time.Time) time.Month { return t.Month() }
63
64// holiday names the day if it is one worth knowing about. US holidays plus the
65// handful of others a question might turn on.
66func holiday(t time.Time) string {
67 y := t.Year()
68 for name, day := range holidays(y) {
69 if sameDay(t, day) {
70 return name
71 }
72 }
73 return ""
74}
75
76func nextHoliday(t time.Time) (string, int) {
77 best, bestDays := "", 1<<30
78 for _, y := range []int{t.Year(), t.Year() + 1} {
79 for name, day := range holidays(y) {
80 d := int(day.Sub(truncDay(t)).Hours() / 24)
81 if d > 0 && d < bestDays {
82 best, bestDays = name, d
83 }
84 }
85 }
86 if best == "" {
87 return "", 0
88 }
89 return best, bestDays
90}
91
92func holidays(y int) map[string]time.Time {
93 loc := localNow().Location()
94 d := func(m time.Month, day int) time.Time { return time.Date(y, m, day, 0, 0, 0, 0, loc) }
95 return map[string]time.Time{
96 "New Year's Day": d(time.January, 1),
97 "Valentine's Day": d(time.February, 14),
98 "St Patrick's Day": d(time.March, 17),
99 "Easter Sunday": easter(y, loc),
100 "Independence Day": d(time.July, 4),
101 "Halloween": d(time.October, 31),
102 "Thanksgiving": nthWeekday(y, time.November, time.Thursday, 4, loc),
103 "Christmas Eve": d(time.December, 24),
104 "Christmas Day": d(time.December, 25),
105 "New Year's Eve": d(time.December, 31),
106 "Memorial Day": lastWeekday(y, time.May, time.Monday, loc),
107 "Labor Day": nthWeekday(y, time.September, time.Monday, 1, loc),
108 "Mother's Day": nthWeekday(y, time.May, time.Sunday, 2, loc),
109 "Father's Day": nthWeekday(y, time.June, time.Sunday, 3, loc),
110 }
111}
112
113// easter is the anonymous Gregorian computus. It is here because several
114// holidays hang off it and it is fifteen lines.
115func easter(y int, loc *time.Location) time.Time {
116 a := y % 19
117 b := y / 100
118 c := y % 100
119 dd := b / 4
120 e := b % 4
121 f := (b + 8) / 25
122 g := (b - f + 1) / 3
123 h := (19*a + b - dd - g + 15) % 30
124 i := c / 4
125 k := c % 4
126 l := (32 + 2*e + 2*i - h - k) % 7
127 m := (a + 11*h + 22*l) / 451
128 month := (h + l - 7*m + 114) / 31
129 day := (h+l-7*m+114)%31 + 1
130 return time.Date(y, time.Month(month), day, 0, 0, 0, 0, loc)
131}
132
133func nthWeekday(y int, m time.Month, wd time.Weekday, n int, loc *time.Location) time.Time {
134 t := time.Date(y, m, 1, 0, 0, 0, 0, loc)
135 for t.Weekday() != wd {
136 t = t.AddDate(0, 0, 1)
137 }
138 return t.AddDate(0, 0, 7*(n-1))
139}
140
141func lastWeekday(y int, m time.Month, wd time.Weekday, loc *time.Location) time.Time {
142 t := time.Date(y, m+1, 1, 0, 0, 0, 0, loc).AddDate(0, 0, -1)
143 for t.Weekday() != wd {
144 t = t.AddDate(0, 0, -1)
145 }
146 return t
147}
148
149func truncDay(t time.Time) time.Time {
150 return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
151}
152
153func sameDay(a, b time.Time) bool {
154 return a.Year() == b.Year() && a.YearDay() == b.YearDay()
155}