Support stream for multimodal chat (#14537)

### What problem does this PR solve?

Support stream for multimodal chat

### Type of change

- [x] Refactoring
This commit is contained in:
qinling0210
2026-04-30 19:33:57 +08:00
committed by GitHub
parent 5fd4579a2f
commit 12af73f2ca
15 changed files with 369 additions and 227 deletions

View File

@@ -562,7 +562,7 @@ func (s *ChatSessionService) asyncChatSolo(dialog *entity.Chat, session *entity.
chatConfig := s.buildChatConfig(dialog, config)
// Perform chat
response, err := chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, chatModel.APIConfig, msgs, chatConfig)
response, err := chatModel.ModelDriver.ChatWithMessages(*chatModel.ModelName, msgs, chatModel.APIConfig, chatConfig)
if err != nil {
logger.Error("asyncChatSolo chat failed", err)
return nil, err
@@ -604,26 +604,31 @@ func (s *ChatSessionService) asyncChatSoloStream(dialog *entity.Chat, session *e
return
}
// Convert messages to single string for ChatStreamlyWithSender
var msgBuilder strings.Builder
// Convert messages to []modelModule.Message for ChatStreamlyWithSender
var chatMessages []modelModule.Message
if systemPrompt != "" {
msgBuilder.WriteString("System: " + systemPrompt + "\n")
chatMessages = append(chatMessages, modelModule.Message{
Role: "system",
Content: systemPrompt,
})
}
for _, msg := range processedMessages {
role, _ := msg["role"].(string)
content, _ := msg["content"].(string)
if role != "" && content != "" && role != "system" {
msgBuilder.WriteString(role + ": " + content + "\n")
content := msg["content"]
if role != "" && content != nil && role != "system" {
chatMessages = append(chatMessages, modelModule.Message{
Role: role,
Content: content,
})
}
}
messageStr := msgBuilder.String()
// Get ChatConfig directly from dialog and config
chatConfig := s.buildChatConfig(dialog, config)
// Perform streaming chat using ChatStreamlyWithSender
fullAnswer := ""
err = chatModel.ModelDriver.ChatStreamlyWithSender(chatModel.ModelName, &messageStr, chatModel.APIConfig, chatConfig, func(answer *string, reason *string) error {
err = chatModel.ModelDriver.ChatStreamlyWithSender(*chatModel.ModelName, chatMessages, chatModel.APIConfig, chatConfig, func(answer *string, reason *string) error {
if reason != nil && *reason != "" {
fullAnswer += *reason
ans := s.structureAnswer(session, fullAnswer, messageID, session.ID, reference)

View File

@@ -740,7 +740,7 @@ func (m *ModelProviderService) ChatToModelWithMessages(providerName, instanceNam
apiConfig.ApiKey = &instance.APIKey
var response *modelModule.ChatResponse
response, err = providerInfo.ModelDriver.ChatWithMessages(modelName, apiConfig, messages, modelConfig)
response, err = providerInfo.ModelDriver.ChatWithMessages(modelName, messages, apiConfig, modelConfig)
if err != nil {
return nil, common.CodeServerError, err
}
@@ -776,7 +776,7 @@ func (m *ModelProviderService) ChatToModelWithMessages(providerName, instanceNam
newProviderInfo := providerInfo.ModelDriver.NewInstance(newURL)
var response *modelModule.ChatResponse
response, err = newProviderInfo.ChatWithMessages(modelName, apiConfig, messages, modelConfig)
response, err = newProviderInfo.ChatWithMessages(modelName, messages, apiConfig, modelConfig)
if err != nil {
return nil, common.CodeServerError, err
}
@@ -803,7 +803,7 @@ func (m *ModelProviderService) ChatWithMessagesToModelByApiKey(providerName, mod
}
var response *modelModule.ChatResponse
response, err = providerInfo.ModelDriver.ChatWithMessages(modelName, &modelModule.APIConfig{ApiKey: &apiKey}, messages, nil)
response, err = providerInfo.ModelDriver.ChatWithMessages(modelName, messages, &modelModule.APIConfig{ApiKey: &apiKey}, nil)
if err != nil {
return nil, common.CodeServerError, err
}
@@ -815,7 +815,7 @@ func (m *ModelProviderService) ChatWithMessagesToModelByApiKey(providerName, mod
}
// ChatToModelStreamWithSender streams chat response directly via sender function (best performance, no channel)
func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanceName, modelName, userID, message string, apiConfig *modelModule.APIConfig, modelConfig *modelModule.ChatConfig, sender func(*string, *string) error) (common.ErrorCode, error) {
func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanceName, modelName, userID string, messages []modelModule.Message, apiConfig *modelModule.APIConfig, modelConfig *modelModule.ChatConfig, sender func(*string, *string) error) (common.ErrorCode, error) {
// Get tenant ID from user
tenants, err := m.userTenantDAO.GetByUserIDAndRole(userID, "owner")
if err != nil {
@@ -861,7 +861,7 @@ func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanc
apiConfig.Region = &region
apiConfig.ApiKey = &instance.APIKey
err = providerInfo.ModelDriver.ChatStreamlyWithSender(&modelName, &message, apiConfig, modelConfig, sender)
err = providerInfo.ModelDriver.ChatStreamlyWithSender(modelName, messages, apiConfig, modelConfig, sender)
if err != nil {
return common.CodeServerError, err
}
@@ -893,7 +893,7 @@ func (m *ModelProviderService) ChatToModelStreamWithSender(providerName, instanc
}
newProviderInfo := providerInfo.ModelDriver.NewInstance(newURL)
err = newProviderInfo.ChatStreamlyWithSender(&modelName, &message, apiConfig, modelConfig, sender)
err = newProviderInfo.ChatStreamlyWithSender(modelName, messages, apiConfig, modelConfig, sender)
if err != nil {
return common.CodeServerError, err
}