aient 1.1.86__tar.gz → 1.1.88__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.
Files changed (51) hide show
  1. {aient-1.1.86 → aient-1.1.88}/PKG-INFO +1 -1
  2. {aient-1.1.86 → aient-1.1.88}/aient/core/response.py +13 -3
  3. {aient-1.1.86 → aient-1.1.88}/aient/core/utils.py +28 -1
  4. {aient-1.1.86 → aient-1.1.88}/aient/models/chatgpt.py +3 -0
  5. {aient-1.1.86 → aient-1.1.88}/aient.egg-info/PKG-INFO +1 -1
  6. {aient-1.1.86 → aient-1.1.88}/pyproject.toml +1 -1
  7. {aient-1.1.86 → aient-1.1.88}/LICENSE +0 -0
  8. {aient-1.1.86 → aient-1.1.88}/README.md +0 -0
  9. {aient-1.1.86 → aient-1.1.88}/aient/__init__.py +0 -0
  10. {aient-1.1.86 → aient-1.1.88}/aient/core/__init__.py +0 -0
  11. {aient-1.1.86 → aient-1.1.88}/aient/core/log_config.py +0 -0
  12. {aient-1.1.86 → aient-1.1.88}/aient/core/models.py +0 -0
  13. {aient-1.1.86 → aient-1.1.88}/aient/core/request.py +0 -0
  14. {aient-1.1.86 → aient-1.1.88}/aient/core/test/test_base_api.py +0 -0
  15. {aient-1.1.86 → aient-1.1.88}/aient/core/test/test_geminimask.py +0 -0
  16. {aient-1.1.86 → aient-1.1.88}/aient/core/test/test_image.py +0 -0
  17. {aient-1.1.86 → aient-1.1.88}/aient/core/test/test_payload.py +0 -0
  18. {aient-1.1.86 → aient-1.1.88}/aient/models/__init__.py +0 -0
  19. {aient-1.1.86 → aient-1.1.88}/aient/models/audio.py +0 -0
  20. {aient-1.1.86 → aient-1.1.88}/aient/models/base.py +0 -0
  21. {aient-1.1.86 → aient-1.1.88}/aient/plugins/__init__.py +0 -0
  22. {aient-1.1.86 → aient-1.1.88}/aient/plugins/arXiv.py +0 -0
  23. {aient-1.1.86 → aient-1.1.88}/aient/plugins/config.py +0 -0
  24. {aient-1.1.86 → aient-1.1.88}/aient/plugins/excute_command.py +0 -0
  25. {aient-1.1.86 → aient-1.1.88}/aient/plugins/get_time.py +0 -0
  26. {aient-1.1.86 → aient-1.1.88}/aient/plugins/image.py +0 -0
  27. {aient-1.1.86 → aient-1.1.88}/aient/plugins/list_directory.py +0 -0
  28. {aient-1.1.86 → aient-1.1.88}/aient/plugins/read_file.py +0 -0
  29. {aient-1.1.86 → aient-1.1.88}/aient/plugins/read_image.py +0 -0
  30. {aient-1.1.86 → aient-1.1.88}/aient/plugins/readonly.py +0 -0
  31. {aient-1.1.86 → aient-1.1.88}/aient/plugins/registry.py +0 -0
  32. {aient-1.1.86 → aient-1.1.88}/aient/plugins/run_python.py +0 -0
  33. {aient-1.1.86 → aient-1.1.88}/aient/plugins/websearch.py +0 -0
  34. {aient-1.1.86 → aient-1.1.88}/aient/plugins/write_file.py +0 -0
  35. {aient-1.1.86 → aient-1.1.88}/aient/utils/__init__.py +0 -0
  36. {aient-1.1.86 → aient-1.1.88}/aient/utils/prompt.py +0 -0
  37. {aient-1.1.86 → aient-1.1.88}/aient/utils/scripts.py +0 -0
  38. {aient-1.1.86 → aient-1.1.88}/aient.egg-info/SOURCES.txt +0 -0
  39. {aient-1.1.86 → aient-1.1.88}/aient.egg-info/dependency_links.txt +0 -0
  40. {aient-1.1.86 → aient-1.1.88}/aient.egg-info/requires.txt +0 -0
  41. {aient-1.1.86 → aient-1.1.88}/aient.egg-info/top_level.txt +0 -0
  42. {aient-1.1.86 → aient-1.1.88}/setup.cfg +0 -0
  43. {aient-1.1.86 → aient-1.1.88}/test/test_Web_crawler.py +0 -0
  44. {aient-1.1.86 → aient-1.1.88}/test/test_ddg_search.py +0 -0
  45. {aient-1.1.86 → aient-1.1.88}/test/test_google_search.py +0 -0
  46. {aient-1.1.86 → aient-1.1.88}/test/test_ollama.py +0 -0
  47. {aient-1.1.86 → aient-1.1.88}/test/test_plugin.py +0 -0
  48. {aient-1.1.86 → aient-1.1.88}/test/test_search.py +0 -0
  49. {aient-1.1.86 → aient-1.1.88}/test/test_url.py +0 -0
  50. {aient-1.1.86 → aient-1.1.88}/test/test_whisper.py +0 -0
  51. {aient-1.1.86 → aient-1.1.88}/test/test_yjh.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.1.86
