patient_llm 0.7.0 → 0.8.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: 74014452123a066e2e43338aea8a78473d4d1e76740ae9ef4067093c3af96c5c
4
- data.tar.gz: 1ae189616ab9daee96f8b8782da08871eb572024d4292c45c456d53de6706524
3
+ metadata.gz: 55806cbf3beeef58969661d79224bf6ff527ac3e73d92e8426ef854c0635dca0
4
+ data.tar.gz: bdae58940e5c112a237d5e64455ed956d42577ad0d2241bb7ea0a4576df01f02
5
5
  SHA512:
6
- metadata.gz: cb5627c92970f28ce39f1e3d7da045eeb5641270a1f0b9d22413c71e68c57bd987e2d3d56cdcca2b3e80ad3c0571ecdd22729d04d39a8bcba8442b90f546055b
7
- data.tar.gz: 56fb911160aa80525325c94d15a74a833610428bc67d7702c16737b8ec6c1671afa6a3d59fcb2c92b2a58a0daa0405be28981017cfca99106d5873233c53f93e
6
+ metadata.gz: ca5d9f04997f0bf171a4de6f5edb599b2b33991c36ce4835cde1574e251b5e6d926887de53d5a31ff7d3e76b294bb9e56e41e467ebb671b3dc36d7031d128b7c
7
+ data.tar.gz: 533df1b81438b348387a5824df29b3a74a9102292f2cd82de910b0c7fe85d7864cd3364292e5bd5cdca93f10181026987926c681b349668efac6feab5fea9bd3
data/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ 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.8.0
8
+
9
+ ### Added
10
+
11
+ - Requests can name the PatientHttp processor that executes them. Pass `processor:` to `PatientLLM.ask` (or through agent `ask` options), or set a default for all LLM requests with `config.processor` (a Symbol, String, or callable). When neither is set, requests use the default processor. The processor is preserved across automatic tool-loop iterations. Requires patient_http 1.5.0.
12
+
13
+ ### Changed
14
+
15
+ - patient_http minimum version is now 1.5.0.
16
+
7
17
  ## 0.7.0
8
18
 
9
19
  ### Changed
data/README.md CHANGED
@@ -163,6 +163,16 @@ end
163
163
 
164
164
  Validation of a callable's result (serializer names, authentication headers) happens at lookup time instead of registration time.
165
165
 
166
+ ### Naming the request processor
167
+
168
+ Job-system integrations for patient_http can run multiple named processors with different configurations — for example, one tuned for long-running LLM requests and another for quick webhook deliveries. Set `processor` to route every LLM request to a named processor; it can also be a callable, resolved on every request. When unset, requests use the default processor. A per-request `processor:` option on `ask` overrides the configured value.
169
+
170
+ ```ruby
171
+ PatientLLM.configure do |config|
172
+ config.processor = :llm
173
+ end
174
+ ```
175
+
166
176
  ### Request signing (preprocessors)
167
177
 
