Class: NitroIntelligence::Observability::UploadHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/nitro_intelligence/observability/upload_handler.rb

Instance Method Summary collapse

Constructor Details

#initialize(auth_token:) ⇒ UploadHandler

Returns a new instance of UploadHandler.



9
10
11
12
13
# File 'lib/nitro_intelligence/observability/upload_handler.rb', line 9

def initialize(auth_token:)
  @host = NitroIntelligence.config.observability_base_url
  @auth_token = auth_token
  @uploaded_media = []
end

Instance Method Details

#replace_base64_with_media_references(payload) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/nitro_intelligence/observability/upload_handler.rb', line 15

def replace_base64_with_media_references(payload)
  # Make it easier to lookup message style image_urls
  media_lookup = @uploaded_media.index_by { |image| "data:#{image.mime_type};base64,#{image.base64}" }

  replace_base64_image_url = ->(node) do
    case node
    when Hash
      url_key = if node.key?(:url)
                  :url
                else
                  (node.key?("url") ? "url" : nil)
                end

      if url_key
        url_value = node[url_key]

        # Replace base64 strings if they match with our uploaded media
        if (media = media_lookup[url_value])
          # Overwrite base64 string with Langfuse media ref
          # This *should* be rendering inline in the gui
          # https://github.com/langfuse/langfuse/issues/4555
          # https://github.com/langfuse/langfuse/issues/5030
          node[url_key] = "@@@langfuseMedia:type=#{media.mime_type}|id=#{media.reference_id}|source=bytes@@@"
        # Sometimes models can generate unwanted images that will not have a reference
        # these untracked base64 strings can easily push 4.5mb Langfuse limit
        elsif url_value.is_a?(String) && url_value.start_with?("data:")
          node[url_key] = "[Discarded media]"
        end
      end

      node.each_value { |val| replace_base64_image_url.call(val) }

    when Array
      node.each { |val| replace_base64_image_url.call(val) }
    end
  end

  replace_base64_image_url.call(payload)

  payload
end

#upload(trace_id, upload_queue: Queue.new) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/nitro_intelligence/observability/upload_handler.rb', line 57

def upload(trace_id, upload_queue: Queue.new)
  until upload_queue.empty?
    media = upload_queue.pop

    content_length = media.byte_string.bytesize
    content_sha256 = Base64.strict_encode64(Digest::SHA256.digest(media.byte_string))

    # returns {"mediaId" -> "", "uploadUrl" => ""}
    upload_url_response = get_upload_url({
                                           traceId: trace_id,
                                           contentType: media.mime_type,
                                           contentLength: content_length,
                                           sha256Hash: content_sha256,
                                           field: media.direction,
                                         })

    # NOTE: uploadUrl is None if the file is stored in Langfuse already
    # there is no need to upload it again.
    upload_response = upload_media(
      upload_url_response["mediaId"],
      upload_url_response["uploadUrl"],
      media.mime_type,
      content_sha256,
      media.byte_string
    )

    associate_media(upload_url_response["mediaId"], upload_response) if upload_response.present?

    media.reference_id = upload_url_response["mediaId"]
    @uploaded_media.append(media)
  end

  @uploaded_media
end