lm-deluge 0.0.41__tar.gz → 0.0.42__tar.gz

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.

Potentially problematic release.


This version of lm-deluge might be problematic. Click here for more details.

Files changed (78) hide show
  1. {lm_deluge-0.0.41/src/lm_deluge.egg-info → lm_deluge-0.0.42}/PKG-INFO +1 -1
  2. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/pyproject.toml +1 -1
  3. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/bedrock.py +151 -32
  4. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/openai.py +8 -0
  5. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/client.py +3 -1
  6. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/bedrock.py +29 -0
  7. {lm_deluge-0.0.41 → lm_deluge-0.0.42/src/lm_deluge.egg-info}/PKG-INFO +1 -1
  8. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/LICENSE +0 -0
  9. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/README.md +0 -0
  10. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/setup.cfg +0 -0
  11. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/__init__.py +0 -0
  12. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/agent.py +0 -0
  13. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/__init__.py +0 -0
  14. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/anthropic.py +0 -0
  15. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/base.py +0 -0
  16. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/common.py +0 -0
  17. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/deprecated/bedrock.py +0 -0
  18. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/deprecated/cohere.py +0 -0
  19. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/deprecated/deepseek.py +0 -0
  20. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/deprecated/mistral.py +0 -0
  21. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/deprecated/vertex.py +0 -0
  22. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/gemini.py +0 -0
  23. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/mistral.py +0 -0
  24. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/api_requests/response.py +0 -0
  25. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/batches.py +0 -0
  26. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/anthropic/__init__.py +0 -0
  27. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/anthropic/bash.py +0 -0
  28. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/anthropic/computer_use.py +0 -0
  29. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/anthropic/editor.py +0 -0
  30. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/base.py +0 -0
  31. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/built_in_tools/openai.py +0 -0
  32. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/cache.py +0 -0
  33. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/cli.py +0 -0
  34. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/config.py +0 -0
  35. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/embed.py +0 -0
  36. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/errors.py +0 -0
  37. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/file.py +0 -0
  38. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/gemini_limits.py +0 -0
  39. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/image.py +0 -0
  40. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/__init__.py +0 -0
  41. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/classify.py +0 -0
  42. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/extract.py +0 -0
  43. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/locate.py +0 -0
  44. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/ocr.py +0 -0
  45. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/score.py +0 -0
  46. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/llm_tools/translate.py +0 -0
  47. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/__init__.py +0 -0
  48. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/anthropic.py +0 -0
  49. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/cerebras.py +0 -0
  50. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/cohere.py +0 -0
  51. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/deepseek.py +0 -0
  52. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/fireworks.py +0 -0
  53. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/google.py +0 -0
  54. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/grok.py +0 -0
  55. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/groq.py +0 -0
  56. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/meta.py +0 -0
  57. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/mistral.py +0 -0
  58. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/openai.py +0 -0
  59. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/openrouter.py +0 -0
  60. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/models/together.py +0 -0
  61. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/prompt.py +0 -0
  62. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/request_context.py +0 -0
  63. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/rerank.py +0 -0
  64. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/tool.py +0 -0
  65. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/tracker.py +0 -0
  66. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/usage.py +0 -0
  67. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/harmony.py +0 -0
  68. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/json.py +0 -0
  69. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/logprobs.py +0 -0
  70. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/spatial.py +0 -0
  71. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/validation.py +0 -0
  72. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge/util/xml.py +0 -0
  73. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge.egg-info/SOURCES.txt +0 -0
  74. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge.egg-info/dependency_links.txt +0 -0
  75. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge.egg-info/requires.txt +0 -0
  76. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/src/lm_deluge.egg-info/top_level.txt +0 -0
  77. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/tests/test_builtin_tools.py +0 -0
  78. {lm_deluge-0.0.41 → lm_deluge-0.0.42}/tests/test_native_mcp_server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lm_deluge
3
- Version: 0.0.41
3
+ Version: 0.0.42
4
4
  Summary: Python utility for using LLM API models.
5
5
  Author-email: Benjamin Anderson <ben@trytaylor.ai>
6
6
  Requires-Python: >=3.10
@@ -3,7 +3,7 @@ requires = ["setuptools", "wheel"]
3
3
 
4
4
  [project]
5
5
  name = "lm_deluge"
6
- version = "0.0.41"
6
+ version = "0.0.42"
7
7
  authors = [{ name = "Benjamin Anderson", email = "ben@trytaylor.ai" }]