168
178
  Some providers require request signing rather than a static authentication header — for example, AWS Bedrock with SigV4, where a signature is computed over the final outgoing request. For these, register a [request preprocessor](https://github.com/bdurand/patient_http#request-preprocessors) on the PatientHttp configuration and reference it by name from the provider. Like secrets, only the preprocessor name is serialized into the job queue; the signing logic and credentials stay on the processor side.
@@ -455,7 +465,8 @@ PatientLLM.ask(session,
455
465
  params: {max_completion_tokens: 1000}, # Additional request parameters
456
466
  preprocessors: :aws_sigv4, # Replace the provider's request preprocessors
457
467
  timeout: 600, # Request timeout in seconds
458
- max_tool_iterations: 3 # Tool loop cap for this request
468
+ max_tool_iterations: 3, # Tool loop cap for this request
469
+ processor: :llm # Named PatientHttp processor for this request
459
470
  )
460
471
  ```
461
472
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.0
1
+ 0.8.0
@@ -276,7 +276,7 @@ module PatientLLM
276
276
  # agent. Defaults to sending the hooks to the agent itself.
277
277
  # @param options [Hash] per-request overrides forwarded to {PatientLLM.ask}
278
278
  # (url:, serializer:, path:, headers:, params:, preprocessors:, timeout:,
279
- # max_tool_iterations:), plus session options (model:, temperature:,
279
+ # max_tool_iterations:, processor:), plus session options (model:, temperature:,
280
280
  # extra:, etc. — any PromptBuilder::Session::INITIALIZE_OPTIONS key)
281
281
  # applied to the newly built session; session options raise
282
282
  # ArgumentError when a session: is supplied.
@@ -28,9 +28,18 @@ module PatientLLM
28
28
 
29
29
  attr_reader :session_offload_options
30
30
 
31
+ # Name of the PatientHttp processor that executes LLM requests, used when a
32
+ # request does not pass its own processor: option. The value can be a
33
+ # Symbol, a String, or a callable resolved on every request. When nil, the
34
+ # default processor is used.
35
+ #
36
+ # @return [Symbol, String, #call, nil]
37
+ attr_accessor :processor
38
+
31
39
  def initialize
32
40
  @providers = {}
33
41
  @session_offload_options = nil
42
+ @processor = nil
34
43
  end
35
44
 
36
45
  # Register a provider.
data/lib/patient_llm.rb CHANGED
@@ -156,8 +156,11 @@ module PatientLLM
156
156
  # @param max_tool_iterations [Integer, nil] Maximum automatic tool-execution rounds
157
157
  # for this request. Overrides the provider's setting; defaults to
158
158
  # {Callback::MAX_TOOL_ITERATIONS}.
159
+ # @param processor [String, Symbol, nil] Name of the PatientHttp processor that
160
+ # should execute this request. Overrides the configuration's processor;
161
+ # defaults to nil, which uses the default processor.
159
162
  # @return [Object] Handler-specific identifier for the enqueued request
160
- def ask(session, provider:, callback:, callback_args: {}, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil)
163
+ def ask(session, provider:, callback:, callback_args: {}, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil, processor: nil)
161
164
  request_options = build_request_options(
162
165
  url: url,
163
166
  serializer: serializer,
@@ -166,7 +169,8 @@ module PatientLLM
166
169
  params: params,
167
170
  preprocessors: preprocessors,
168
171
  timeout: timeout,
169
- max_tool_iterations: max_tool_iterations
172
+ max_tool_iterations: max_tool_iterations,
173
+ processor: processor
170
174
  )
171
175
 
172
176
  dispatch(session, provider: provider, callback: callback, callback_args: callback_args, request_options: request_options)
@@ -195,8 +199,10 @@ module PatientLLM
195
199
  # @param timeout [Numeric, nil] Accepted for parity with {.ask}; does not affect the preview.
196
200
  # @param max_tool_iterations [Integer, nil] Accepted for parity with {.ask}; does not
197
201
  # affect the preview.
202
+ # @param processor [String, Symbol, nil] Accepted for parity with {.ask}; does not
203
+ # affect the preview.
198
204
  # @return [RequestPreview] The url, headers, and JSON payload the request would send
199
- def preview_request(session, provider:, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil)
205
+ def preview_request(session, provider:, url: nil, serializer: nil, path: nil, headers: nil, params: nil, preprocessors: nil, timeout: nil, max_tool_iterations: nil, processor: nil)
200
206
  request_options = build_request_options(
201
207
  url: url,
202
208
  serializer: serializer,
@@ -205,7 +211,8 @@ module PatientLLM
205
211
  params: params,
206
212
  preprocessors: preprocessors,
207
213
  timeout: timeout,
208
- max_tool_iterations: max_tool_iterations
214
+ max_tool_iterations: max_tool_iterations,
215
+ processor: processor
209
216
  )
210
217
 
211
218
  resolved = resolve_request(session, self.provider(provider) || {}, request_options)
@@ -250,7 +257,8 @@ module PatientLLM
250
257
  json: resolved.payload,
251
258
  headers: resolved.headers,
252
259
  preprocessors: resolved.preprocessors,
253
- timeout: resolved.timeout
260
+ timeout: resolved.timeout,
261
+ processor: resolved.processor
254
262
  )
255
263
  PatientHttp.execute_inline(
256
264
  request: request,
@@ -265,6 +273,7 @@ module PatientLLM
265
273
  headers: resolved.headers,
266
274
  preprocessors: resolved.preprocessors,
267
275
  timeout: resolved.timeout,
276
+ processor: resolved.processor,
268
277
  raise_error_responses: true,
269
278
  callback: PatientLLM::Callback,
270
279
  callback_args: dispatch_callback_args
@@ -276,14 +285,14 @@ module PatientLLM
276
285
 
277
286
  # Fully resolved request produced by merging per-request options over the
278
287
  # provider configuration.
279
- ResolvedRequest = Data.define(:url, :serializer, :headers, :payload, :preprocessors, :timeout, :max_tool_iterations)
288
+ ResolvedRequest = Data.define(:url, :serializer, :headers, :payload, :preprocessors, :timeout, :max_tool_iterations, :processor)
280
289
  private_constant :ResolvedRequest
281
290
 
282
291
  # Normalize per-request overrides into a request options hash. The request
283
292
  # options travel through the job queue in the callback args, which only
284
293
  # permit JSON-native values; convert Symbols (e.g. serializer names,
285
294
  # preprocessor names, header/param values) to Strings up front.
286
- def build_request_options(url:, serializer:, path:, headers:, params:, preprocessors:, timeout:, max_tool_iterations:)
295
+ def build_request_options(url:, serializer:, path:, headers:, params:, preprocessors:, timeout:, max_tool_iterations:, processor:)
287
296
  request_options = {}
288
297
  request_options["url"] = url if url
289
298
  request_options["serializer"] = serializer.to_s if serializer
@@ -293,6 +302,7 @@ module PatientLLM
293
302
  request_options["preprocessors"] = preprocessors if preprocessors
294
303
  request_options["timeout"] = timeout if timeout
295
304
  request_options["max_tool_iterations"] = max_tool_iterations if max_tool_iterations
305
+ request_options["processor"] = processor.to_s if processor
296
306
 
297
307
  PromptBuilder.jsonify(request_options)
298
308
  end
@@ -335,10 +345,19 @@ module PatientLLM
335
345
  payload: payload,
336
346
  preprocessors: request_options["preprocessors"] || provider_config[:preprocessors],
337
347
  timeout: request_options["timeout"] || provider_config[:timeout],
338
- max_tool_iterations: (request_options["max_tool_iterations"] || provider_config[:max_tool_iterations] || Callback::MAX_TOOL_ITERATIONS).to_i
348
+ max_tool_iterations: (request_options["max_tool_iterations"] || provider_config[:max_tool_iterations] || Callback::MAX_TOOL_ITERATIONS).to_i,
349
+ processor: request_options["processor"] || configured_processor
339
350
  )
340
351
  end
341
352
 
353
+ # The processor name from the configuration, calling a callable value and
354
+ # normalizing the result to a String. Nil when no processor is configured.
355
+ def configured_processor
356
+ value = @configuration&.processor
357
+ value = value.call if value.respond_to?(:call)
358
+ value&.to_s
359
+ end
360
+
342
361
  # Replace secret reference header values with placeholders so a preview
343
362
  # never resolves or exposes secret values.
344
363
  def redact_secret_headers(headers)
data/patient_llm.gemspec CHANGED
@@ -37,6 +37,6 @@ Gem::Specification.new do |spec|
37
37
 
38
38
  spec.required_ruby_version = ">= 3.2"
39
39
 
40
- spec.add_dependency "patient_http", "~> 1.3"
40
+ spec.add_dependency "patient_http", ">= 1.5.0"
41
41
  spec.add_dependency "prompt_builder", "~> 0.4"
42
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: patient_llm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Durand
@@ -13,16 +13,16 @@ dependencies:
13
13
  name: patient_http
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '1.3'
18
+ version: 1.5.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - "~>"
23
+ - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '1.3'
25
+ version: 1.5.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: prompt_builder
28
28
  requirement: !ruby/object:Gem::Requirement