138 lines
5.6 KiB
Go
138 lines
5.6 KiB
Go
package proposal_generation
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/config"
|
|
"gitea.maximumdirect.net/eric/audita/internal/core/schema"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/contracts"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/outcomes"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/proposals"
|
|
"gitea.maximumdirect.net/eric/audita/internal/framework/structuredoutput"
|
|
"gitea.maximumdirect.net/eric/audita/internal/prompts"
|
|
)
|
|
|
|
func TestExecuteModuleProposalBuildsMessagesFromSectionAndDescription(t *testing.T) {
|
|
client := &fakeStructuredClient{
|
|
responses: []StructuredCorrectionSet{
|
|
{Corrections: []StructuredCorrectionProposal{{TargetSegmentID: 1, OriginalText: "teh", CorrectedText: "the", Confidence: 0.9}}},
|
|
},
|
|
}
|
|
section := contracts.SectionMetadata{Index: 7}
|
|
cfg := config.Config{}
|
|
cfg.Context.Description = "Hearing transcript with role titles."
|
|
transcript := &schema.Transcript{Segments: []schema.Segment{{ID: 1, Speaker: "A", Start: 0, End: 1, Text: "teh"}}}
|
|
glossary := &schema.Glossary{Entries: []schema.GlossaryEntry{{Name: "X"}}}
|
|
|
|
var gotSectionIndex int
|
|
var gotDescription string
|
|
var gotTranscript *schema.Transcript
|
|
var gotGlossary *schema.Glossary
|
|
|
|
out, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{
|
|
ProposalRequest: contracts.ProposalRequest{
|
|
ExecutionContext: contracts.ExecutionContext{
|
|
Config: &cfg,
|
|
WorkingTranscript: transcript,
|
|
Glossary: glossary,
|
|
Section: §ion,
|
|
},
|
|
RunSpec: contracts.ModuleRunSpec{
|
|
ModuleKey: "grammar",
|
|
InstanceName: "grammar",
|
|
ReplacementPolicy: proposals.ReplacementPolicyRequireUnique,
|
|
},
|
|
LLMClient: client,
|
|
},
|
|
PromptID: prompts.PromptIDModuleGrammarProposal,
|
|
BuildVariables: func(inTranscript *schema.Transcript, inGlossary *schema.Glossary, sectionIndex int, transcriptDescription string) (map[string]string, error) {
|
|
gotSectionIndex = sectionIndex
|
|
gotDescription = transcriptDescription
|
|
gotTranscript = inTranscript
|
|
gotGlossary = inGlossary
|
|
return map[string]string{"SectionJSON": "[]"}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("ExecuteModuleProposal error: %v", err)
|
|
}
|
|
if gotSectionIndex != 7 {
|
|
t.Fatalf("section index: got=%d want=%d", gotSectionIndex, 7)
|
|
}
|
|
if gotDescription != cfg.Context.Description {
|
|
t.Fatalf("transcript description: got=%q want=%q", gotDescription, cfg.Context.Description)
|
|
}
|
|
if gotTranscript != transcript {
|
|
t.Fatalf("expected shared transcript pointer")
|
|
}
|
|
if gotGlossary != glossary {
|
|
t.Fatalf("expected shared glossary pointer")
|
|
}
|
|
if len(client.calls) != 1 || client.calls[0].PromptID != prompts.PromptIDModuleGrammarProposal || client.calls[0].Context.SectionIndex == nil || *client.calls[0].Context.SectionIndex != 7 {
|
|
t.Fatalf("unexpected stage name calls: %+v", client.calls)
|
|
}
|
|
if len(out.Proposals) != 1 || out.Proposals[0].CorrectedText != "the" {
|
|
t.Fatalf("unexpected proposals: %+v", out)
|
|
}
|
|
}
|
|
|
|
func TestExecuteModuleProposalValidatesInputs(t *testing.T) {
|
|
if _, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{}); err == nil {
|
|
t.Fatalf("expected missing message builder error")
|
|
}
|
|
|
|
_, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{
|
|
BuildVariables: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) (map[string]string, error) {
|
|
return nil, nil
|
|
},
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected empty prompt ID error")
|
|
}
|
|
|
|
_, err = ExecuteModuleProposal(context.Background(), ModuleProposalRequest{
|
|
PromptID: "missing.prompt.id",
|
|
BuildVariables: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) (map[string]string, error) {
|
|
return map[string]string{"SectionJSON": "[]"}, nil
|
|
},
|
|
})
|
|
if err == nil {
|
|
t.Fatalf("expected unknown prompt ID error")
|
|
}
|
|
}
|
|
|
|
func TestExecuteModuleProposalPropagatesBuilderError(t *testing.T) {
|
|
wantErr := errors.New("builder failed")
|
|
_, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{
|
|
PromptID: prompts.PromptIDModuleGlossaryProposal,
|
|
BuildVariables: func(transcript *schema.Transcript, glossary *schema.Glossary, sectionIndex int, transcriptDescription string) (map[string]string, error) {
|
|
return nil, wantErr
|
|
},
|
|
})
|
|
if !errors.Is(err, wantErr) {
|
|
t.Fatalf("expected builder error, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteModuleProposalPreservesFatalOperation(t *testing.T) {
|
|
cause := errors.New("missing embedded asset")
|
|
client := &fakeStructuredClient{err: &structuredoutput.Failure{Class: structuredoutput.FailureFatal, Reason: outcomes.ReasonSetupFailure, Message: "model setup failed", Cause: cause}}
|
|
section := contracts.SectionMetadata{Index: 4}
|
|
result, err := ExecuteModuleProposal(context.Background(), ModuleProposalRequest{
|
|
ProposalRequest: contracts.ProposalRequest{
|
|
ExecutionContext: contracts.ExecutionContext{Section: §ion},
|
|
RunSpec: contracts.ModuleRunSpec{ModuleKey: "grammar", InstanceName: "grammar_2", ReplacementPolicy: proposals.ReplacementPolicyRequireUnique},
|
|
LLMClient: client,
|
|
},
|
|
PromptID: prompts.PromptIDModuleGrammarProposal,
|
|
BuildVariables: func(*schema.Transcript, *schema.Glossary, int, string) (map[string]string, error) {
|
|
return map[string]string{"SectionJSON": "[]"}, nil
|
|
},
|
|
})
|
|
if !errors.Is(err, cause) || len(result.Operations) != 1 || result.Operations[0].Reference.ModuleInstance != "grammar_2" || result.Operations[0].Reference.SectionIndex != 4 {
|
|
t.Fatalf("fatal operation lost: %+v, %v", result, err)
|
|
}
|
|
}
|