Use local builders for rendered templates

This commit is contained in:
2026-10-09 00:18:39 +00:00
parent dd89be3b03
commit 58a5bbe790
4 changed files with 138 additions and 5 deletions

View File

@@ -1,7 +1,6 @@
package prompt
import (
"bytes"
"context"
"errors"
"fmt"
@@ -126,7 +125,7 @@ func (r *goRenderer) Render(ctx context.Context, definition *domain.PromptDefini
if err := ctx.Err(); err != nil {
return nil, err
}
var buf bytes.Buffer
var buf strings.Builder
executeErr := tmpl.Execute(&buf, vars)
if err := ctx.Err(); err != nil {
return nil, err
@@ -235,7 +234,7 @@ func executeSessionTemplate(ctx context.Context, tmpl *template.Template, vars m
if err := ctx.Err(); err != nil {
return "", err
}
var buf bytes.Buffer
var buf strings.Builder
executeErr := tmpl.Execute(&buf, vars)
if err := ctx.Err(); err != nil {
return "", err

View File

@@ -4,8 +4,11 @@ import (
"bytes"
"context"
"errors"
"fmt"
"strings"
"sync"
"testing"
"text/template"
"gitea.maximumdirect.net/eric/promptkit/internal/domain"
)
@@ -501,6 +504,75 @@ func TestGoRendererArtifactTextLifecycle(t *testing.T) {
}
}
func TestCompiledRendererKeepsConcurrentRequestsIndependent(t *testing.T) {
const (
promptID = "concurrent-render"
version = "v1"
)
sessionTemplate, err := CompileTemplate("session", "session-{{.request}}")
if err != nil {
t.Fatalf("compile session template: %v", err)
}
messageTemplate, err := CompileTemplate("message", `request={{.request}};document={{input "document"}}`)
if err != nil {
t.Fatalf("compile message template: %v", err)
}
renderer := NewCompiledRenderer(compiledRendererTestLookup{
id: promptID,
version: version,
templates: CompiledTemplates{
Session: sessionTemplate,
Messages: []*template.Template{messageTemplate},
},
})
definition := &domain.PromptDefinition{
ID: promptID, Version: version, SessionID: "session-{{.request}}",
Inputs: []domain.PromptInput{{Name: "document"}},
Templates: []domain.PromptMessageTemplate{{Role: "user", Content: `request={{.request}};document={{input "document"}}`}},
}
const requestCount = 24
errs := make(chan error, requestCount)
var wait sync.WaitGroup
wait.Add(requestCount)
for i := 0; i < requestCount; i++ {
go func(i int) {
defer wait.Done()
request := fmt.Sprintf("request-%d", i)
document := fmt.Sprintf("document-%d", i)
rendered, err := renderer.Render(context.Background(), definition,
map[string]*domain.Artifact{"document": {Body: []byte(document)}},
map[string]string{"request": request},
)
if err != nil {
errs <- fmt.Errorf("render %s: %w", request, err)
return
}
if rendered.SessionID != "session-"+request || len(rendered.Messages) != 1 ||
rendered.Messages[0].Content != "request="+request+";document="+document {
errs <- fmt.Errorf("render %s returned session %q and messages %#v", request, rendered.SessionID, rendered.Messages)
}
}(i)
}
wait.Wait()
close(errs)
for err := range errs {
t.Error(err)
}
}
type compiledRendererTestLookup struct {
id, version string
templates CompiledTemplates
}
func (lookup compiledRendererTestLookup) GetCompiledTemplates(id, version string) (CompiledTemplates, bool) {
if id != lookup.id || version != lookup.version {
return CompiledTemplates{}, false
}
return lookup.templates, true
}
// BenchmarkGoRendererArtifactReferences measures NewGoRenderer's per-call
// template-parsing fallback rather than the captured compiled path.
func BenchmarkGoRendererArtifactReferences(b *testing.B) {