prompt_builder 0.3.0 → 0.4.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6a857e2a0958425d04263986bca11967fb575af1c1e40ada5bee63556447fe0
4
- data.tar.gz: 9840a2750ac27e265aea1e25d9290ee3aecb56cd24889d5903b481891a2925db
3
+ metadata.gz: 81ca025b0770c1b045ba525bc7fb6839a25b2d0b760b06ba85698de84c0a36b7
4
+ data.tar.gz: e8fc9eded433a202f7b2c6e9c79d0a0f8a9325b156cc884d09e1f7af535679a0
5
5
  SHA512:
6
- metadata.gz: 70fe6418fdd6865e12ec8babb5d5a7542ff31e93b44e0dfb389c1e0853955d5657bbf3482462e1ec091fca8031ac988bfc70222195a8ad2fd50833eb2542c4a1
7
- data.tar.gz: bd0d9abb2cbb42d10d70c8f1d15322cc58a4c88c6401f937a45844fbde2dcf8013b183cf19d206b1e4c0e48cf9c0a03fb3ad5b35c17ed083b12d7c73f00224c6
6
+ metadata.gz: e5eab3ec44e9c2a958b60d6c8c24dd740c8586eef8e5d05b6d0ab67807bc5526c3946b8ddd50439d60a860fdcc96e7372d637c552d15938383ef36ecfa173486
7
+ data.tar.gz: b0aaf0e28017996c603101d8fbde94fc4c242ffa42d471caa7cb0bbaad55f812962873237cf839d51755a86d844ec4fe7676516d3ed8c87df322a6bcd33b424c
data/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 0.4.0
8
+
9
+ ### Added
10
+
11
+ - `Response.parse` (and the serializer `parse_response` methods) accept an optional `headers:` keyword with the HTTP response headers, for formats that return response metadata in headers rather than in the body. The Converse serializer uses it to populate `Response#id` from the `x-amzn-requestid` request metadata header, since the Converse API does not include a response id in the body. The header name lookup is case-insensitive.
12
+
7
13
  ## 0.3.0
8
14
 
9
15
  ### Added
data/README.md CHANGED
@@ -171,6 +171,13 @@ You can also pass a serializer class directly:
171
171
  response = PromptBuilder::Response.parse(JSON.parse(response_body), PromptBuilder::Serializers::ChatCompletion)
172
172
  ```
173
173
 
174
+ `Response.parse` accepts an optional `headers:` keyword with the HTTP response headers, for formats that return response metadata in headers rather than in the body. The Converse API is one of them: Bedrock puts the response id in the `x-amzn-requestid` request metadata header, so pass the headers to populate `response.id` (the header name lookup is case-insensitive):
175
+
176
+ ```ruby
177
+ response = PromptBuilder::Response.parse(JSON.parse(response_body), :converse, headers: http_response_headers)
178
+ response.id # => "6e1d5a7b-..."
179
+ ```
180
+
174
181
  The `Response` object provides convenient accessors:
175
182
 
176
183
  ```ruby
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -158,10 +158,18 @@ module PromptBuilder
158
158
  # @param serializer_class [Class, Symbol] a serializer class (e.g. Serializers::ChatCompletion)
159
159
  # or a symbol shorthand (+:open_responses+, +:chat_completion+, +:messages+,
160
160
  # +:gemini+, +:converse+)
161
+ # @param headers [Hash, #each, nil] the HTTP response headers, for formats
162
+ # that return response metadata in headers rather than in the body
163
+ # (e.g. the Converse response id)
161
164
  # @return [Response]
162
165
  # @raise [ArgumentError] if a symbol is given that does not map to a known serializer
163
- def parse(hash, serializer_class)
164
- Serializers.resolve(serializer_class).parse_response(hash)
166
+ def parse(hash, serializer_class, headers: nil)
167
+ serializer = Serializers.resolve(serializer_class)
168
+ # Send the keyword only when headers are given, so serializer classes
169
+ # whose parse_response does not accept it keep working.
170
+ return serializer.parse_response(hash) if headers.nil?
171
+
172
+ serializer.parse_response(hash, headers: headers)
165
173
  end
166
174
 
167
175
  # Deserialize a Response from a Hash.
@@ -15,11 +15,19 @@ module PromptBuilder
15
15
  end
16
16
 
17
17
  # Parse a response from the target format into an PromptBuilder::Response.
18
+ # Format classes that define a nested Response parser delegate to it.
18
19
  #
19
20
  # @param hash [Hash] the response hash in the target format
21
+ # @param headers [Hash, #each, nil] the HTTP response headers, for
22
+ # formats that return response metadata in headers rather than in
23
+ # the body
20
24
  # @return [Response] the parsed response
21
25
  # @raise [ErrorResponseError] if the payload is an API error envelope
22
- def parse_response(hash)
26
+ def parse_response(hash, headers: nil)
27
+ if const_defined?(:Response, false)
28
+ return const_get(:Response, false).parse_response(hash, headers: headers)
29
+ end
30
+
23
31
  check_error_response!(hash)
24
32
  deserialize_response(hash)
25
33
  end
@@ -16,14 +16,6 @@ module PromptBuilder
16
16
  def request_payload(session)
