Files
velox-bot/internal/tldr/tldrbench/suggest.go
T
FernandoJVideiraandClaude Opus 5.5 17548bbf7d Add a local benchmark for /tldr with a dashboard
`go test -tags bench ./internal/tldr -run TestBench` runs the real /tldr
pipeline against one or more Ollama models and prompt variants on a chat dump
from disk (text copied from Discord, "Author: message" lines, or a
DiscordChatExporter JSON export) and writes a self-contained HTML dashboard
plus a JSON of the results. Scoring uses an optional facts file (a fact
passes only when one bullet holds all its details) and automatic checks:
numbers not in the chat, copying the chat, an English intro, cut-off output.

TestFactsSkeleton proposes candidate facts from the chat to prune by hand.
Chat dumps and results stay local: bench-out/ and the private folders are
git-ignored. See internal/tldr/tldrbench/README.md.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-20 18:46:18 +01:00

141 lines
3.9 KiB
Go

package tldrbench
import (
"fmt"
"regexp"
"sort"
"strings"
"unicode"
)
var (
// Things a good overview has to get right: figures, times, money, days.
figureRe = regexp.MustCompile(`\d+(?:[.,:]\d+)*(?:h\d*|€|%|k|gb|mb|min)?`)
weekdayRe = regexp.MustCompile(`(?i)\b(segunda|ter[çc]a|quarta|quinta|sexta|s[áa]bado|domingo|monday|tuesday|wednesday|thursday|friday|saturday|sunday|amanh[ãa]|tomorrow|hoje|today)\b`)
moneyRe = regexp.MustCompile(`(?i)€|\$|\beur\b|\beuros?\b`)
wordRe = regexp.MustCompile(`[\p{L}][\p{L}'-]{5,}`)
// Common long words that make poor topic keywords.
stopwords = map[string]bool{
"porque": true, "também": true, "tambem": true, "depois": true, "ontem": true, "ainda": true, "estava": true,
"podemos": true, "devíamos": true, "devemos": true, "fazer": true, "mesmo": true, "sempre": true, "ficou": true,
"because": true, "should": true, "would": true, "could": true, "really": true, "maybe": true, "already": true,
}
)
// signals counts how many different "this matters" markers a line has.
func signals(line string) int {
n := 0
if figureRe.MatchString(line) {
n++
}
if weekdayRe.MatchString(line) {
n++
}
if moneyRe.MatchString(line) {
n++
}
if strings.Contains(line, "[link") || strings.Contains(line, "(preview:") {
n++
}
return n
}
// SuggestFacts proposes candidate facts from transcript lines ("Author: text").
// It does not understand the chat: it picks the lines that carry figures,
// times, days, money or links, and for each suggests patterns (the figures and
// days in it, plus one topic word). You are meant to prune and merge them into
// the 10 to 20 facts that matter, then check the patterns against a real
// overview. At most max candidates are returned, chronologically.
func SuggestFacts(lines []string, max int) []Fact {
type scored struct {
idx, signals int
line string
}
var cands []scored
for i, ln := range lines {
ln = strings.TrimSpace(ln)
if ln == "" {
continue
}
if s := signals(ln); s > 0 {
cands = append(cands, scored{i, s, ln})
}
}
// Keep the strongest, then restore chat order.
sort.SliceStable(cands, func(a, b int) bool { return cands[a].signals > cands[b].signals })
if max > 0 && len(cands) > max {
cands = cands[:max]
}
sort.Slice(cands, func(a, b int) bool { return cands[a].idx < cands[b].idx })
var facts []Fact
for n, c := range cands {
facts = append(facts, Fact{
Name: fmt.Sprintf("fact %d: %s", n+1, excerpt(c.line, 48)),
All: suggestPatterns(c.line),
Note: c.line,
})
}
return facts
}
func suggestPatterns(line string) []string {
// Drop the "Author: " prefix so names do not become patterns.
text := line
if i := strings.Index(line, ": "); i > 0 && i <= 32 {
text = line[i+2:]
}
seen := map[string]bool{}
var pats []string
add := func(p string) {
key := strings.ToLower(p)
if p == "" || len(pats) >= 3 {
return
}
for have := range seen {
if strings.Contains(have, key) || strings.Contains(key, have) {
return // already covered, e.g. "segunda" next to "segunda-feira"
}
}
seen[key] = true
pats = append(pats, p)
}
// A topic word first, so the fact stays tied to its subject.
best := ""
for _, w := range wordRe.FindAllString(text, -1) {
lw := strings.ToLower(w)
if stopwords[lw] || strings.ContainsAny(lw, "0123456789") {
continue
}
if len([]rune(w)) > len([]rune(best)) {
best = w
}
}
if best != "" {
add(regexp.QuoteMeta(strings.ToLower(trimWord(best))))
}
for _, d := range weekdayRe.FindAllString(text, -1) {
add(regexp.QuoteMeta(strings.ToLower(d)))
}
for _, f := range figureRe.FindAllString(text, -1) {
add(regexp.QuoteMeta(strings.ToLower(f)))
}
return pats
}
func trimWord(w string) string {
return strings.TrimFunc(w, func(r rune) bool { return !unicode.IsLetter(r) })
}
func excerpt(s string, n int) string {
s = strings.Join(strings.Fields(s), " ")
r := []rune(s)
if len(r) <= n {
return s
}
return string(r[:n]) + "…"
}