You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_termination_condition.py 13 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. import asyncio
  2. import pytest
  3. from autogen_agentchat.base import TerminatedException
  4. from autogen_agentchat.conditions import (
  5. ExternalTermination,
  6. FunctionCallTermination,
  7. HandoffTermination,
  8. MaxMessageTermination,
  9. SourceMatchTermination,
  10. StopMessageTermination,
  11. TextMentionTermination,
  12. TextMessageTermination,
  13. TimeoutTermination,
  14. TokenUsageTermination,
  15. )
  16. from autogen_agentchat.messages import (
  17. HandoffMessage,
  18. StopMessage,
  19. TextMessage,
  20. ToolCallExecutionEvent,
  21. UserInputRequestedEvent,
  22. )
  23. from autogen_core.models import FunctionExecutionResult, RequestUsage
  24. @pytest.mark.asyncio
  25. async def test_handoff_termination() -> None:
  26. termination = HandoffTermination("target")
  27. assert await termination([]) is None
  28. await termination.reset()
  29. assert await termination([TextMessage(content="Hello", source="user")]) is None
  30. await termination.reset()
  31. assert await termination([HandoffMessage(target="target", source="user", content="Hello")]) is not None
  32. assert termination.terminated
  33. await termination.reset()
  34. assert await termination([HandoffMessage(target="another", source="user", content="Hello")]) is None
  35. assert not termination.terminated
  36. await termination.reset()
  37. assert (
  38. await termination(
  39. [
  40. TextMessage(content="Hello", source="user"),
  41. HandoffMessage(target="target", source="user", content="Hello"),
  42. ]
  43. )
  44. is not None
  45. )
  46. assert termination.terminated
  47. await termination.reset()
  48. @pytest.mark.asyncio
  49. async def test_stop_message_termination() -> None:
  50. termination = StopMessageTermination()
  51. assert await termination([]) is None
  52. await termination.reset()
  53. assert await termination([TextMessage(content="Hello", source="user")]) is None
  54. await termination.reset()
  55. assert await termination([StopMessage(content="Stop", source="user")]) is not None
  56. await termination.reset()
  57. assert (
  58. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="World", source="agent")])
  59. is None
  60. )
  61. await termination.reset()
  62. assert (
  63. await termination([TextMessage(content="Hello", source="user"), StopMessage(content="Stop", source="user")])
  64. is not None
  65. )
  66. @pytest.mark.asyncio
  67. async def test_text_message_termination() -> None:
  68. termination = TextMessageTermination()
  69. assert await termination([]) is None
  70. await termination.reset()
  71. assert await termination([StopMessage(content="Hello", source="user")]) is None
  72. await termination.reset()
  73. assert await termination([TextMessage(content="Hello", source="user")]) is not None
  74. assert termination.terminated
  75. await termination.reset()
  76. assert (
  77. await termination([StopMessage(content="Hello", source="user"), TextMessage(content="World", source="agent")])
  78. is not None
  79. )
  80. assert termination.terminated
  81. with pytest.raises(TerminatedException):
  82. await termination([TextMessage(content="Hello", source="user")])
  83. termination = TextMessageTermination(source="user")
  84. assert await termination([]) is None
  85. await termination.reset()
  86. assert await termination([TextMessage(content="Hello", source="user")]) is not None
  87. assert termination.terminated
  88. await termination.reset()
  89. termination = TextMessageTermination(source="agent")
  90. assert await termination([]) is None
  91. await termination.reset()
  92. assert await termination([TextMessage(content="Hello", source="user")]) is None
  93. await termination.reset()
  94. assert await termination([TextMessage(content="Hello", source="agent")]) is not None
  95. assert termination.terminated
  96. @pytest.mark.asyncio
  97. async def test_max_message_termination() -> None:
  98. termination = MaxMessageTermination(2)
  99. assert await termination([]) is None
  100. await termination.reset()
  101. assert await termination([TextMessage(content="Hello", source="user")]) is None
  102. await termination.reset()
  103. assert (
  104. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="World", source="agent")])
  105. is not None
  106. )
  107. termination = MaxMessageTermination(2, include_agent_event=True)
  108. assert await termination([]) is None
  109. await termination.reset()
  110. assert await termination([TextMessage(content="Hello", source="user")]) is None
  111. await termination.reset()
  112. assert (
  113. await termination(
  114. [TextMessage(content="Hello", source="user"), UserInputRequestedEvent(request_id="1", source="agent")]
  115. )
  116. is not None
  117. )
  118. @pytest.mark.asyncio
  119. async def test_mention_termination() -> None:
  120. termination = TextMentionTermination("stop")
  121. assert await termination([]) is None
  122. await termination.reset()
  123. assert await termination([TextMessage(content="Hello", source="user")]) is None
  124. await termination.reset()
  125. assert await termination([TextMessage(content="stop", source="user")]) is not None
  126. await termination.reset()
  127. assert (
  128. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="stop", source="user")])
  129. is not None
  130. )
  131. termination = TextMentionTermination("stop", sources=["agent"])
  132. assert await termination([TextMessage(content="stop", source="user")]) is None
  133. await termination.reset()
  134. assert (
  135. await termination([TextMessage(content="stop", source="user"), TextMessage(content="stop", source="agent")])
  136. is not None
  137. )
  138. @pytest.mark.asyncio
  139. async def test_token_usage_termination() -> None:
  140. termination = TokenUsageTermination(max_total_token=10)
  141. assert await termination([]) is None
  142. await termination.reset()
  143. assert (
  144. await termination(
  145. [
  146. TextMessage(
  147. content="Hello", source="user", models_usage=RequestUsage(prompt_tokens=10, completion_tokens=10)
  148. )
  149. ]
  150. )
  151. is not None
  152. )
  153. await termination.reset()
  154. assert (
  155. await termination(
  156. [
  157. TextMessage(
  158. content="Hello", source="user", models_usage=RequestUsage(prompt_tokens=1, completion_tokens=1)
  159. ),
  160. TextMessage(
  161. content="World", source="agent", models_usage=RequestUsage(prompt_tokens=1, completion_tokens=1)
  162. ),
  163. ]
  164. )
  165. is None
  166. )
  167. await termination.reset()
  168. assert (
  169. await termination(
  170. [
  171. TextMessage(
  172. content="Hello", source="user", models_usage=RequestUsage(prompt_tokens=5, completion_tokens=0)
  173. ),
  174. TextMessage(
  175. content="stop", source="user", models_usage=RequestUsage(prompt_tokens=0, completion_tokens=5)
  176. ),
  177. ]
  178. )
  179. is not None
  180. )
  181. @pytest.mark.asyncio
  182. async def test_and_termination() -> None:
  183. termination = MaxMessageTermination(2) & TextMentionTermination("stop")
  184. assert await termination([]) is None
  185. await termination.reset()
  186. assert await termination([TextMessage(content="Hello", source="user")]) is None
  187. await termination.reset()
  188. assert (
  189. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="World", source="agent")])
  190. is None
  191. )
  192. await termination.reset()
  193. assert (
  194. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="stop", source="user")])
  195. is not None
  196. )
  197. @pytest.mark.asyncio
  198. async def test_or_termination() -> None:
  199. termination = MaxMessageTermination(3) | TextMentionTermination("stop")
  200. assert await termination([]) is None
  201. await termination.reset()
  202. assert await termination([TextMessage(content="Hello", source="user")]) is None
  203. await termination.reset()
  204. assert (
  205. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="World", source="agent")])
  206. is None
  207. )
  208. await termination.reset()
  209. assert (
  210. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="stop", source="user")])
  211. is not None
  212. )
  213. await termination.reset()
  214. assert (
  215. await termination([TextMessage(content="Hello", source="user"), TextMessage(content="Hello", source="user")])
  216. is None
  217. )
  218. await termination.reset()
  219. assert (
  220. await termination(
  221. [
  222. TextMessage(content="Hello", source="user"),
  223. TextMessage(content="Hello", source="user"),
  224. TextMessage(content="Hello", source="user"),
  225. ]
  226. )
  227. is not None
  228. )
  229. await termination.reset()
  230. assert (
  231. await termination(
  232. [
  233. TextMessage(content="Hello", source="user"),
  234. TextMessage(content="Hello", source="user"),
  235. TextMessage(content="stop", source="user"),
  236. ]
  237. )
  238. is not None
  239. )
  240. await termination.reset()
  241. assert (
  242. await termination(
  243. [
  244. TextMessage(content="Hello", source="user"),
  245. TextMessage(content="Hello", source="user"),
  246. TextMessage(content="Hello", source="user"),
  247. TextMessage(content="stop", source="user"),
  248. ]
  249. )
  250. is not None
  251. )
  252. @pytest.mark.asyncio
  253. async def test_timeout_termination() -> None:
  254. termination = TimeoutTermination(0.1) # 100ms timeout
  255. assert await termination([]) is None
  256. assert not termination.terminated
  257. await asyncio.sleep(0.2)
  258. assert await termination([]) is not None
  259. assert termination.terminated
  260. await termination.reset()
  261. assert not termination.terminated
  262. assert await termination([]) is None
  263. assert await termination([TextMessage(content="Hello", source="user")]) is None
  264. await asyncio.sleep(0.2)
  265. assert await termination([TextMessage(content="World", source="user")]) is not None
  266. @pytest.mark.asyncio
  267. async def test_external_termination() -> None:
  268. termination = ExternalTermination()
  269. assert await termination([]) is None
  270. assert not termination.terminated
  271. termination.set()
  272. assert await termination([]) is not None
  273. assert termination.terminated
  274. await termination.reset()
  275. assert await termination([]) is None
  276. @pytest.mark.asyncio
  277. async def test_source_match_termination() -> None:
  278. termination = SourceMatchTermination(sources=["Assistant"])
  279. assert await termination([]) is None
  280. continue_messages = [TextMessage(content="Hello", source="agent"), TextMessage(content="Hello", source="user")]
  281. assert await termination(continue_messages) is None
  282. terminate_messages = [
  283. TextMessage(content="Hello", source="agent"),
  284. TextMessage(content="Hello", source="Assistant"),
  285. TextMessage(content="Hello", source="user"),
  286. ]
  287. result = await termination(terminate_messages)
  288. assert isinstance(result, StopMessage)
  289. assert termination.terminated
  290. with pytest.raises(TerminatedException):
  291. await termination([])
  292. await termination.reset()
  293. assert not termination.terminated
  294. @pytest.mark.asyncio
  295. async def test_function_call_termination() -> None:
  296. termination = FunctionCallTermination(function_name="test_function")
  297. assert await termination([]) is None
  298. await termination.reset()
  299. assert await termination([TextMessage(content="Hello", source="user")]) is None
  300. await termination.reset()
  301. assert (
  302. await termination(
  303. [TextMessage(content="Hello", source="user"), ToolCallExecutionEvent(content=[], source="assistant")]
  304. )
  305. is None
  306. )
  307. await termination.reset()
  308. assert (
  309. await termination(
  310. [
  311. TextMessage(content="Hello", source="user"),
  312. ToolCallExecutionEvent(
  313. content=[FunctionExecutionResult(content="", name="test_function", call_id="")], source="assistant"
  314. ),
  315. ]
  316. )
  317. is not None
  318. )
  319. assert termination.terminated
  320. await termination.reset()
  321. assert (
  322. await termination(
  323. [
  324. TextMessage(content="Hello", source="user"),
  325. ToolCallExecutionEvent(
  326. content=[FunctionExecutionResult(content="", name="another_function", call_id="")],
  327. source="assistant",
  328. ),
  329. ]
  330. )
  331. is None
  332. )
  333. assert not termination.terminated
  334. await termination.reset()