Refactor: split prompt definition from execution settings and migrate run contracts to prompt_* + execution_target
This commit is contained in:
@@ -23,16 +23,19 @@ func NewGoRenderer() Renderer {
|
||||
return &goRenderer{}
|
||||
}
|
||||
|
||||
func (r *goRenderer) Render(ctx context.Context, profile *domain.PromptProfile, inputs map[string]*domain.Artifact, vars map[string]string) (*domain.RenderedPrompt, error) {
|
||||
if profile == nil {
|
||||
return nil, fmt.Errorf("%w: nil profile", ErrRenderFailure)
|
||||
func (r *goRenderer) Render(ctx context.Context, definition *domain.PromptDefinition, inputs map[string]*domain.Artifact, vars map[string]string) (*domain.RenderedPrompt, error) {
|
||||
if definition == nil {
|
||||
return nil, fmt.Errorf("%w: nil prompt definition", ErrRenderFailure)
|
||||
}
|
||||
|
||||
// 1. Verify required inputs
|
||||
for _, req := range profile.ExpectedInputs {
|
||||
art, ok := inputs[req]
|
||||
for _, in := range definition.Inputs {
|
||||
if !in.Required {
|
||||
continue
|
||||
}
|
||||
art, ok := inputs[in.Name]
|
||||
if !ok || art == nil {
|
||||
return nil, fmt.Errorf("%w: %s", ErrMissingRequiredInput, req)
|
||||
return nil, fmt.Errorf("%w: %s", ErrMissingRequiredInput, in.Name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +52,7 @@ func (r *goRenderer) Render(ctx context.Context, profile *domain.PromptProfile,
|
||||
|
||||
var renderedMessages []domain.RenderedMessage
|
||||
|
||||
for i, tmplMsg := range profile.Templates {
|
||||
for i, tmplMsg := range definition.Templates {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
@@ -61,6 +64,9 @@ func (r *goRenderer) Render(ctx context.Context, profile *domain.PromptProfile,
|
||||
}
|
||||
|
||||
// Parse and execute template
|
||||
if tmplMsg.ContentFile != "" {
|
||||
return nil, fmt.Errorf("%w: message %d: content_file is not implemented yet", ErrRenderFailure, i)
|
||||
}
|
||||
tmpl, err := template.New(fmt.Sprintf("msg_%d", i)).Funcs(funcs).Option("missingkey=error").Parse(tmplMsg.Content)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: message %d: %v", ErrInvalidTemplate, i, err)
|
||||
|
||||
@@ -7,5 +7,5 @@ import (
|
||||
|
||||
// Renderer renders prompt templates using named artifacts and variables.
|
||||
type Renderer interface {
|
||||
Render(ctx context.Context, profile *domain.PromptProfile, inputs map[string]*domain.Artifact, vars map[string]string) (*domain.RenderedPrompt, error)
|
||||
Render(ctx context.Context, definition *domain.PromptDefinition, inputs map[string]*domain.Artifact, vars map[string]string) (*domain.RenderedPrompt, error)
|
||||
}
|
||||
|
||||
@@ -12,9 +12,9 @@ func TestGoRenderer_Render(t *testing.T) {
|
||||
renderer := NewGoRenderer()
|
||||
ctx := context.Background()
|
||||
|
||||
profile := &domain.PromptProfile{
|
||||
profile := &domain.PromptDefinition{
|
||||
ID: "test-profile",
|
||||
ExpectedInputs: []string{"transcript"},
|
||||
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
|
||||
Templates: []domain.PromptMessageTemplate{
|
||||
{Role: "system", Content: "You are a {{.role}}."},
|
||||
{Role: "user", Content: "Analyze this: {{input \"transcript\"}}"},
|
||||
@@ -54,7 +54,8 @@ func TestGoRenderer_Render(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("unknown input in template", func(t *testing.T) {
|
||||
profileUnknown := &domain.PromptProfile{
|
||||
profileUnknown := &domain.PromptDefinition{
|
||||
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
|
||||
Templates: []domain.PromptMessageTemplate{
|
||||
{Role: "user", Content: "Hello {{input \"ghost\"}}"},
|
||||
},
|
||||
@@ -69,7 +70,8 @@ func TestGoRenderer_Render(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid template syntax", func(t *testing.T) {
|
||||
profileInvalid := &domain.PromptProfile{
|
||||
profileInvalid := &domain.PromptDefinition{
|
||||
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
|
||||
Templates: []domain.PromptMessageTemplate{
|
||||
{Role: "user", Content: "Hello {{.unclosed"},
|
||||
},
|
||||
@@ -81,7 +83,8 @@ func TestGoRenderer_Render(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("empty message role", func(t *testing.T) {
|
||||
profileNoRole := &domain.PromptProfile{
|
||||
profileNoRole := &domain.PromptDefinition{
|
||||
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
|
||||
Templates: []domain.PromptMessageTemplate{
|
||||
{Role: "", Content: "Hello"},
|
||||
},
|
||||
@@ -93,7 +96,8 @@ func TestGoRenderer_Render(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("missing variable in template", func(t *testing.T) {
|
||||
profileMissingVar := &domain.PromptProfile{
|
||||
profileMissingVar := &domain.PromptDefinition{
|
||||
Inputs: []domain.PromptInput{{Name: "transcript", Required: true}},
|
||||
Templates: []domain.PromptMessageTemplate{
|
||||
{Role: "system", Content: "You are {{.missing}}"},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user