Ground item occurrences by canonical names
This commit is contained in:
@@ -12,7 +12,7 @@ import (
|
||||
func TestExtractGroundsOccurrencesInRequiredRegistry(t *testing.T) {
|
||||
id := itemidentity.DeriveID("Torch")
|
||||
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{
|
||||
{ItemID: id, Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
{Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
}}}
|
||||
req := extractionRequest()
|
||||
req.References = itemRegistryReferences(t)
|
||||
@@ -24,55 +24,38 @@ func TestExtractGroundsOccurrencesInRequiredRegistry(t *testing.T) {
|
||||
t.Fatalf("occurrences = %#v", result.Value.Occurrences)
|
||||
}
|
||||
input := client.requests[0].Inputs[ItemRegistryReferenceSlot]
|
||||
if input.Name != ItemRegistryReferenceSlot || string(input.Content) == "" {
|
||||
t.Fatalf("registry prompt input = %#v", input)
|
||||
if input.Name != ItemRegistryReferenceSlot || string(input.Content) != `{"items":[{"name":"Torch"}]}` || strings.Contains(string(input.Content), "item:sha256:") {
|
||||
t.Fatalf("registry prompt input = %#v, want names-only projection", input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractRejectsInvalidRegistryPairs(t *testing.T) {
|
||||
id := itemidentity.DeriveID("Torch")
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
occurrence itemOccurrenceResponse
|
||||
wantError string
|
||||
}{
|
||||
{
|
||||
name: "unknown item ID",
|
||||
occurrence: itemOccurrenceResponse{ItemID: "unknown", Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
wantError: "occurrences[0].item_id is not in the item registry",
|
||||
},
|
||||
{
|
||||
name: "mismatched item name",
|
||||
occurrence: itemOccurrenceResponse{ItemID: id, Name: "Lantern", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
wantError: "occurrences[0].name does not match item_id",
|
||||
},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{test.occurrence}}}
|
||||
req := extractionRequest()
|
||||
req.References = itemRegistryReferences(t)
|
||||
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
||||
if err == nil || !strings.Contains(err.Error(), test.wantError) {
|
||||
t.Fatalf("Extract() error = %v, want %q", err, test.wantError)
|
||||
}
|
||||
if len(result.Value.Occurrences) != 0 {
|
||||
t.Fatalf("Extract() returned partial occurrences: %#v", result.Value.Occurrences)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractRejectsResponseWithInvalidRegistryPairAfterValidOccurrence(t *testing.T) {
|
||||
func TestExtractCanonicalizesComparisonEquivalentNames(t *testing.T) {
|
||||
id := itemidentity.DeriveID("Torch")
|
||||
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{
|
||||
{ItemID: id, Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
{ItemID: "unknown", Name: "Unknown", Kind: "lost", From: "party", SourceRefs: responseRefs(2, 2)},
|
||||
{Name: " tORCH ", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
}}}
|
||||
req := extractionRequest()
|
||||
req.References = itemRegistryReferences(t)
|
||||
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
||||
if err == nil || !strings.Contains(err.Error(), "occurrences[1].item_id") {
|
||||
t.Fatalf("Extract() error = %v, want occurrence index and item ID", err)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
occurrence := result.Value.Occurrences[0]
|
||||
if occurrence.ItemID != id || occurrence.Name != "Torch" {
|
||||
t.Fatalf("canonical occurrence = %#v", occurrence)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractRejectsUnknownNameAfterValidOccurrence(t *testing.T) {
|
||||
client := &fakeItemOccurrencesLLMClient{response: extractionResponse{Occurrences: []itemOccurrenceResponse{
|
||||
{Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)},
|
||||
{Name: "Unknown", Kind: "lost", From: "party", SourceRefs: responseRefs(2, 2)},
|
||||
}}}
|
||||
req := extractionRequest()
|
||||
req.References = itemRegistryReferences(t)
|
||||
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
||||
if err == nil || !strings.Contains(err.Error(), "occurrences[1].name is not in the item registry") {
|
||||
t.Fatalf("Extract() error = %v, want occurrence index and unknown name", err)
|
||||
}
|
||||
if len(result.Value.Occurrences) != 0 {
|
||||
t.Fatalf("Extract() returned partial occurrences: %#v", result.Value.Occurrences)
|
||||
@@ -86,9 +69,36 @@ func TestExtractRequiresItemRegistry(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractAcceptsOnlyEmptyResponseForEmptyRegistry(t *testing.T) {
|
||||
references := emptyItemRegistryReferences(t)
|
||||
for _, test := range []struct {
|
||||
name string
|
||||
response extractionResponse
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "empty", response: extractionResponse{Occurrences: []itemOccurrenceResponse{}}},
|
||||
{name: "selection", response: extractionResponse{Occurrences: []itemOccurrenceResponse{{Name: "Torch", Kind: "lost", From: "party", SourceRefs: responseRefs(1, 1)}}}, wantErr: true},
|
||||
} {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
client := &fakeItemOccurrencesLLMClient{response: test.response}
|
||||
req := extractionRequest()
|
||||
req.References = references
|
||||
result, err := newExtractor(t, client, references).Extract(context.Background(), req)
|
||||
if test.wantErr {
|
||||
if err == nil || !strings.Contains(err.Error(), "name is not in the item registry") || len(result.Value.Occurrences) != 0 {
|
||||
t.Fatalf("Extract() = %#v, %v; want no accepted occurrences", result, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil || result.Value.Occurrences == nil || len(result.Value.Occurrences) != 0 {
|
||||
t.Fatalf("Extract() = %#v, %v; want present empty occurrences", result, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractPreservesNullableFields(t *testing.T) {
|
||||
id := itemidentity.DeriveID("Torch")
|
||||
client := &fakeItemOccurrencesLLMClient{content: []byte(`{"occurrences":[{"item_id":"` + id + `","name":"Torch","kind":"discovered","quantity":null,"from":null,"to":null,"source_refs":[{"start_segment":1,"end_segment":1}]}]}`)}
|
||||
client := &fakeItemOccurrencesLLMClient{content: []byte(`{"occurrences":[{"name":"Torch","kind":"discovered","quantity":null,"from":null,"to":null,"source_refs":[{"start_segment":1,"end_segment":1}]}]}`)}
|
||||
req := extractionRequest()
|
||||
req.References = itemRegistryReferences(t)
|
||||
result, err := newExtractor(t, client, req.References).Extract(context.Background(), req)
|
||||
|
||||
Reference in New Issue
Block a user