8
8
  description = "Python utility for using LLM API models."
9
9
  readme = "README.md"
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import json
3
3
  import os
4
+ import warnings
4
5
 
5
6
  from aiohttp import ClientResponse
6
7
 
@@ -135,27 +136,110 @@ async def _build_anthropic_bedrock_request(
135
136
  return request_json, base_headers, auth, url, region
136
137
 
137
138
 
139
+ async def _build_openai_bedrock_request(
140
+ model: APIModel,
141
+ context: RequestContext,
142
+ ):
143
+ prompt = context.prompt
144
+ tools = context.tools
145
+ sampling_params = context.sampling_params
146
+
147
+ # Handle AWS auth
148
+ access_key = os.getenv("AWS_ACCESS_KEY_ID")
149
+ secret_key = os.getenv("AWS_SECRET_ACCESS_KEY")
150
+ session_token = os.getenv("AWS_SESSION_TOKEN")
151
+
152
+ if not access_key or not secret_key:
153
+ raise ValueError(
154
+ "AWS credentials not found. Please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables."
155
+ )
156
+
157
+ # Determine region - GPT-OSS is available in us-west-2
158
+ region = "us-west-2"
159
+
160
+ # Construct the endpoint URL for OpenAI-compatible endpoint
161
+ service = "bedrock"
162
+ url = f"https://bedrock-runtime.{region}.amazonaws.com/openai/v1/chat/completions"
163
+
164
+ # Prepare headers
165
+ auth = AWS4Auth(
166
+ access_key,
167
+ secret_key,
168
+ region,
169
+ service,
170
+ session_token=session_token,
171
+ )
172
+
173
+ # Setup basic headers (AWS4Auth will add the Authorization header)
174
+ base_headers = {
175
+ "Content-Type": "application/json",
176
+ }
177
+
178
+ # Prepare request body in OpenAI format
179
+ request_json = {
180
+ "model": model.name,
181
+ "messages": prompt.to_openai(),
182
+ "temperature": sampling_params.temperature,
183
+ "top_p": sampling_params.top_p,
184
+ "max_completion_tokens": sampling_params.max_new_tokens,
185
+ }
186
+
187
+ # Note: GPT-OSS on Bedrock doesn't support response_format parameter
188
+ # Even though the model supports JSON, we can't use the response_format parameter
189
+ if sampling_params.json_mode and model.supports_json:
190
+ warnings.warn(
191
+ f"JSON mode requested for {model.name} but response_format parameter not supported on Bedrock"
192
+ )
193
+
194
+ if tools:
195
+ request_tools = []
196
+ for tool in tools:
197
+ if isinstance(tool, Tool):
198
+ request_tools.append(tool.dump_for("openai-completions"))
199
+ elif isinstance(tool, MCPServer):
200
+ as_tools = await tool.to_tools()
201
+ request_tools.extend(
202
+ [t.dump_for("openai-completions") for t in as_tools]
203
+ )
204
+ request_json["tools"] = request_tools
205
+
206
+ return request_json, base_headers, auth, url, region
207
+
208
+
138
209
  class BedrockRequest(APIRequestBase):
139
210
  def __init__(self, context: RequestContext):
140
211
  super().__init__(context=context)
141
212
 
142
213
  self.model = APIModel.from_registry(self.context.model_name)
143
214
  self.region = None # Will be set during build_request
215
+ self.is_openai_model = self.model.name.startswith("openai.")
144
216
 
145
217
  async def build_request(self):
146
- self.url = f"{self.model.api_base}/messages"
147
-
148
- # Lock images as bytes if caching is enabled
149
- if self.context.cache is not None:
150
- self.context.prompt.lock_images_as_bytes()
151
-
152
- (
153
- self.request_json,
154
- base_headers,
155
- self.auth,
156
- self.url,
157
- self.region,
158
- ) = await _build_anthropic_bedrock_request(self.model, self.context)
218
+ if self.is_openai_model:
219
+ # Use OpenAI-compatible endpoint
220
+ (
221
+ self.request_json,
222
+ base_headers,
223
+ self.auth,
224
+ self.url,
225
+ self.region,
226
+ ) = await _build_openai_bedrock_request(self.model, self.context)
227
+ else:
228
+ # Use Anthropic-style endpoint
229
+ self.url = f"{self.model.api_base}/messages"
230
+
231
+ # Lock images as bytes if caching is enabled
232
+ if self.context.cache is not None:
233
+ self.context.prompt.lock_images_as_bytes()
234
+
235
+ (
236
+ self.request_json,
237
+ base_headers,
238
+ self.auth,
239
+ self.url,
240
+ self.region,
241
+ ) = await _build_anthropic_bedrock_request(self.model, self.context)
242
+
159
243
  self.request_header = self.merge_headers(
160
244
  base_headers, exclude_patterns=["anthropic", "openai", "gemini", "mistral"]
161
245
  )
@@ -232,34 +316,64 @@ class BedrockRequest(APIRequestBase):
232
316
  thinking = None
233
317
  content = None
234
318
  usage = None
319
+ finish_reason = None
235
320
  status_code = http_response.status
236
321
  mimetype = http_response.headers.get("Content-Type", None)
322
+ data = None
237
323
  assert self.context.status_tracker
238
324
 
239
325
  if status_code >= 200 and status_code < 300:
240
326
  try:
241
327
  data = await http_response.json()
242
- response_content = data["content"]
243
-
244
- # Parse response into Message with parts
245
- parts = []
246
- for item in response_content:
247
- if item["type"] == "text":
248
- parts.append(Text(item["text"]))
249
- elif item["type"] == "thinking":
250
- thinking = item["thinking"]
251
- parts.append(Thinking(item["thinking"]))
252
- elif item["type"] == "tool_use":
253
- parts.append(
254
- ToolCall(
255
- id=item["id"],
256
- name=item["name"],
257
- arguments=item["input"],
328
+
329
+ if self.is_openai_model:
330
+ # Handle OpenAI-style response
331
+ parts = []
332
+ message = data["choices"][0]["message"]
333
+ finish_reason = data["choices"][0]["finish_reason"]
334
+
335
+ # Add text content if present
336
+ if message.get("content"):
337
+ parts.append(Text(message["content"]))
338
+
339
+ # Add tool calls if present
340
+ if "tool_calls" in message:
341
+ for tool_call in message["tool_calls"]:
342
+ parts.append(
343
+ ToolCall(
344
+ id=tool_call["id"],
345
+ name=tool_call["function"]["name"],
346
+ arguments=json.loads(
347
+ tool_call["function"]["arguments"]
348
+ ),
349
+ )
350
+ )
351
+
352
+ content = Message("assistant", parts)
353
+ usage = Usage.from_openai_usage(data["usage"])
354
+ else:
355
+ # Handle Anthropic-style response
356
+ response_content = data["content"]
357
+
358
+ # Parse response into Message with parts
359
+ parts = []
360
+ for item in response_content:
361
+ if item["type"] == "text":
362
+ parts.append(Text(item["text"]))
363
+ elif item["type"] == "thinking":
364
+ thinking = item["thinking"]
365
+ parts.append(Thinking(item["thinking"]))
366
+ elif item["type"] == "tool_use":
367
+ parts.append(
368
+ ToolCall(
369
+ id=item["id"],
370
+ name=item["name"],
371
+ arguments=item["input"],
372
+ )
258
373
  )
259
- )
260
374
 
261
- content = Message("assistant", parts)
262
- usage = Usage.from_anthropic_usage(data["usage"])
375
+ content = Message("assistant", parts)
376
+ usage = Usage.from_anthropic_usage(data["usage"])
263
377
  except Exception as e:
264
378
  is_error = True
265
379
  error_message = (
@@ -275,6 +389,7 @@ class BedrockRequest(APIRequestBase):
275
389
  error_message = text
276
390
 
277
391
  # Handle special kinds of errors
392
+ retry_with_different_model = status_code in [529, 429, 400, 401, 403, 413]
278
393
  if is_error and error_message is not None:
279
394
  if (
280
395
  "rate limit" in error_message.lower()
@@ -286,6 +401,7 @@ class BedrockRequest(APIRequestBase):
286
401
  if "context length" in error_message or "too long" in error_message:
287
402
  error_message += " (Context length exceeded, set retries to 0.)"
288
403
  self.context.attempts_left = 0
404
+ retry_with_different_model = True
289
405
 
290
406
  return APIResponse(
291
407
  id=self.context.task_id,
@@ -299,4 +415,7 @@ class BedrockRequest(APIRequestBase):
299
415
  region=self.region,
300
416
  sampling_params=self.context.sampling_params,
301
417
  usage=usage,
418
+ raw_response=data,
419
+ finish_reason=finish_reason,
420
+ retry_with_different_model=retry_with_different_model,
302
421
  )
@@ -113,6 +113,9 @@ class OpenAIRequest(APIRequestBase):
113
113
  finish_reason = None
114
114
  assert self.context.status_tracker
115
115
 
116
+ if status_code == 500:
117
+ print("Internal Server Error: ", (await http_response.text()))
118
+
116
119
  if status_code >= 200 and status_code < 300:
117
120
  try:
118
121
  data = await http_response.json()
@@ -305,6 +308,9 @@ class OpenAIResponsesRequest(APIRequestBase):
305
308
  data = None
306
309
  assert self.context.status_tracker
307
310
 
311
+ if status_code == 500:
312
+ print("Internal Server Error: ", http_response.text())
313
+
308
314
  if status_code >= 200 and status_code < 300:
309
315
  try:
310
316
  data = await http_response.json()
@@ -428,10 +434,12 @@ class OpenAIResponsesRequest(APIRequestBase):
428
434
  error_message = f"Error parsing {self.model.name} responses API response: {str(e)}"
429
435
 
430
436
  elif mimetype and "json" in mimetype.lower():
437
+ print("is_error True, json response")
431
438
  is_error = True
432
439
  data = await http_response.json()
433
440
  error_message = json.dumps(data)
434
441
  else:
442
+ print("is_error True, non-json response")
435
443
  is_error = True
436
444
  text = await http_response.text()
437
445
  error_message = text
@@ -294,7 +294,7 @@ class _LLMClient(BaseModel):
294
294
 
295
295
  # Print error message for debugging
296
296
  error_msg = (
297
- f"Error task {context.task_id}. Model: {response.model_internal}"
297
+ f"😔 Error task {context.task_id}. Model: {response.model_internal}"
298
298
  )
299
299
  if response.status_code:
300
300
  error_msg += f" Code: {response.status_code},"
@@ -474,6 +474,7 @@ class _LLMClient(BaseModel):
474
474
  show_progress=True,
475
475
  tools: list[Tool | dict | MCPServer] | None = None,
476
476
  cache: CachePattern | None = None,
477
+ use_responses_api: bool = False,
477
478
  ):
478
479
  return asyncio.run(
479
480
  self.process_prompts_async(
@@ -482,6 +483,7 @@ class _LLMClient(BaseModel):
482
483
  show_progress=show_progress,
483
484
  tools=tools,
484
485
  cache=cache,
486
+ use_responses_api=use_responses_api,
485
487
  )
486
488
  )
487
489
 
@@ -96,4 +96,33 @@ BEDROCK_MODELS = {
96
96
  "tokens_per_minute": 400_000,
97
97
  "reasoning_model": True,
98
98
  },
99
+ # GPT-OSS on AWS Bedrock
100
+ "gpt-oss-120b-bedrock": {
101
+ "id": "gpt-oss-120b-bedrock",
102
+ "name": "openai.gpt-oss-120b-1:0",
103
+ "regions": ["us-west-2"],
104
+ "api_base": "",
105
+ "api_key_env_var": "",
106
+ "api_spec": "bedrock",
107
+ "input_cost": 0.0,
108
+ "output_cost": 0.0,
109
+ "supports_json": False,
110
+ "supports_logprobs": False,
111
+ "supports_responses": False,
112
+ "reasoning_model": False,
113
+ },
114
+ "gpt-oss-20b-bedrock": {
115
+ "id": "gpt-oss-20b-bedrock",
116
+ "name": "openai.gpt-oss-20b-1:0",
117
+ "regions": ["us-west-2"],
118
+ "api_base": "",
119
+ "api_key_env_var": "",
120
+ "api_spec": "bedrock",
121
+ "input_cost": 0.0,
122
+ "output_cost": 0.0,
123
+ "supports_json": False,
124
+ "supports_logprobs": False,
125
+ "supports_responses": False,
126
+ "reasoning_model": False,
127
+ },
99
128
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lm_deluge
3
- Version: 0.0.41
3
+ Version: 0.0.42
4
4
  Summary: Python utility for using LLM API models.
5
5
  Author-email: Benjamin Anderson <ben@trytaylor.ai>
6
6
  Requires-Python: >=3.10
File without changes
File without changes
File without changes