aient 1.2.38__tar.gz → 1.2.40__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 (54) hide show
  1. {aient-1.2.38 → aient-1.2.40}/PKG-INFO +1 -1
  2. {aient-1.2.38 → aient-1.2.40}/aient/models/chatgpt.py +19 -12
  3. {aient-1.2.38 → aient-1.2.40}/aient/utils/scripts.py +55 -0
  4. {aient-1.2.38 → aient-1.2.40}/aient.egg-info/PKG-INFO +1 -1
  5. {aient-1.2.38 → aient-1.2.40}/pyproject.toml +1 -1
  6. {aient-1.2.38 → aient-1.2.40}/LICENSE +0 -0
  7. {aient-1.2.38 → aient-1.2.40}/README.md +0 -0
  8. {aient-1.2.38 → aient-1.2.40}/aient/__init__.py +0 -0
  9. {aient-1.2.38 → aient-1.2.40}/aient/architext/architext/__init__.py +0 -0
  10. {aient-1.2.38 → aient-1.2.40}/aient/architext/architext/core.py +0 -0
  11. {aient-1.2.38 → aient-1.2.40}/aient/architext/test/openai_client.py +0 -0
  12. {aient-1.2.38 → aient-1.2.40}/aient/architext/test/test.py +0 -0
  13. {aient-1.2.38 → aient-1.2.40}/aient/architext/test/test_save_load.py +0 -0
  14. {aient-1.2.38 → aient-1.2.40}/aient/core/__init__.py +0 -0
  15. {aient-1.2.38 → aient-1.2.40}/aient/core/log_config.py +0 -0
  16. {aient-1.2.38 → aient-1.2.40}/aient/core/models.py +0 -0
  17. {aient-1.2.38 → aient-1.2.40}/aient/core/request.py +0 -0
  18. {aient-1.2.38 → aient-1.2.40}/aient/core/response.py +0 -0
  19. {aient-1.2.38 → aient-1.2.40}/aient/core/test/test_base_api.py +0 -0
  20. {aient-1.2.38 → aient-1.2.40}/aient/core/test/test_geminimask.py +0 -0
  21. {aient-1.2.38 → aient-1.2.40}/aient/core/test/test_image.py +0 -0
  22. {aient-1.2.38 → aient-1.2.40}/aient/core/test/test_payload.py +0 -0
  23. {aient-1.2.38 → aient-1.2.40}/aient/core/utils.py +0 -0
  24. {aient-1.2.38 → aient-1.2.40}/aient/models/__init__.py +0 -0
  25. {aient-1.2.38 → aient-1.2.40}/aient/models/audio.py +0 -0
  26. {aient-1.2.38 → aient-1.2.40}/aient/models/base.py +0 -0
  27. {aient-1.2.38 → aient-1.2.40}/aient/plugins/__init__.py +0 -0
  28. {aient-1.2.38 → aient-1.2.40}/aient/plugins/arXiv.py +0 -0
  29. {aient-1.2.38 → aient-1.2.40}/aient/plugins/config.py +0 -0
  30. {aient-1.2.38 → aient-1.2.40}/aient/plugins/excute_command.py +0 -0
  31. {aient-1.2.38 → aient-1.2.40}/aient/plugins/get_time.py +0 -0
  32. {aient-1.2.38 → aient-1.2.40}/aient/plugins/image.py +0 -0
  33. {aient-1.2.38 → aient-1.2.40}/aient/plugins/list_directory.py +0 -0
  34. {aient-1.2.38 → aient-1.2.40}/aient/plugins/read_file.py +0 -0
  35. {aient-1.2.38 → aient-1.2.40}/aient/plugins/read_image.py +0 -0
  36. {aient-1.2.38 → aient-1.2.40}/aient/plugins/readonly.py +0 -0
  37. {aient-1.2.38 → aient-1.2.40}/aient/plugins/registry.py +0 -0
  38. {aient-1.2.38 → aient-1.2.40}/aient/plugins/run_python.py +0 -0
  39. {aient-1.2.38 → aient-1.2.40}/aient/plugins/websearch.py +0 -0
  40. {aient-1.2.38 → aient-1.2.40}/aient/plugins/write_file.py +0 -0
  41. {aient-1.2.38 → aient-1.2.40}/aient/utils/__init__.py +0 -0
  42. {aient-1.2.38 → aient-1.2.40}/aient/utils/prompt.py +0 -0
  43. {aient-1.2.38 → aient-1.2.40}/aient.egg-info/SOURCES.txt +0 -0
  44. {aient-1.2.38 → aient-1.2.40}/aient.egg-info/dependency_links.txt +0 -0
  45. {aient-1.2.38 → aient-1.2.40}/aient.egg-info/requires.txt +0 -0
  46. {aient-1.2.38 → aient-1.2.40}/aient.egg-info/top_level.txt +0 -0
  47. {aient-1.2.38 → aient-1.2.40}/setup.cfg +0 -0
  48. {aient-1.2.38 → aient-1.2.40}/test/test_Web_crawler.py +0 -0
  49. {aient-1.2.38 → aient-1.2.40}/test/test_ddg_search.py +0 -0
  50. {aient-1.2.38 → aient-1.2.40}/test/test_google_search.py +0 -0
  51. {aient-1.2.38 → aient-1.2.40}/test/test_ollama.py +0 -0
  52. {aient-1.2.38 → aient-1.2.40}/test/test_plugin.py +0 -0
  53. {aient-1.2.38 → aient-1.2.40}/test/test_url.py +0 -0
  54. {aient-1.2.38 → aient-1.2.40}/test/test_whisper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.2.38
