feat: 分析响应JSON解析
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// parseAnalysisResponse 解析分析模型输出的判定 JSON。
|
||||
// 容错:剥 ```json 代码块/首尾空白/多余文字,取首个 {...}。
|
||||
func parseAnalysisResponse(content string) (retryable bool, reason string, err error) {
|
||||
s := strings.TrimSpace(content)
|
||||
s = strings.TrimPrefix(s, "```json")
|
||||
s = strings.TrimSuffix(s, "```")
|
||||
s = strings.TrimSpace(s)
|
||||
start, end := strings.IndexByte(s, '{'), strings.LastIndexByte(s, '}')
|
||||
if start < 0 || end <= start {
|
||||
return false, "", fmt.Errorf("分析响应中未找到JSON对象: %q", content)
|
||||
}
|
||||
var obj struct {
|
||||
Retryable bool `json:"retryable"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
if err = json.Unmarshal([]byte(s[start:end+1]), &obj); err != nil {
|
||||
return false, "", fmt.Errorf("分析响应JSON解析失败: %v", err)
|
||||
}
|
||||
return obj.Retryable, obj.Reason, nil
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package service
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseAnalysisResponse(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
in string
|
||||
wantRetry bool
|
||||
wantErr bool
|
||||
}{
|
||||
{"纯JSON", `{"retryable": true, "reason": "限流"}`, true, false},
|
||||
{"带json代码块", "```json\n{\"retryable\": false, \"reason\": \"参数错误\"}\n```", false, false},
|
||||
{"带前后文字", `分析结果: {"retryable": true, "reason": "瞬时故障"} 完毕`, true, false},
|
||||
{"非法响应", `抱歉,我无法分析`, false, true},
|
||||
{"空串", ``, false, true},
|
||||
}
|
||||
for _, c := range cases {
|
||||
retry, _, err := parseAnalysisResponse(c.in)
|
||||
if c.wantErr {
|
||||
if err == nil {
|
||||
t.Fatalf("[%s] 期望错误, got retry=%v", c.name, retry)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("[%s] 不应报错: %v", c.name, err)
|
||||
}
|
||||
if retry != c.wantRetry {
|
||||
t.Fatalf("[%s] retryable = %v, want %v", c.name, retry, c.wantRetry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseAnalysisResponseReason(t *testing.T) {
|
||||
_, reason, err := parseAnalysisResponse(`{"retryable": true, "reason": "服务过载"}`)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if reason != "服务过载" {
|
||||
t.Fatalf("reason = %q, want 服务过载", reason)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user