// buildLineBytes is the most bytes of one line in a build input or usage log.
const buildLineBytes = 1 << 20
+// buildWaitTimeout is the longest wait for pending memory builds.
+const buildWaitTimeout = time.Second
+
// buildQuotaLimit is the largest increase in used quota points of a run.
const buildQuotaLimit = 15.0
-// buildCallLimit is the most model calls of a run.
-const buildCallLimit = 660
-
// BuildRun appends messages, builds their tree, and stops the run by the rules
// of buildStop.
type BuildRun struct {
usagePath string
}
+// DatedMessage is one message with an optional RFC 3339 date.
+type DatedMessage struct {
+ Kind string `json:"kind"`
+ Text string `json:"text"`
+ Date string `json:"date,omitempty"`
+}
+
// Run appends the entries. It waits for the builds only before a user message,
// as a turn does, so up to buildMax builds run at once in between, and it waits
// for all builds at the end. It returns the number of messages appended and why
// waitBuilds waits up to one second without leaving a child context open.
func (r *BuildRun) waitBuilds(ctx context.Context) error {
- ctx, cancel := context.WithTimeout(ctx, time.Second)
+ ctx, cancel := context.WithTimeout(ctx, buildWaitTimeout)
defer cancel()
return r.memory.Wait(ctx)
}
-// DatedMessage is one message with an optional RFC 3339 date.
-type DatedMessage struct {
- Kind string `json:"kind"`
- Text string `json:"text"`
- Date string `json:"date,omitempty"`
-}
-
// buildReadUsage reads the records of usage.jsonl at path, in the order of the
// start of their calls. The file has them in the order of the end of their
// calls, which differs when calls run at once.
scanner := bufio.NewScanner(file)
scanner.Buffer(make([]byte, 64*1024), buildLineBytes)
+
for scanner.Scan() {
var record ModelUsageRecord
+
err = json.Unmarshal(scanner.Bytes(), &record)
if err != nil {
return nil, fmt.Errorf("decode usage: %w", err)
// buildWriteReport writes the result of a build run.
func buildWriteReport(out io.Writer, appended int, stop string, records []ModelUsageRecord, sizes []int) error {
var input, cached, output, failed int
+
for _, record := range records {
input += record.InputTokens
cached += record.CachedTokens
}
var lines []string
+
if stop != "" {
lines = append(lines, "stopped early: "+stop)
}
}
var events []event
+
seconds := make([]float64, 0, len(records))
total := 0.0
for _, record := range records {
}
wall := events[len(events)-1].at.Sub(events[0].at).Seconds()
+
slices.Sort(seconds)
return fmt.Sprintf("time: %.0f s in all, %.1f calls per minute, %.1f s per call (median %.1f, max %.1f), calls at once: at most %d, %.1f on average", wall, 60*float64(len(seconds))/max(wall, 1e-9), total/float64(len(seconds)), seconds[len(seconds)/2], seconds[len(seconds)-1], most, total/max(wall, 1e-9))