feat(metadata): enhance metadata extraction with heuristic fallback support
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
)
|
||||
@@ -250,3 +251,93 @@ func TestExtractMetadataUsesReasoningContentWhenContentEmpty(t *testing.T) {
|
||||
t.Fatalf("metadata people = %#v, want [Hein]", metadata.People)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractMetadataFallsBackToHeuristicsWhenModelsFail(t *testing.T) {
|
||||
var calls atomic.Int32
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
_ = calls.Add(1)
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"choices": []map[string]any{
|
||||
{"message": map[string]any{"content": "not json"}},
|
||||
},
|
||||
})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := New(Config{
|
||||
Name: "test",
|
||||
BaseURL: server.URL,
|
||||
APIKey: "secret",
|
||||
MetadataModel: "primary",
|
||||
FallbackMetadataModel: "secondary",
|
||||
HTTPClient: server.Client(),
|
||||
Log: discardLogger(),
|
||||
})
|
||||
|
||||
input := "Personal profile - Hein (Warkanum):\n- Born: 23 May 1989\n- Wife: Cindy, born 16 November 1994"
|
||||
metadata, err := client.ExtractMetadata(context.Background(), input)
|
||||
if err != nil {
|
||||
t.Fatalf("ExtractMetadata() error = %v", err)
|
||||
}
|
||||
if calls.Load() != 2 {
|
||||
t.Fatalf("call count = %d, want 2", calls.Load())
|
||||
}
|
||||
if metadata.Type != "person_note" {
|
||||
t.Fatalf("metadata type = %q, want person_note", metadata.Type)
|
||||
}
|
||||
if len(metadata.DatesMentioned) < 2 {
|
||||
t.Fatalf("metadata dates = %#v, want extracted dates", metadata.DatesMentioned)
|
||||
}
|
||||
if len(metadata.People) == 0 || !strings.EqualFold(metadata.People[0], "Cindy") {
|
||||
t.Fatalf("metadata people = %#v, want Cindy", metadata.People)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractMetadataRetriesEmptyResponse(t *testing.T) {
|
||||
var calls atomic.Int32
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
call := calls.Add(1)
|
||||
var req chatCompletionsRequest
|
||||
_ = json.NewDecoder(r.Body).Decode(&req)
|
||||
|
||||
if req.Stream == nil || *req.Stream {
|
||||
t.Fatalf("expected stream=false, got %#v", req.Stream)
|
||||
}
|
||||
|
||||
if call == 1 {
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"choices": []map[string]any{
|
||||
{"message": map[string]any{"content": ""}},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{
|
||||
"choices": []map[string]any{
|
||||
{"message": map[string]any{"content": "{\"people\":[],\"action_items\":[],\"dates_mentioned\":[],\"topics\":[\"mcp\"],\"type\":\"observation\",\"source\":\"mcp\"}"}},
|
||||
},
|
||||
})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
client := New(Config{
|
||||
Name: "test",
|
||||
BaseURL: server.URL,
|
||||
APIKey: "secret",
|
||||
MetadataModel: "meta-model",
|
||||
HTTPClient: server.Client(),
|
||||
Log: discardLogger(),
|
||||
})
|
||||
|
||||
metadata, err := client.ExtractMetadata(context.Background(), "hello")
|
||||
if err != nil {
|
||||
t.Fatalf("ExtractMetadata() error = %v", err)
|
||||
}
|
||||
if calls.Load() < 2 {
|
||||
t.Fatalf("call count = %d, want >= 2", calls.Load())
|
||||
}
|
||||
if metadata.Type != "observation" {
|
||||
t.Fatalf("metadata type = %q, want observation", metadata.Type)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user