aient 1.2.2__py3-none-any.whl → 1.2.3__py3-none-any.whl
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.
- aient/architext/architext/core.py +52 -18
- aient/architext/test/test.py +22 -0
- {aient-1.2.2.dist-info → aient-1.2.3.dist-info}/METADATA +1 -1
- {aient-1.2.2.dist-info → aient-1.2.3.dist-info}/RECORD +7 -7
- {aient-1.2.2.dist-info → aient-1.2.3.dist-info}/WHEEL +0 -0
- {aient-1.2.2.dist-info → aient-1.2.3.dist-info}/licenses/LICENSE +0 -0
- {aient-1.2.2.dist-info → aient-1.2.3.dist-info}/top_level.txt +0 -0
@@ -142,6 +142,15 @@ class Texts(ContextProvider):
|
|
142
142
|
async def render(self) -> Optional[str]:
|
143
143
|
return self.content
|
144
144
|
|
145
|
+
def __eq__(self, other):
|
146
|
+
if not isinstance(other, Texts):
|
147
|
+
return NotImplemented
|
148
|
+
# If either object is dynamic, they are only equal if they are the exact same object.
|
149
|
+
if self._is_dynamic or (hasattr(other, '_is_dynamic') and other._is_dynamic):
|
150
|
+
return self is other
|
151
|
+
# For static content, compare the actual content.
|
152
|
+
return self.content == other.content
|
153
|
+
|
145
154
|
class Tools(ContextProvider):
|
146
155
|
def __init__(self, tools_json: Optional[List[Dict]] = None, name: str = "tools"):
|
147
156
|
super().__init__(name)
|
@@ -154,6 +163,11 @@ class Tools(ContextProvider):
|
|
154
163
|
return None
|
155
164
|
return f"<tools>{str(self._tools_json)}</tools>"
|
156
165
|
|
166
|
+
def __eq__(self, other):
|
167
|
+
if not isinstance(other, Tools):
|
168
|
+
return NotImplemented
|
169
|
+
return self._tools_json == other._tools_json
|
170
|
+
|
157
171
|
class Files(ContextProvider):
|
158
172
|
def __init__(self, *paths: Union[str, List[str]], name: str = "files"):
|
159
173
|
super().__init__(name)
|
@@ -230,6 +244,11 @@ class Files(ContextProvider):
|
|
230
244
|
if not self._files: return None
|
231
245
|
return "<latest_file_content>" + "\n".join([f"<file><file_path>{p}</file_path><file_content>{c}</file_content></file>" for p, c in self._files.items()]) + "\n</latest_file_content>"
|
232
246
|
|
247
|
+
def __eq__(self, other):
|
248
|
+
if not isinstance(other, Files):
|
249
|
+
return NotImplemented
|
250
|
+
return self._files == other._files
|
251
|
+
|
233
252
|
class Images(ContextProvider):
|
234
253
|
def __init__(self, url: str, name: Optional[str] = None):
|
235
254
|
super().__init__(name or url)
|
@@ -250,6 +269,11 @@ class Images(ContextProvider):
|
|
250
269
|
logging.warning(f"Image file not found: {self.url}. Skipping.")
|
251
270
|
return None # Or handle error appropriately
|
252
271
|
|
272
|
+
def __eq__(self, other):
|
273
|
+
if not isinstance(other, Images):
|
274
|
+
return NotImplemented
|
275
|
+
return self.url == other.url
|
276
|
+
|
253
277
|
# 3. 消息类 (已合并 MessageContent)
|
254
278
|
class Message(ABC):
|
255
279
|
def __init__(self, role: str, *initial_items: Union[ContextProvider, str, list]):
|
@@ -356,26 +380,36 @@ class Message(ABC):
|
|
356
380
|
return type(self)(*new_items)
|
357
381
|
return NotImplemented
|
358
382
|
|
359
|
-
def __getitem__(self, key: str) -> Any:
|
383
|
+
def __getitem__(self, key: Union[str, int]) -> Any:
|
360
384
|
"""
|
361
|
-
使得 Message 对象支持字典风格的访问 (e.g., message['content'])
|
385
|
+
使得 Message 对象支持字典风格的访问 (e.g., message['content'])
|
386
|
+
和列表风格的索引访问 (e.g., message[-1])。
|
362
387
|
"""
|
363
|
-
if key
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
388
|
+
if isinstance(key, str):
|
389
|
+
if key == 'role':
|
390
|
+
return self.role
|
391
|
+
elif key == 'content':
|
392
|
+
# 直接调用 to_dict 并提取 'content',确保逻辑一致
|
393
|
+
rendered_dict = self.to_dict()
|
394
|
+
return rendered_dict.get('content') if rendered_dict else None
|
395
|
+
# 对于 tool_calls 等特殊属性,也通过 to_dict 获取
|
396
|
+
elif hasattr(self, key):
|
397
|
+
rendered_dict = self.to_dict()
|
398
|
+
if rendered_dict and key in rendered_dict:
|
399
|
+
return rendered_dict[key]
|
400
|
+
|
401
|
+
# 如果在对象本身或其 to_dict() 中都找不到,则引发 KeyError
|
402
|
+
if hasattr(self, key):
|
403
|
+
return getattr(self, key)
|
404
|
+
raise KeyError(f"'{key}'")
|
405
|
+
elif isinstance(key, int):
|
406
|
+
return self._items[key]
|
407
|
+
else:
|
408
|
+
raise TypeError(f"Message indices must be integers or strings, not {type(key).__name__}")
|
409
|
+
|
410
|
+
def __len__(self) -> int:
|
411
|
+
"""返回消息中 provider 的数量。"""
|
412
|
+
return len(self._items)
|
379
413
|
|
380
414
|
def __repr__(self): return f"Message(role='{self.role}', items={[i.name for i in self._items]})"
|
381
415
|
def __bool__(self) -> bool:
|
aient/architext/test/test.py
CHANGED
@@ -1136,6 +1136,28 @@ Current time: {Texts(lambda: datetime.now().strftime("%Y-%m-%d %H:%M:%S"))}
|
|
1136
1136
|
await p.refresh()
|
1137
1137
|
self.assertEqual(role_message.content, "通过工厂创建的内容")
|
1138
1138
|
|
1139
|
+
async def test_za_message_indexing_and_length(self):
|
1140
|
+
"""测试 Message 对象是否支持通过索引访问 provider 以及获取长度"""
|
1141
|
+
# 1. 创建一个 UserMessage
|
1142
|
+
mess = UserMessage(
|
1143
|
+
Texts("some instruction"),
|
1144
|
+
Texts("hi", name="done")
|
1145
|
+
)
|
1146
|
+
|
1147
|
+
# 2. 测试获取长度
|
1148
|
+
# 这在实现 __len__ 之前会失败
|
1149
|
+
self.assertEqual(len(mess), 2)
|
1150
|
+
|
1151
|
+
# 3. 测试通过索引访问
|
1152
|
+
# 这在修改 __getitem__ 之前会失败
|
1153
|
+
self.assertEqual(mess[-1].name, "done")
|
1154
|
+
self.assertEqual(mess[0].name, Texts("some instruction").name)
|
1155
|
+
self.assertEqual(mess[0], Texts("some instruction"))
|
1156
|
+
|
1157
|
+
# 4. 测试索引越界
|
1158
|
+
with self.assertRaises(IndexError):
|
1159
|
+
_ = mess[2]
|
1160
|
+
|
1139
1161
|
# ==============================================================================
|
1140
1162
|
# 6. 演示
|
1141
1163
|
# ==============================================================================
|
@@ -1,8 +1,8 @@
|
|
1
1
|
aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
|
2
2
|
aient/architext/architext/__init__.py,sha256=79Ih1151rfcqZdr7F8HSZSTs_iT2SKd1xCkehMsXeXs,19
|
3
|
-
aient/architext/architext/core.py,sha256=
|
3
|
+
aient/architext/architext/core.py,sha256=qSRiIfx9Cl_OZIDfGMFr7AKbwRWTBrJNt_jqJeOr5Lw,25636
|
4
4
|
aient/architext/test/openai_client.py,sha256=Dqtbmubv6vwF8uBqcayG0kbsiO65of7sgU2-DRBi-UM,4590
|
5
|
-
aient/architext/test/test.py,sha256=
|
5
|
+
aient/architext/test/test.py,sha256=efWn_qYdgPZO-Wz68o33QoWhWiJjU-cAzPbIVL0sjhw,55316
|
6
6
|
aient/architext/test/test_save_load.py,sha256=o8DqH6gDYZkFkQy-a7blqLtJTRj5e4a-Lil48pJ0V3g,3260
|
7
7
|
aient/core/__init__.py,sha256=NxjebTlku35S4Dzr16rdSqSTWUvvwEeACe8KvHJnjPg,34
|
8
8
|
aient/core/log_config.py,sha256=kz2_yJv1p-o3lUQOwA3qh-LSc3wMHv13iCQclw44W9c,274
|
@@ -35,8 +35,8 @@ aient/plugins/write_file.py,sha256=Jt8fOEwqhYiSWpCbwfAr1xoi_BmFnx3076GMhuL06uI,3
|
|
35
35
|
aient/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
36
|
aient/utils/prompt.py,sha256=UcSzKkFE4-h_1b6NofI6xgk3GoleqALRKY8VBaXLjmI,11311
|
37
37
|
aient/utils/scripts.py,sha256=VqtK4RFEx7KxkmcqG3lFDS1DxoNlFFGErEjopVcc8IE,40974
|
38
|
-
aient-1.2.
|
39
|
-
aient-1.2.
|
40
|
-
aient-1.2.
|
41
|
-
aient-1.2.
|
42
|
-
aient-1.2.
|
38
|
+
aient-1.2.3.dist-info/licenses/LICENSE,sha256=XNdbcWldt0yaNXXWB_Bakoqnxb3OVhUft4MgMA_71ds,1051
|
39
|
+
aient-1.2.3.dist-info/METADATA,sha256=HupXkB_iUMlrUCSb45q3nBmmHPENpd52JAZjNGudCTo,4841
|
40
|
+
aient-1.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
41
|
+
aient-1.2.3.dist-info/top_level.txt,sha256=3oXzrP5sAVvyyqabpeq8A2_vfMtY554r4bVE-OHBrZk,6
|
42
|
+
aient-1.2.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|