Implement classification redesign
This commit is contained in:
@@ -190,7 +190,7 @@ func mockClassifier(t *testing.T, a *App, inspect ...func(*http.Request)) {
|
||||
return
|
||||
}
|
||||
var prompt struct {
|
||||
Categories []struct{ ID, Name string } `json:"categories"`
|
||||
Categories []struct{ ID, Path string } `json:"categories"`
|
||||
}
|
||||
if len(req.Messages) != 2 || json.Unmarshal([]byte(req.Messages[1].Content), &prompt) != nil {
|
||||
w.WriteHeader(400)
|
||||
@@ -198,11 +198,11 @@ func mockClassifier(t *testing.T, a *App, inspect ...func(*http.Request)) {
|
||||
}
|
||||
category := ""
|
||||
for _, c := range prompt.Categories {
|
||||
if strings.Contains(strings.ToLower(c.Name), "groceries") {
|
||||
if strings.Contains(strings.ToLower(c.Path), "groceries") {
|
||||
category = c.ID
|
||||
}
|
||||
}
|
||||
content, _ := json.Marshal(map[string]any{"merchant_id": nil, "new_merchant": "REWE", "category_id": category, "tag_ids": []string{}})
|
||||
content, _ := json.Marshal(map[string]any{"merchant_id": nil, "new_merchant": "REWE", "category_id": category, "tag_ids": []string{}, "confidence": "high"})
|
||||
json.NewEncoder(w).Encode(map[string]any{"choices": []any{map[string]any{"finish_reason": "stop", "message": map[string]any{"content": string(content)}}}})
|
||||
}))
|
||||
t.Cleanup(mock.Close)
|
||||
@@ -289,3 +289,46 @@ func TestStalePreviewCannotOverwriteManualCorrection(t *testing.T) {
|
||||
t.Fatal("stale apply partially changed records")
|
||||
}
|
||||
}
|
||||
func TestTaxonomyProposalApprovalMintsOnlyApprovedEntries(t *testing.T) {
|
||||
a, s := testApp(t)
|
||||
s = seed(t, a, s)
|
||||
provider := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
content := `{"categories":[{"name":"Food","parent":"","kind":"expense","hint":"Food purchases","because":["REWE"]},{"name":"Dining","parent":"Food","kind":"expense","hint":"Restaurants","because":["EDEKA"]}],"tags":[{"name":"Recurring","hint":"Repeats regularly"}],"merchants":[{"name":"REWE","aliases":["REWE"]}]}`
|
||||
json.NewEncoder(w).Encode(map[string]any{"choices": []any{map[string]any{
|
||||
"finish_reason": "stop",
|
||||
"message": map[string]any{"content": content},
|
||||
}}})
|
||||
}))
|
||||
defer provider.Close()
|
||||
a.classifier = classification.Client{APIKey: "test", Model: "test/model", BaseURL: provider.URL}
|
||||
preview, err := a.ProposeTaxonomy(context.Background(), TaxonomyProposalRequest{
|
||||
Revision: s.Revision,
|
||||
Model: "test/model",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(preview.Sample) != 2 || len(preview.Proposal.Categories) != 2 {
|
||||
t.Fatalf("unexpected taxonomy preview: %+v", preview)
|
||||
}
|
||||
approved := classification.TaxonomyProposal{
|
||||
Categories: []classification.ProposedCategory{
|
||||
preview.Proposal.Categories[1],
|
||||
},
|
||||
}
|
||||
applied, err := a.ApplyTaxonomy(context.Background(), preview.ID, preview.Revision, approved)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
foundFood, foundDining := false, false
|
||||
for _, category := range applied.Data.Categories {
|
||||
foundFood = foundFood || category.Name == "Food"
|
||||
foundDining = foundDining || category.Name == "Dining"
|
||||
}
|
||||
if !foundFood || !foundDining {
|
||||
t.Fatalf("approved child did not bring its parent: %+v", applied.Data.Categories)
|
||||
}
|
||||
if len(applied.Data.Tags) != len(s.Data.Tags) || len(applied.Data.Merchants) != len(s.Data.Merchants) {
|
||||
t.Fatal("unapproved taxonomy entries were written")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user