Enhance retry mechanism with flexible action handling

- Modify HookRetry to support returning NextAction
- Update streamChat to handle different retry response types
- Add type switching for retry hook return values
- Implement execution of NextAction in retry flow
- Improve error handling and response processing during retry
This commit is contained in:
Max 2025-03-04 15:27:40 +08:00
parent f469568d85
commit dafd6b029b
2 changed files with 31 additions and 9 deletions

View file

@ -623,19 +623,32 @@ func (ast *Assistant) streamChat(
ctx.Retry = true // Set the retry mode ctx.Retry = true // Set the retry mode
// Hook retry // Hook retry
prompt, retryErr := ast.HookRetry(c, ctx, messages, contents, exception.Trim(retry)) promptAny, retryErr := ast.HookRetry(c, ctx, messages, contents, exception.Trim(retry))
if retryErr != nil { if retryErr != nil {
color.Red("%s, try to fix the error %d times, but failed with %s", exception.Trim(retry), ctx.RetryTimes, exception.Trim(retryErr)) color.Red("%s, try to fix the error %d times, but failed with %s", exception.Trim(retry), ctx.RetryTimes, exception.Trim(retryErr))
chatMessage.New().Error(retry.Error()).Done().Callback(cb).Write(c.Writer) chatMessage.New().Error(retry.Error()).Done().Callback(cb).Write(c.Writer)
return nil, retry return nil, retry
} }
// if the prompt is empty, return the error if promptAny == nil {
if prompt == "" {
chatMessage.New().Error(retry.Error()).Done().Callback(cb).Write(c.Writer) chatMessage.New().Error(retry.Error()).Done().Callback(cb).Write(c.Writer)
return nil, retry return nil, retry
} }
var prompt string = ""
switch v := promptAny.(type) {
case NextAction:
result, err := v.Execute(c, ctx, contents, cb)
if err != nil {
chatMessage.New().Error(err.Error()).Done().Callback(cb).Write(c.Writer)
return nil, retry
}
return result, nil
case string:
prompt = v
}
// Add the prompt to the messages // Add the prompt to the messages
retryMessages, retryErr := ast.retryMessages(messages, prompt) retryMessages, retryErr := ast.retryMessages(messages, prompt)
if retryErr != nil { if retryErr != nil {
@ -645,7 +658,8 @@ func (ast *Assistant) streamChat(
} }
// Retry the chat // Retry the chat
return ast.streamChat(c, ctx, retryMessages, options, clientBreak, contents, cb) retryContents := chatMessage.NewContents()
return ast.execute(c, ctx, retryMessages, options, retryContents, cb)
} }
// Handle error // Handle error

View file

@ -135,7 +135,7 @@ func (ast *Assistant) HookStream(c *gin.Context, context chatctx.Context, input
} }
// HookRetry Handle retry of assistant response // HookRetry Handle retry of assistant response
func (ast *Assistant) HookRetry(c *gin.Context, context chatctx.Context, input []message.Message, contents *chatMessage.Contents, errmsg string) (string, error) { func (ast *Assistant) HookRetry(c *gin.Context, context chatctx.Context, input []message.Message, contents *chatMessage.Contents, errmsg string) (interface{}, error) {
ctx := ast.createBackgroundContext() ctx := ast.createBackgroundContext()
output := []message.Data{} output := []message.Data{}
if len(input) < 1 { if len(input) < 1 {
@ -158,12 +158,20 @@ func (ast *Assistant) HookRetry(c *gin.Context, context chatctx.Context, input [
return "", err return "", err
} }
res, ok := v.(string) switch v := v.(type) {
if !ok { case string:
return "", fmt.Errorf("invalid return type: %T", v) return v, nil
case map[string]interface{}:
var next NextAction
raw, _ := jsoniter.MarshalToString(v)
err := jsoniter.UnmarshalFromString(raw, &next)
if err != nil {
return "", err
}
return next, nil
} }
return res, nil return "", nil
} }
// HookDone Handle completion of assistant response // HookDone Handle completion of assistant response