Skip to content

Commit

Permalink
googleai: move downloadImageData to separate file (#530)
Browse files Browse the repository at this point in the history
  • Loading branch information
eliben authored Jan 18, 2024
1 parent 111c09f commit b8fc0e3
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 37 deletions.
1 change: 1 addition & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ linters:
- exhaustruct
- varnamelen
- nlreturn
- gomnd
- wrapcheck # TODO: we should probably enable this one (at least for new code).
- testpackage
- nolintlint # see https://github.com/golangci/golangci-lint/issues/3228.
Expand Down
33 changes: 33 additions & 0 deletions llms/googleai/download.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package googleai

import (
"fmt"
"io"
"net/http"
"strings"
)

// downloadImageData downloads the content from the given URL and returns the
// image type and data. The image type is the second part of the response's
// MIME (e.g. "png" from "image/png").
func downloadImageData(url string) (string, []byte, error) {
resp, err := http.Get(url) //nolint
if err != nil {
return "", nil, fmt.Errorf("failed to fetch image from url: %w", err)
}
defer resp.Body.Close()

urlData, err := io.ReadAll(resp.Body)
if err != nil {
return "", nil, fmt.Errorf("failed to read image bytes: %w", err)
}

mimeType := resp.Header.Get("Content-Type")

parts := strings.Split(mimeType, "/")
if len(parts) != 2 {
return "", nil, ErrInvalidMimeType
}

return parts[1], urlData, nil
}
41 changes: 5 additions & 36 deletions llms/googleai/googleai_llm.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import (
"context"
"errors"
"fmt"
"io"
"log"
"net/http"
"strings"

"github.com/google/generative-ai-go/genai"
Expand Down Expand Up @@ -115,35 +113,6 @@ func (g *GoogleAI) GenerateContent(ctx context.Context, messages []llms.MessageC
return response, nil
}

// downloadImageData downloads the content from the given URL and returns it as
// a *genai.Blob.
func downloadImageData(url string) (*genai.Blob, error) {
resp, err := http.Get(url) //nolint
if err != nil {
return nil, fmt.Errorf("failed to fetch image from url: %w", err)
}
defer resp.Body.Close()

urlData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read image bytes: %w", err)
}

mimeType := resp.Header.Get("Content-Type")

// The convenience function genai.ImageData requires just the right part of
// the mime type, so we need to parse it
parts := strings.Split(mimeType, "/")

if len(parts) != 2 { //nolint
return nil, ErrInvalidMimeType
}

blob := genai.ImageData(parts[1], urlData)

return &blob, nil
}

// convertCandidates converts a sequence of genai.Candidate to a response.
func convertCandidates(candidates []*genai.Candidate) (*llms.ContentResponse, error) {
var contentResponse llms.ContentResponse
Expand Down Expand Up @@ -197,18 +166,18 @@ func convertParts(parts []llms.ContentPart) ([]genai.Part, error) {
convertedParts := make([]genai.Part, 0, len(parts))
for _, part := range parts {
var out genai.Part
var err error

switch p := part.(type) {
case llms.TextContent:
out = genai.Text(p.Text)
case llms.BinaryContent:
out = genai.Blob{MIMEType: p.MIMEType, Data: p.Data}
case llms.ImageURLContent:
out, err = downloadImageData(p.URL)
}
if err != nil {
return nil, err
typ, data, err := downloadImageData(p.URL)
if err != nil {
return nil, err
}
out = genai.ImageData(typ, data)
}

convertedParts = append(convertedParts, out)
Expand Down
1 change: 0 additions & 1 deletion llms/googleai/googleai_option.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
//nolint:gomnd
package googleai

// options is a set of options for GoogleAI clients.
Expand Down

0 comments on commit b8fc0e3

Please sign in to comment.