patient_llm 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +7 -7
- data/VERSION +1 -1
- data/lib/patient_llm/callback.rb +1 -1
- data/lib/patient_llm/configuration.rb +9 -3
- data/lib/patient_llm.rb +22 -13
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5a3fc235def2976b4a57107239ab72e51a50a2b3abdfed579c0c0d4ea6f681d
|
|
4
|
+
data.tar.gz: 77b63683fc706598ab29e2fa710d9d6650c568712301e1ff4d87bd8a50668228
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e43ffc0679e0ab348e8462884042ba538d734101acfb5b7ecb5e4058167dc3fdd7aa50ad953a091695faae5ad1ce4c25ff1b13614c2ac553587b3568115e8f9a
|
|
7
|
+
data.tar.gz: 034554bf031c5696ddb2bf877463f9cbcf5e57e32cdc39563975de22f0ea6cde189be72cfe053ea1338144b320254196ed51589ded11ba753161e4af544de3e4
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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.3.0
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Renamed the `completion_path` argument to `path` on both `PatientLLM.ask` and provider configuration. The `completion_path` name is still accepted as a deprecated alias and now emits a deprecation warning.
|
|
12
|
+
- The path is now joined with the base URL using `URI.join` to ensure proper handling of relative paths in the `path` argument. If the path starts with a slash, it will be treated as an absolute path and will replace the base URL's path. If it does not start with a slash, it will be treated as a relative path and will be appended to the base URL's path.
|
|
13
|
+
|
|
7
14
|
## 0.2.0
|
|
8
15
|
|
|
9
16
|
### Added
|
data/README.md
CHANGED
|
@@ -185,9 +185,9 @@ session.max_output_tokens = 1000
|
|
|
185
185
|
PatientLLM.ask(session,
|
|
186
186
|
provider: :openai,
|
|
187
187
|
callback: LLMCallback,
|
|
188
|
-
url: "http://localhost:1234",
|
|
188
|
+
url: "http://localhost:1234", # Override the provider's base URL
|
|
189
189
|
serializer: :messages, # Override the API format
|
|
190
|
-
|
|
190
|
+
path: "/chat/completions", # Override the endpoint path
|
|
191
191
|
headers: {"X-Custom" => "value"}, # Additional HTTP headers
|
|
192
192
|
params: {max_completion_tokens: 1000} # Additional request parameters
|
|
193
193
|
)
|
|
@@ -195,24 +195,24 @@ PatientLLM.ask(session,
|
|
|
195
195
|
|
|
196
196
|
### URL composition
|
|
197
197
|
|
|
198
|
-
The full request URL is built by concatenating the base URL (from the provider registry or the `url:` option) with the `
|
|
198
|
+
The full request URL is built by concatenating the base URL (from the provider registry or the `url:` option) with the `path`. When you don't set `path`, it defaults to the path for the active serializer (`/v1/chat/completions` for `:chat_completion`, `/v1/responses` for `:open_responses`, `/v1/messages` for `:messages`, `/converse` for `:converse`, `/v1beta/models/{model}:generateContent` for `:gemini`). A `{model}` placeholder in the path is replaced with the session's model at dispatch time, which is how the Gemini default targets Google's `/v1beta/models/{model}:generateContent` endpoint. Trailing slashes on the base and leading slashes on the path are normalized, so:
|
|
199
199
|
|
|
200
200
|
```
|
|
201
|
-
url = "https://api.openai.com"
|
|
201
|
+
url = "https://api.openai.com" path = "/v1/chat/completions"
|
|
202
202
|
-> https://api.openai.com/v1/chat/completions
|
|
203
203
|
|
|
204
|
-
url = "http://localhost:1234"
|
|
204
|
+
url = "http://localhost:1234" path = "/v1/chat/completions"
|
|
205
205
|
-> http://localhost:1234/v1/chat/completions
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
If your base URL already includes a `/v1` prefix, override the
|
|
208
|
+
If your base URL already includes a `/v1` prefix, override the path to avoid duplication:
|
|
209
209
|
|
|
210
210
|
```ruby
|
|
211
211
|
PatientLLM.ask(session,
|
|
212
212
|
provider: :openai,
|
|
213
213
|
callback: LLMCallback,
|
|
214
214
|
url: "https://my-gateway.internal/openai/v1",
|
|
215
|
-
|
|
215
|
+
path: "chat/completions"
|
|
216
216
|
)
|
|
217
217
|
```
|
|
218
218
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.3.0
|
data/lib/patient_llm/callback.rb
CHANGED
|
@@ -213,7 +213,7 @@ module PatientLLM
|
|
|
213
213
|
# Restore per-request overrides
|
|
214
214
|
ask_kwargs[:url] = request_options["url"] if request_options["url"]
|
|
215
215
|
ask_kwargs[:serializer] = request_options["serializer"].to_sym if request_options["serializer"]
|
|
216
|
-
ask_kwargs[:
|
|
216
|
+
ask_kwargs[:path] = request_options["path"] if request_options["path"]
|
|
217
217
|
ask_kwargs[:headers] = request_options["headers"] if request_options["headers"]
|
|
218
218
|
ask_kwargs[:params] = request_options["params"] if request_options["params"]
|
|
219
219
|
|
|
@@ -26,10 +26,16 @@ module PatientLLM
|
|
|
26
26
|
# @param url [String] Base URL for the provider API
|
|
27
27
|
# @param headers [Hash] Default headers for requests
|
|
28
28
|
# @param serializer [Symbol] API format (:chat_completion, :open_responses, :messages, :converse, :gemini)
|
|
29
|
-
# @param
|
|
29
|
+
# @param path [String, nil] Override the default endpoint path
|
|
30
|
+
# @param completion_path [String, nil] Deprecated alias for +path+
|
|
30
31
|
# @param params [Hash] Additional parameters to merge into every request payload
|
|
31
32
|
# @return [void]
|
|
32
|
-
def provider(name, url:, headers: {}, serializer: :chat_completion, completion_path: nil, params: {})
|
|
33
|
+
def provider(name, url:, headers: {}, serializer: :chat_completion, path: nil, completion_path: nil, params: {})
|
|
34
|
+
if completion_path
|
|
35
|
+
warn "PatientLLM::Configuration#provider: the `completion_path:` argument is deprecated; use `path:` instead", uplevel: 1
|
|
36
|
+
path ||= completion_path
|
|
37
|
+
end
|
|
38
|
+
|
|
33
39
|
sym = serializer.to_sym
|
|
34
40
|
unless PatientLLM::VALID_SERIALIZERS.include?(sym)
|
|
35
41
|
raise ArgumentError, "Unknown serializer: #{sym.inspect}. Valid options: #{PatientLLM::VALID_SERIALIZERS.map(&:inspect).join(", ")}"
|
|
@@ -41,7 +47,7 @@ module PatientLLM
|
|
|
41
47
|
url: url,
|
|
42
48
|
headers: headers,
|
|
43
49
|
serializer: sym,
|
|
44
|
-
|
|
50
|
+
path: path,
|
|
45
51
|
params: params
|
|
46
52
|
}
|
|
47
53
|
end
|
data/lib/patient_llm.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "patient_http"
|
|
4
4
|
require "prompt_builder"
|
|
5
|
+
require "uri"
|
|
5
6
|
|
|
6
7
|
module PatientLLM
|
|
7
8
|
VERSION = File.read(File.join(__dir__, "../VERSION")).strip
|
|
@@ -16,11 +17,11 @@ module PatientLLM
|
|
|
16
17
|
# dispatch time, matching Google's `/v1beta/models/{model}:generateContent`
|
|
17
18
|
# endpoint.
|
|
18
19
|
SERIALIZER_PATHS = {
|
|
19
|
-
chat_completion: "
|
|
20
|
-
open_responses: "
|
|
21
|
-
messages: "
|
|
22
|
-
converse: "
|
|
23
|
-
gemini: "
|
|
20
|
+
chat_completion: "v1/chat/completions",
|
|
21
|
+
open_responses: "v1/responses",
|
|
22
|
+
messages: "v1/messages",
|
|
23
|
+
converse: "converse",
|
|
24
|
+
gemini: "v1beta/models/{model}:generateContent"
|
|
24
25
|
}.freeze
|
|
25
26
|
|
|
26
27
|
# Required version header for the Anthropic Messages API.
|
|
@@ -62,11 +63,17 @@ module PatientLLM
|
|
|
62
63
|
# @param callback_args [Hash] Custom arguments passed through to the callback
|
|
63
64
|
# @param url [String, nil] Override the provider's base URL for this request
|
|
64
65
|
# @param serializer [Symbol, nil] Override the provider's serializer for this request
|
|
65
|
-
# @param
|
|
66
|
+
# @param path [String, nil] Override the endpoint path for this request
|
|
67
|
+
# @param completion_path [String, nil] Deprecated alias for +path+
|
|
66
68
|
# @param headers [Hash, nil] Additional headers merged on top of provider headers
|
|
67
69
|
# @param params [Hash, nil] Additional params merged into the request payload
|
|
68
70
|
# @return [Object] Handler-specific identifier for the enqueued request
|
|
69
|
-
def ask(session, provider:, callback:, callback_args: {}, url: nil, serializer: nil, completion_path: nil, headers: nil, params: nil, tool_iteration: 0, original_request_id: nil) # :nodoc: tool_iteration and original_request_id are internal
|
|
71
|
+
def ask(session, provider:, callback:, callback_args: {}, url: nil, serializer: nil, path: nil, completion_path: nil, headers: nil, params: nil, tool_iteration: 0, original_request_id: nil) # :nodoc: tool_iteration and original_request_id are internal
|
|
72
|
+
if completion_path
|
|
73
|
+
warn "PatientLLM.ask: the `completion_path:` argument is deprecated; use `path:` instead", uplevel: 1
|
|
74
|
+
path ||= completion_path
|
|
75
|
+
end
|
|
76
|
+
|
|
70
77
|
provider_config = self.provider(provider) || {}
|
|
71
78
|
provider_name = provider.to_s
|
|
72
79
|
|
|
@@ -79,9 +86,9 @@ module PatientLLM
|
|
|
79
86
|
|
|
80
87
|
resolved_serializer = (serializer || provider_config[:serializer] || :chat_completion).to_sym
|
|
81
88
|
validate_serializer!(resolved_serializer)
|
|
82
|
-
|
|
83
|
-
if
|
|
84
|
-
|
|
89
|
+
resolved_path = path || provider_config[:path] || SERIALIZER_PATHS[resolved_serializer] || "/v1/chat/completions"
|
|
90
|
+
if resolved_path.include?("{model}")
|
|
91
|
+
resolved_path = resolved_path.gsub("{model}", session.model.to_s)
|
|
85
92
|
end
|
|
86
93
|
resolved_headers = (provider_config[:headers] || {}).merge(headers || {})
|
|
87
94
|
if resolved_serializer == :messages && !resolved_headers.key?("anthropic-version")
|
|
@@ -92,12 +99,12 @@ module PatientLLM
|
|
|
92
99
|
payload = session.request_payload(resolved_serializer)
|
|
93
100
|
payload = deep_merge(payload, deep_stringify_keys(resolved_params)) unless resolved_params.empty?
|
|
94
101
|
|
|
95
|
-
request_url = join_url(resolved_url,
|
|
102
|
+
request_url = join_url(resolved_url, resolved_path)
|
|
96
103
|
|
|
97
104
|
request_options = {}
|
|
98
105
|
request_options["url"] = url if url
|
|
99
106
|
request_options["serializer"] = serializer.to_s if serializer
|
|
100
|
-
request_options["
|
|
107
|
+
request_options["path"] = path if path
|
|
101
108
|
request_options["headers"] = headers if headers && !headers.empty?
|
|
102
109
|
request_options["params"] = params if params && !params.empty?
|
|
103
110
|
|
|
@@ -128,7 +135,9 @@ module PatientLLM
|
|
|
128
135
|
end
|
|
129
136
|
|
|
130
137
|
def join_url(base, path)
|
|
131
|
-
|
|
138
|
+
base_uri = URI.parse(base)
|
|
139
|
+
base_uri.path = "#{base_uri.path}/" unless base_uri.path&.end_with?("/")
|
|
140
|
+
URI.join(base_uri, path).to_s
|
|
132
141
|
end
|
|
133
142
|
|
|
134
143
|
def deep_merge(hash1, hash2)
|