3
+ Version: 1.1.88
4
4
  Summary: Aient: The Awakening of Agent.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -183,7 +183,7 @@ async def fetch_vertex_claude_response_stream(client, url, headers, payload, mod
183
183
  function_call_id = function_call["id"]
184
184
  sse_string = await generate_sse_response(timestamp, model, content=None, tools_id=function_call_id, function_call_name=function_call_name)
185
185
  yield sse_string
186
- function_full_response = json.dumps(function_call["input"])
186
+ function_full_response = await asyncio.to_thread(json.dumps, function_call["input"])
187
187
  sse_string = await generate_sse_response(timestamp, model, content=None, tools_id=function_call_id, function_call_name=None, function_call_content=function_full_response)
188
188
  yield sse_string
189
189
 
@@ -213,6 +213,9 @@ async def fetch_gpt_response_stream(client, url, headers, payload, timeout):
213
213
  while "\n" in buffer:
214
214
  line, buffer = buffer.split("\n", 1)
215
215
  # logger.info("line: %s", repr(line))
216
+ if line.startswith(": keepalive"):
217
+ yield line + end_of_line
218
+ continue
216
219
  if line and not line.startswith(":") and (result:=line.lstrip("data: ").strip()):
217
220
  if result.strip() == "[DONE]":
218
221
  break
@@ -272,6 +275,11 @@ async def fetch_gpt_response_stream(client, url, headers, payload, timeout):
272
275
 
273
276
  no_stream_content = safe_get(line, "choices", 0, "message", "content", default=None)
274
277
  openrouter_reasoning = safe_get(line, "choices", 0, "delta", "reasoning", default="")
278
+ openrouter_base64_image = safe_get(line, "choices", 0, "delta", "images", 0, "image_url", "url", default="")
279
+ if openrouter_base64_image:
280
+ sse_string = await generate_sse_response(timestamp, payload["model"], content=f"\n\n![image]({openrouter_base64_image})")
281
+ yield sse_string
282
+ continue
275
283
  azure_databricks_claude_summary_content = safe_get(line, "choices", 0, "delta", "content", 0, "summary", 0, "text", default="")
276
284
  azure_databricks_claude_signature_content = safe_get(line, "choices", 0, "delta", "content", 0, "summary", 0, "signature", default="")
277
285
  # print("openrouter_reasoning", repr(openrouter_reasoning), openrouter_reasoning.endswith("\\\\"), openrouter_reasoning.endswith("\\"))
@@ -306,7 +314,8 @@ async def fetch_gpt_response_stream(client, url, headers, payload, timeout):
306
314
  else:
307
315
  if no_stream_content:
308
316
  del line["choices"][0]["message"]
309
- yield "data: " + json.dumps(line).strip() + end_of_line
317
+ json_line = await asyncio.to_thread(json.dumps, line)
318
+ yield "data: " + json_line.strip() + end_of_line
310
319
  yield "data: [DONE]" + end_of_line
311
320
 
312
321
  async def fetch_azure_response_stream(client, url, headers, payload, timeout):
@@ -363,7 +372,8 @@ async def fetch_azure_response_stream(client, url, headers, payload, timeout):
363
372
  else:
364
373
  if no_stream_content:
365
374
  del line["choices"][0]["message"]
366
- yield "data: " + json.dumps(line).strip() + end_of_line
375
+ json_line = await asyncio.to_thread(json.dumps, line)
376
+ yield "data: " + json_line.strip() + end_of_line
367
377
  yield "data: [DONE]" + end_of_line
368
378
 
369
379
  async def fetch_cloudflare_response_stream(client, url, headers, payload, model, timeout):
@@ -243,7 +243,8 @@ def parse_rate_limit(limit_string):
243
243
  'h': 3600, 'hr': 3600, 'hour': 3600,
244
244
  'd': 86400, 'day': 86400,
245
245
  'mo': 2592000, 'month': 2592000,
246
- 'y': 31536000, 'year': 31536000
246
+ 'y': 31536000, 'year': 31536000,
247
+ 'tpr': -1,
247
248
  }
