repos
/ orchard main

orchard

mirror

Every 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

4.9 KB · 156 lines · Go Raw History
  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}