mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-08-15 05:04:27 +08:00
fix(models): guard unsafe index access in Google and Ollama drivers (#15819)
### What problem does this PR solve? Fixes four panic / spurious-error paths in the Go model layer. Closes #15818. | # | File | Bug | Fix | |---|------|-----|-----| | 1 | | Thinking-mode streaming path: accessed unconditionally; Gemini emits usage-only chunks with an empty slice, causing a runtime panic | Guard each step: , , before indexing | | 2 | | is a plain for ordinary requests; the cast to silently returns , then panics immediately | Switch on concrete type; handle both and | | 3 | | Identical panic on the streaming path | Same switch-on-type fix | | 4 | | The field is optional (absent for non-thinking models) but the code returned an error when it was missing, breaking every ordinary Ollama completion | Change to a silent comma-ok assertion; is empty string when the field is absent | ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -266,7 +266,11 @@ func (g *GoogleModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
|
||||
var responseContent string
|
||||
if chatModelConfig != nil && chatModelConfig.Thinking != nil && *chatModelConfig.Thinking {
|
||||
responseContent = response.Candidates[0].Content.Parts[0].Text
|
||||
if len(response.Candidates) > 0 &&
|
||||
response.Candidates[0].Content != nil &&
|
||||
len(response.Candidates[0].Content.Parts) > 0 {
|
||||
responseContent = response.Candidates[0].Content.Parts[0].Text
|
||||
}
|
||||
}
|
||||
|
||||
if responseContent != "" {
|
||||
|
||||
@@ -33,6 +33,26 @@ type OllamaModel struct {
|
||||
baseModel BaseModel
|
||||
}
|
||||
|
||||
// contentToText extracts a plain-text string from a Message.Content value.
|
||||
// Content may be a raw string or an OpenAI-style multimodal array
|
||||
// ([]interface{} where each element is {"type": "text", "text": "..."}).
|
||||
// The first non-empty "text" value found is returned; empty string on no match.
|
||||
func contentToText(content interface{}) string {
|
||||
switch c := content.(type) {
|
||||
case string:
|
||||
return c
|
||||
case []interface{}:
|
||||
for _, item := range c {
|
||||
if part, ok := item.(map[string]interface{}); ok {
|
||||
if text, ok := part["text"].(string); ok && text != "" {
|
||||
return text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewOllamaModel creates a new Ollama AI model instance
|
||||
func NewOllamaModel(baseURL map[string]string, urlSuffix URLSuffix) *OllamaModel {
|
||||
return &OllamaModel{
|
||||
@@ -80,15 +100,9 @@ func (o *OllamaModel) ChatWithMessages(modelName string, messages []Message, api
|
||||
// Convert messages to API format
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
arr, _ := msg.Content.([]interface{})
|
||||
|
||||
first, _ := arr[0].(map[string]interface{})
|
||||
|
||||
text, _ := first["text"].(string)
|
||||
|
||||
apiMessages[i] = map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": text,
|
||||
"content": contentToText(msg.Content),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +192,7 @@ func (o *OllamaModel) ChatWithMessages(modelName string, messages []Message, api
|
||||
return nil, fmt.Errorf("failed to parse response: content not found")
|
||||
}
|
||||
|
||||
reasonContent, ok := message["thinking"].(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to parse response: thinking not found")
|
||||
}
|
||||
reasonContent, _ := message["thinking"].(string)
|
||||
|
||||
chatResponse := &ChatResponse{
|
||||
Answer: &content,
|
||||
@@ -209,15 +220,9 @@ func (o *OllamaModel) ChatStreamlyWithSender(modelName string, messages []Messag
|
||||
// Convert messages to API format (supporting multimodal content)
|
||||
apiMessages := make([]map[string]interface{}, len(messages))
|
||||
for i, msg := range messages {
|
||||
arr, _ := msg.Content.([]interface{})
|
||||
|
||||
first, _ := arr[0].(map[string]interface{})
|
||||
|
||||
text, _ := first["text"].(string)
|
||||
|
||||
apiMessages[i] = map[string]interface{}{
|
||||
"role": msg.Role,
|
||||
"content": text,
|
||||
"content": contentToText(msg.Content),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user