ask-llm-providers 0.1.1 → 0.1.2
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/lib/ask/llm/version.rb +1 -1
- data/lib/ask/provider/openai.rb +27 -7
- 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: b0b23746b8ee8cc98e50c44f9e88df977ea81d9214bbda9a25be770021234cc2
|
|
4
|
+
data.tar.gz: 2a2e628b12eb8e731ea9d46ae0f4076dd42591f03db0cf50759d77d6485e748e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e31b5f82ae3aaab7a7bf337df1ebd5afc20b272efc2b630523145bbf82ebbd12faddcaacdb30e531df3cd3a379a82d9d2e96b97d9ff33877eff6eb0c638d320
|
|
7
|
+
data.tar.gz: 2db527541cb1a8934c6f5ff2e62fbb8ebddf633600e332b040231461eaf9c9b5cb37ec3a70f0079a85404cf8b5fb3751c4f9b88ef075366681044d046ebfdd6b
|
data/lib/ask/llm/version.rb
CHANGED
data/lib/ask/provider/openai.rb
CHANGED
|
@@ -7,6 +7,7 @@ module Ask
|
|
|
7
7
|
# +base_url+ override.
|
|
8
8
|
class OpenAI < Ask::Provider
|
|
9
9
|
def initialize(config = {})
|
|
10
|
+
@provider_keys = extract_provider_keys(config)
|
|
10
11
|
config = normalize_config(config)
|
|
11
12
|
super(config)
|
|
12
13
|
@http = build_http
|
|
@@ -57,22 +58,31 @@ module Ask
|
|
|
57
58
|
end
|
|
58
59
|
def configuration_options; %i[api_key base_url organization_id project_id]; end
|
|
59
60
|
def configuration_requirements; %i[api_key]; end
|
|
60
|
-
def
|
|
61
|
-
(config.respond_to?(:api_key) && !config.api_key.to_s.empty?) ||
|
|
62
|
-
(config.respond_to?(:openai_api_key) && !config.openai_api_key.to_s.empty?)
|
|
63
|
-
end
|
|
61
|
+
def assume_models_exist?; false; end
|
|
64
62
|
end
|
|
65
63
|
|
|
66
64
|
private
|
|
67
65
|
|
|
66
|
+
# Extract and store any provider-specific config keys (e.g., opencode_api_key).
|
|
67
|
+
# These are not part of the standard OpenAI config but are used by subclasses.
|
|
68
|
+
def extract_provider_keys(config)
|
|
69
|
+
return {} unless config.is_a?(Hash)
|
|
70
|
+
known = %i[api_key base_url organization_id project_id openai_api_key]
|
|
71
|
+
config.reject { |k, _| known.include?(k.to_sym) }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Restore provider-specific keys after normalize_config strips standard ones.
|
|
68
75
|
def normalize_config(config)
|
|
69
76
|
return config if !config.is_a?(Hash)
|
|
70
|
-
|
|
77
|
+
|
|
78
|
+
merged = {
|
|
71
79
|
api_key: config[:api_key] || config["api_key"] || config[:openai_api_key],
|
|
72
80
|
base_url: config[:base_url] || config["base_url"],
|
|
73
81
|
organization_id: config[:organization_id] || config["organization_id"],
|
|
74
82
|
project_id: config[:project_id] || config["project_id"]
|
|
75
|
-
)
|
|
83
|
+
}.merge(@provider_keys)
|
|
84
|
+
|
|
85
|
+
Ask::LLM::Config.new(merged)
|
|
76
86
|
end
|
|
77
87
|
|
|
78
88
|
def build_http
|
|
@@ -140,12 +150,22 @@ module Ask
|
|
|
140
150
|
parsed = JSON.parse(data) rescue next
|
|
141
151
|
choice = parsed.dig("choices", 0) or next
|
|
142
152
|
delta = choice["delta"] || {}
|
|
143
|
-
|
|
153
|
+
thinking = extract_thinking(parsed, delta)
|
|
154
|
+
chunk = Ask::Chunk.new(content: delta["content"], tool_calls: parse_stream_tool_calls(delta["tool_calls"]), finish_reason: choice["finish_reason"], usage: parsed["usage"], thinking: thinking)
|
|
144
155
|
stream.add(chunk)
|
|
145
156
|
yield chunk if block_given?
|
|
146
157
|
end
|
|
147
158
|
end
|
|
148
159
|
|
|
160
|
+
# Extract thinking/reasoning content from provider response.
|
|
161
|
+
# Some providers (Anthropic, DeepSeek) send thinking in a separate field.
|
|
162
|
+
def extract_thinking(parsed, delta)
|
|
163
|
+
delta["reasoning_content"] || delta["thinking"] ||
|
|
164
|
+
parsed.dig("choices", 0, "delta", "reasoning_content") ||
|
|
165
|
+
parsed.dig("choices", 0, "delta", "thinking") ||
|
|
166
|
+
parsed.dig("choices", 0, "reasoning_content")
|
|
167
|
+
end
|
|
168
|
+
|
|
149
169
|
def parse_stream_tool_calls(calls)
|
|
150
170
|
return nil unless calls&.any?
|
|
151
171
|
calls.map { |tc| { id: tc["id"], name: tc.dig("function", "name"), arguments: tc.dig("function", "arguments"), index: tc["index"] } }
|