Repository: ollama/ollama
File: openai/openai.go (Go)

Code before:
		Created: r.ModifiedAt.Unix(),
		OwnedBy: model.ParseName(m).Namespace,
	}
}

func fromChatRequest(r ChatCompletionRequest) (api.ChatRequest, error) {
	var messages []api.Message
	for _, msg := range r.Messages {
		switch content := msg.Content.(type) {
		case string:
			messages = append(messages, api.Message{Role: msg.Role, Content: content})
		case []any:
			message := api.Message{Role: msg.Role}
			for _, c := range content {
				data, ok := c.(map[string]any)
				if !ok {
					return api.ChatRequest{}, fmt.Errorf("invalid message format")
				}
				switch data["type"] {
				case "text":
					text, ok := data["text"].(string)
					if !ok {
						return api.ChatRequest{}, fmt.Errorf("invalid message format")
					}
					message.Content = text
				case "image_url":
					urlMap, ok := data["image_url"].(map[string]any)
					if !ok {
						return api.ChatRequest{}, fmt.Errorf("invalid message format")
					}
					url, ok := urlMap["url"].(string)
					if !ok {
						return api.ChatRequest{}, fmt.Errorf("invalid message format")
					}
					types := []string{"jpeg", "jpg", "png"}
					for _, t := range types {
						url = strings.TrimPrefix(url, "data:image/"+t+";base64,")
					}
					img, err := base64.StdEncoding.DecodeString(url)
					if err != nil {
						return api.ChatRequest{}, fmt.Errorf("invalid message format")
					}
					message.Images = append(message.Images, img)
				default:
					return api.ChatRequest{}, fmt.Errorf("invalid message format")
				}
			}
			messages = append(messages, message)
		default:
			return api.ChatRequest{}, fmt.Errorf("invalid message content type: %T", content)
		}

Review comment (suggestion):
We can merge this as-is, however with @mxyng 's new messages changes that collate messages, it would be better to instead create individual messages for each text and image content type we see


Code after:
		Created: r.ModifiedAt.Unix(),
		OwnedBy: model.ParseName(m).Namespace,
	}
}

func fromChatRequest(r ChatCompletionRequest) (*api.ChatRequest, error) {
	var messages []api.Message
	for _, msg := range r.Messages {
		switch content := msg.Content.(type) {
		case string:
			messages = append(messages, api.Message{Role: msg.Role, Content: content})
		case []any:
			message := api.Message{Role: msg.Role}
			for _, c := range content {
				data, ok := c.(map[string]any)
				if !ok {
					return nil, fmt.Errorf("invalid message format")
				}
				switch data["type"] {
				case "text":
					text, ok := data["text"].(string)
					if !ok {
						return nil, fmt.Errorf("invalid message format")
					}
					message.Content = text
				case "image_url":
					var url string
					if urlMap, ok := data["image_url"].(map[string]any); ok {
						if url, ok = urlMap["url"].(string); !ok {
							return nil, fmt.Errorf("invalid message format")
						}
					} else {
						if url, ok = data["image_url"].(string); !ok {
							return nil, fmt.Errorf("invalid message format")
						}
					}

					types := []string{"jpeg", "jpg", "png"}
					valid := false
					for _, t := range types {
						prefix := "data:image/" + t + ";base64,"
						if strings.HasPrefix(url, prefix) {
							url = strings.TrimPrefix(url, prefix)
							valid = true
							break
						}
					}

					if !valid {
						return nil, fmt.Errorf("invalid image input")
					}