3
+ Version: 1.2.40
4
4
  Summary: Aient: The Awakening of Agent.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -12,7 +12,7 @@ from typing import Union, Optional, Callable
12
12
  from .base import BaseLLM
13
13
  from ..plugins.registry import registry
14
14
  from ..plugins import PLUGINS, get_tools_result_async, function_call_list, update_tools_config
15
- from ..utils.scripts import safe_get, async_generator_to_sync, parse_function_xml, parse_continuous_json, convert_functions_to_xml, remove_xml_tags_and_content
15
+ from ..utils.scripts import safe_get, async_generator_to_sync, parse_function_xml, parse_continuous_json, convert_functions_to_xml, remove_xml_tags_and_content, find_most_frequent_phrase
16
16
  from ..core.request import prepare_request_payload
17
17
  from ..core.response import fetch_response_stream, fetch_response
18
18
  from ..architext.architext import Messages, SystemMessage, UserMessage, AssistantMessage, ToolCalls, ToolResults, Texts, RoleMessage, Images, Files
@@ -81,6 +81,14 @@ class TaskComplete(Exception):
81
81
  super().__init__(f"Task completed with message: {message}")
82
82
 
83
83
 
84
+ class RepetitiveResponseError(Exception):
85
+ """Custom exception for detecting repetitive and meaningless generated strings."""
86
+ def __init__(self, message, phrase, count):
87
+ super().__init__(message)
88
+ self.phrase = phrase
89
+ self.count = count
90
+
91
+
84
92
  class chatgpt(BaseLLM):
