payloop 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/lib/payloop/version.rb +1 -1
- data/lib/payloop/wrappers/base.rb +52 -1
- data/lib/payloop/wrappers/openai.rb +24 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0d134effe2b909cc928b4dfc80149d3c9dcde238be7630bb37dba541fa33be0a
|
|
4
|
+
data.tar.gz: ddf58b4672381d25ab90b349c6bf29391e4fe099f9e304ba20f5169d3ee6bf1c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b943601582c65f45f66209c6c7aa37c0041f3f961130b3fce5109f09369359d05cc2c7264ca85ffea99b067c95b7c1419d165bf11d847fb994f43a29697c4df
|
|
7
|
+
data.tar.gz: 2d4ff576bccc13c526dc80ae8ab9b2dfb72a9480f3f6c88ed261a723a217271867a3f6f88e2083f8bb5a65813362b5603e8396bd5a6c944885cbf1c4010fe963
|
data/CHANGELOG.md
CHANGED
|
@@ -29,4 +29,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
29
29
|
## [0.0.3] - 2025-10-27
|
|
30
30
|
|
|
31
31
|
### Fixed
|
|
32
|
-
-
|
|
32
|
+
- Correct Payloop request payload structure for Google GenAI
|
|
33
|
+
|
|
34
|
+
## [0.0.4] - 2025-10-28
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
- Correct Payloop request payload structure for OpenAI streaming
|
data/lib/payloop/version.rb
CHANGED
|
@@ -84,11 +84,62 @@ module Payloop
|
|
|
84
84
|
collector.submit_async(payload)
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
+
def payloop_merge_streaming_chunk(accumulated, chunk)
|
|
88
|
+
chunk.each do |key, value|
|
|
89
|
+
if accumulated.key?(key)
|
|
90
|
+
case accumulated[key]
|
|
91
|
+
when Hash
|
|
92
|
+
payloop_merge_streaming_chunk(accumulated[key], value) if value.is_a?(Hash)
|
|
93
|
+
when Array
|
|
94
|
+
# Concatenate arrays (matches Python SDK behavior: data[key].extend(chunk_value))
|
|
95
|
+
accumulated[key].concat(value) if value.is_a?(Array)
|
|
96
|
+
else
|
|
97
|
+
accumulated[key] = value
|
|
98
|
+
end
|
|
99
|
+
else
|
|
100
|
+
accumulated[key] = value
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
accumulated
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def payloop_normalize_openai_chunk(chunk)
|
|
107
|
+
# Normalize OpenAI streaming chunks to match Python SDK format
|
|
108
|
+
# Ensure delta objects have all keys present with null values
|
|
109
|
+
return chunk unless chunk.is_a?(Hash)
|
|
110
|
+
|
|
111
|
+
if chunk["choices"].is_a?(Array)
|
|
112
|
+
chunk["choices"].each do |choice|
|
|
113
|
+
next unless choice.is_a?(Hash) && choice.key?("delta")
|
|
114
|
+
|
|
115
|
+
delta = choice["delta"]
|
|
116
|
+
if delta.is_a?(Hash)
|
|
117
|
+
# Add missing keys with nil values to match Python SDK
|
|
118
|
+
delta["role"] ||= nil unless delta.key?("role")
|
|
119
|
+
delta["content"] ||= nil unless delta.key?("content")
|
|
120
|
+
delta["refusal"] ||= nil unless delta.key?("refusal")
|
|
121
|
+
delta["tool_calls"] ||= nil unless delta.key?("tool_calls")
|
|
122
|
+
delta["function_call"] ||= nil unless delta.key?("function_call")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
chunk
|
|
128
|
+
end
|
|
129
|
+
|
|
87
130
|
private
|
|
88
131
|
|
|
89
132
|
def extract_query(_method, _args, kwargs)
|
|
90
133
|
# Deep copy to avoid mutation issues
|
|
91
|
-
deep_copy(kwargs)
|
|
134
|
+
query = deep_copy(kwargs)
|
|
135
|
+
|
|
136
|
+
# Normalize stream parameter: convert Proc to boolean true
|
|
137
|
+
# This ensures streaming requests are properly serialized to JSON
|
|
138
|
+
if query.is_a?(Hash) && query[:stream].is_a?(Proc)
|
|
139
|
+
query[:stream] = true
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
query
|
|
92
143
|
rescue StandardError
|
|
93
144
|
{}
|
|
94
145
|
end
|
|
@@ -45,15 +45,38 @@ module Payloop
|
|
|
45
45
|
define_method(:chat) do |parameters: {}|
|
|
46
46
|
start_time = Time.now
|
|
47
47
|
|
|
48
|
+
# Detect streaming and wrap callback to accumulate chunks
|
|
49
|
+
streaming = parameters[:stream].is_a?(Proc)
|
|
50
|
+
accumulated_response = {} if streaming
|
|
51
|
+
|
|
52
|
+
if streaming
|
|
53
|
+
# Configure streaming to include usage (matches Python SDK behavior)
|
|
54
|
+
parameters[:stream_options] ||= {}
|
|
55
|
+
parameters[:stream_options][:include_usage] = true
|
|
56
|
+
|
|
57
|
+
user_callback = parameters[:stream]
|
|
58
|
+
parameters[:stream] = proc do |chunk, bytesize|
|
|
59
|
+
# Normalize chunk to match Python SDK format (add missing delta keys with nil)
|
|
60
|
+
normalized_chunk = payloop_normalize_openai_chunk(chunk)
|
|
61
|
+
# Accumulate chunk (merge into accumulated_response)
|
|
62
|
+
payloop_merge_streaming_chunk(accumulated_response, normalized_chunk)
|
|
63
|
+
# Call user's original callback with original chunk (don't modify user's data)
|
|
64
|
+
user_callback.call(chunk, bytesize)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
48
68
|
# Call original method
|
|
49
69
|
response = original_chat(parameters: parameters)
|
|
50
70
|
|
|
71
|
+
# Use accumulated response for streaming, otherwise use returned response
|
|
72
|
+
final_response = streaming ? accumulated_response : response
|
|
73
|
+
|
|
51
74
|
# Submit analytics
|
|
52
75
|
payloop_submit_analytics(
|
|
53
76
|
method: :chat,
|
|
54
77
|
args: [],
|
|
55
78
|
kwargs: parameters,
|
|
56
|
-
response:
|
|
79
|
+
response: final_response,
|
|
57
80
|
start_time: start_time,
|
|
58
81
|
end_time: Time.now,
|
|
59
82
|
title: OPENAI_CLIENT_TITLE
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: payloop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Payloop
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-10-
|
|
11
|
+
date: 2025-10-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: concurrent-ruby
|