Demonstrate coordinated conversation workflows

This commit is contained in:
2026-11-14 01:31:22 +00:00
parent 68daa61867
commit 31cc0069fc
4 changed files with 175 additions and 34 deletions

View File

@@ -69,12 +69,16 @@ func (l *eventLog) terminal() (promptkit.ExecutionEvent, error) {
}
type summary struct {
ProposalAttempts uint64 `json:"proposal_attempts"`
ProposalTransientRetries uint64 `json:"proposal_transient_retries"`
ProposalUsageComplete bool `json:"proposal_usage_complete"`
AssessmentAttempts uint64 `json:"assessment_attempts"`
AssessmentTransientRetries uint64 `json:"assessment_transient_retries"`
AssessmentOutcome string `json:"assessment_outcome"`
ProposalAttempts uint64 `json:"proposal_attempts"`
ProposalTransientRetries uint64 `json:"proposal_transient_retries"`
ProposalUsageComplete bool `json:"proposal_usage_complete"`
AssessmentAttempts uint64 `json:"assessment_attempts"`
AssessmentTransientRetries uint64 `json:"assessment_transient_retries"`
AssessmentOutcome string `json:"assessment_outcome"`
CoordinationOutcome promptkit.CoordinationOutcome `json:"coordination_outcome"`
ExhaustedOutcome promptkit.CoordinationOutcome `json:"exhausted_outcome"`
GroupMembers int `json:"group_members"`
GroupAttempts uint64 `json:"group_attempts"`
}
func run() (summary, error) {
@@ -104,8 +108,9 @@ func run() (summary, error) {
}
var proposalLog eventLog
var executions promptkit.ExecutionGroup
proposal, err := engine.Run(context.Background(), promptkit.RunRequest{
PromptID: "example.proposal", Inputs: map[string]promptkit.ArtifactRef{"idea": promptkit.Inline("Reduce queue cleanup toil.")}, Observer: proposalLog.record,
PromptID: "example.proposal", Inputs: map[string]promptkit.ArtifactRef{"idea": promptkit.Inline("Reduce queue cleanup toil.")}, CaptureExchange: true, Observer: promptkit.ComposeObservers(proposalLog.record, executions.Observe),
})
if err != nil {
return summary{}, err
@@ -118,35 +123,55 @@ func run() (summary, error) {
return summary{}, err
}
var assessmentLog eventLog
assessment, err := engine.Run(context.Background(), promptkit.RunRequest{
PromptID: "example.assessment", Inputs: map[string]promptkit.ArtifactRef{"proposal": promptkit.Inline(proposal.RawOutput)}, Observer: assessmentLog.record,
decision := "rejected"
coordination, err := engine.Coordinate(context.Background(), promptkit.CoordinateRequest{
Start: proposal.Exchange, AdditionalTurns: 1, Observer: executions.Observe,
Next: func(ctx context.Context, turn promptkit.ConversationTurn) (*promptkit.RunRequest, error) {
if turn.Result == nil {
return &promptkit.RunRequest{PromptID: "example.proposal", Inputs: map[string]promptkit.ArtifactRef{"idea": promptkit.Inline("Refine the proposal.")}}, nil
}
if !turn.Result.Validation.IsValid {
return nil, fmt.Errorf("follow-up failed structural validation")
}
assessment, err := engine.Run(ctx, promptkit.RunRequest{PromptID: "example.assessment", Inputs: map[string]promptkit.ArtifactRef{"proposal": promptkit.Inline(turn.Result.RawOutput)}, Observer: promptkit.ComposeObservers(assessmentLog.record, executions.Observe)})
if err != nil {
return nil, err
}
if !assessment.Validation.IsValid {
return nil, fmt.Errorf("assessment failed structural validation")
}
var proposalValue struct {
Risk string `json:"risk"`
}
var assessmentValue struct {
Recommendation string `json:"recommendation"`
}
if err := json.Unmarshal([]byte(turn.Result.RawOutput), &proposalValue); err != nil {
return nil, err
}
if err := json.Unmarshal([]byte(assessment.RawOutput), &assessmentValue); err != nil {
return nil, err
}
if proposalValue.Risk == "low" && assessmentValue.Recommendation == "accept" {
decision = "accepted"
}
return nil, nil
},
})
if err != nil {
return summary{}, err
}
if !assessment.Validation.IsValid {
return summary{}, fmt.Errorf("assessment failed structural validation")
exhausted, err := engine.Coordinate(context.Background(), promptkit.CoordinateRequest{Start: proposal.Exchange, Next: func(context.Context, promptkit.ConversationTurn) (*promptkit.RunRequest, error) {
return &promptkit.RunRequest{PromptID: "example.proposal"}, nil
}})
if err != nil {
return summary{}, err
}
assessmentTerminal, err := assessmentLog.terminal()
if err != nil {
return summary{}, err
}
var proposalValue struct {
Risk string `json:"risk"`
}
var assessmentValue struct {
Recommendation string `json:"recommendation"`
}
if err := json.Unmarshal([]byte(proposal.RawOutput), &proposalValue); err != nil {
return summary{}, err
}
if err := json.Unmarshal([]byte(assessment.RawOutput), &assessmentValue); err != nil {
return summary{}, err
}
decision := "rejected"
if proposalValue.Risk == "low" && assessmentValue.Recommendation == "accept" {
decision = "accepted"
}
group := executions.Snapshot()
return summary{
ProposalAttempts: proposalTerminal.Attempts,
ProposalTransientRetries: proposalTerminal.TransientRetries,
@@ -154,6 +179,10 @@ func run() (summary, error) {
AssessmentAttempts: assessmentTerminal.Attempts,
AssessmentTransientRetries: assessmentTerminal.TransientRetries,
AssessmentOutcome: decision,
CoordinationOutcome: coordination.Outcome,
ExhaustedOutcome: exhausted.Outcome,
GroupMembers: len(group.Members),
GroupAttempts: group.Attempts,
}, nil
}

View File

@@ -12,19 +12,23 @@ func TestObserveExample(t *testing.T) {
t.Fatal(err)
}
var got struct {
ProposalAttempts *int `json:"proposal_attempts"`
ProposalRetries *int `json:"proposal_transient_retries"`
UsageComplete *bool `json:"proposal_usage_complete"`
AssessmentAttempts *int `json:"assessment_attempts"`
AssessmentRetries *int `json:"assessment_transient_retries"`
Outcome string `json:"assessment_outcome"`
ProposalAttempts *int `json:"proposal_attempts"`
ProposalRetries *int `json:"proposal_transient_retries"`
UsageComplete *bool `json:"proposal_usage_complete"`
AssessmentAttempts *int `json:"assessment_attempts"`
AssessmentRetries *int `json:"assessment_transient_retries"`
Outcome string `json:"assessment_outcome"`
CoordinationOutcome string `json:"coordination_outcome"`
ExhaustedOutcome string `json:"exhausted_outcome"`
GroupMembers int `json:"group_members"`
GroupAttempts int `json:"group_attempts"`
}
if err := json.Unmarshal(output.Bytes(), &got); err != nil {
t.Fatal(err)
}
if got.ProposalAttempts == nil || *got.ProposalAttempts != 2 || got.ProposalRetries == nil || *got.ProposalRetries != 1 ||
got.UsageComplete == nil || *got.UsageComplete || got.AssessmentAttempts == nil || *got.AssessmentAttempts != 1 ||
got.AssessmentRetries == nil || *got.AssessmentRetries != 0 || got.Outcome != "accepted" {
got.AssessmentRetries == nil || *got.AssessmentRetries != 0 || got.Outcome != "accepted" || got.CoordinationOutcome != "stopped" || got.ExhaustedOutcome != "exhausted" || got.GroupMembers != 3 || got.GroupAttempts != 4 {
t.Fatalf("unexpected observation summary: %+v", got)
}
}