248
249
 
249
250
  # 处理多个限制条件
@@ -377,6 +378,32 @@ class ThreadSafeCircularList:
377
378
  logger.warning(f"All API keys are rate limited!")
378
379
  raise HTTPException(status_code=429, detail="Too many requests")
379
380
 
381
+ async def is_tpr_exceeded(self, model: str = None, tokens: int = 0) -> bool:
382
+ """Checks if the request exceeds the TPR (Tokens Per Request) limit."""
383
+ if not tokens:
384
+ return False
385
+
386
+ async with self.lock:
387
+ rate_limit = None
388
+ model_key = model or "default"
389
+ if model and model_key in self.rate_limits:
390
+ rate_limit = self.rate_limits[model_key]
391
+ else:
392
+ # fuzzy match
393
+ for limit_model in self.rate_limits:
394
+ if limit_model != "default" and model and limit_model in model:
395
+ rate_limit = self.rate_limits[limit_model]
396
+ break
397
+ if rate_limit is None:
398
+ rate_limit = self.rate_limits.get("default", [])
399
+
400
+ for limit_count, limit_period in rate_limit:
401
+ if limit_period == -1: # TPR limit
402
+ if tokens > limit_count:
403
+ # logger.warning(f"API provider for model {model_key} exceeds TPR limit ({tokens}/{limit_count}).")
404
+ return True
405
+ return False
406
+
380
407
  async def is_all_rate_limited(self, model: str = None) -> bool:
381
408
  """检查是否所有的items都被速率限制
382
409
 
@@ -844,6 +844,9 @@ class chatgpt(BaseLLM):
844
844
  except BadRequestError as e:
845
845
  self.logger.error(f"Bad request error: {e}")
846
846
  raise
847
+ except GeneratorExit:
848
+ self.logger.warning("GeneratorExit caught, closing stream.")
849
+ break
847
850
  except ValidationError as e:
848
851
  self.logger.warning(f"Validation failed: {e}. Retrying with corrective prompt.")
849
852
  need_done_prompt = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.1.86
3
+ Version: 1.1.88
4
4
  Summary: Aient: The Awakening of Agent.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aient"
3
- version = "1.1.86"
3
+ version = "1.1.88"
4
4
  description = "Aient: The Awakening of Agent."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes