Skip to content

Commit 3456989

Browse files
authored
Compatible with the 2023-07-01-preview API interface of Azure Openai, when content interception is triggered, the error message will contain innererror (#460)
* Compatible with Azure Openai's 2023-07-01-preview version API interface about the error information returned by the intercepted interface * Compatible with the 2023-07-01-preview API interface of Azure Openai, when content interception is triggered, the error message will contain innererror.InnerError struct is only valid for Azure OpenAI Service.
1 parent 71a2493 commit 3456989

File tree

2 files changed

+98
-5
lines changed

2 files changed

+98
-5
lines changed

error.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,20 @@ import (
77
)
88

99
// APIError provides error information returned by the OpenAI API.
10+
// InnerError struct is only valid for Azure OpenAI Service.
1011
type APIError struct {
11-
Code any `json:"code,omitempty"`
12-
Message string `json:"message"`
13-
Param *string `json:"param,omitempty"`
14-
Type string `json:"type"`
15-
HTTPStatusCode int `json:"-"`
12+
Code any `json:"code,omitempty"`
13+
Message string `json:"message"`
14+
Param *string `json:"param,omitempty"`
15+
Type string `json:"type"`
16+
HTTPStatusCode int `json:"-"`
17+
InnerError *InnerError `json:"innererror,omitempty"`
18+
}
19+
20+
// InnerError Azure Content filtering. Only valid for Azure OpenAI Service.
21+
type InnerError struct {
22+
Code string `json:"code,omitempty"`
23+
ContentFilterResults ContentFilterResults `json:"content_filter_result,omitempty"`
1624
}
1725

1826
// RequestError provides informations about generic request errors.
@@ -61,6 +69,13 @@ func (e *APIError) UnmarshalJSON(data []byte) (err error) {
6169
}
6270
}
6371

72+
if _, ok := rawMap["innererror"]; ok {
73+
err = json.Unmarshal(rawMap["innererror"], &e.InnerError)
74+
if err != nil {
75+
return
76+
}
77+
}
78+
6479
// optional fields
6580
if _, ok := rawMap["param"]; ok {
6681
err = json.Unmarshal(rawMap["param"], &e.Param)

error_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package openai_test
33
import (
44
"errors"
55
"net/http"
6+
"reflect"
67
"testing"
78

89
. "github.com/sashabaranov/go-openai"
@@ -57,6 +58,77 @@ func TestAPIErrorUnmarshalJSON(t *testing.T) {
5758
assertAPIErrorMessage(t, apiErr, "")
5859
},
5960
},
61+
{
62+
name: "parse succeeds when the innerError is not exists (Azure Openai)",
63+
response: `{
64+
"message": "test message",
65+
"type": null,
66+
"param": "prompt",
67+
"code": "content_filter",
68+
"status": 400,
69+
"innererror": {
70+
"code": "ResponsibleAIPolicyViolation",
71+
"content_filter_result": {
72+
"hate": {
73+
"filtered": false,
74+
"severity": "safe"
75+
},
76+
"self_harm": {
77+
"filtered": false,
78+
"severity": "safe"
79+
},
80+
"sexual": {
81+
"filtered": true,
82+
"severity": "medium"
83+
},
84+
"violence": {
85+
"filtered": false,
86+
"severity": "safe"
87+
}
88+
}
89+
}
90+
}`,
91+
hasError: false,
92+
checkFunc: func(t *testing.T, apiErr APIError) {
93+
assertAPIErrorInnerError(t, apiErr, &InnerError{
94+
Code: "ResponsibleAIPolicyViolation",
95+
ContentFilterResults: ContentFilterResults{
96+
Hate: Hate{
97+
Filtered: false,
98+
Severity: "safe",
99+
},
100+
SelfHarm: SelfHarm{
101+
Filtered: false,
102+
Severity: "safe",
103+
},
104+
Sexual: Sexual{
105+
Filtered: true,
106+
Severity: "medium",
107+
},
108+
Violence: Violence{
109+
Filtered: false,
110+
Severity: "safe",
111+
},
112+
},
113+
})
114+
},
115+
},
116+
{
117+
name: "parse succeeds when the innerError is empty (Azure Openai)",
118+
response: `{"message": "","type": null,"param": "","code": "","status": 0,"innererror": {}}`,
119+
hasError: false,
120+
checkFunc: func(t *testing.T, apiErr APIError) {
121+
assertAPIErrorInnerError(t, apiErr, &InnerError{})
122+
},
123+
},
124+
{
125+
name: "parse succeeds when the innerError is not InnerError struct (Azure Openai)",
126+
response: `{"message": "","type": null,"param": "","code": "","status": 0,"innererror": "test"}`,
127+
hasError: true,
128+
checkFunc: func(t *testing.T, apiErr APIError) {
129+
assertAPIErrorInnerError(t, apiErr, &InnerError{})
130+
},
131+
},
60132
{
61133
name: "parse failed when the message is object",
62134
response: `{"message":{},"type":"invalid_request_error","param":null,"code":null}`,
@@ -152,6 +224,12 @@ func assertAPIErrorMessage(t *testing.T, apiErr APIError, expected string) {
152224
}
153225
}
154226

227+
func assertAPIErrorInnerError(t *testing.T, apiErr APIError, expected interface{}) {
228+
if !reflect.DeepEqual(apiErr.InnerError, expected) {
229+
t.Errorf("Unexpected APIError InnerError: %v; expected: %v; ", apiErr, expected)
230+
}
231+
}
232+
155233
func assertAPIErrorCode(t *testing.T, apiErr APIError, expected interface{}) {
156234
switch v := apiErr.Code.(type) {
157235
case int:

0 commit comments

Comments
 (0)