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_user_defined_functions.py 6.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # File based from: https://github.com/microsoft/autogen/blob/main/test/coding/test_user_defined_functions.py
  2. # Credit to original authors
  3. import tempfile
  4. import polars
  5. import pytest
  6. from agnext.components.code_executor import (
  7. CodeBlock,
  8. LocalCommandLineCodeExecutor,
  9. )
  10. from agnext.components.func_with_reqs import (
  11. FunctionWithRequirements,
  12. with_requirements,
  13. )
  14. def add_two_numbers(a: int, b: int) -> int:
  15. """Add two numbers together."""
  16. return a + b
  17. @with_requirements(python_packages=["polars"], global_imports=["polars"])
  18. def load_data() -> polars.DataFrame:
  19. """Load some sample data.
  20. Returns:
  21. polars.DataFrame: A DataFrame with the following columns: name(str), location(str), age(int)
  22. """
  23. data = {
  24. "name": ["John", "Anna", "Peter", "Linda"],
  25. "location": ["New York", "Paris", "Berlin", "London"],
  26. "age": [24, 13, 53, 33],
  27. }
  28. return polars.DataFrame(data)
  29. @with_requirements(global_imports=["NOT_A_REAL_PACKAGE"])
  30. def function_incorrect_import() -> "polars.DataFrame":
  31. return polars.DataFrame()
  32. @with_requirements(python_packages=["NOT_A_REAL_PACKAGE"])
  33. def function_incorrect_dep() -> "polars.DataFrame":
  34. return polars.DataFrame()
  35. def function_missing_reqs() -> "polars.DataFrame":
  36. return polars.DataFrame()
  37. def test_can_load_function_with_reqs() -> None:
  38. with tempfile.TemporaryDirectory() as temp_dir:
  39. executor = LocalCommandLineCodeExecutor(
  40. work_dir=temp_dir, functions=[load_data]
  41. )
  42. code = f"""from {executor.functions_module} import load_data
  43. import polars
  44. # Get first row's name
  45. data = load_data()
  46. print(data['name'][0])"""
  47. result = executor.execute_code_blocks(
  48. code_blocks=[
  49. CodeBlock(language="python", code=code),
  50. ]
  51. )
  52. assert result.output == "John\n"
  53. assert result.exit_code == 0
  54. def test_can_load_function() -> None:
  55. with tempfile.TemporaryDirectory() as temp_dir:
  56. executor = LocalCommandLineCodeExecutor(
  57. work_dir=temp_dir, functions=[add_two_numbers]
  58. )
  59. code = f"""from {executor.functions_module} import add_two_numbers
  60. print(add_two_numbers(1, 2))"""
  61. result = executor.execute_code_blocks(
  62. code_blocks=[
  63. CodeBlock(language="python", code=code),
  64. ]
  65. )
  66. assert result.output == "3\n"
  67. assert result.exit_code == 0
  68. def test_fails_for_function_incorrect_import() -> None:
  69. with tempfile.TemporaryDirectory() as temp_dir:
  70. executor = LocalCommandLineCodeExecutor(
  71. work_dir=temp_dir, functions=[function_incorrect_import]
  72. )
  73. code = f"""from {executor.functions_module} import function_incorrect_import
  74. function_incorrect_import()"""
  75. with pytest.raises(ValueError):
  76. executor.execute_code_blocks(
  77. code_blocks=[
  78. CodeBlock(language="python", code=code),
  79. ]
  80. )
  81. def test_fails_for_function_incorrect_dep() -> None:
  82. with tempfile.TemporaryDirectory() as temp_dir:
  83. executor = LocalCommandLineCodeExecutor(
  84. work_dir=temp_dir, functions=[function_incorrect_dep]
  85. )
  86. code = f"""from {executor.functions_module} import function_incorrect_dep
  87. function_incorrect_dep()"""
  88. with pytest.raises(ValueError):
  89. executor.execute_code_blocks(
  90. code_blocks=[
  91. CodeBlock(language="python", code=code),
  92. ]
  93. )
  94. def test_formatted_prompt() -> None:
  95. with tempfile.TemporaryDirectory() as temp_dir:
  96. executor = LocalCommandLineCodeExecutor(
  97. work_dir=temp_dir, functions=[add_two_numbers]
  98. )
  99. result = executor.format_functions_for_prompt()
  100. assert (
  101. '''def add_two_numbers(a: int, b: int) -> int:
  102. """Add two numbers together."""
  103. '''
  104. in result
  105. )
  106. def test_formatted_prompt_str_func() -> None:
  107. with tempfile.TemporaryDirectory() as temp_dir:
  108. func = FunctionWithRequirements.from_str(
  109. '''
  110. def add_two_numbers(a: int, b: int) -> int:
  111. """Add two numbers together."""
  112. return a + b
  113. '''
  114. )
  115. executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[func])
  116. result = executor.format_functions_for_prompt()
  117. assert (
  118. '''def add_two_numbers(a: int, b: int) -> int:
  119. """Add two numbers together."""
  120. '''
  121. in result
  122. )
  123. def test_can_load_str_function_with_reqs() -> None:
  124. with tempfile.TemporaryDirectory() as temp_dir:
  125. func = FunctionWithRequirements.from_str(
  126. '''
  127. def add_two_numbers(a: int, b: int) -> int:
  128. """Add two numbers together."""
  129. return a + b
  130. '''
  131. )
  132. executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[func])
  133. code = f"""from {executor.functions_module} import add_two_numbers
  134. print(add_two_numbers(1, 2))"""
  135. result = executor.execute_code_blocks(
  136. code_blocks=[
  137. CodeBlock(language="python", code=code),
  138. ]
  139. )
  140. assert result.output == "3\n"
  141. assert result.exit_code == 0
  142. def test_cant_load_broken_str_function_with_reqs() -> None:
  143. with pytest.raises(ValueError):
  144. _ = FunctionWithRequirements.from_str(
  145. '''
  146. invaliddef add_two_numbers(a: int, b: int) -> int:
  147. """Add two numbers together."""
  148. return a + b
  149. '''
  150. )
  151. def test_cant_run_broken_str_function_with_reqs() -> None:
  152. with tempfile.TemporaryDirectory() as temp_dir:
  153. func = FunctionWithRequirements.from_str(
  154. '''
  155. def add_two_numbers(a: int, b: int) -> int:
  156. """Add two numbers together."""
  157. return a + b
  158. '''
  159. )
  160. executor = LocalCommandLineCodeExecutor(work_dir=temp_dir, functions=[func])
  161. code = f"""from {executor.functions_module} import add_two_numbers
  162. print(add_two_numbers(object(), False))"""
  163. result = executor.execute_code_blocks(
  164. code_blocks=[
  165. CodeBlock(language="python", code=code),
  166. ]
  167. )
  168. assert "TypeError: unsupported operand type(s) for +:" in result.output
  169. assert result.exit_code == 1

This is a mirror of AutoGen from GitHub. AutoGen is a framework that enables the development of LLM applications using multiple agents that can converse with each other to solve tasks.