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

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