17
17
  Request.request_payload(session)
18
18
  end
19
-
20
- # Parse a Chat Completions response into an PromptBuilder::Response.
21
- #
22
- # @param hash [Hash] the response hash in Chat Completions format
23
- # @return [PromptBuilder::Response] the parsed response
24
- def parse_response(hash)
25
- Response.parse_response(hash)
26
- end
27
19
  end
28
20
  end
29
21
  end
@@ -7,7 +7,24 @@ module PromptBuilder
7
7
  class Converse < Base
8
8
  # Response parser for the Amazon Bedrock Converse API format.
9
9
  class Response < Base
10
+ # The response id header set by Bedrock (the AWS request metadata id).
11
+ RESPONSE_ID_HEADER = "x-amzn-requestid"
12
+
10
13
  class << self
14
+ # Parse a Converse response into a PromptBuilder::Response. The
15
+ # Converse API does not include a response id in the body; Bedrock
16
+ # returns it in the request metadata headers, so the id is read
17
+ # from +headers+ when they are given.
18
+ #
19
+ # @param hash [Hash] the response hash in Converse format
20
+ # @param headers [Hash, #each, nil] the HTTP response headers
21
+ # @return [PromptBuilder::Response] the parsed response
22
+ # @raise [ErrorResponseError] if the payload is an API error envelope
23
+ def parse_response(hash, headers: nil)
24
+ check_error_response!(hash)
25
+ deserialize_response(hash, headers)
26
+ end
27
+
11
28
  private
12
29
 
13
30
  # Bedrock exception bodies carry a top-level "message" (the exception
@@ -25,7 +42,7 @@ module PromptBuilder
25
42
  [error_type, message].compact.join(": ")
26
43
  end
27
44
 
28
- def deserialize_response(hash)
45
+ def deserialize_response(hash, headers = nil)
29
46
  require_response_key!(hash, "output")
30
47
  require_response_key!(hash, "stopReason")
31
48
 
@@ -50,7 +67,7 @@ module PromptBuilder
50
67
  content_blocks = message["content"] || []
51
68
 
52
69
  PromptBuilder::Response.new(
53
- id: nil,
70
+ id: response_id_from_headers(headers),
54
71
  object: nil,
55
72
  model: nil,
56
73
  output: build_output_items(content_blocks),
@@ -61,6 +78,22 @@ module PromptBuilder
61
78
  )
62
79
  end
63
80
 
81
+ # Find the response id header with a case-insensitive name match.
82
+ # Header values may be scalars or arrays of values, depending on
83
+ # the HTTP client the headers come from.
84
+ def response_id_from_headers(headers)
85
+ return nil unless headers.respond_to?(:each)
86
+
87
+ headers.each do |name, value|
88
+ next unless name.to_s.casecmp?(RESPONSE_ID_HEADER)
89
+
90
+ value = value.first if value.is_a?(Array)
91
+ value = value.to_s.strip
92
+ return value unless value.empty?
93
+ end
94
+ nil
95
+ end
96
+
64
97
  def map_stop_reason(reason)
65
98
  case reason
66
99
  when "end_turn", "tool_use", "stop_sequence"
@@ -16,14 +16,6 @@ module PromptBuilder
16
16
  def request_payload(session)
17
17
  Request.request_payload(session)
18
18
  end
19
-
20
- # Parse a Converse response into a PromptBuilder::Response.
21
- #
22
- # @param hash [Hash] the response hash in Converse format
23
- # @return [PromptBuilder::Response] the parsed response
24
- def parse_response(hash)
25
- Response.parse_response(hash)
26
- end
27
19
  end
28
20
  end
29
21
  end
@@ -16,14 +16,6 @@ module PromptBuilder
16
16
  def request_payload(session)
17
17
  Request.request_payload(session)
18
18
  end
19
-
20
- # Parse a Gemini response into a PromptBuilder::Response.
21
- #
22
- # @param hash [Hash] the response hash in Gemini format
23
- # @return [PromptBuilder::Response] the parsed response
24
- def parse_response(hash)
25
- Response.parse_response(hash)
26
- end
27
19
  end
28
20
  end
29
21
  end
@@ -16,14 +16,6 @@ module PromptBuilder
16
16
  def request_payload(session)
17
17
  Request.request_payload(session)
18
18
  end
19
-
20
- # Parse a Messages response into an PromptBuilder::Response.
21
- #
22
- # @param hash [Hash] the response hash in Messages format
23
- # @return [PromptBuilder::Response] the parsed response
24
- def parse_response(hash)
25
- Response.parse_response(hash)
26
- end
27
19
  end
28
20
  end
29
21
  end
@@ -16,14 +16,6 @@ module PromptBuilder
16
16
  def request_payload(session)
17
17
  Request.request_payload(session)
18
18
  end
19
-
20
- # Parse an Open Responses response into an PromptBuilder::Response.
21
- #
22
- # @param hash [Hash] the response hash in Open Responses format
23
- # @return [PromptBuilder::Response] the parsed response
24
- def parse_response(hash)
25
- Response.parse_response(hash)
26
- end
27
19
  end
28
20
  end
29
21
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prompt_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand