Preserve proposal outcomes and classify filtered proposals
This commit is contained in:
@@ -5,6 +5,7 @@ package proposal_generation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -13,11 +14,11 @@ import (
|
||||
"gitea.maximumdirect.net/eric/audita/internal/core/schema"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/contracts"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/llm"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/outcomes"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/proposals"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/responseschema"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/stagename"
|
||||
"gitea.maximumdirect.net/eric/audita/internal/framework/structuredoutput"
|
||||
stagewarnings "gitea.maximumdirect.net/eric/audita/internal/framework/warnings"
|
||||
)
|
||||
|
||||
// InteractionDiagnosticsWriter writes machine-readable prompt/response artifacts.
|
||||
@@ -70,7 +71,7 @@ type Request struct {
|
||||
type Result struct {
|
||||
Corrections []proposals.CorrectionProposal `json:"corrections"`
|
||||
Enriched []proposals.EnrichedCorrectionProposal `json:"enriched"`
|
||||
Warnings []stagewarnings.StageWarning `json:"warnings,omitempty"`
|
||||
Operations []outcomes.Operation `json:"operations,omitempty"`
|
||||
Artifacts InteractionArtifacts `json:"artifacts,omitempty"`
|
||||
}
|
||||
|
||||
@@ -121,6 +122,17 @@ func GenerateCandidates(ctx context.Context, req Request) (Result, error) {
|
||||
Variables: req.Variables, Schema: responseschema.CorrectionSetKey,
|
||||
Context: structuredoutput.DiagnosticContext{Role: "proposal", ModuleKey: req.ModuleKey, ModuleInstance: req.ModuleInstance, SectionIndex: sectionIndexPtr(req.Section)},
|
||||
}, &response)
|
||||
sectionIndex := 0
|
||||
if req.Section != nil {
|
||||
sectionIndex = req.Section.Index
|
||||
}
|
||||
operation := outcomes.Operation{
|
||||
Reference: outcomes.Reference{
|
||||
ModuleKey: req.ModuleKey, ModuleInstance: req.ModuleInstance,
|
||||
SectionIndex: sectionIndex, Kind: outcomes.OperationProposal,
|
||||
},
|
||||
Counts: completion.Execution,
|
||||
}
|
||||
|
||||
requestMetadata := map[string]any{
|
||||
"module_key": req.ModuleKey,
|
||||
@@ -143,13 +155,25 @@ func GenerateCandidates(ctx context.Context, req Request) (Result, error) {
|
||||
}
|
||||
|
||||
if callErr != nil {
|
||||
if structuredoutput.IsMalformedError(callErr) {
|
||||
return Result{
|
||||
Warnings: []stagewarnings.StageWarning{newMalformedProposalWarning(req.Section, artifacts, callErr)},
|
||||
Artifacts: artifacts,
|
||||
}, nil
|
||||
var failure *structuredoutput.Failure
|
||||
if errors.As(callErr, &failure) {
|
||||
operation.FailureReason = failure.Reason
|
||||
}
|
||||
return Result{}, fmt.Errorf("proposal generation completion failed: %w", callErr)
|
||||
if operation.FailureReason == "" {
|
||||
operation.FailureReason = outcomes.ReasonInternalFailure
|
||||
}
|
||||
result := Result{Operations: []outcomes.Operation{operation}, Artifacts: artifacts}
|
||||
if structuredoutput.IsRecoverable(callErr) && failure != nil && failure.Reason != "" {
|
||||
return result, nil
|
||||
}
|
||||
return result, fmt.Errorf("proposal generation completion failed: %w", callErr)
|
||||
}
|
||||
operation.Succeeded = true
|
||||
if completion.Execution.StructuralRepairs > 0 {
|
||||
operation.RecoveryReasons = append(operation.RecoveryReasons, outcomes.RecoveryOutputRepaired)
|
||||
}
|
||||
if completion.Execution.TransientRetries > 0 {
|
||||
operation.RecoveryReasons = append(operation.RecoveryReasons, outcomes.RecoveryServiceRecovered)
|
||||
}
|
||||
|
||||
corrections := make([]proposals.CorrectionProposal, 0, len(response.Corrections))
|
||||
@@ -181,7 +205,7 @@ func GenerateCandidates(ctx context.Context, req Request) (Result, error) {
|
||||
return Result{
|
||||
Corrections: corrections,
|
||||
Enriched: enriched,
|
||||
Warnings: nil,
|
||||
Operations: []outcomes.Operation{operation},
|
||||
Artifacts: artifacts,
|
||||
}, nil
|
||||
}
|
||||
@@ -193,27 +217,6 @@ func errPayload(err error) any {
|
||||
return map[string]any{"error": err.Error()}
|
||||
}
|
||||
|
||||
func newMalformedProposalWarning(section *contracts.SectionMetadata, artifacts InteractionArtifacts, err error) stagewarnings.StageWarning {
|
||||
warning := stagewarnings.StageWarning{
|
||||
Scope: stagewarnings.ScopeProposalGeneration,
|
||||
ReasonCode: "proposal_response_malformed",
|
||||
Message: strings.TrimSpace(err.Error()),
|
||||
DiagnosticArtifactPath: diagnosticArtifactPath(artifacts),
|
||||
}
|
||||
if section != nil {
|
||||
sectionIndex := section.Index
|
||||
warning.SectionIndex = §ionIndex
|
||||
}
|
||||
return warning
|
||||
}
|
||||
|
||||
func diagnosticArtifactPath(artifacts InteractionArtifacts) string {
|
||||
if artifacts.ErrorPayloadPath != "" {
|
||||
return artifacts.ErrorPayloadPath
|
||||
}
|
||||
return artifacts.ResponsePayloadPath
|
||||
}
|
||||
|
||||
func sectionIndexPtr(section *contracts.SectionMetadata) *int {
|
||||
if section == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user