Canonicalize chunk units before extraction
This commit is contained in:
@@ -341,6 +341,106 @@ func TestRunAllowsPartialCoverageAndOverlappingChunks(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunCanonicalizesChunkUnitsBeforeExtraction(t *testing.T) {
|
||||
modules := defaultRunnerModules()
|
||||
modules.input.doc = sourceDocumentWithUnitMetadata()
|
||||
modules.chunker.chunks = []contracts.SourceChunk{
|
||||
{
|
||||
ID: "chunk-0",
|
||||
SourceID: "source-1",
|
||||
Index: 0,
|
||||
Units: []source.SourceUnit{
|
||||
{
|
||||
ID: "u1",
|
||||
Kind: "mutated-kind",
|
||||
Text: "mutated text",
|
||||
Metadata: map[string]any{
|
||||
"speaker": "chunker-speaker",
|
||||
"note": "chunker note",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
output, err := New(newRunnerRegistries(t, modules)).Run(context.Background(), RunInput{Pipeline: resolvedPipeline()})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
if len(output.Approved) != 1 {
|
||||
t.Fatalf("len(Approved) = %d, want 1", len(output.Approved))
|
||||
}
|
||||
|
||||
extractor := modules.extractors["extract-alpha"]
|
||||
if len(extractor.requests) != 1 {
|
||||
t.Fatalf("len(extractor requests) = %d, want 1", len(extractor.requests))
|
||||
}
|
||||
chunk := extractor.requests[0].Chunk
|
||||
if chunk == nil {
|
||||
t.Fatal("extractor chunk = nil, want canonical chunk")
|
||||
}
|
||||
if chunk.Units[0].ID != "u1" || chunk.Units[0].Kind != "source-kind" || chunk.Units[0].Text != "source text" {
|
||||
t.Fatalf("chunk unit = %#v, want source document unit values", chunk.Units[0])
|
||||
}
|
||||
if got := chunk.Units[0].Metadata["speaker"]; got != "source-speaker" {
|
||||
t.Fatalf("chunk unit metadata = %#v, want source document metadata", chunk.Units[0].Metadata)
|
||||
}
|
||||
if got := chunk.Units[0].Metadata["topic"]; got != "source-topic" {
|
||||
t.Fatalf("chunk unit metadata = %#v, want cloned source document metadata", chunk.Units[0].Metadata)
|
||||
}
|
||||
|
||||
modules.input.doc.Units[0].Kind = "changed-kind"
|
||||
modules.input.doc.Units[0].Text = "changed text"
|
||||
modules.input.doc.Units[0].Metadata["speaker"] = "changed-speaker"
|
||||
if chunk.Units[0].Kind != "source-kind" || chunk.Units[0].Text != "source text" || chunk.Units[0].Metadata["speaker"] != "source-speaker" {
|
||||
t.Fatalf("chunk unit changed after source mutation: %#v", chunk.Units[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunPreservesChunkMetadataDuringCanonicalization(t *testing.T) {
|
||||
modules := defaultRunnerModules()
|
||||
modules.chunker.chunks = []contracts.SourceChunk{
|
||||
{
|
||||
ID: "chunk-0",
|
||||
SourceID: "source-1",
|
||||
Index: 0,
|
||||
Units: []source.SourceUnit{
|
||||
unitWithID("u1"),
|
||||
},
|
||||
Metadata: map[string]any{
|
||||
"scene_title": "Original scene",
|
||||
"boundary_note": "Chunker note",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := New(newRunnerRegistries(t, modules)).Run(context.Background(), RunInput{Pipeline: resolvedPipeline()})
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v, want nil", err)
|
||||
}
|
||||
|
||||
extractor := modules.extractors["extract-alpha"]
|
||||
if len(extractor.requests) != 1 || extractor.requests[0].Chunk == nil {
|
||||
t.Fatalf("extractor requests = %#v, want one canonical chunk", extractor.requests)
|
||||
}
|
||||
if got := extractor.requests[0].Chunk.Metadata["scene_title"]; got != "Original scene" {
|
||||
t.Fatalf("chunk metadata = %#v, want chunker metadata", extractor.requests[0].Chunk.Metadata)
|
||||
}
|
||||
if got := extractor.requests[0].Chunk.Metadata["boundary_note"]; got != "Chunker note" {
|
||||
t.Fatalf("chunk metadata = %#v, want chunker metadata", extractor.requests[0].Chunk.Metadata)
|
||||
}
|
||||
|
||||
modules.chunker.chunks[0].Metadata["scene_title"] = "changed"
|
||||
modules.chunker.chunks[0].Metadata["boundary_note"] = "changed"
|
||||
if got := extractor.requests[0].Chunk.Metadata["scene_title"]; got != "Original scene" {
|
||||
t.Fatalf("chunk metadata aliased to chunker map: %#v", extractor.requests[0].Chunk.Metadata)
|
||||
}
|
||||
if got := extractor.requests[0].Chunk.Metadata["boundary_note"]; got != "Chunker note" {
|
||||
t.Fatalf("chunk metadata aliased to chunker map: %#v", extractor.requests[0].Chunk.Metadata)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunExecutesChunksAndPassesChunkAndLLMClient(t *testing.T) {
|
||||
modules := defaultRunnerModules()
|
||||
llmClient := fakeLLMClient{}
|
||||
@@ -1334,6 +1434,34 @@ func validSourceDocument() *source.SourceDocument {
|
||||
}
|
||||
}
|
||||
|
||||
func sourceDocumentWithUnitMetadata() *source.SourceDocument {
|
||||
return &source.SourceDocument{
|
||||
ID: "source-1",
|
||||
Kind: "document",
|
||||
Format: "text/plain",
|
||||
Digest: "sha256:source",
|
||||
Units: []source.SourceUnit{
|
||||
{
|
||||
ID: "u1",
|
||||
Kind: "source-kind",
|
||||
Text: "source text",
|
||||
Metadata: map[string]any{
|
||||
"speaker": "source-speaker",
|
||||
"topic": "source-topic",
|
||||
},
|
||||
},
|
||||
{
|
||||
ID: "u2",
|
||||
Kind: "source-kind",
|
||||
Text: "second source text",
|
||||
Metadata: map[string]any{
|
||||
"speaker": "source-speaker-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func sourceChunkWithID(id string, index int) contracts.SourceChunk {
|
||||
return contracts.SourceChunk{
|
||||
ID: id,
|
||||
|
||||
Reference in New Issue
Block a user