85
93
  """
86
94
  Official ChatGPT API
@@ -438,6 +446,13 @@ class chatgpt(BaseLLM):
438
446
 
439
447
  if not full_response.strip() and not need_function_call:
440
448
  raise EmptyResponseError("Response is empty")
449
+ most_frequent_phrase, most_frequent_phrase_count = find_most_frequent_phrase(full_response)
450
+ if most_frequent_phrase_count > 100:
451
+ raise RepetitiveResponseError(
452
+ f"Detected repetitive and meaningless content. The phrase '{most_frequent_phrase}' appeared {most_frequent_phrase_count} times.",
453
+ most_frequent_phrase,
454
+ most_frequent_phrase_count
455
+ )
441
456
 
442
457
  if self.print_log:
443
458
  self.logger.info(f"total_tokens: {total_tokens}")
@@ -660,17 +675,6 @@ class chatgpt(BaseLLM):
660
675
  self.add_to_conversation(full_response, response_role, convo_id=convo_id, total_tokens=total_tokens, pass_history=pass_history)
661
676
  self.function_calls_counter = {}
662
677
 
663
- # 清理翻译引擎相关的历史记录
664
- if pass_history <= 2 and len(self.conversation[convo_id]) >= 2 \
665
- and (
666
- "You are a translation engine" in self.conversation[convo_id][-2]["content"] \
667
- or "You are a translation engine" in safe_get(self.conversation, convo_id, -2, "content", 0, "text", default="") \
668
- or "你是一位精通简体中文的专业翻译" in self.conversation[convo_id][-2]["content"] \
669
- or "你是一位精通简体中文的专业翻译" in safe_get(self.conversation, convo_id, -2, "content", 0, "text", default="")
670
- ):
671
- self.conversation[convo_id].pop(-1)
672
- self.conversation[convo_id].pop(-1)
673
-
674
678
  async def _ask_stream_handler(
675
679
  self,
676
680
  prompt: list,
@@ -811,6 +815,9 @@ class chatgpt(BaseLLM):
811
815
  except EmptyResponseError as e:
812
816
  self.logger.warning(f"{e}, retrying...")
813
817
  continue
818
+ except RepetitiveResponseError as e:
819
+ self.logger.warning(f"{e}, retrying...")
820
+ continue
814
821
  except TaskComplete as e:
815
822
  raise
816
823
  except ModelNotFoundError as e:
@@ -3,10 +3,65 @@ import re
3
3
  import json
4
4
  import fnmatch
5
5
  import requests
6
+ import collections
6
7
  import urllib.parse
7
8
 
8
9
  from ..core.utils import get_image_message
9
10
 
11
+ def find_most_frequent_phrase(s, min_len=4, max_phrase_len=20):
12
+ """
13
+ 查找字符串中出现次数最多的短语(单词序列)。
14
+ 此版本经过性能优化,并增加了最大短语长度限制。
15
+
16
+ Args:
17
+ s: 输入字符串。
18
+ min_len: 短语的最小字符长度。
19
+ max_phrase_len: 要搜索的最大短语长度(以单词为单位)。
20
+
21
+ Returns:
22
+ 一个元组 (most_frequent_phrase, count),其中
23
+ most_frequent_phrase 是出现次数最多的短语,
24
+ count 是它的出现次数。
25
+ 如果没有找到符合条件的重复短语,则返回 ("", 0)。
26
+ """
27
+ # start_time = time.time()
28
+ if not s or len(s) < min_len:
29
+ return "", 0
30
+
31
+ words = [word for word in re.split(r'[\s\n]+', s) if word]
32
+ if not words:
33
+ return "", 0
34
+ n = len(words)
35
+
36
+ phrase_counts = collections.defaultdict(int)
37
+
38
+ # 确定要检查的实际最大长度
39
+ effective_max_len = min(n // 2, max_phrase_len)
40
+
41
+ # 优化的核心:直接在单词列表上生成并统计所有可能的短语(n-grams)
42
+ for length in range(1, effective_max_len + 1):
43
+ for i in range(n - length + 1):
44
+ phrase_tuple = tuple(words[i:i + length])
45
+ phrase_counts[phrase_tuple] += 1
46
+ # 筛选出重复次数大于1且满足最小长度要求的短语
47
+ best_phrase = ""
48
+ max_count = 0
49
+
50
+ for phrase_tuple, count in phrase_counts.items():
51
+ if count > 1:
52
+ phrase = " ".join(phrase_tuple)
53
+ if len(phrase) >= min_len:
54
+ if count > max_count:
55
+ max_count = count
56
+ best_phrase = phrase
57
+ elif count == max_count and len(phrase) > len(best_phrase):
58
+ best_phrase = phrase
59
+
60
+ if max_count > 0:
61
+ return best_phrase, max_count
62
+ else:
63
+ return "", 0
64
+
10
65
  def get_doc_from_url(url):
11
66
  filename = urllib.parse.unquote(url.split("/")[-1])
12
67
  response = requests.get(url, stream=True)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.2.38
3
+ Version: 1.2.40
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.2.38"
3
+ version = "1.2.40"
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