86 lines
4.8 KiB
Go
86 lines
4.8 KiB
Go
package weknora
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestLiveDirectToolResultShapeBecomesStructuredReferences(t *testing.T) {
|
|
stream := "data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"get_document_info\",\"success\":true,\"data\":{\"total_docs\":1,\"documents\":[{\"knowledge_id\":\"doc-live\",\"title\":\"现场文档\",\"chunk_count\":8}]}}}\n\n" +
|
|
"data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"wiki_search\",\"success\":true,\"data\":{\"found_kbs\":{\"entity/cra\":[\"wiki-kb\"]}}}}\n\n" +
|
|
"data: {\"response_type\":\"answer\",\"content\":\"回答\",\"done\":true}\n\n"
|
|
|
|
result, err := parseSSE(strings.NewReader(stream))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.References) != 2 {
|
|
t.Fatalf("references=%+v", result.References)
|
|
}
|
|
if result.References[0].KnowledgeID != "doc-live" || result.References[1].ID != "wiki:wiki-kb:entity/cra" {
|
|
t.Fatalf("references=%+v", result.References)
|
|
}
|
|
}
|
|
|
|
func TestLiveFlattenedToolResultShapeBecomesStructuredReferences(t *testing.T) {
|
|
stream := "data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"knowledge_search\",\"success\":true,\"count\":1,\"results\":[{\"knowledge_id\":\"doc-flat\",\"knowledge_title\":\"现场文档\"}]}}\n\n" +
|
|
"data: {\"response_type\":\"answer\",\"content\":\"回答\",\"done\":true}\n\n"
|
|
|
|
result, err := parseSSE(strings.NewReader(stream))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.References) != 1 || result.References[0].KnowledgeID != "doc-flat" {
|
|
t.Fatalf("references=%+v", result.References)
|
|
}
|
|
}
|
|
|
|
func TestCanonicalReferencesReplaceSyntheticToolFallbacks(t *testing.T) {
|
|
stream := "data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"knowledge_search\",\"success\":true,\"data\":{\"count\":1,\"results\":[{\"knowledge_id\":\"doc-1\",\"knowledge_title\":\"标题\"}]}}}\n\n" +
|
|
"data: {\"response_type\":\"references\",\"knowledge_references\":[{\"id\":\"chunk-1\",\"knowledge_id\":\"doc-1\",\"content\":\"完整引用一\",\"score\":0.9},{\"id\":\"chunk-2\",\"knowledge_id\":\"doc-1\",\"content\":\"完整引用二\",\"score\":0.8}]}\n\n" +
|
|
"data: {\"response_type\":\"answer\",\"content\":\"回答\",\"done\":true}\n\n"
|
|
|
|
result, err := parseSSE(strings.NewReader(stream))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.References) != 2 || result.References[0].ID != "chunk-1" || result.References[1].ID != "chunk-2" {
|
|
t.Fatalf("canonical references were not preserved: %+v", result.References)
|
|
}
|
|
}
|
|
|
|
func TestSmartReasoningToolResultsBecomeStructuredReferences(t *testing.T) {
|
|
stream := "data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"knowledge_search\",\"result\":{\"success\":true,\"data\":{\"count\":2,\"results\":[{\"knowledge_id\":\"doc-1\",\"knowledge_title\":\"CRA介绍\"},{\"knowledge_id\":\"doc-2\",\"knowledge_title\":\"CRA手册\"}]}}}}\n\n" +
|
|
"data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"grep_chunks\",\"result\":{\"success\":true,\"data\":{\"document_count\":2,\"knowledge_results\":[{\"knowledge_id\":\"doc-2\",\"knowledge_title\":\"CRA手册\",\"chunk_hit_count\":3},{\"knowledge_id\":\"doc-3\",\"knowledge_title\":\"案例视频\",\"chunk_hit_count\":5}]}}}}\n\n" +
|
|
"data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"list_knowledge_chunks\",\"result\":{\"success\":true,\"data\":{\"knowledge_id\":\"doc-3\",\"knowledge_title\":\"案例视频\",\"fetched_chunks\":20}}}}\n\n" +
|
|
"data: {\"response_type\":\"answer\",\"content\":\"完整回答\",\"done\":true}\n\n"
|
|
|
|
result, err := parseSSE(strings.NewReader(stream))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.References) != 3 {
|
|
t.Fatalf("references=%+v", result.References)
|
|
}
|
|
for index, want := range []string{"doc-1", "doc-2", "doc-3"} {
|
|
if result.References[index].KnowledgeID != want {
|
|
t.Fatalf("references[%d]=%+v want knowledge %s", index, result.References[index], want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSmartReasoningEmptyOrFailedToolResultsRemainUncovered(t *testing.T) {
|
|
stream := "data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"knowledge_search\",\"result\":{\"success\":true,\"data\":{\"count\":0,\"results\":[]}}}}\n\n" +
|
|
"data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"grep_chunks\",\"result\":{\"success\":false,\"data\":{\"document_count\":2,\"knowledge_results\":[{\"knowledge_id\":\"must-not-count\",\"chunk_hit_count\":2}]}}}}\n\n" +
|
|
"data: {\"response_type\":\"tool_result\",\"data\":{\"tool_name\":\"list_knowledge_chunks\",\"result\":{\"success\":true,\"data\":{\"knowledge_id\":\"also-empty\",\"fetched_chunks\":0}}}}\n\n" +
|
|
"data: {\"response_type\":\"answer\",\"content\":\"回答\",\"done\":true}\n\n"
|
|
|
|
result, err := parseSSE(strings.NewReader(stream))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(result.References) != 0 {
|
|
t.Fatalf("empty/failed tools produced references: %+v", result.References)
|
|
}
|
|
}
|