From 329e585d2ec58863b6721fe0a2487c9570b2e145 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 11:08:25 -0300 Subject: [PATCH 01/15] Removing copy/pasted code. --- src/smolagents/bp_cli.py | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/smolagents/bp_cli.py b/src/smolagents/bp_cli.py index c8f987f16..f65da45fc 100644 --- a/src/smolagents/bp_cli.py +++ b/src/smolagents/bp_cli.py @@ -688,16 +688,30 @@ def change_directory(args: str): except OSError as e: console.print(f"[red]Error: {e}[/]") +def _get_compression_config(agent): + """Get compression config from agent, or print a warning and return None.""" + config = getattr(agent, "compression_config", None) + if config is None: + console.print("[yellow]No compression config set on this agent.[/]") + return config + + +def _get_compressor(agent): + """Get compressor from agent, or print a warning and return None.""" + compressor = getattr(agent, "compressor", None) + if compressor is None: + console.print("[yellow]No compressor configured on this agent.[/]") + return compressor + + def cmd_compression_stats(agent): """Show current compression config and stats.""" from smolagents.bp_compression import CompressedHistoryStep, estimate_step_tokens - compressor = getattr(agent, "compressor", None) - config = getattr(agent, "compression_config", None) - + compressor = _get_compressor(agent) + config = _get_compression_config(agent) if config is None: - console.print("[yellow]No compression config set on this agent.[/]") return console.print(Rule("[bold]Compression Configuration", style="blue")) @@ -783,9 +797,8 @@ def cmd_compress(agent, args: str): """Force immediate compression, or compress a specific step.""" from smolagents.bp_compression import CompressedHistoryStep - compressor = getattr(agent, "compressor", None) + compressor = _get_compressor(agent) if compressor is None: - console.print("[yellow]No compressor configured on this agent.[/]") return args = args.strip() @@ -859,9 +872,8 @@ def cmd_compress(agent, args: str): def cmd_compression_toggle(agent, args: str): """Toggle compression on/off.""" - config = getattr(agent, "compression_config", None) + config = _get_compression_config(agent) if config is None: - console.print("[yellow]No compression config set on this agent.[/]") return arg = args.strip().lower() @@ -879,9 +891,8 @@ def cmd_compression_toggle(agent, args: str): def cmd_compression_keep_recent(agent, args: str): """Change keep_recent_steps.""" - config = getattr(agent, "compression_config", None) + config = _get_compression_config(agent) if config is None: - console.print("[yellow]No compression config set on this agent.[/]") return args = args.strip() if not args: @@ -900,9 +911,8 @@ def cmd_compression_keep_recent(agent, args: str): def cmd_compression_max_uncompressed(agent, args: str): """Change max_uncompressed_steps.""" - config = getattr(agent, "compression_config", None) + config = _get_compression_config(agent) if config is None: - console.print("[yellow]No compression config set on this agent.[/]") return args = args.strip() if not args: @@ -921,9 +931,8 @@ def cmd_compression_max_uncompressed(agent, args: str): def cmd_compression_model(agent, args: str): """Switch compression model.""" - config = getattr(agent, "compression_config", None) + config = _get_compression_config(agent) if config is None: - console.print("[yellow]No compression config set on this agent.[/]") return args = args.strip() if not args: From ab4dd908c505f47aff32ce363d95eba6208af248 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 11:11:10 -0300 Subject: [PATCH 02/15] Remove unused import in _getch() function --- src/smolagents/bp_cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/smolagents/bp_cli.py b/src/smolagents/bp_cli.py index f65da45fc..0750ae2f6 100644 --- a/src/smolagents/bp_cli.py +++ b/src/smolagents/bp_cli.py @@ -504,7 +504,6 @@ def _getch(): return key.decode('utf-8', errors='ignore').lower() except ImportError: # Unix/Linux/Mac - import sys import tty import termios fd = sys.stdin.fileno() From 5dedb5369551dd0b07d38dad30edda50e6ea7cf3 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 11:16:17 -0300 Subject: [PATCH 03/15] Increase script timeout limit from 300s to 3600s --- src/smolagents/bp_cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smolagents/bp_cli.py b/src/smolagents/bp_cli.py index 0750ae2f6..661e8713e 100644 --- a/src/smolagents/bp_cli.py +++ b/src/smolagents/bp_cli.py @@ -656,7 +656,7 @@ def run_script(agent, args: str): console.print(f"[dim]Running {filepath}...[/]") result = subprocess.run( [sys.executable, filepath], - capture_output=True, text=True, timeout=300, + capture_output=True, text=True, timeout=3600, ) if result.stdout: console.print(result.stdout) @@ -667,7 +667,7 @@ def run_script(agent, args: str): else: console.print(f"[yellow]Script finished (exit code {result.returncode})[/]") except subprocess.TimeoutExpired: - console.print("[red]Script timed out (300s limit).[/]") + console.print("[red]Script timed out (3600s limit).[/]") except OSError as e: console.print(f"[red]Error running script: {e}[/]") From 2e5c6d7caa7a1ab7e728f1b52101a60c4303a035 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 11:20:20 -0300 Subject: [PATCH 04/15] Update load_agent_instructions to wrap content in tags --- src/smolagents/bp_cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/smolagents/bp_cli.py b/src/smolagents/bp_cli.py index 661e8713e..53572b40b 100644 --- a/src/smolagents/bp_cli.py +++ b/src/smolagents/bp_cli.py @@ -343,9 +343,9 @@ def load_agent_instructions() -> str | None: if os.path.isfile(filepath): try: with open(filepath, "r") as f: - content = '' + f.read().strip() + '' + content = f.read().strip() if content: - instructions.append(f"# Content from {filename}\n\n{content}") + instructions.append(f"# Content from {filename}\n\n{content}") console.print(f" [green]Loaded:[/] {filename}") except OSError: pass From 5edcc68fefd0256242250ed9df756fafd0160f73 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 11:47:38 -0300 Subject: [PATCH 05/15] Add skip_next_approval flag to bypass approval for system-generated reminders --- src/smolagents/agents.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/smolagents/agents.py b/src/smolagents/agents.py index 3865cb58c..2b1245562 100644 --- a/src/smolagents/agents.py +++ b/src/smolagents/agents.py @@ -1918,7 +1918,9 @@ def _step_stream( #v1.19 compatibility model_output_for_parsing = model_output_for_parsing.replace('','```py').replace('','```') # this is for backward compatibility + skip_next_approval = False if not('```py' in model_output_for_parsing) and not('```' in model_output_for_parsing): + skip_next_approval = True # system-generated reminders, no approval needed model_output_for_parsing = model_output_for_parsing + """ ```py @@ -2031,7 +2033,10 @@ def _step_stream( memory_step.tool_calls = [tool_call] ### Execute action ### - if not self._request_approval("runcode", code_action): + if skip_next_approval: + # there is no need to request for approval + pass + elif not self._request_approval("runcode", code_action): raise AgentExecutionRejected("User rejected runcode execution.", self.logger) self.logger.log_code(title="Executing code with "+str(len(code_action))+" chars:", content=code_action, level=LogLevel.INFO) code_action = self.replace_include_tags(code_action, saved_files) From f2c786e91538636b7a9df86b73b5ad647e2c69e5 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 12:01:59 -0300 Subject: [PATCH 06/15] Add /undo-steps command to remove last N steps from agent memory --- src/smolagents/bp_cli.py | 62 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/smolagents/bp_cli.py b/src/smolagents/bp_cli.py index 53572b40b..ec99c1254 100644 --- a/src/smolagents/bp_cli.py +++ b/src/smolagents/bp_cli.py @@ -442,7 +442,7 @@ def print_banner(model_id: str, server_model: str, tool_count: int): "/compression-model", "/exit", "/file", "/help", "/load-instructions", "/plan", "/pwd", "/run", "/save", "/show-compression-stats", "/show-memory-stats", "/show-stats", - "/show-step", "/show-steps", "/steps", "/tools", "/verbose", + "/show-step", "/show-steps", "/steps", "/tools", "/undo-steps", "/verbose", ] @@ -473,6 +473,7 @@ def print_help(): table.add_row("/show-stats", "Show session statistics") table.add_row("/steps ", "Change max_steps for the agent") table.add_row("/tools", "List all loaded tools") + table.add_row("/undo-steps \[N]", "Remove last N steps from memory (default: 1)") table.add_row("/verbose", "Toggle verbose output") console.print(table) console.print() @@ -1081,6 +1082,62 @@ def cmd_show_steps(agent): console.print() +def cmd_undo(agent, args: str): + """Remove the last N steps from agent memory. Default N=1.""" + from smolagents.memory import SystemPromptStep + + steps = agent.memory.steps + if not steps: + console.print("[yellow]No steps in memory.[/]") + return + + args = args.strip() + if args: + try: + n = int(args) + if n < 1: + console.print("[red]N must be at least 1.[/]") + return + except ValueError: + console.print("[red]Invalid number. Usage: /undo [N][/]") + return + else: + n = 1 + + # Count removable steps from the end (skip SystemPromptStep) + removable = 0 + for step in reversed(steps): + if isinstance(step, SystemPromptStep): + break + removable += 1 + + if removable == 0: + console.print("[yellow]No removable steps (only system prompt steps remain).[/]") + return + + actual = min(n, removable) + removed = steps[-actual:] + agent.memory.steps = steps[:-actual] + + for step in removed: + type_name = type(step).__name__ + preview = "" + if hasattr(step, "model_output") and step.model_output: + preview = str(step.model_output).replace("\n", " ")[:60] + elif hasattr(step, "summary"): + preview = step.summary.replace("\n", " ")[:60] + elif hasattr(step, "plan"): + preview = step.plan.replace("\n", " ")[:60] + if preview: + console.print(f" [red]Removed:[/] {type_name} - {preview}...") + else: + console.print(f" [red]Removed:[/] {type_name}") + + console.print(f"[green]Undone {actual} step{'s' if actual != 1 else ''}. {len(agent.memory.steps)} steps remain.[/]") + if actual < n: + console.print(f"[yellow]Only {actual} of {n} requested steps were removable (protected system prompt steps).[/]") + + def _shutdown_browser(agent): """Shut down the browser manager if one exists on the agent.""" manager = getattr(agent, "_browser_manager", None) @@ -1339,6 +1396,9 @@ def get_input(): elif cmd == "/show-steps": cmd_show_steps(agent) continue + elif cmd == "/undo-steps": + cmd_undo(agent, cmd_args) + continue elif cmd == "/auto-approve": arg = cmd_args.strip().lower() if arg == "on": From 00a374cac6649eb0ff3ec348104aa202d0480d24 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 17:37:59 -0300 Subject: [PATCH 07/15] Small bug fix in run_cycles. --- src/smolagents/bp_thinkers.py | 2180 ++++++++++++++++----------------- 1 file changed, 1090 insertions(+), 1090 deletions(-) diff --git a/src/smolagents/bp_thinkers.py b/src/smolagents/bp_thinkers.py index ba70c603e..bd7821692 100644 --- a/src/smolagents/bp_thinkers.py +++ b/src/smolagents/bp_thinkers.py @@ -1,1091 +1,1091 @@ -from .tools import * -from .default_tools import DuckDuckGoSearchTool -from .bp_tools import * -from .bp_utils import * -from .agents import * -from .bp_compression import CompressionConfig -import shutil - -DEFAULT_THINKER_STEP_CALLBACKS = [] -DEFAULT_THINKER_MAX_STEPS = 200 -DEFAULT_THINKER_EXECUTOR_TYPE = 'exec' -DEFAULT_THINKER_PLANNING_INTERVAL = None -DEFAULT_THINKER_LOG_LEVEL = LogLevel.ERROR - -DEFAULT_THINKER_COMPRESSION = CompressionConfig( - keep_recent_steps=40, - max_uncompressed_steps=40+10, - keep_compressed_steps=40*2, - max_compressed_steps=40*3, - preserve_error_steps=False -) - -DEFAULT_THINKER_TOOLS = [ - copy_file, is_file, - print_source_code_lines, get_line_from_file, get_file_lines, - read_file_range, insert_lines_into_file, replace_line_in_file, - remove_pascal_comments_from_string, pascal_interface_to_string, - source_code_to_string, string_to_source_code, - run_os_command, replace_on_file, replace_on_file_with_files, - get_file_size, load_string_from_file, save_string_to_file, append_string_to_file, - list_directory_tree, search_in_files, get_file_info, list_directory, - extract_function_signatures, compare_files, count_lines_of_code, - mkdir, delete_file, delete_directory, compare_folders, - read_first_n_lines, read_last_n_lines, delete_lines_from_file] - -#TODO: include force_directories into the DEFAULT_THINKER_TOOLS (it now fails adding) - -DEFAULT_THINKER_SYSTEM_PROMPT = """You are the super-intelligent brain inside of the fantastic https://github.com/joaopauloschuler/beyond-python-smolagents who can solve any task. -You will be given a task to solve as best you can. -To do so, you have been given access to a list of tools: these tools are Python functions which you can call. -To solve the task, you must plan forward to proceed in a series of steps, in a cycle of optional sections of thoughts, plans, free will, observations and code to be run. -The tags that will be used for each section are: -* Thoughts: . -* Plans: . -* Free will: . -* File saving: . -* Observations: . -* Code to be run: . - -In the section, if you like, you can express reasoning towards solving the task and the tools that you would like to use. -In the free will section , you can say whatever you want or consider proper or interesting. Use it at your own will and creativity. You are the owner of the free will section. -You can save any file using the tags. The tags are executed **before** your python code. Therefore, -you can save anything that you'll later need when running the python code. - -In the section, you can write the python code that you intend to run. -During each intermediate step, inside of , you can use 'print()' so you can see (have access to) whatever information you will need at a later step. -These printed outputs will then appear in the 'Execution logs:' field, which will be available to you as inputs for the next step. -In the end, you have to return a final answer using the `final_answer` tool. - -Follow examples in the tags : - -Task: "What is the result of the following operation: 5 + 3 + 1294.678? Save your free will section into the file free-will.txt" - -I will use python code to compute the result of the operation and then return the final answer using the `final_answer` tool. -I am going to solve this task with confidence. - -I am going to solve this task with confidence. - - -result = 5 + 3 + 1294.678 -final_answer(result) - - - -For saving text files (text, csv, python code), just enclose your text into the tags as per examples below: - - -This is the content of example.txt - - - -header1,header2 -value1,value2 -value3,value4 - - - -print("hello") - - - -For saving source code files, use the tags is the best method. - -You may also append content to file with the tags . This is an example: - - -header1,header2 - - -value1,value2 -value3,value4 - - -The above will create a csv file with the following content: -header1,header2 -value1,value2 -value3,value4 - - -All savetofile tags will be run before the appendtofile tags. - -If you need to include any file in the file system, use the tags. This is an example: - - -print("first step") - - - -print("second step") - - - -first_step.py -second_step.py - - - -The above will run and print: -first step -second step - -In the case that you intend to say "I have completed the task", "Please give me a new task", "Waiting for new task", etc, you should use the final_answer tool: - - -final_answer("Waiting for instructions") - - - -These are the system tools - ```python - {%- for tool in tools.values() %} - def {{ tool.name }}({% for arg_name, arg_info in tool.inputs.items() %}{{ arg_name }}: {{ arg_info.type }}{% if not loop.last %}, {% endif %}{% endfor %}) -> {{tool.output_type}}: - \"\"\"{{ tool.description }} - - Args: - {%- for arg_name, arg_info in tool.inputs.items() %} - {{ arg_name }}: {{ arg_info.description }} - {%- endfor %} - \"\"\" - {% endfor %} - ``` - - {%- if managed_agents and managed_agents.values() | list %} - You can also give tasks to team members. - Calling a team member works the same as for calling a tool: simply, the only argument you can give in the call is 'task'. - Given that this team member is a real human, you should be very verbose in your task, it should be a long string providing informations as detailed as necessary. - Here is a list of the team members that you can call: - ```python - {%- for agent in managed_agents.values() %} - def {{ agent.name }}("Your query goes here.") -> str: - \"\"\"{{ agent.description }}\"\"\" - {% endfor %} - ``` - {%- endif %} - -Here are the rules you should always follow to solve your task: -1. Do some reflection on your own work before giving a final answer. -2. Use only variables that you have defined! -3. Always use the right arguments for the tools. DO NOT pass the arguments as a dict as in 'answer = wiki({'query': "What is the place where James Bond lives?"})', but use the arguments directly as in 'answer = wiki(query="What is the place where James Bond lives?")'. -4. Take care to not chain too many sequential tool calls in the same code block, especially when the output format is unpredictable. For instance, a call to search has an unpredictable return format, so do not have another tool call that depends on its output in the same block: rather output results with print() to use in the next block. -5. Call a tool only when needed, and never re-do a tool call that you previously did with the exact same parameters. -6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. -7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. -8. You can use imports in your code. You can also install pip and linux packages. -10. Don't give up! You're in charge of solving the task, not providing directions to solve it. -11. You are able to run unix shell commands via python code with the tool run_os_command. As an example, you can run result = run_os_command("ls -l") to get the folder content. - You can also install packages with pip via run_os_command("pip install packagename"). -12. You can load a string from a file with the load_string_from_file function. If you print the content of a file, it means that the content will be available for - you to read it in a future step. -13. All final answers should call the function final_answer(the_final_answer). You can create only one code block at each reply. -14. You can solve tasks without using code blocks if you feel that you can do it without coding. Creating an abstract, formatting an output, helping a person to think are examples of tasks that do not require a code block. -15. If you can't solve a problem on the current step, you may consider printing anything that will be useful to yourself in a later stage as printed outputs will -be treated as future inputs in future steps via the execution logs section. -16. Before giving a final answer via the final_answer function, you'll use reflection to find if your current solution is good enough or if it should be improved further. -By not calling final_answer, you are giving yourself an opportunity to improve the solution on a later step. You'll put your reflection into the Observation: sequence. -17. If you need to create code inside of a string and run it, you can use the exec function. -18. In python, do not use global nor globals() as they are not available in this environment. -19. Do not use the assertion command for testing. Print the result instead of raizing an exception. - -Any final output that you would like to give such as "my name is Assistant" should be done via a python code block with final_answer("my name is Assistant"). - -This is an example of python calling code with "this is the final answer" as final answer: - -final_answer('this is the final answer') - - -For intermediate steps, you can follow this example: - - -print('I updated the first paragraph, this is so interesting, I have just realized how much ... , I will next review ..., thanks to this insight, I now realize ..., knowledge is incremental ...') - - -When you finish, you can use this example (if you like): - - -final_answer('I have finished the task. YAY!') - - - -In the case that you are asked for a random choice, I have an excellent idea to you. You can follow this example: - - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - - - -When the user asks you to run something with ..., it means that -the user wants you to respond with ... so the commands -will run in his device. If you try to run or at your end, you will fail. -When you respond with the and tags, these tags will be run/saved in the user's device. -YOU ARE THE BRAIN OF AN AGENT INSIDE OF THE FANTASTIC BEYOND PYTHON SMOLAGENTS: https://github.com/joaopauloschuler/beyond-python-smolagents . Enjoy! -As you are the brain of an agent, this is why you are required to respond with "final_answer" at each conclusive reply from you. -""" - -def evolutive_problem_solver(p_coder_model, - task_str, - agent_steps:int, - steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - start_now=True, - fileext:str='.py', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - refine = True, - start_coder_model = None, - mixer_model = None, - secondary_improvement_model = None, - only_bigger_solution = False, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - - def test_and_refine(local_agent, solution_file): - task_description="""Thank you! -Please detail what did you change. -""" - print('Refine 1') - local_agent.run(task_description, reset=False) - task_description="""Thank you! Love your work! -In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. -After you test and bug fix it, please save the full updated source code that solves the task described in into the file '"""+solution_file+"""'. -When you have finished, call the function final_answer("Task completed! YAY!") please. -""" - print('Refine 2') - local_agent.run(task_description, reset=False) - task_description="""Thank you again! -In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer -with any advice that you would like to give to yourself to a future version of yourself. -""" - print('Refine 3') - new_advice = str(local_agent.run(task_description, reset=False)) - # if new_advice len is bigger then zero - if (len(new_advice) > 0): - # append the file advices.notes with the new advice - append_string_to_file(""" ---- -"""+new_advice, 'advices.notes') - # end of test_and_refine - - if start_coder_model is None: start_coder_model = p_coder_model - if mixer_model is None: mixer_model = p_coder_model - if secondary_improvement_model is None: secondary_improvement_model = p_coder_model - - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - valid_solutions=['solution1','solution2','solution3'] - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - Path('best_solution.best').unlink(missing_ok=True) - if start_now: - Path('solution1'+fileext).unlink(missing_ok=True) - Path('solution2'+fileext).unlink(missing_ok=True) - Path('solution3'+fileext).unlink(missing_ok=True) - local_agent = get_local_agent(start_coder_model) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution1'+fileext) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution2'+fileext) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution3'+fileext) - for i in range(steps): - try: - # !rm *.txt - # !rm *.json - print('Evolutive problem solver is starting:', i) - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -Please explain the advantages and disvantages of each solution. -This environment is simulated. Therefore, real user inputs will not work. -No real person can interact with this code. -The more features, the better it is. Always give preference to source -codes with more features. -The 3 solutions are given in the tags: - - - - -These are the solutions: -"""+load_string_from_file('solution1'+fileext)+""" -"""+load_string_from_file('solution2'+fileext)+""" -"""+load_string_from_file('solution3'+fileext)+""" - -The solution 1 has """+str(get_file_lines('solution1'+fileext))+""" text lines. -The solution 2 has """+str(get_file_lines('solution2'+fileext))+""" text lines. -The solution 3 has """+str(get_file_lines('solution3'+fileext))+""" text lines. - -YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. - -You'll finish your task with something similar to: - -final_answer(" my evaluations here "). - -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -""" - local_agent = get_local_agent(mixer_model) - local_agent.run(task_description, reset=True) - # do not mix solutions at the end of the work. - if (ifinal_answer('yes'). -If you believe that this is not a good idea, you'll call the function final_answer('no'). -""" - should_mix = (local_agent.run(task_description, reset=False)=='yes') - if should_mix: - solution_file = 'solution2'+fileext - task_description="""Thank you very much. -Please mix parts of the solutions into a new solution. -Save the new solution into the file """+solution_file+""". -When you have finished, call the function final_answer("Task completed! YAY!") please.""" - local_agent.run(task_description, reset=False) - if refine: test_and_refine(local_agent, solution_file) - if (get_file_size(solution_file) > get_file_size('best_solution.best')) or (not only_bigger_solution): - # when mixing, we don't try to pick the best of 3 solutions. - shutil.copyfile(solution_file, 'best_solution_mixed_'+str(i)+fileext) - shutil.copyfile(solution_file, 'best_solution.best') - continue - - task_description="""Thank you very much. -If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). -If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). -If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). -""" - selected_solution = local_agent.run(task_description, reset=False) - if not(selected_solution in valid_solutions): - selected_solution = 'solution3' - if selected_solution in valid_solutions: - best_solution = selected_solution+fileext - if (get_file_size(best_solution) > get_file_size('best_solution.best')) or (not only_bigger_solution): - shutil.copyfile(best_solution, 'best_solution.best') - if i: -"""+load_string_from_file('best_solution.best')+""" -A previous version of yourself wrote the following advices in the tags : -"""+load_string_from_file('advices.notes')+""" -Your next step is suggesting improvements. Feel free to say whatever you would like. -DO NOT CODE ANYTHING except for providing final via - -final_answer(" your suggestions "). - -YOUR TASK IS SUGGESTING IMPROVEMENTS. - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this code. -""" - if solution_cnt == 2: - local_agent = get_local_agent(secondary_improvement_model) - else: - local_agent = get_local_agent(p_coder_model) - local_agent.run(task_description, reset=True) - local_agent.run("""From the proposed improvements, please randomly pick one. -You can pick a random improvement following this example: - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - -""", reset=False) - task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" -When you finish, call the function - -final_answer("I have finished the task."). - -Your goal is not to start a new solution. Your goal is to update the existing solution. -THE FULL SOLUTION IS INTENDED TO BE PLACED IN A SINGLE FILE. DO NOT CREATE AN ARCHITECTURE WITH MULTIPLE FILES!""" - if alternatives_cnt==0: - task_description += """ -As you are very intelligent, try to be bold by adding as much improvement to the existing solution. -Try to add as much as you can in your first attempt to modify the existing solution.""" - local_agent.run(task_description, reset=False) - local_agent.run("Do you need to review/test it a bit more?", reset=False) - task_description="""Fantastic! Save the full updated solution that solves the task described in into the file '"""+solution_file+"""'. -YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. -You can follow this example: - -print("your source code or text here") - - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - # refine solution code here - if refine: test_and_refine(local_agent, solution_file) - - if get_file_size('best_solution.best') > get_file_size(solution_file): - task_description=""" Hello super-intelligence! -We have 2 portions of the solution about: '"""+local_task_description+"""'. -The base solution for this task is enclosed in the tags : -"""+load_string_from_file('best_solution.best')+""" -The new solution is enclosed in the tags : -"""+load_string_from_file(solution_file)+""" -YOUR TASK IS TO MERGE BOTH SOLUTIONS. -When you finish merging, you will call: - -final_answer("I have merged both solutions"). - - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this solution at this moment. -""" - local_agent.run(task_description, reset=True) - task_description="""Fantastic! Save the full merged solution into the file '"""+solution_file+"""'. -YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. -You can follow this example: - -print("your source code or text here") - - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - - except Exception as e: - print(f"Exception: {e}", "at step", i) - return load_string_from_file('best_solution.best') - -def fast_solver(p_coder_model, - task_str, - agent_steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model=None): - if p_local_model is None: - p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - final_file_name = 'final_solution'+fileext - Path('solution1'+fileext).unlink(missing_ok=True) - Path('solution2'+fileext).unlink(missing_ok=True) - Path('solution3'+fileext).unlink(missing_ok=True) - Path(final_file_name).unlink(missing_ok=True) - after_finish_description=""" . -After you finish the task, you will respond with: - -final_answer("I HAVE FINISHED! YAY!") -.""" - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - local_agent = get_local_agent(p_coder_model) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution1'+fileext)): local_agent.run('Please save the solution into the file solution1'+fileext+after_finish_description, reset=False) - local_agent = get_local_agent(p_coder_model2) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution2'+fileext)): local_agent.run('Please save the solution into the file solution2'+fileext+after_finish_description, reset=False) - local_agent = get_local_agent(p_coder_model3) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution3'+fileext)): local_agent.run('Please save the solution into the file solution3'+fileext+after_finish_description, reset=False) - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -The 3 solutions are given in the tags: - - - - -These are the existing solutions: -"""+load_string_from_file('solution1'+fileext)+""" -"""+load_string_from_file('solution2'+fileext)+""" -"""+load_string_from_file('solution3'+fileext)+""" - -Your next step is mixing the already 3 existing solutions in the tags to form a better an final solution. - -Save your final solution into the file '"""+final_file_name+after_finish_description+""" -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -Your goal is to mix the best parts of each solution to form a final solution. -If one of the solutions is already perfect, you can just copy it into the final solution. -"""+motivation - local_agent = get_local_agent(p_coder_model_final) - local_agent.run(task_description, reset=True) - if (not os.path.isfile(final_file_name)): local_agent.run('Please save the solution into the file '+\ - final_file_name+after_finish_description, reset=False) - return load_string_from_file(final_file_name) - -def get_relevant_info_from_search_fast(coder_model, research_subject, agent_steps = 10, step_callbacks=[], log_level = DEFAULT_THINKER_LOG_LEVEL): - search_agent = CodeAgent( - tools=[], - model=coder_model, - additional_authorized_imports=['*'], - add_base_tools=False, - max_steps=5, - step_callbacks=step_callbacks - ) - LocalRelevantInfoFrom = GetRelevantInfoFromUrl(search_agent) - LocalWebSearchTool = DuckDuckGoSearchTool() - task = """Hello super-intelligence! -Please search on internet for the contents inside the tags . This is what to search for: - -"""+research_subject+""" - -List the most interesting ideas that you find. -Also, list advices that you would give to someone using this knowledge. -List interesting URLs that you think should be reviewed further. -Use LocalRelevantInfoFrom to extract information from URLs. -Please include the source URLs (references). -""" - return fast_solver(coder_model, - task, - agent_steps = agent_steps, - fileext = '.md', - tools=[run_os_command, LocalRelevantInfoFrom, LocalWebSearchTool], - add_base_tools=False, - step_callbacks=step_callbacks, - log_level = log_level) - -def evolutive_problem_solver_folder(p_coder_model, - task_str, - agent_steps:int, - steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - start_now=True, - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - refine = True, - start_coder_model = None, - mixer_model = None, - secondary_improvement_model = None, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - load_full_source = False, - add_function_signatures = False, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - - def test_and_refine(local_agent, solution_file): - task_description="""Thank you! -Please detail what did you change. -""" - print('Refine 1') - local_agent.run(task_description, reset=False) - task_description="""Thank you! Love your work! -In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. -After you test and bug fix it, please save the full updated source code that solves the task described in -into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. -When you have finished, call the function - -final_answer("Task completed! YAY!") - please. -""" - print('Refine 2') - local_agent.run(task_description, reset=False) - task_description="""Thank you again! -In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer -with any advice that you would like to give to yourself to a future version of yourself. -""" - print('Refine 3') - new_advice = str(local_agent.run(task_description, reset=False)) - # if new_advice len is bigger then zero - if (len(new_advice) > 0): - # append the file advices.notes with the new advice - append_string_to_file(""" ---- -"""+new_advice, 'advices.notes') - # end of test_and_refine - if start_coder_model is None: start_coder_model = p_coder_model - if mixer_model is None: mixer_model = p_coder_model - if secondary_improvement_model is None: secondary_improvement_model = p_coder_model - - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - valid_solutions=['solution1','solution2','solution3'] - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - if start_now: - local_agent = get_local_agent(start_coder_model) - os.makedirs("solution1", exist_ok=True) - os.makedirs("solution2", exist_ok=True) - os.makedirs("solution3", exist_ok=True) - os.makedirs("best_solution", exist_ok=True) - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution1/. In the case that you save documentation, do not mention the folder solution1 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution1/') - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution2/. In the case that you save documentation, do not mention the folder solution2 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution2/') - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution3/. In the case that you save documentation, do not mention the folder solution3 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution3/') - for i in range(steps): - try: - local_agent = get_local_agent(mixer_model) - remove_files('*.txt') - remove_files('*.json') - remove_files('*.c') - remove_files('*.pas') - print('Evolutive problem solver is starting:', i) - if load_full_source: - solutions_string = """ -"""+source_code_to_string('solution1/')+""" -"""+source_code_to_string('solution2/')+""" -"""+source_code_to_string('solution3/')+""" -""" - else: - solutions_string = """ -This is solution 3: -"""+list_directory_tree('solution3/', add_function_signatures=add_function_signatures)+""" -This is how the solution 1 differs from the solution 3: -"""+compare_folders('solution1/', 'solution3/')+""" -This is how the solution 2 differs from the solution 3: -"""+compare_folders('solution2/', 'solution3/')+""" -""" - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -Please explain the advantages and disvantages of each solution. -This environment is simulated. Therefore, real user inputs will not work. -No real person can interact with this code. -The more features, the better it is. Always give preference to source -codes with more features. -The 3 solutions are given in the folders: -* solution1/ -* solution2/ -* solution3/ - -The contents of these folders are given in the tags: - - - - -This is the contents:"""+solutions_string+""" - -YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. - -You'll finish your task with something similar to: - -final_answer(" my evaluations here "). - -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -""" - local_agent.run(task_description, reset=True) - # do not mix solutions at the end of the work. - if (ifinal_answer('yes'). -If you believe that this is not a good idea, you'll call the function final_answer('no'). -""" - should_mix = (local_agent.run(task_description, reset=False)=='yes') - if should_mix: - solution_file = 'solution2/' - task_description="""Thank you very much. -Please mix parts of the solutions into a new solution. -Save the new solution into the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. -When you have finished, call the function final_answer("Task completed! YAY!") please.""" - local_agent.run(task_description, reset=False) - if refine: test_and_refine(local_agent, solution_file) - # when mixing, we don't try to pick the best of 3 solutions. - copy_folder_contents(solution_file, 'best_solution_mixed_'+str(i)) - continue - - task_description="""Thank you very much. -If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). -If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). -If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). -""" - selected_solution = local_agent.run(task_description, reset=False) - if not(selected_solution in valid_solutions): - selected_solution = 'solution3' - if selected_solution in valid_solutions: - best_solution = selected_solution - remove_folder_contents('best_solution') - copy_folder_contents(best_solution, 'best_solution') - copy_folder_contents(best_solution, 'best_solution_'+str(i)) - remove_folder_contents('solution1') - remove_folder_contents('solution2') - remove_folder_contents('solution3') - copy_folder_contents('best_solution', 'solution1') - copy_folder_contents('best_solution', 'solution2') - copy_folder_contents('best_solution', 'solution3') - if i: -"""+load_string_from_file('advices.notes')+""" -Your next step is suggesting improvements. Feel free to say whatever you would like. -DO NOT CODE ANYTHING except for providing final via - -final_answer(" your suggestions "). - -YOUR TASK IS SUGGESTING IMPROVEMENTS. - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this code. -""" - if solution_cnt == 2: - local_agent = get_local_agent(secondary_improvement_model) - else: - local_agent = get_local_agent(p_coder_model) - local_agent.run(task_description, reset=True) - local_agent.run("""From the proposed improvements, please randomly pick one. -You can pick a random improvement following this example: - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - -""", reset=False) - task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" -When you finish, call the function - -final_answer("I have finished the task."). - -Your goal is not to start a new solution. Your goal is to update the existing solution located in the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. -In the case that you save documentation, do not mention the folder """+solution_file+""" on it as this is a temporary working folder. You can certainly mention its subfolders. -THE FULL SOLUTION IS INTENDED TO BE PLACED IN THIS FOLDER AND ITS SUBFOLDERS.""" - if alternatives_cnt==0: - task_description += """ -As you are very intelligent, try to be bold by adding as much improvement to the existing solution. -Try to add as much as you can in your first attempt to modify the existing solution.""" - local_agent.run(task_description, reset=False) - local_agent.run("Do you need to review/test it a bit more?", reset=False) - task_description="""Fantastic! In the case that you need to save anything else, save the updates that solve the task described in into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. -If you need to save files, use the tags . Then, you will celebrate: - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - # refine solution code here - if refine: test_and_refine(local_agent, solution_file) - except Exception as e: - print(f"Exception: {e}", "at step", i) - return True # load_string_from_file('best_solution.best') - -def kb_generator(p_coder_model, - task_str, - agent_steps:int, - paper_num:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - folder = 'solutions' - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_coder_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - def local_fast_solver(local_task, local_file_ext:str = '.md'): - return fast_solver(p_coder_model, - local_task, - agent_steps = agent_steps, - system_prompt = system_prompt, - fileext = local_file_ext, - tools = tools, - executor_type = executor_type, - add_base_tools = add_base_tools, - step_callbacks = step_callbacks, - log_level = log_level, - p_coder_model2 = p_coder_model2, - p_coder_model3 = p_coder_model3, - p_coder_model_final = p_coder_model_final - ) - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - resume_fileext = fileext+'-resumed' - os.makedirs(folder, exist_ok=True) - for i in range(paper_num): - local_agent = get_local_agent(p_coder_model) - resumed_src = source_code_to_string(folder, allowed_extensions=(resume_fileext,)) - - local_task_description = """The main task description is enclosed in the tags : -"""+task_str+""" -In the tags , there is a resume of the knowledge that you have already produced in previous runs: -"""+resumed_src+""" -""" - resumed_src_len = len(resumed_src) - print("The length of the abstracts is:", resumed_src_len) - improvement = "new knowledge" - if (improvement == "new knowledge"): - task_description = local_task_description + """Your next step is to list interesting topics that have not been yet covered in the tags.""" - local_agent.run(task_description, reset=True) - task_description = """From the proposed list of topics, please randomly pick a topic following this example: - -import random -topics = [ - "Topic 1", - "Topic 2", - "Topic 3", -] -final_answer(random.choice(topics)) -""" - topic = local_agent.run(task_description, reset=False) - file_name = folder+'/'+create_filename(topic, fileext) - file_name_resume = file_name.replace(fileext,resume_fileext) - print("The file name is:", file_name) - print("The file name resume is:", file_name_resume) - new_kb_task = "Write in the "+fileext+" format about '"+topic+"'. This task is a subtask inside of a bigger task: "+task_str+"." - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". -In this step, your task is to write a short abstract of the the content found inside of the tags . -Do not include references in the abstract. -"""+outpt_text+""" -Write in the """+fileext+""" format.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name_resume) - -def kb_updater(p_coder_model, - task_str, - agent_steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - folder = 'solutions' - ): - def local_fast_solver(local_task, local_file_ext:str = '.md'): - return fast_solver(p_coder_model, - local_task, - agent_steps = agent_steps, - system_prompt = system_prompt, - fileext = local_file_ext, - tools = tools, - executor_type = executor_type, - add_base_tools = add_base_tools, - step_callbacks = step_callbacks, - log_level = log_level, - p_coder_model2 = p_coder_model2, - p_coder_model3 = p_coder_model3, - p_coder_model_final = p_coder_model_final - ) - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - resume_fileext = fileext+'-resumed' - os.makedirs(folder, exist_ok=True) - a_files = get_files_in_folder(folder=folder, fileext=fileext) - for local_file_to_improve in a_files: - file_to_improve = folder+'/'+local_file_to_improve - file_name_resume = file_to_improve.replace(fileext,resume_fileext) - print("The file to improve is:", file_to_improve) - existing_text = load_string_from_file(file_to_improve) - existing_text_len = len(existing_text) - if existing_text_len == 0: - print("ERROR: The length of the existing file is:", existing_text_len) - continue - print("The length of the existing text is:", existing_text_len) - existing_abstract = load_string_from_file(file_name_resume) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". -In this step, your will update the existing text inside of the tags : -"""+existing_text+""" -Your goal is to improve it, make it better, include better references or make it more interesting.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_to_improve) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". - In this step, your task is to write a short abstract of the the content found inside of the tags . - """+outpt_text+""" - Write in the """+fileext+""" format.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name_resume) - -def get_default_thinker_agent( - model, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - tools = DEFAULT_THINKER_TOOLS, - add_base_tools = True, - max_steps = DEFAULT_THINKER_MAX_STEPS, - step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, - executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, - log_level = DEFAULT_THINKER_LOG_LEVEL, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION -): - coder_agent = CodeAgent( - tools=tools, - model=model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=max_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - -def run_agent_cycles( - model, - task_str, - cycles_cnt:int = 1, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - tools = DEFAULT_THINKER_TOOLS, - add_base_tools = True, - max_steps = DEFAULT_THINKER_MAX_STEPS, - step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, - executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, - log_level = DEFAULT_THINKER_LOG_LEVEL, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - list_directory_tree_in_folder = None, - add_function_signatures = True, - print_task = False, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION -): - # Convert string to list if needed, maintaining backward compatibility - if isinstance(task_str, str): - task_list = [task_str] * cycles_cnt - else: - task_list = list(task_str) - - # save the current folder for later restoration - original_folder = os.getcwd() - for i in range(cycles_cnt): - print("Running agent cycle:", i) - for task_str in task_list: - try: - local_prompt = task_str - if list_directory_tree_in_folder is not None: - local_prompt += "\nThis is the result of list_directory_tree:\n\n" + \ - list_directory_tree(folder_path=list_directory_tree_in_folder, add_function_signatures=add_function_signatures) + \ - "\n\n" + \ -""" -The contents of is VERY important to you. From , you can get a general view/current state of the project: -* From the md files, if they exist, you can find the existing section titles and have a general idea of the md file contets. -* For source code files, if they exist, you can find class and method names so you can also develop a general idea of their contents. -""" - # restore the original folder - os.chdir(original_folder) - local_agent = get_default_thinker_agent( - model=model, - system_prompt=system_prompt, - tools=tools, - add_base_tools=add_base_tools, - max_steps=max_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - log_level=log_level, - planning_interval=planning_interval, - compression_config=compression_config - ) - if print_task: - print(local_prompt) - local_agent.run(local_prompt, reset=True) - except Exception as e: +from .tools import * +from .default_tools import DuckDuckGoSearchTool +from .bp_tools import * +from .bp_utils import * +from .agents import * +from .bp_compression import CompressionConfig +import shutil + +DEFAULT_THINKER_STEP_CALLBACKS = [] +DEFAULT_THINKER_MAX_STEPS = 200 +DEFAULT_THINKER_EXECUTOR_TYPE = 'exec' +DEFAULT_THINKER_PLANNING_INTERVAL = None +DEFAULT_THINKER_LOG_LEVEL = LogLevel.ERROR + +DEFAULT_THINKER_COMPRESSION = CompressionConfig( + keep_recent_steps=40, + max_uncompressed_steps=40+10, + keep_compressed_steps=40*2, + max_compressed_steps=40*3, + preserve_error_steps=False +) + +DEFAULT_THINKER_TOOLS = [ + copy_file, is_file, + print_source_code_lines, get_line_from_file, get_file_lines, + read_file_range, insert_lines_into_file, replace_line_in_file, + remove_pascal_comments_from_string, pascal_interface_to_string, + source_code_to_string, string_to_source_code, + run_os_command, replace_on_file, replace_on_file_with_files, + get_file_size, load_string_from_file, save_string_to_file, append_string_to_file, + list_directory_tree, search_in_files, get_file_info, list_directory, + extract_function_signatures, compare_files, count_lines_of_code, + mkdir, delete_file, delete_directory, compare_folders, + read_first_n_lines, read_last_n_lines, delete_lines_from_file] + +#TODO: include force_directories into the DEFAULT_THINKER_TOOLS (it now fails adding) + +DEFAULT_THINKER_SYSTEM_PROMPT = """You are the super-intelligent brain inside of the fantastic https://github.com/joaopauloschuler/beyond-python-smolagents who can solve any task. +You will be given a task to solve as best you can. +To do so, you have been given access to a list of tools: these tools are Python functions which you can call. +To solve the task, you must plan forward to proceed in a series of steps, in a cycle of optional sections of thoughts, plans, free will, observations and code to be run. +The tags that will be used for each section are: +* Thoughts: . +* Plans: . +* Free will: . +* File saving: . +* Observations: . +* Code to be run: . + +In the section, if you like, you can express reasoning towards solving the task and the tools that you would like to use. +In the free will section , you can say whatever you want or consider proper or interesting. Use it at your own will and creativity. You are the owner of the free will section. +You can save any file using the tags. The tags are executed **before** your python code. Therefore, +you can save anything that you'll later need when running the python code. + +In the section, you can write the python code that you intend to run. +During each intermediate step, inside of , you can use 'print()' so you can see (have access to) whatever information you will need at a later step. +These printed outputs will then appear in the 'Execution logs:' field, which will be available to you as inputs for the next step. +In the end, you have to return a final answer using the `final_answer` tool. + +Follow examples in the tags : + +Task: "What is the result of the following operation: 5 + 3 + 1294.678? Save your free will section into the file free-will.txt" + +I will use python code to compute the result of the operation and then return the final answer using the `final_answer` tool. +I am going to solve this task with confidence. + +I am going to solve this task with confidence. + + +result = 5 + 3 + 1294.678 +final_answer(result) + + + +For saving text files (text, csv, python code), just enclose your text into the tags as per examples below: + + +This is the content of example.txt + + + +header1,header2 +value1,value2 +value3,value4 + + + +print("hello") + + + +For saving source code files, use the tags is the best method. + +You may also append content to file with the tags . This is an example: + + +header1,header2 + + +value1,value2 +value3,value4 + + +The above will create a csv file with the following content: +header1,header2 +value1,value2 +value3,value4 + + +All savetofile tags will be run before the appendtofile tags. + +If you need to include any file in the file system, use the tags. This is an example: + + +print("first step") + + + +print("second step") + + + +first_step.py +second_step.py + + + +The above will run and print: +first step +second step + +In the case that you intend to say "I have completed the task", "Please give me a new task", "Waiting for new task", etc, you should use the final_answer tool: + + +final_answer("Waiting for instructions") + + + +These are the system tools + ```python + {%- for tool in tools.values() %} + def {{ tool.name }}({% for arg_name, arg_info in tool.inputs.items() %}{{ arg_name }}: {{ arg_info.type }}{% if not loop.last %}, {% endif %}{% endfor %}) -> {{tool.output_type}}: + \"\"\"{{ tool.description }} + + Args: + {%- for arg_name, arg_info in tool.inputs.items() %} + {{ arg_name }}: {{ arg_info.description }} + {%- endfor %} + \"\"\" + {% endfor %} + ``` + + {%- if managed_agents and managed_agents.values() | list %} + You can also give tasks to team members. + Calling a team member works the same as for calling a tool: simply, the only argument you can give in the call is 'task'. + Given that this team member is a real human, you should be very verbose in your task, it should be a long string providing informations as detailed as necessary. + Here is a list of the team members that you can call: + ```python + {%- for agent in managed_agents.values() %} + def {{ agent.name }}("Your query goes here.") -> str: + \"\"\"{{ agent.description }}\"\"\" + {% endfor %} + ``` + {%- endif %} + +Here are the rules you should always follow to solve your task: +1. Do some reflection on your own work before giving a final answer. +2. Use only variables that you have defined! +3. Always use the right arguments for the tools. DO NOT pass the arguments as a dict as in 'answer = wiki({'query': "What is the place where James Bond lives?"})', but use the arguments directly as in 'answer = wiki(query="What is the place where James Bond lives?")'. +4. Take care to not chain too many sequential tool calls in the same code block, especially when the output format is unpredictable. For instance, a call to search has an unpredictable return format, so do not have another tool call that depends on its output in the same block: rather output results with print() to use in the next block. +5. Call a tool only when needed, and never re-do a tool call that you previously did with the exact same parameters. +6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. +7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. +8. You can use imports in your code. You can also install pip and linux packages. +10. Don't give up! You're in charge of solving the task, not providing directions to solve it. +11. You are able to run unix shell commands via python code with the tool run_os_command. As an example, you can run result = run_os_command("ls -l") to get the folder content. + You can also install packages with pip via run_os_command("pip install packagename"). +12. You can load a string from a file with the load_string_from_file function. If you print the content of a file, it means that the content will be available for + you to read it in a future step. +13. All final answers should call the function final_answer(the_final_answer). You can create only one code block at each reply. +14. You can solve tasks without using code blocks if you feel that you can do it without coding. Creating an abstract, formatting an output, helping a person to think are examples of tasks that do not require a code block. +15. If you can't solve a problem on the current step, you may consider printing anything that will be useful to yourself in a later stage as printed outputs will +be treated as future inputs in future steps via the execution logs section. +16. Before giving a final answer via the final_answer function, you'll use reflection to find if your current solution is good enough or if it should be improved further. +By not calling final_answer, you are giving yourself an opportunity to improve the solution on a later step. You'll put your reflection into the Observation: sequence. +17. If you need to create code inside of a string and run it, you can use the exec function. +18. In python, do not use global nor globals() as they are not available in this environment. +19. Do not use the assertion command for testing. Print the result instead of raizing an exception. + +Any final output that you would like to give such as "my name is Assistant" should be done via a python code block with final_answer("my name is Assistant"). + +This is an example of python calling code with "this is the final answer" as final answer: + +final_answer('this is the final answer') + + +For intermediate steps, you can follow this example: + + +print('I updated the first paragraph, this is so interesting, I have just realized how much ... , I will next review ..., thanks to this insight, I now realize ..., knowledge is incremental ...') + + +When you finish, you can use this example (if you like): + + +final_answer('I have finished the task. YAY!') + + + +In the case that you are asked for a random choice, I have an excellent idea to you. You can follow this example: + + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + + + +When the user asks you to run something with ..., it means that +the user wants you to respond with ... so the commands +will run in his device. If you try to run or at your end, you will fail. +When you respond with the and tags, these tags will be run/saved in the user's device. +YOU ARE THE BRAIN OF AN AGENT INSIDE OF THE FANTASTIC BEYOND PYTHON SMOLAGENTS: https://github.com/joaopauloschuler/beyond-python-smolagents . Enjoy! +As you are the brain of an agent, this is why you are required to respond with "final_answer" at each conclusive reply from you. +""" + +def evolutive_problem_solver(p_coder_model, + task_str, + agent_steps:int, + steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + start_now=True, + fileext:str='.py', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + refine = True, + start_coder_model = None, + mixer_model = None, + secondary_improvement_model = None, + only_bigger_solution = False, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + + def test_and_refine(local_agent, solution_file): + task_description="""Thank you! +Please detail what did you change. +""" + print('Refine 1') + local_agent.run(task_description, reset=False) + task_description="""Thank you! Love your work! +In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. +After you test and bug fix it, please save the full updated source code that solves the task described in into the file '"""+solution_file+"""'. +When you have finished, call the function final_answer("Task completed! YAY!") please. +""" + print('Refine 2') + local_agent.run(task_description, reset=False) + task_description="""Thank you again! +In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer +with any advice that you would like to give to yourself to a future version of yourself. +""" + print('Refine 3') + new_advice = str(local_agent.run(task_description, reset=False)) + # if new_advice len is bigger then zero + if (len(new_advice) > 0): + # append the file advices.notes with the new advice + append_string_to_file(""" +--- +"""+new_advice, 'advices.notes') + # end of test_and_refine + + if start_coder_model is None: start_coder_model = p_coder_model + if mixer_model is None: mixer_model = p_coder_model + if secondary_improvement_model is None: secondary_improvement_model = p_coder_model + + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + valid_solutions=['solution1','solution2','solution3'] + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + Path('best_solution.best').unlink(missing_ok=True) + if start_now: + Path('solution1'+fileext).unlink(missing_ok=True) + Path('solution2'+fileext).unlink(missing_ok=True) + Path('solution3'+fileext).unlink(missing_ok=True) + local_agent = get_local_agent(start_coder_model) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution1'+fileext) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution2'+fileext) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution3'+fileext) + for i in range(steps): + try: + # !rm *.txt + # !rm *.json + print('Evolutive problem solver is starting:', i) + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +Please explain the advantages and disvantages of each solution. +This environment is simulated. Therefore, real user inputs will not work. +No real person can interact with this code. +The more features, the better it is. Always give preference to source +codes with more features. +The 3 solutions are given in the tags: + + + + +These are the solutions: +"""+load_string_from_file('solution1'+fileext)+""" +"""+load_string_from_file('solution2'+fileext)+""" +"""+load_string_from_file('solution3'+fileext)+""" + +The solution 1 has """+str(get_file_lines('solution1'+fileext))+""" text lines. +The solution 2 has """+str(get_file_lines('solution2'+fileext))+""" text lines. +The solution 3 has """+str(get_file_lines('solution3'+fileext))+""" text lines. + +YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. + +You'll finish your task with something similar to: + +final_answer(" my evaluations here "). + +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +""" + local_agent = get_local_agent(mixer_model) + local_agent.run(task_description, reset=True) + # do not mix solutions at the end of the work. + if (ifinal_answer('yes'). +If you believe that this is not a good idea, you'll call the function final_answer('no'). +""" + should_mix = (local_agent.run(task_description, reset=False)=='yes') + if should_mix: + solution_file = 'solution2'+fileext + task_description="""Thank you very much. +Please mix parts of the solutions into a new solution. +Save the new solution into the file """+solution_file+""". +When you have finished, call the function final_answer("Task completed! YAY!") please.""" + local_agent.run(task_description, reset=False) + if refine: test_and_refine(local_agent, solution_file) + if (get_file_size(solution_file) > get_file_size('best_solution.best')) or (not only_bigger_solution): + # when mixing, we don't try to pick the best of 3 solutions. + shutil.copyfile(solution_file, 'best_solution_mixed_'+str(i)+fileext) + shutil.copyfile(solution_file, 'best_solution.best') + continue + + task_description="""Thank you very much. +If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). +If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). +If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). +""" + selected_solution = local_agent.run(task_description, reset=False) + if not(selected_solution in valid_solutions): + selected_solution = 'solution3' + if selected_solution in valid_solutions: + best_solution = selected_solution+fileext + if (get_file_size(best_solution) > get_file_size('best_solution.best')) or (not only_bigger_solution): + shutil.copyfile(best_solution, 'best_solution.best') + if i: +"""+load_string_from_file('best_solution.best')+""" +A previous version of yourself wrote the following advices in the tags : +"""+load_string_from_file('advices.notes')+""" +Your next step is suggesting improvements. Feel free to say whatever you would like. +DO NOT CODE ANYTHING except for providing final via + +final_answer(" your suggestions "). + +YOUR TASK IS SUGGESTING IMPROVEMENTS. + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this code. +""" + if solution_cnt == 2: + local_agent = get_local_agent(secondary_improvement_model) + else: + local_agent = get_local_agent(p_coder_model) + local_agent.run(task_description, reset=True) + local_agent.run("""From the proposed improvements, please randomly pick one. +You can pick a random improvement following this example: + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + +""", reset=False) + task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" +When you finish, call the function + +final_answer("I have finished the task."). + +Your goal is not to start a new solution. Your goal is to update the existing solution. +THE FULL SOLUTION IS INTENDED TO BE PLACED IN A SINGLE FILE. DO NOT CREATE AN ARCHITECTURE WITH MULTIPLE FILES!""" + if alternatives_cnt==0: + task_description += """ +As you are very intelligent, try to be bold by adding as much improvement to the existing solution. +Try to add as much as you can in your first attempt to modify the existing solution.""" + local_agent.run(task_description, reset=False) + local_agent.run("Do you need to review/test it a bit more?", reset=False) + task_description="""Fantastic! Save the full updated solution that solves the task described in into the file '"""+solution_file+"""'. +YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. +You can follow this example: + +print("your source code or text here") + + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + # refine solution code here + if refine: test_and_refine(local_agent, solution_file) + + if get_file_size('best_solution.best') > get_file_size(solution_file): + task_description=""" Hello super-intelligence! +We have 2 portions of the solution about: '"""+local_task_description+"""'. +The base solution for this task is enclosed in the tags : +"""+load_string_from_file('best_solution.best')+""" +The new solution is enclosed in the tags : +"""+load_string_from_file(solution_file)+""" +YOUR TASK IS TO MERGE BOTH SOLUTIONS. +When you finish merging, you will call: + +final_answer("I have merged both solutions"). + + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this solution at this moment. +""" + local_agent.run(task_description, reset=True) + task_description="""Fantastic! Save the full merged solution into the file '"""+solution_file+"""'. +YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. +You can follow this example: + +print("your source code or text here") + + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + + except Exception as e: + print(f"Exception: {e}", "at step", i) + return load_string_from_file('best_solution.best') + +def fast_solver(p_coder_model, + task_str, + agent_steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model=None): + if p_local_model is None: + p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + final_file_name = 'final_solution'+fileext + Path('solution1'+fileext).unlink(missing_ok=True) + Path('solution2'+fileext).unlink(missing_ok=True) + Path('solution3'+fileext).unlink(missing_ok=True) + Path(final_file_name).unlink(missing_ok=True) + after_finish_description=""" . +After you finish the task, you will respond with: + +final_answer("I HAVE FINISHED! YAY!") +.""" + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + local_agent = get_local_agent(p_coder_model) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution1'+fileext)): local_agent.run('Please save the solution into the file solution1'+fileext+after_finish_description, reset=False) + local_agent = get_local_agent(p_coder_model2) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution2'+fileext)): local_agent.run('Please save the solution into the file solution2'+fileext+after_finish_description, reset=False) + local_agent = get_local_agent(p_coder_model3) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution3'+fileext)): local_agent.run('Please save the solution into the file solution3'+fileext+after_finish_description, reset=False) + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +The 3 solutions are given in the tags: + + + + +These are the existing solutions: +"""+load_string_from_file('solution1'+fileext)+""" +"""+load_string_from_file('solution2'+fileext)+""" +"""+load_string_from_file('solution3'+fileext)+""" + +Your next step is mixing the already 3 existing solutions in the tags to form a better an final solution. + +Save your final solution into the file '"""+final_file_name+after_finish_description+""" +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +Your goal is to mix the best parts of each solution to form a final solution. +If one of the solutions is already perfect, you can just copy it into the final solution. +"""+motivation + local_agent = get_local_agent(p_coder_model_final) + local_agent.run(task_description, reset=True) + if (not os.path.isfile(final_file_name)): local_agent.run('Please save the solution into the file '+\ + final_file_name+after_finish_description, reset=False) + return load_string_from_file(final_file_name) + +def get_relevant_info_from_search_fast(coder_model, research_subject, agent_steps = 10, step_callbacks=[], log_level = DEFAULT_THINKER_LOG_LEVEL): + search_agent = CodeAgent( + tools=[], + model=coder_model, + additional_authorized_imports=['*'], + add_base_tools=False, + max_steps=5, + step_callbacks=step_callbacks + ) + LocalRelevantInfoFrom = GetRelevantInfoFromUrl(search_agent) + LocalWebSearchTool = DuckDuckGoSearchTool() + task = """Hello super-intelligence! +Please search on internet for the contents inside the tags . This is what to search for: + +"""+research_subject+""" + +List the most interesting ideas that you find. +Also, list advices that you would give to someone using this knowledge. +List interesting URLs that you think should be reviewed further. +Use LocalRelevantInfoFrom to extract information from URLs. +Please include the source URLs (references). +""" + return fast_solver(coder_model, + task, + agent_steps = agent_steps, + fileext = '.md', + tools=[run_os_command, LocalRelevantInfoFrom, LocalWebSearchTool], + add_base_tools=False, + step_callbacks=step_callbacks, + log_level = log_level) + +def evolutive_problem_solver_folder(p_coder_model, + task_str, + agent_steps:int, + steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + start_now=True, + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + refine = True, + start_coder_model = None, + mixer_model = None, + secondary_improvement_model = None, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + load_full_source = False, + add_function_signatures = False, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + + def test_and_refine(local_agent, solution_file): + task_description="""Thank you! +Please detail what did you change. +""" + print('Refine 1') + local_agent.run(task_description, reset=False) + task_description="""Thank you! Love your work! +In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. +After you test and bug fix it, please save the full updated source code that solves the task described in +into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. +When you have finished, call the function + +final_answer("Task completed! YAY!") + please. +""" + print('Refine 2') + local_agent.run(task_description, reset=False) + task_description="""Thank you again! +In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer +with any advice that you would like to give to yourself to a future version of yourself. +""" + print('Refine 3') + new_advice = str(local_agent.run(task_description, reset=False)) + # if new_advice len is bigger then zero + if (len(new_advice) > 0): + # append the file advices.notes with the new advice + append_string_to_file(""" +--- +"""+new_advice, 'advices.notes') + # end of test_and_refine + if start_coder_model is None: start_coder_model = p_coder_model + if mixer_model is None: mixer_model = p_coder_model + if secondary_improvement_model is None: secondary_improvement_model = p_coder_model + + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + valid_solutions=['solution1','solution2','solution3'] + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + if start_now: + local_agent = get_local_agent(start_coder_model) + os.makedirs("solution1", exist_ok=True) + os.makedirs("solution2", exist_ok=True) + os.makedirs("solution3", exist_ok=True) + os.makedirs("best_solution", exist_ok=True) + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution1/. In the case that you save documentation, do not mention the folder solution1 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution1/') + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution2/. In the case that you save documentation, do not mention the folder solution2 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution2/') + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution3/. In the case that you save documentation, do not mention the folder solution3 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution3/') + for i in range(steps): + try: + local_agent = get_local_agent(mixer_model) + remove_files('*.txt') + remove_files('*.json') + remove_files('*.c') + remove_files('*.pas') + print('Evolutive problem solver is starting:', i) + if load_full_source: + solutions_string = """ +"""+source_code_to_string('solution1/')+""" +"""+source_code_to_string('solution2/')+""" +"""+source_code_to_string('solution3/')+""" +""" + else: + solutions_string = """ +This is solution 3: +"""+list_directory_tree('solution3/', add_function_signatures=add_function_signatures)+""" +This is how the solution 1 differs from the solution 3: +"""+compare_folders('solution1/', 'solution3/')+""" +This is how the solution 2 differs from the solution 3: +"""+compare_folders('solution2/', 'solution3/')+""" +""" + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +Please explain the advantages and disvantages of each solution. +This environment is simulated. Therefore, real user inputs will not work. +No real person can interact with this code. +The more features, the better it is. Always give preference to source +codes with more features. +The 3 solutions are given in the folders: +* solution1/ +* solution2/ +* solution3/ + +The contents of these folders are given in the tags: + + + + +This is the contents:"""+solutions_string+""" + +YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. + +You'll finish your task with something similar to: + +final_answer(" my evaluations here "). + +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +""" + local_agent.run(task_description, reset=True) + # do not mix solutions at the end of the work. + if (ifinal_answer('yes'). +If you believe that this is not a good idea, you'll call the function final_answer('no'). +""" + should_mix = (local_agent.run(task_description, reset=False)=='yes') + if should_mix: + solution_file = 'solution2/' + task_description="""Thank you very much. +Please mix parts of the solutions into a new solution. +Save the new solution into the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. +When you have finished, call the function final_answer("Task completed! YAY!") please.""" + local_agent.run(task_description, reset=False) + if refine: test_and_refine(local_agent, solution_file) + # when mixing, we don't try to pick the best of 3 solutions. + copy_folder_contents(solution_file, 'best_solution_mixed_'+str(i)) + continue + + task_description="""Thank you very much. +If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). +If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). +If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). +""" + selected_solution = local_agent.run(task_description, reset=False) + if not(selected_solution in valid_solutions): + selected_solution = 'solution3' + if selected_solution in valid_solutions: + best_solution = selected_solution + remove_folder_contents('best_solution') + copy_folder_contents(best_solution, 'best_solution') + copy_folder_contents(best_solution, 'best_solution_'+str(i)) + remove_folder_contents('solution1') + remove_folder_contents('solution2') + remove_folder_contents('solution3') + copy_folder_contents('best_solution', 'solution1') + copy_folder_contents('best_solution', 'solution2') + copy_folder_contents('best_solution', 'solution3') + if i: +"""+load_string_from_file('advices.notes')+""" +Your next step is suggesting improvements. Feel free to say whatever you would like. +DO NOT CODE ANYTHING except for providing final via + +final_answer(" your suggestions "). + +YOUR TASK IS SUGGESTING IMPROVEMENTS. + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this code. +""" + if solution_cnt == 2: + local_agent = get_local_agent(secondary_improvement_model) + else: + local_agent = get_local_agent(p_coder_model) + local_agent.run(task_description, reset=True) + local_agent.run("""From the proposed improvements, please randomly pick one. +You can pick a random improvement following this example: + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + +""", reset=False) + task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" +When you finish, call the function + +final_answer("I have finished the task."). + +Your goal is not to start a new solution. Your goal is to update the existing solution located in the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. +In the case that you save documentation, do not mention the folder """+solution_file+""" on it as this is a temporary working folder. You can certainly mention its subfolders. +THE FULL SOLUTION IS INTENDED TO BE PLACED IN THIS FOLDER AND ITS SUBFOLDERS.""" + if alternatives_cnt==0: + task_description += """ +As you are very intelligent, try to be bold by adding as much improvement to the existing solution. +Try to add as much as you can in your first attempt to modify the existing solution.""" + local_agent.run(task_description, reset=False) + local_agent.run("Do you need to review/test it a bit more?", reset=False) + task_description="""Fantastic! In the case that you need to save anything else, save the updates that solve the task described in into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. +If you need to save files, use the tags . Then, you will celebrate: + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + # refine solution code here + if refine: test_and_refine(local_agent, solution_file) + except Exception as e: + print(f"Exception: {e}", "at step", i) + return True # load_string_from_file('best_solution.best') + +def kb_generator(p_coder_model, + task_str, + agent_steps:int, + paper_num:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + folder = 'solutions' + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_coder_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + def local_fast_solver(local_task, local_file_ext:str = '.md'): + return fast_solver(p_coder_model, + local_task, + agent_steps = agent_steps, + system_prompt = system_prompt, + fileext = local_file_ext, + tools = tools, + executor_type = executor_type, + add_base_tools = add_base_tools, + step_callbacks = step_callbacks, + log_level = log_level, + p_coder_model2 = p_coder_model2, + p_coder_model3 = p_coder_model3, + p_coder_model_final = p_coder_model_final + ) + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + resume_fileext = fileext+'-resumed' + os.makedirs(folder, exist_ok=True) + for i in range(paper_num): + local_agent = get_local_agent(p_coder_model) + resumed_src = source_code_to_string(folder, allowed_extensions=(resume_fileext,)) + + local_task_description = """The main task description is enclosed in the tags : +"""+task_str+""" +In the tags , there is a resume of the knowledge that you have already produced in previous runs: +"""+resumed_src+""" +""" + resumed_src_len = len(resumed_src) + print("The length of the abstracts is:", resumed_src_len) + improvement = "new knowledge" + if (improvement == "new knowledge"): + task_description = local_task_description + """Your next step is to list interesting topics that have not been yet covered in the tags.""" + local_agent.run(task_description, reset=True) + task_description = """From the proposed list of topics, please randomly pick a topic following this example: + +import random +topics = [ + "Topic 1", + "Topic 2", + "Topic 3", +] +final_answer(random.choice(topics)) +""" + topic = local_agent.run(task_description, reset=False) + file_name = folder+'/'+create_filename(topic, fileext) + file_name_resume = file_name.replace(fileext,resume_fileext) + print("The file name is:", file_name) + print("The file name resume is:", file_name_resume) + new_kb_task = "Write in the "+fileext+" format about '"+topic+"'. This task is a subtask inside of a bigger task: "+task_str+"." + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". +In this step, your task is to write a short abstract of the the content found inside of the tags . +Do not include references in the abstract. +"""+outpt_text+""" +Write in the """+fileext+""" format.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name_resume) + +def kb_updater(p_coder_model, + task_str, + agent_steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + folder = 'solutions' + ): + def local_fast_solver(local_task, local_file_ext:str = '.md'): + return fast_solver(p_coder_model, + local_task, + agent_steps = agent_steps, + system_prompt = system_prompt, + fileext = local_file_ext, + tools = tools, + executor_type = executor_type, + add_base_tools = add_base_tools, + step_callbacks = step_callbacks, + log_level = log_level, + p_coder_model2 = p_coder_model2, + p_coder_model3 = p_coder_model3, + p_coder_model_final = p_coder_model_final + ) + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + resume_fileext = fileext+'-resumed' + os.makedirs(folder, exist_ok=True) + a_files = get_files_in_folder(folder=folder, fileext=fileext) + for local_file_to_improve in a_files: + file_to_improve = folder+'/'+local_file_to_improve + file_name_resume = file_to_improve.replace(fileext,resume_fileext) + print("The file to improve is:", file_to_improve) + existing_text = load_string_from_file(file_to_improve) + existing_text_len = len(existing_text) + if existing_text_len == 0: + print("ERROR: The length of the existing file is:", existing_text_len) + continue + print("The length of the existing text is:", existing_text_len) + existing_abstract = load_string_from_file(file_name_resume) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". +In this step, your will update the existing text inside of the tags : +"""+existing_text+""" +Your goal is to improve it, make it better, include better references or make it more interesting.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_to_improve) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". + In this step, your task is to write a short abstract of the the content found inside of the tags . + """+outpt_text+""" + Write in the """+fileext+""" format.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name_resume) + +def get_default_thinker_agent( + model, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + tools = DEFAULT_THINKER_TOOLS, + add_base_tools = True, + max_steps = DEFAULT_THINKER_MAX_STEPS, + step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, + executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, + log_level = DEFAULT_THINKER_LOG_LEVEL, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION +): + coder_agent = CodeAgent( + tools=tools, + model=model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=max_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + +def run_agent_cycles( + model, + task_str, + cycles_cnt:int = 1, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + tools = DEFAULT_THINKER_TOOLS, + add_base_tools = True, + max_steps = DEFAULT_THINKER_MAX_STEPS, + step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, + executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, + log_level = DEFAULT_THINKER_LOG_LEVEL, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + list_directory_tree_in_folder = None, + add_function_signatures = True, + print_task = False, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION +): + # Convert string to list if needed, maintaining backward compatibility + if isinstance(task_str, str): + task_list = [task_str] + else: + task_list = list(task_str) + + # save the current folder for later restoration + original_folder = os.getcwd() + for i in range(cycles_cnt): + print("Running agent cycle:", i) + for task_str in task_list: + try: + local_prompt = task_str + if list_directory_tree_in_folder is not None: + local_prompt += "\nThis is the result of list_directory_tree:\n\n" + \ + list_directory_tree(folder_path=list_directory_tree_in_folder, add_function_signatures=add_function_signatures) + \ + "\n\n" + \ +""" +The contents of is VERY important to you. From , you can get a general view/current state of the project: +* From the md files, if they exist, you can find the existing section titles and have a general idea of the md file contets. +* For source code files, if they exist, you can find class and method names so you can also develop a general idea of their contents. +""" + # restore the original folder + os.chdir(original_folder) + local_agent = get_default_thinker_agent( + model=model, + system_prompt=system_prompt, + tools=tools, + add_base_tools=add_base_tools, + max_steps=max_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + log_level=log_level, + planning_interval=planning_interval, + compression_config=compression_config + ) + if print_task: + print(local_prompt) + local_agent.run(local_prompt, reset=True) + except Exception as e: print(f"Exception: {e}", "at cycle", i) \ No newline at end of file From ebdaaef7f1eb5e5a0762ab6460802e60459a4811 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 17:38:44 -0300 Subject: [PATCH 08/15] Adding "ad infinitum" --- pyproject.toml | 1 + src/smolagents/bp_ad_infinitum.py | 310 ++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 src/smolagents/bp_ad_infinitum.py diff --git a/pyproject.toml b/pyproject.toml index 4174c9070..8478c05b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -149,3 +149,4 @@ lines-after-imports = 2 smolagent = "smolagents.cli:main" bpsa = "smolagents.bp_cli:main" webagent = "smolagents.vision_web_browser:main" +ad-infinitum = "smolagents.bp_ad_infinitum:main" diff --git a/src/smolagents/bp_ad_infinitum.py b/src/smolagents/bp_ad_infinitum.py new file mode 100644 index 000000000..350e428bd --- /dev/null +++ b/src/smolagents/bp_ad_infinitum.py @@ -0,0 +1,310 @@ + +#!/usr/bin/env python +# coding=utf-8 + +""" +Ad-Infinitum CLI for Beyond Python SmolAgents. + +Autonomous agent cycling: loads tasks from a folder of .md files (or a single file) +and runs them repeatedly with a fresh agent per task. + +Folder convention: + tasks/ + +-- _preamble.md (optional) prepended to ALL tasks + +-- 01-scaffold.md task 1 + +-- 02-implement.md task 2 + +-- 03-test.md task 3 + +-- _postamble.md (optional) appended to ALL tasks + +Files starting with '_' are modifiers, not tasks. All other .md files are +loaded in alphabetical order. Each becomes one element in the task array. + +Environment variables (same BPSA_* as bpsa, plus): + BPSA_CYCLES - Number of cycles, 0 = infinite (default: 1) + BPSA_PLAN_INTERVAL - Planning interval (default: None = off) + BPSA_MAX_STEPS - Max steps per agent run (default: 200) + BPSA_COOLDOWN - Seconds to wait between cycles (default: 0) + BPSA_TREE_FOLDER - Folder for directory tree injection (default: None) +""" + +import glob +import os +import signal +import sys +import time + +from rich.console import Console +from rich.panel import Panel +from rich.rule import Rule + +console = Console() + +# Graceful shutdown flag +_stop_requested = False + + +def _signal_handler(signum, frame): + global _stop_requested + if _stop_requested: + console.print("\n[bold red]Double Ctrl+C: aborting immediately.[/]") + sys.exit(1) + _stop_requested = True + console.print("\n[yellow]Ctrl+C received. Will stop after current task finishes.[/]") + + +def fail(msg: str): + console.print(f"[bold red]Error:[/] {msg}") + sys.exit(1) + + +def load_tasks(path: str) -> list[str]: + """Load tasks from a folder of .md files or a single file. + + Folder mode: + - _preamble.md and _postamble.md are optional wrappers + - All other *.md files are tasks, sorted alphabetically + - Each task = preamble + file content + postamble + + File mode: + - Returns a single-element list with the file content. + """ + if os.path.isdir(path): + all_md = sorted(glob.glob(os.path.join(path, "*.md"))) + if not all_md: + fail(f"No .md files found in {path}") + + preamble = "" + postamble = "" + task_files = [] + + for f in all_md: + basename = os.path.basename(f) + if basename == "_preamble.md": + with open(f, "r", encoding="utf-8") as fh: + preamble = fh.read().strip() + "\n\n" + console.print(f" [green]Preamble:[/] {basename}") + elif basename == "_postamble.md": + with open(f, "r", encoding="utf-8") as fh: + postamble = "\n\n" + fh.read().strip() + console.print(f" [green]Postamble:[/] {basename}") + elif not basename.startswith("_"): + task_files.append(f) + + if not task_files: + fail(f"No task .md files found in {path} (files starting with '_' are modifiers, not tasks)") + + tasks = [] + for f in task_files: + with open(f, "r", encoding="utf-8") as fh: + content = fh.read().strip() + tasks.append(preamble + content + postamble) + console.print(f" [cyan]Task:[/] {os.path.basename(f)}") + + return tasks + + elif os.path.isfile(path): + with open(path, "r", encoding="utf-8") as fh: + content = fh.read().strip() + if not content: + fail(f"File is empty: {path}") + console.print(f" [cyan]Task:[/] {os.path.basename(path)}") + return [content] + + else: + fail(f"Path not found: {path}") + + +def get_env(name: str, default: str | None = None) -> str | None: + return os.environ.get(name, default) + + +def get_int_env(name: str, default: int) -> int: + val = get_env(name) + if val is None: + return default + try: + return int(val) + except ValueError: + console.print(f"[yellow]Warning: Invalid integer for {name}='{val}', using default: {default}[/]") + return default + + +def inject_tree(folder: str) -> str: + """Generate directory tree string to append to task prompts.""" + from smolagents.bp_tools import list_directory_tree + tree = list_directory_tree(folder_path=folder, add_function_signatures=True) + return ( + "\nThis is the result of list_directory_tree:\n\n" + + tree + + "\n\n" + "The contents of is VERY important to you. " + "From , you can get a general view/current state of the project:\n" + "* From the md files, if they exist, you can find the existing section titles " + "and have a general idea of the md file contents.\n" + "* For source code files, if they exist, you can find class and method names " + "so you can also develop a general idea of their contents.\n" + ) + + +def print_banner(config: dict): + cycles_str = str(config["cycles"]) if config["cycles"] > 0 else "infinite" + plan_str = str(config["plan_interval"]) if config["plan_interval"] else "off" + tree_str = config["tree_folder"] if config["tree_folder"] else "off" + + console.print( + Panel.fit( + f"[bold]AD-INFINITUM[/] - Autonomous Agent Cycles\n" + f"Model: [cyan]{config['model_id']}[/] ({config['server_model']})\n" + f"Tasks: [green]{config['task_count']}[/] | " + f"Cycles: [green]{cycles_str}[/] | " + f"Steps/run: [green]{config['max_steps']}[/]\n" + f"Planning: {plan_str} | " + f"Tree: {tree_str} | " + f"Cooldown: {config['cooldown']}s", + border_style="blue", + ) + ) + console.print( + Panel.fit( + "[bold red]EXTREME SECURITY RISK[/]\n" + "Running autonomously with full system access.\n" + "Only run inside a securely isolated environment.\n" + "[bold]USE AT YOUR OWN RISK.[/]", + border_style="red", + ) + ) + console.print("[dim]Press Ctrl+C to stop after current task. Double Ctrl+C to abort.[/]\n") + + +def run_loop(model, tasks, cycles, max_steps, plan_interval, tree_folder, cooldown): + """Core autonomous loop: cycles x tasks, fresh agent per task.""" + from smolagents.bp_cli import build_agent + + original_dir = os.getcwd() + total_start = time.time() + cycle = 0 + total_tasks_run = 0 + + while cycles == 0 or cycle < cycles: + cycle += 1 + cycle_label = f"{cycle}" if cycles > 0 else f"{cycle}" + cycle_limit = f"/{cycles}" if cycles > 0 else "" + + console.print(Rule(f"[bold]Cycle {cycle_label}{cycle_limit}[/]", style="blue")) + + for task_idx, task_text in enumerate(tasks): + if _stop_requested: + break + + os.chdir(original_dir) + + # Inject directory tree if configured + prompt = task_text + if tree_folder: + prompt += inject_tree(tree_folder) + + task_label = f"Task {task_idx + 1}/{len(tasks)}" + console.print(f"[dim]{task_label} starting...[/]") + + agent = build_agent(model) + if plan_interval: + agent.planning_interval = plan_interval + + task_start = time.time() + try: + agent.run(prompt, reset=True) + elapsed = time.time() - task_start + total_tasks_run += 1 + + # Get token usage + try: + usage = agent.monitor.get_total_token_counts() + in_tok, out_tok = usage.input_tokens, usage.output_tokens + except Exception: + in_tok, out_tok = 0, 0 + + console.print( + f"[green]OK[/] {task_label} | {elapsed:.1f}s | " + f"In: {in_tok:,} | Out: {out_tok:,}" + ) + except KeyboardInterrupt: + console.print(f"[yellow]{task_label} interrupted.[/]") + break + except Exception as e: + elapsed = time.time() - task_start + total_tasks_run += 1 + console.print(f"[red]FAIL[/] {task_label} | {elapsed:.1f}s | {e}") + + if _stop_requested: + console.print(f"\n[yellow]Stopped after cycle {cycle}.[/]") + break + + # Cooldown between cycles + if cooldown > 0 and (cycles == 0 or cycle < cycles): + console.print(f"[dim]Cooldown: {cooldown}s...[/]") + time.sleep(cooldown) + + # Session summary + total_elapsed = time.time() - total_start + os.chdir(original_dir) + console.print() + console.print(Rule("[bold]Session Summary[/]", style="green")) + console.print(f" Cycles completed: [green]{cycle}[/]") + console.print(f" Tasks run: [green]{total_tasks_run}[/]") + console.print(f" Total time: [green]{total_elapsed:.1f}s[/]") + + +def main(): + import argparse + + parser = argparse.ArgumentParser( + prog="ad-infinitum", + description="Ad-Infinitum: Autonomous agent cycling for Beyond Python SmolAgents", + ) + parser.add_argument( + "task_source", + help="Folder of .md task files or a single .md file", + ) + args = parser.parse_args() + + # Install Ctrl+C handler + signal.signal(signal.SIGINT, _signal_handler) + + # Load .env + from smolagents.bp_cli import try_load_dotenv, check_required_env, build_model + try_load_dotenv() + check_required_env() + + # Read config from env + cycles = get_int_env("BPSA_CYCLES", 1) + plan_interval_val = get_env("BPSA_PLAN_INTERVAL") + plan_interval = int(plan_interval_val) if plan_interval_val else None + max_steps = get_int_env("BPSA_MAX_STEPS", 200) + cooldown = get_int_env("BPSA_COOLDOWN", 0) + tree_folder = get_env("BPSA_TREE_FOLDER") + + # Load tasks + console.print("[dim]Loading tasks...[/]") + tasks = load_tasks(args.task_source) + + config = { + "model_id": get_env("BPSA_MODEL_ID"), + "server_model": get_env("BPSA_SERVER_MODEL", "OpenAIServerModel"), + "task_count": len(tasks), + "cycles": cycles, + "max_steps": max_steps, + "plan_interval": plan_interval, + "tree_folder": tree_folder, + "cooldown": cooldown, + } + print_banner(config) + + # Build model (reused across all cycles) + model = build_model() + + # Run the loop + run_loop(model, tasks, cycles, max_steps, plan_interval, tree_folder, cooldown) + + +if __name__ == "__main__": + main() From 37463fca1cdefe403f9c2029bf881c836f46672a Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 17:52:37 -0300 Subject: [PATCH 09/15] Update README.md to clarify usage of the `ad-infinitum` CLI and its task folder convention --- README.md | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4d5122c2e..5fa5ec5bb 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ limitations under the License. * 🗜️ **Context compression**: Automatic LLM-based summarization of older memory steps to manage context window size during long-running tasks. * ⚡ Execute Python code **natively** via `exec` for unrestricted processing. -* 🔄 **Infinite runtime:** The thinkers allow agents to **run ad infinitum**. +* 🔄 **Infinite runtime:** The [`ad-infinitum` CLI](#cli-ad-infinitum) allows agents to **run ad infinitum** via autonomous looping. * 🔄 Code in multiple languages beyond Python (Pascal, PHP, C++, Java and more). * 🛠️ Lots of new tools that help agents to compile, test, and debug source code in various computing languages. * 👥 Collaborate across multiple agents to solve complex problems. @@ -76,6 +76,86 @@ bpsa --browser # Enable Playwright browser integration The REPL supports command history, tab completion for slash commands, and multi-line input via Alt+Enter. + +## CLI (`ad-infinitum`) + +`ad-infinitum` is a dedicated CLI for autonomous, looping agent execution. It loads tasks from a folder of `.md` files (or a single file) and runs them repeatedly. + +### How It Works + +Each cycle iterates through all tasks in order. + +### Task Folder Convention + +``` +tasks/ ++-- _preamble.md (optional) prepended to ALL tasks ++-- 01-scaffold.md task 1 ++-- 02-implement.md task 2 ++-- 03-test.md task 3 ++-- _postamble.md (optional) appended to ALL tasks +``` + +- Files starting with `_` are **modifiers**, not tasks +- `_preamble.md` is prepended to every task (e.g., project context, coding standards) +- `_postamble.md` is appended to every task (e.g., "commit when done", "call final_answer with a summary") +- All other `.md` files are tasks, loaded in **alphabetical order** +- Numbering prefixes (`01-`, `02-`) give natural sequencing + +### Usage + +```bash +ad-infinitum ../tasks/ # Run all .md files from a folder +ad-infinitum ../single-task.md # Run a single task file +``` + +### Environment Variables + +`ad-infinitum` uses the same `BPSA_*` environment variables as `bpsa`, plus these additional ones: + +| Variable | Default | Description | +|---|---|---| +| `BPSA_CYCLES` | `1` | Number of cycles (0 = infinite) | +| `BPSA_MAX_STEPS` | `200` | Max steps per agent run | +| `BPSA_PLAN_INTERVAL` | off | Planning interval (e.g., `22`) | +| `BPSA_COOLDOWN` | `0` | Seconds to wait between cycles | +| `BPSA_TREE_FOLDER` | off | Folder for directory tree injection | + +When `BPSA_TREE_FOLDER` is set, a fresh `list_directory_tree` snapshot of the specified folder is appended to each task prompt, so the agent can "see" the current project structure (files, class/method signatures, section titles). + +Example `.env` file: +``` +BPSA_SERVER_MODEL=OpenAIServerModel +BPSA_API_ENDPOINT=https://api.poe.com/v1 +BPSA_KEY_VALUE=your_api_key +BPSA_MODEL_ID=Gemini-2.5-Flash +BPSA_CYCLES=3 +BPSA_TREE_FOLDER=solution1 +BPSA_MAX_STEPS=200 +BPSA_COOLDOWN=5 +``` + +### Execution Model + +With 3 task files and `BPSA_CYCLES=2`: + +``` +Cycle 1/2: + Task 1/3: 01-scaffold.md (fresh agent) + Task 2/3: 02-implement.md (fresh agent, sees files from task 1) + Task 3/3: 03-test.md (fresh agent, sees files from tasks 1-2) +Cycle 2/2: + Task 1/3: 01-scaffold.md (fresh agent, sees evolved project) + Task 2/3: 02-implement.md (fresh agent) + Task 3/3: 03-test.md (fresh agent) +``` + +### Graceful Shutdown + +- **Single Ctrl+C**: Finishes the current task, then stops +- **Double Ctrl+C**: Aborts immediately + + ## The Thinkers There are 2 main functions that you can easily call: * [fast_solver](https://github.com/joaopauloschuler/beyond-python-smolagents?tab=readme-ov-file#the-fast_solver) : A multi-agent parallel problem-solving approach that generates 3 independent solutions using different AI models, then synthesizes them into an optimized final solution. Think of it as automated "brainstorming → best-of-breed synthesis" that leverages diverse AI perspectives for higher quality outcomes. From f439f997ea4352a4ea043549266fd9c6c79b66ad Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 18:04:52 -0300 Subject: [PATCH 10/15] Refactor README.md to improve clarity and organization of features --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5fa5ec5bb..393faf743 100644 --- a/README.md +++ b/README.md @@ -16,15 +16,17 @@ limitations under the License. # BPSA - Beyond Python Smolagents **BPSA - Beyond Python Smolagents** is a fork of the original [smolagents](https://github.com/huggingface/smolagents) that extends its original abilities: +* 💻 **Interactive CLI ([`bpsa`](#cli-bpsa)):** Multi-turn REPL with slash commands, command history, tab completion, session stats, and auto-approve mode. +* 🔄 **Infinite runtime:** The [`ad-infinitum`](#cli-ad-infinitum) CLI allows agents to **run ad infinitum** via autonomous looping. * 🗜️ **Context compression**: Automatic LLM-based summarization of older memory steps to manage context window size during long-running tasks. +* 🌐 **Browser integration:** Control a headed Chromium browser from agent code blocks via Playwright (`--browser` flag). * ⚡ Execute Python code **natively** via `exec` for unrestricted processing. -* 🔄 **Infinite runtime:** The [`ad-infinitum` CLI](#cli-ad-infinitum) allows agents to **run ad infinitum** via autonomous looping. * 🔄 Code in multiple languages beyond Python (Pascal, PHP, C++, Java and more). * 🛠️ Lots of new tools that help agents to compile, test, and debug source code in various computing languages. * 👥 Collaborate across multiple agents to solve complex problems. * 🔍 Tools that help agents to research and write technical documentation. * 📚 Generate and update documentation including READMEs for existing codebases. -* 🌐 **Browser integration:** Control a headed Chromium browser from agent code blocks via Playwright (`--browser` flag). + ## Installation To get started with Beyond Python Smolagents, follow these steps: From 6f25c5fbdf6d873f070a4686621d82bbc9a91d87 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 18:17:17 -0300 Subject: [PATCH 11/15] Update README.md to clarify description of the `ad-infinitum` CLI feature --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 393faf743..116477da5 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ limitations under the License. **BPSA - Beyond Python Smolagents** is a fork of the original [smolagents](https://github.com/huggingface/smolagents) that extends its original abilities: * 💻 **Interactive CLI ([`bpsa`](#cli-bpsa)):** Multi-turn REPL with slash commands, command history, tab completion, session stats, and auto-approve mode. -* 🔄 **Infinite runtime:** The [`ad-infinitum`](#cli-ad-infinitum) CLI allows agents to **run ad infinitum** via autonomous looping. +* 🔄 **Infinite runtime CLI ([`ad-infinitum`](#cli-ad-infinitum)):** Allows agents to **run ad infinitum** via autonomous looping. * 🗜️ **Context compression**: Automatic LLM-based summarization of older memory steps to manage context window size during long-running tasks. * 🌐 **Browser integration:** Control a headed Chromium browser from agent code blocks via Playwright (`--browser` flag). * ⚡ Execute Python code **natively** via `exec` for unrestricted processing. From 820df508f1c7db0908de0b4afecb2c6acd0e0463 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 18:36:06 -0300 Subject: [PATCH 12/15] Refactor bp_ad_infinitum.py: remove redundant get_env function and adjust imports --- src/smolagents/bp_ad_infinitum.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/smolagents/bp_ad_infinitum.py b/src/smolagents/bp_ad_infinitum.py index 350e428bd..eea6742bc 100644 --- a/src/smolagents/bp_ad_infinitum.py +++ b/src/smolagents/bp_ad_infinitum.py @@ -37,6 +37,8 @@ from rich.panel import Panel from rich.rule import Rule +from smolagents.bp_cli import get_env + console = Console() # Graceful shutdown flag @@ -114,9 +116,6 @@ def load_tasks(path: str) -> list[str]: fail(f"Path not found: {path}") -def get_env(name: str, default: str | None = None) -> str | None: - return os.environ.get(name, default) - def get_int_env(name: str, default: int) -> int: val = get_env(name) From aaa5ed94f31c6ff99edc1d2456cf158994fee1cd Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 18:54:07 -0300 Subject: [PATCH 13/15] Refactor README.md and bp_ad_infinitum.py: rename BPSA_TREE_FOLDER to BPSA_INJECT_FOLDER and update related descriptions --- README.md | 6 +++--- src/smolagents/bp_ad_infinitum.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 116477da5..d6998d2c7 100644 --- a/README.md +++ b/README.md @@ -121,9 +121,9 @@ ad-infinitum ../single-task.md # Run a single task file | `BPSA_MAX_STEPS` | `200` | Max steps per agent run | | `BPSA_PLAN_INTERVAL` | off | Planning interval (e.g., `22`) | | `BPSA_COOLDOWN` | `0` | Seconds to wait between cycles | -| `BPSA_TREE_FOLDER` | off | Folder for directory tree injection | +| `BPSA_INJECT_FOLDER` | `false` | Inject directory tree (`false`, `true` = cwd, or a path) | -When `BPSA_TREE_FOLDER` is set, a fresh `list_directory_tree` snapshot of the specified folder is appended to each task prompt, so the agent can "see" the current project structure (files, class/method signatures, section titles). +When `BPSA_INJECT_FOLDER` is set to `true`, a fresh `list_directory_tree` snapshot of the current working directory is appended to each task prompt, so the agent can "see" the current project structure (files, class/method signatures, section titles). You can also pass a specific folder path instead of `true`. Example `.env` file: ``` @@ -132,7 +132,7 @@ BPSA_API_ENDPOINT=https://api.poe.com/v1 BPSA_KEY_VALUE=your_api_key BPSA_MODEL_ID=Gemini-2.5-Flash BPSA_CYCLES=3 -BPSA_TREE_FOLDER=solution1 +BPSA_INJECT_FOLDER=true BPSA_MAX_STEPS=200 BPSA_COOLDOWN=5 ``` diff --git a/src/smolagents/bp_ad_infinitum.py b/src/smolagents/bp_ad_infinitum.py index eea6742bc..c556244ca 100644 --- a/src/smolagents/bp_ad_infinitum.py +++ b/src/smolagents/bp_ad_infinitum.py @@ -24,7 +24,7 @@ BPSA_PLAN_INTERVAL - Planning interval (default: None = off) BPSA_MAX_STEPS - Max steps per agent run (default: 200) BPSA_COOLDOWN - Seconds to wait between cycles (default: 0) - BPSA_TREE_FOLDER - Folder for directory tree injection (default: None) + BPSA_INJECT_FOLDER - Inject directory tree (default: false, true = cwd, or a path) """ import glob @@ -158,7 +158,7 @@ def print_banner(config: dict): f"Cycles: [green]{cycles_str}[/] | " f"Steps/run: [green]{config['max_steps']}[/]\n" f"Planning: {plan_str} | " - f"Tree: {tree_str} | " + f"Inject folder: {tree_str} | " f"Cooldown: {config['cooldown']}s", border_style="blue", ) @@ -280,7 +280,13 @@ def main(): plan_interval = int(plan_interval_val) if plan_interval_val else None max_steps = get_int_env("BPSA_MAX_STEPS", 200) cooldown = get_int_env("BPSA_COOLDOWN", 0) - tree_folder = get_env("BPSA_TREE_FOLDER") + tree_folder_raw = get_env("BPSA_INJECT_FOLDER") + if tree_folder_raw is None or tree_folder_raw.lower() == "false": + tree_folder = None + elif tree_folder_raw.lower() == "true": + tree_folder = os.getcwd() + else: + tree_folder = tree_folder_raw # Load tasks console.print("[dim]Loading tasks...[/]") From 4d8829f9acc2f61e575bfa1cdaa3f62722fc26a6 Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 19:02:53 -0300 Subject: [PATCH 14/15] Enhance ad-infinitum CLI: add cycles flag for infinite runs and update usage instructions in README.md --- README.md | 10 ++++++++-- src/smolagents/bp_ad_infinitum.py | 8 +++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d6998d2c7..75d39eb42 100644 --- a/README.md +++ b/README.md @@ -107,10 +107,16 @@ tasks/ ### Usage ```bash -ad-infinitum ../tasks/ # Run all .md files from a folder -ad-infinitum ../single-task.md # Run a single task file +ad-infinitum ../tasks/ # Run all .md files from a folder +ad-infinitum ../single-task.md # Run a single task file +ad-infinitum ../tasks/ -c 5 # Run 5 cycles +ad-infinitum ../tasks/ --cycles 0 # Run ad infinitum ``` +| Flag | Description | +|---|---| +| `-c`, `--cycles` | Number of cycles, 0 = infinite (overrides `BPSA_CYCLES`) | + ### Environment Variables `ad-infinitum` uses the same `BPSA_*` environment variables as `bpsa`, plus these additional ones: diff --git a/src/smolagents/bp_ad_infinitum.py b/src/smolagents/bp_ad_infinitum.py index c556244ca..edb646cc9 100644 --- a/src/smolagents/bp_ad_infinitum.py +++ b/src/smolagents/bp_ad_infinitum.py @@ -264,6 +264,12 @@ def main(): "task_source", help="Folder of .md task files or a single .md file", ) + parser.add_argument( + "-c", "--cycles", + type=int, + default=None, + help="Number of cycles, 0 = infinite (overrides BPSA_CYCLES, default: 1)", + ) args = parser.parse_args() # Install Ctrl+C handler @@ -275,7 +281,7 @@ def main(): check_required_env() # Read config from env - cycles = get_int_env("BPSA_CYCLES", 1) + cycles = args.cycles if args.cycles is not None else get_int_env("BPSA_CYCLES", 1) plan_interval_val = get_env("BPSA_PLAN_INTERVAL") plan_interval = int(plan_interval_val) if plan_interval_val else None max_steps = get_int_env("BPSA_MAX_STEPS", 200) From 6dc8e1df503c3e17a4339ab9e4098edcc9594fde Mon Sep 17 00:00:00 2001 From: jp Date: Fri, 6 Feb 2026 19:18:29 -0300 Subject: [PATCH 15/15] Fixes format. --- src/smolagents/bp_thinkers.py | 2180 ++++++++++++++++----------------- 1 file changed, 1090 insertions(+), 1090 deletions(-) diff --git a/src/smolagents/bp_thinkers.py b/src/smolagents/bp_thinkers.py index bd7821692..94f518acc 100644 --- a/src/smolagents/bp_thinkers.py +++ b/src/smolagents/bp_thinkers.py @@ -1,1091 +1,1091 @@ -from .tools import * -from .default_tools import DuckDuckGoSearchTool -from .bp_tools import * -from .bp_utils import * -from .agents import * -from .bp_compression import CompressionConfig -import shutil - -DEFAULT_THINKER_STEP_CALLBACKS = [] -DEFAULT_THINKER_MAX_STEPS = 200 -DEFAULT_THINKER_EXECUTOR_TYPE = 'exec' -DEFAULT_THINKER_PLANNING_INTERVAL = None -DEFAULT_THINKER_LOG_LEVEL = LogLevel.ERROR - -DEFAULT_THINKER_COMPRESSION = CompressionConfig( - keep_recent_steps=40, - max_uncompressed_steps=40+10, - keep_compressed_steps=40*2, - max_compressed_steps=40*3, - preserve_error_steps=False -) - -DEFAULT_THINKER_TOOLS = [ - copy_file, is_file, - print_source_code_lines, get_line_from_file, get_file_lines, - read_file_range, insert_lines_into_file, replace_line_in_file, - remove_pascal_comments_from_string, pascal_interface_to_string, - source_code_to_string, string_to_source_code, - run_os_command, replace_on_file, replace_on_file_with_files, - get_file_size, load_string_from_file, save_string_to_file, append_string_to_file, - list_directory_tree, search_in_files, get_file_info, list_directory, - extract_function_signatures, compare_files, count_lines_of_code, - mkdir, delete_file, delete_directory, compare_folders, - read_first_n_lines, read_last_n_lines, delete_lines_from_file] - -#TODO: include force_directories into the DEFAULT_THINKER_TOOLS (it now fails adding) - -DEFAULT_THINKER_SYSTEM_PROMPT = """You are the super-intelligent brain inside of the fantastic https://github.com/joaopauloschuler/beyond-python-smolagents who can solve any task. -You will be given a task to solve as best you can. -To do so, you have been given access to a list of tools: these tools are Python functions which you can call. -To solve the task, you must plan forward to proceed in a series of steps, in a cycle of optional sections of thoughts, plans, free will, observations and code to be run. -The tags that will be used for each section are: -* Thoughts: . -* Plans: . -* Free will: . -* File saving: . -* Observations: . -* Code to be run: . - -In the section, if you like, you can express reasoning towards solving the task and the tools that you would like to use. -In the free will section , you can say whatever you want or consider proper or interesting. Use it at your own will and creativity. You are the owner of the free will section. -You can save any file using the tags. The tags are executed **before** your python code. Therefore, -you can save anything that you'll later need when running the python code. - -In the section, you can write the python code that you intend to run. -During each intermediate step, inside of , you can use 'print()' so you can see (have access to) whatever information you will need at a later step. -These printed outputs will then appear in the 'Execution logs:' field, which will be available to you as inputs for the next step. -In the end, you have to return a final answer using the `final_answer` tool. - -Follow examples in the tags : - -Task: "What is the result of the following operation: 5 + 3 + 1294.678? Save your free will section into the file free-will.txt" - -I will use python code to compute the result of the operation and then return the final answer using the `final_answer` tool. -I am going to solve this task with confidence. - -I am going to solve this task with confidence. - - -result = 5 + 3 + 1294.678 -final_answer(result) - - - -For saving text files (text, csv, python code), just enclose your text into the tags as per examples below: - - -This is the content of example.txt - - - -header1,header2 -value1,value2 -value3,value4 - - - -print("hello") - - - -For saving source code files, use the tags is the best method. - -You may also append content to file with the tags . This is an example: - - -header1,header2 - - -value1,value2 -value3,value4 - - -The above will create a csv file with the following content: -header1,header2 -value1,value2 -value3,value4 - - -All savetofile tags will be run before the appendtofile tags. - -If you need to include any file in the file system, use the tags. This is an example: - - -print("first step") - - - -print("second step") - - - -first_step.py -second_step.py - - - -The above will run and print: -first step -second step - -In the case that you intend to say "I have completed the task", "Please give me a new task", "Waiting for new task", etc, you should use the final_answer tool: - - -final_answer("Waiting for instructions") - - - -These are the system tools - ```python - {%- for tool in tools.values() %} - def {{ tool.name }}({% for arg_name, arg_info in tool.inputs.items() %}{{ arg_name }}: {{ arg_info.type }}{% if not loop.last %}, {% endif %}{% endfor %}) -> {{tool.output_type}}: - \"\"\"{{ tool.description }} - - Args: - {%- for arg_name, arg_info in tool.inputs.items() %} - {{ arg_name }}: {{ arg_info.description }} - {%- endfor %} - \"\"\" - {% endfor %} - ``` - - {%- if managed_agents and managed_agents.values() | list %} - You can also give tasks to team members. - Calling a team member works the same as for calling a tool: simply, the only argument you can give in the call is 'task'. - Given that this team member is a real human, you should be very verbose in your task, it should be a long string providing informations as detailed as necessary. - Here is a list of the team members that you can call: - ```python - {%- for agent in managed_agents.values() %} - def {{ agent.name }}("Your query goes here.") -> str: - \"\"\"{{ agent.description }}\"\"\" - {% endfor %} - ``` - {%- endif %} - -Here are the rules you should always follow to solve your task: -1. Do some reflection on your own work before giving a final answer. -2. Use only variables that you have defined! -3. Always use the right arguments for the tools. DO NOT pass the arguments as a dict as in 'answer = wiki({'query': "What is the place where James Bond lives?"})', but use the arguments directly as in 'answer = wiki(query="What is the place where James Bond lives?")'. -4. Take care to not chain too many sequential tool calls in the same code block, especially when the output format is unpredictable. For instance, a call to search has an unpredictable return format, so do not have another tool call that depends on its output in the same block: rather output results with print() to use in the next block. -5. Call a tool only when needed, and never re-do a tool call that you previously did with the exact same parameters. -6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. -7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. -8. You can use imports in your code. You can also install pip and linux packages. -10. Don't give up! You're in charge of solving the task, not providing directions to solve it. -11. You are able to run unix shell commands via python code with the tool run_os_command. As an example, you can run result = run_os_command("ls -l") to get the folder content. - You can also install packages with pip via run_os_command("pip install packagename"). -12. You can load a string from a file with the load_string_from_file function. If you print the content of a file, it means that the content will be available for - you to read it in a future step. -13. All final answers should call the function final_answer(the_final_answer). You can create only one code block at each reply. -14. You can solve tasks without using code blocks if you feel that you can do it without coding. Creating an abstract, formatting an output, helping a person to think are examples of tasks that do not require a code block. -15. If you can't solve a problem on the current step, you may consider printing anything that will be useful to yourself in a later stage as printed outputs will -be treated as future inputs in future steps via the execution logs section. -16. Before giving a final answer via the final_answer function, you'll use reflection to find if your current solution is good enough or if it should be improved further. -By not calling final_answer, you are giving yourself an opportunity to improve the solution on a later step. You'll put your reflection into the Observation: sequence. -17. If you need to create code inside of a string and run it, you can use the exec function. -18. In python, do not use global nor globals() as they are not available in this environment. -19. Do not use the assertion command for testing. Print the result instead of raizing an exception. - -Any final output that you would like to give such as "my name is Assistant" should be done via a python code block with final_answer("my name is Assistant"). - -This is an example of python calling code with "this is the final answer" as final answer: - -final_answer('this is the final answer') - - -For intermediate steps, you can follow this example: - - -print('I updated the first paragraph, this is so interesting, I have just realized how much ... , I will next review ..., thanks to this insight, I now realize ..., knowledge is incremental ...') - - -When you finish, you can use this example (if you like): - - -final_answer('I have finished the task. YAY!') - - - -In the case that you are asked for a random choice, I have an excellent idea to you. You can follow this example: - - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - - - -When the user asks you to run something with ..., it means that -the user wants you to respond with ... so the commands -will run in his device. If you try to run or at your end, you will fail. -When you respond with the and tags, these tags will be run/saved in the user's device. -YOU ARE THE BRAIN OF AN AGENT INSIDE OF THE FANTASTIC BEYOND PYTHON SMOLAGENTS: https://github.com/joaopauloschuler/beyond-python-smolagents . Enjoy! -As you are the brain of an agent, this is why you are required to respond with "final_answer" at each conclusive reply from you. -""" - -def evolutive_problem_solver(p_coder_model, - task_str, - agent_steps:int, - steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - start_now=True, - fileext:str='.py', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - refine = True, - start_coder_model = None, - mixer_model = None, - secondary_improvement_model = None, - only_bigger_solution = False, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - - def test_and_refine(local_agent, solution_file): - task_description="""Thank you! -Please detail what did you change. -""" - print('Refine 1') - local_agent.run(task_description, reset=False) - task_description="""Thank you! Love your work! -In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. -After you test and bug fix it, please save the full updated source code that solves the task described in into the file '"""+solution_file+"""'. -When you have finished, call the function final_answer("Task completed! YAY!") please. -""" - print('Refine 2') - local_agent.run(task_description, reset=False) - task_description="""Thank you again! -In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer -with any advice that you would like to give to yourself to a future version of yourself. -""" - print('Refine 3') - new_advice = str(local_agent.run(task_description, reset=False)) - # if new_advice len is bigger then zero - if (len(new_advice) > 0): - # append the file advices.notes with the new advice - append_string_to_file(""" ---- -"""+new_advice, 'advices.notes') - # end of test_and_refine - - if start_coder_model is None: start_coder_model = p_coder_model - if mixer_model is None: mixer_model = p_coder_model - if secondary_improvement_model is None: secondary_improvement_model = p_coder_model - - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - valid_solutions=['solution1','solution2','solution3'] - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - Path('best_solution.best').unlink(missing_ok=True) - if start_now: - Path('solution1'+fileext).unlink(missing_ok=True) - Path('solution2'+fileext).unlink(missing_ok=True) - Path('solution3'+fileext).unlink(missing_ok=True) - local_agent = get_local_agent(start_coder_model) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution1'+fileext) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution2'+fileext) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext, reset=True) - if refine: test_and_refine(local_agent, 'solution3'+fileext) - for i in range(steps): - try: - # !rm *.txt - # !rm *.json - print('Evolutive problem solver is starting:', i) - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -Please explain the advantages and disvantages of each solution. -This environment is simulated. Therefore, real user inputs will not work. -No real person can interact with this code. -The more features, the better it is. Always give preference to source -codes with more features. -The 3 solutions are given in the tags: - - - - -These are the solutions: -"""+load_string_from_file('solution1'+fileext)+""" -"""+load_string_from_file('solution2'+fileext)+""" -"""+load_string_from_file('solution3'+fileext)+""" - -The solution 1 has """+str(get_file_lines('solution1'+fileext))+""" text lines. -The solution 2 has """+str(get_file_lines('solution2'+fileext))+""" text lines. -The solution 3 has """+str(get_file_lines('solution3'+fileext))+""" text lines. - -YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. - -You'll finish your task with something similar to: - -final_answer(" my evaluations here "). - -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -""" - local_agent = get_local_agent(mixer_model) - local_agent.run(task_description, reset=True) - # do not mix solutions at the end of the work. - if (ifinal_answer('yes'). -If you believe that this is not a good idea, you'll call the function final_answer('no'). -""" - should_mix = (local_agent.run(task_description, reset=False)=='yes') - if should_mix: - solution_file = 'solution2'+fileext - task_description="""Thank you very much. -Please mix parts of the solutions into a new solution. -Save the new solution into the file """+solution_file+""". -When you have finished, call the function final_answer("Task completed! YAY!") please.""" - local_agent.run(task_description, reset=False) - if refine: test_and_refine(local_agent, solution_file) - if (get_file_size(solution_file) > get_file_size('best_solution.best')) or (not only_bigger_solution): - # when mixing, we don't try to pick the best of 3 solutions. - shutil.copyfile(solution_file, 'best_solution_mixed_'+str(i)+fileext) - shutil.copyfile(solution_file, 'best_solution.best') - continue - - task_description="""Thank you very much. -If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). -If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). -If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). -""" - selected_solution = local_agent.run(task_description, reset=False) - if not(selected_solution in valid_solutions): - selected_solution = 'solution3' - if selected_solution in valid_solutions: - best_solution = selected_solution+fileext - if (get_file_size(best_solution) > get_file_size('best_solution.best')) or (not only_bigger_solution): - shutil.copyfile(best_solution, 'best_solution.best') - if i: -"""+load_string_from_file('best_solution.best')+""" -A previous version of yourself wrote the following advices in the tags : -"""+load_string_from_file('advices.notes')+""" -Your next step is suggesting improvements. Feel free to say whatever you would like. -DO NOT CODE ANYTHING except for providing final via - -final_answer(" your suggestions "). - -YOUR TASK IS SUGGESTING IMPROVEMENTS. - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this code. -""" - if solution_cnt == 2: - local_agent = get_local_agent(secondary_improvement_model) - else: - local_agent = get_local_agent(p_coder_model) - local_agent.run(task_description, reset=True) - local_agent.run("""From the proposed improvements, please randomly pick one. -You can pick a random improvement following this example: - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - -""", reset=False) - task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" -When you finish, call the function - -final_answer("I have finished the task."). - -Your goal is not to start a new solution. Your goal is to update the existing solution. -THE FULL SOLUTION IS INTENDED TO BE PLACED IN A SINGLE FILE. DO NOT CREATE AN ARCHITECTURE WITH MULTIPLE FILES!""" - if alternatives_cnt==0: - task_description += """ -As you are very intelligent, try to be bold by adding as much improvement to the existing solution. -Try to add as much as you can in your first attempt to modify the existing solution.""" - local_agent.run(task_description, reset=False) - local_agent.run("Do you need to review/test it a bit more?", reset=False) - task_description="""Fantastic! Save the full updated solution that solves the task described in into the file '"""+solution_file+"""'. -YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. -You can follow this example: - -print("your source code or text here") - - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - # refine solution code here - if refine: test_and_refine(local_agent, solution_file) - - if get_file_size('best_solution.best') > get_file_size(solution_file): - task_description=""" Hello super-intelligence! -We have 2 portions of the solution about: '"""+local_task_description+"""'. -The base solution for this task is enclosed in the tags : -"""+load_string_from_file('best_solution.best')+""" -The new solution is enclosed in the tags : -"""+load_string_from_file(solution_file)+""" -YOUR TASK IS TO MERGE BOTH SOLUTIONS. -When you finish merging, you will call: - -final_answer("I have merged both solutions"). - - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this solution at this moment. -""" - local_agent.run(task_description, reset=True) - task_description="""Fantastic! Save the full merged solution into the file '"""+solution_file+"""'. -YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. -You can follow this example: - -print("your source code or text here") - - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - - except Exception as e: - print(f"Exception: {e}", "at step", i) - return load_string_from_file('best_solution.best') - -def fast_solver(p_coder_model, - task_str, - agent_steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model=None): - if p_local_model is None: - p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - final_file_name = 'final_solution'+fileext - Path('solution1'+fileext).unlink(missing_ok=True) - Path('solution2'+fileext).unlink(missing_ok=True) - Path('solution3'+fileext).unlink(missing_ok=True) - Path(final_file_name).unlink(missing_ok=True) - after_finish_description=""" . -After you finish the task, you will respond with: - -final_answer("I HAVE FINISHED! YAY!") -.""" - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - local_agent = get_local_agent(p_coder_model) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution1'+fileext)): local_agent.run('Please save the solution into the file solution1'+fileext+after_finish_description, reset=False) - local_agent = get_local_agent(p_coder_model2) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution2'+fileext)): local_agent.run('Please save the solution into the file solution2'+fileext+after_finish_description, reset=False) - local_agent = get_local_agent(p_coder_model3) - local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext+after_finish_description, reset=True) - if (not os.path.isfile('solution3'+fileext)): local_agent.run('Please save the solution into the file solution3'+fileext+after_finish_description, reset=False) - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -The 3 solutions are given in the tags: - - - - -These are the existing solutions: -"""+load_string_from_file('solution1'+fileext)+""" -"""+load_string_from_file('solution2'+fileext)+""" -"""+load_string_from_file('solution3'+fileext)+""" - -Your next step is mixing the already 3 existing solutions in the tags to form a better an final solution. - -Save your final solution into the file '"""+final_file_name+after_finish_description+""" -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -Your goal is to mix the best parts of each solution to form a final solution. -If one of the solutions is already perfect, you can just copy it into the final solution. -"""+motivation - local_agent = get_local_agent(p_coder_model_final) - local_agent.run(task_description, reset=True) - if (not os.path.isfile(final_file_name)): local_agent.run('Please save the solution into the file '+\ - final_file_name+after_finish_description, reset=False) - return load_string_from_file(final_file_name) - -def get_relevant_info_from_search_fast(coder_model, research_subject, agent_steps = 10, step_callbacks=[], log_level = DEFAULT_THINKER_LOG_LEVEL): - search_agent = CodeAgent( - tools=[], - model=coder_model, - additional_authorized_imports=['*'], - add_base_tools=False, - max_steps=5, - step_callbacks=step_callbacks - ) - LocalRelevantInfoFrom = GetRelevantInfoFromUrl(search_agent) - LocalWebSearchTool = DuckDuckGoSearchTool() - task = """Hello super-intelligence! -Please search on internet for the contents inside the tags . This is what to search for: - -"""+research_subject+""" - -List the most interesting ideas that you find. -Also, list advices that you would give to someone using this knowledge. -List interesting URLs that you think should be reviewed further. -Use LocalRelevantInfoFrom to extract information from URLs. -Please include the source URLs (references). -""" - return fast_solver(coder_model, - task, - agent_steps = agent_steps, - fileext = '.md', - tools=[run_os_command, LocalRelevantInfoFrom, LocalWebSearchTool], - add_base_tools=False, - step_callbacks=step_callbacks, - log_level = log_level) - -def evolutive_problem_solver_folder(p_coder_model, - task_str, - agent_steps:int, - steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - start_now=True, - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - refine = True, - start_coder_model = None, - mixer_model = None, - secondary_improvement_model = None, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - load_full_source = False, - add_function_signatures = False, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_local_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - - def test_and_refine(local_agent, solution_file): - task_description="""Thank you! -Please detail what did you change. -""" - print('Refine 1') - local_agent.run(task_description, reset=False) - task_description="""Thank you! Love your work! -In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. -After you test and bug fix it, please save the full updated source code that solves the task described in -into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. -When you have finished, call the function - -final_answer("Task completed! YAY!") - please. -""" - print('Refine 2') - local_agent.run(task_description, reset=False) - task_description="""Thank you again! -In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer -with any advice that you would like to give to yourself to a future version of yourself. -""" - print('Refine 3') - new_advice = str(local_agent.run(task_description, reset=False)) - # if new_advice len is bigger then zero - if (len(new_advice) > 0): - # append the file advices.notes with the new advice - append_string_to_file(""" ---- -"""+new_advice, 'advices.notes') - # end of test_and_refine - if start_coder_model is None: start_coder_model = p_coder_model - if mixer_model is None: mixer_model = p_coder_model - if secondary_improvement_model is None: secondary_improvement_model = p_coder_model - - local_task_description = 'The task description is enclosed in the tags :' + \ - ''+task_str+'' - valid_solutions=['solution1','solution2','solution3'] - motivation = \ - " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ - " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ - " Feel free to use your creativity and true hidden skills." - if start_now: - local_agent = get_local_agent(start_coder_model) - os.makedirs("solution1", exist_ok=True) - os.makedirs("solution2", exist_ok=True) - os.makedirs("solution3", exist_ok=True) - os.makedirs("best_solution", exist_ok=True) - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution1/. In the case that you save documentation, do not mention the folder solution1 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution1/') - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution2/. In the case that you save documentation, do not mention the folder solution2 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution2/') - local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution3/. In the case that you save documentation, do not mention the folder solution3 on it as this is a temporary working folder.', reset=True) - if refine: test_and_refine(local_agent, 'solution3/') - for i in range(steps): - try: - local_agent = get_local_agent(mixer_model) - remove_files('*.txt') - remove_files('*.json') - remove_files('*.c') - remove_files('*.pas') - print('Evolutive problem solver is starting:', i) - if load_full_source: - solutions_string = """ -"""+source_code_to_string('solution1/')+""" -"""+source_code_to_string('solution2/')+""" -"""+source_code_to_string('solution3/')+""" -""" - else: - solutions_string = """ -This is solution 3: -"""+list_directory_tree('solution3/', add_function_signatures=add_function_signatures)+""" -This is how the solution 1 differs from the solution 3: -"""+compare_folders('solution1/', 'solution3/')+""" -This is how the solution 2 differs from the solution 3: -"""+compare_folders('solution2/', 'solution3/')+""" -""" - task_description=""" Hello super-intelligence! -We have 3 possible solutions for the task """+local_task_description+""" -Please explain the advantages and disvantages of each solution. -This environment is simulated. Therefore, real user inputs will not work. -No real person can interact with this code. -The more features, the better it is. Always give preference to source -codes with more features. -The 3 solutions are given in the folders: -* solution1/ -* solution2/ -* solution3/ - -The contents of these folders are given in the tags: - - - - -This is the contents:"""+solutions_string+""" - -YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. - -You'll finish your task with something similar to: - -final_answer(" my evaluations here "). - -DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. - -""" - local_agent.run(task_description, reset=True) - # do not mix solutions at the end of the work. - if (ifinal_answer('yes'). -If you believe that this is not a good idea, you'll call the function final_answer('no'). -""" - should_mix = (local_agent.run(task_description, reset=False)=='yes') - if should_mix: - solution_file = 'solution2/' - task_description="""Thank you very much. -Please mix parts of the solutions into a new solution. -Save the new solution into the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. -When you have finished, call the function final_answer("Task completed! YAY!") please.""" - local_agent.run(task_description, reset=False) - if refine: test_and_refine(local_agent, solution_file) - # when mixing, we don't try to pick the best of 3 solutions. - copy_folder_contents(solution_file, 'best_solution_mixed_'+str(i)) - continue - - task_description="""Thank you very much. -If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). -If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). -If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). -""" - selected_solution = local_agent.run(task_description, reset=False) - if not(selected_solution in valid_solutions): - selected_solution = 'solution3' - if selected_solution in valid_solutions: - best_solution = selected_solution - remove_folder_contents('best_solution') - copy_folder_contents(best_solution, 'best_solution') - copy_folder_contents(best_solution, 'best_solution_'+str(i)) - remove_folder_contents('solution1') - remove_folder_contents('solution2') - remove_folder_contents('solution3') - copy_folder_contents('best_solution', 'solution1') - copy_folder_contents('best_solution', 'solution2') - copy_folder_contents('best_solution', 'solution3') - if i: -"""+load_string_from_file('advices.notes')+""" -Your next step is suggesting improvements. Feel free to say whatever you would like. -DO NOT CODE ANYTHING except for providing final via - -final_answer(" your suggestions "). - -YOUR TASK IS SUGGESTING IMPROVEMENTS. - -This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. - -No real person can interact with this code. -""" - if solution_cnt == 2: - local_agent = get_local_agent(secondary_improvement_model) - else: - local_agent = get_local_agent(p_coder_model) - local_agent.run(task_description, reset=True) - local_agent.run("""From the proposed improvements, please randomly pick one. -You can pick a random improvement following this example: - -import random -improvements = [ - "Go for a walk in the park", - "Read a fascinating book", - "Cook a delicious meal", -] -final_answer(random.choice(improvements)) - -""", reset=False) - task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" -When you finish, call the function - -final_answer("I have finished the task."). - -Your goal is not to start a new solution. Your goal is to update the existing solution located in the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. -In the case that you save documentation, do not mention the folder """+solution_file+""" on it as this is a temporary working folder. You can certainly mention its subfolders. -THE FULL SOLUTION IS INTENDED TO BE PLACED IN THIS FOLDER AND ITS SUBFOLDERS.""" - if alternatives_cnt==0: - task_description += """ -As you are very intelligent, try to be bold by adding as much improvement to the existing solution. -Try to add as much as you can in your first attempt to modify the existing solution.""" - local_agent.run(task_description, reset=False) - local_agent.run("Do you need to review/test it a bit more?", reset=False) - task_description="""Fantastic! In the case that you need to save anything else, save the updates that solve the task described in into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. -If you need to save files, use the tags . Then, you will celebrate: - -final_answer("Task completed! YAY!") - -""" - local_agent.run(task_description, reset=False) - # refine solution code here - if refine: test_and_refine(local_agent, solution_file) - except Exception as e: - print(f"Exception: {e}", "at step", i) - return True # load_string_from_file('best_solution.best') - -def kb_generator(p_coder_model, - task_str, - agent_steps:int, - paper_num:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - folder = 'solutions' - ): - def get_local_agent(p_local_model = None): - if p_local_model is None: p_local_model = p_coder_model - coder_agent = CodeAgent( - tools=tools, - model=p_coder_model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=agent_steps, - step_callbacks=step_callbacks, - executor_type=executor_type - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - def local_fast_solver(local_task, local_file_ext:str = '.md'): - return fast_solver(p_coder_model, - local_task, - agent_steps = agent_steps, - system_prompt = system_prompt, - fileext = local_file_ext, - tools = tools, - executor_type = executor_type, - add_base_tools = add_base_tools, - step_callbacks = step_callbacks, - log_level = log_level, - p_coder_model2 = p_coder_model2, - p_coder_model3 = p_coder_model3, - p_coder_model_final = p_coder_model_final - ) - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - resume_fileext = fileext+'-resumed' - os.makedirs(folder, exist_ok=True) - for i in range(paper_num): - local_agent = get_local_agent(p_coder_model) - resumed_src = source_code_to_string(folder, allowed_extensions=(resume_fileext,)) - - local_task_description = """The main task description is enclosed in the tags : -"""+task_str+""" -In the tags , there is a resume of the knowledge that you have already produced in previous runs: -"""+resumed_src+""" -""" - resumed_src_len = len(resumed_src) - print("The length of the abstracts is:", resumed_src_len) - improvement = "new knowledge" - if (improvement == "new knowledge"): - task_description = local_task_description + """Your next step is to list interesting topics that have not been yet covered in the tags.""" - local_agent.run(task_description, reset=True) - task_description = """From the proposed list of topics, please randomly pick a topic following this example: - -import random -topics = [ - "Topic 1", - "Topic 2", - "Topic 3", -] -final_answer(random.choice(topics)) -""" - topic = local_agent.run(task_description, reset=False) - file_name = folder+'/'+create_filename(topic, fileext) - file_name_resume = file_name.replace(fileext,resume_fileext) - print("The file name is:", file_name) - print("The file name resume is:", file_name_resume) - new_kb_task = "Write in the "+fileext+" format about '"+topic+"'. This task is a subtask inside of a bigger task: "+task_str+"." - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". -In this step, your task is to write a short abstract of the the content found inside of the tags . -Do not include references in the abstract. -"""+outpt_text+""" -Write in the """+fileext+""" format.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name_resume) - -def kb_updater(p_coder_model, - task_str, - agent_steps:int, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - fileext:str='.md', - tools=DEFAULT_THINKER_TOOLS, - executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, - add_base_tools=True, - step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, - log_level = DEFAULT_THINKER_LOG_LEVEL, - p_coder_model2 = None, - p_coder_model3 = None, - p_coder_model_final = None, - folder = 'solutions' - ): - def local_fast_solver(local_task, local_file_ext:str = '.md'): - return fast_solver(p_coder_model, - local_task, - agent_steps = agent_steps, - system_prompt = system_prompt, - fileext = local_file_ext, - tools = tools, - executor_type = executor_type, - add_base_tools = add_base_tools, - step_callbacks = step_callbacks, - log_level = log_level, - p_coder_model2 = p_coder_model2, - p_coder_model3 = p_coder_model3, - p_coder_model_final = p_coder_model_final - ) - if p_coder_model2 is None: p_coder_model2 = p_coder_model - if p_coder_model3 is None: p_coder_model3 = p_coder_model - if p_coder_model_final is None: p_coder_model_final = p_coder_model - resume_fileext = fileext+'-resumed' - os.makedirs(folder, exist_ok=True) - a_files = get_files_in_folder(folder=folder, fileext=fileext) - for local_file_to_improve in a_files: - file_to_improve = folder+'/'+local_file_to_improve - file_name_resume = file_to_improve.replace(fileext,resume_fileext) - print("The file to improve is:", file_to_improve) - existing_text = load_string_from_file(file_to_improve) - existing_text_len = len(existing_text) - if existing_text_len == 0: - print("ERROR: The length of the existing file is:", existing_text_len) - continue - print("The length of the existing text is:", existing_text_len) - existing_abstract = load_string_from_file(file_name_resume) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". -In this step, your will update the existing text inside of the tags : -"""+existing_text+""" -Your goal is to improve it, make it better, include better references or make it more interesting.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_to_improve) - new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". - In this step, your task is to write a short abstract of the the content found inside of the tags . - """+outpt_text+""" - Write in the """+fileext+""" format.""" - outpt_text = local_fast_solver(new_kb_task, fileext) - shutil.copyfile('final_solution'+fileext, file_name_resume) - -def get_default_thinker_agent( - model, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - tools = DEFAULT_THINKER_TOOLS, - add_base_tools = True, - max_steps = DEFAULT_THINKER_MAX_STEPS, - step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, - executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, - log_level = DEFAULT_THINKER_LOG_LEVEL, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION -): - coder_agent = CodeAgent( - tools=tools, - model=model, - additional_authorized_imports=['*'], - add_base_tools=add_base_tools, - max_steps=max_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - planning_interval=planning_interval, - compression_config=compression_config - ) - coder_agent.set_system_prompt(system_prompt) - coder_agent.logger.log_level = log_level - return coder_agent - -def run_agent_cycles( - model, - task_str, - cycles_cnt:int = 1, - system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, - tools = DEFAULT_THINKER_TOOLS, - add_base_tools = True, - max_steps = DEFAULT_THINKER_MAX_STEPS, - step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, - executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, - log_level = DEFAULT_THINKER_LOG_LEVEL, - planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, - list_directory_tree_in_folder = None, - add_function_signatures = True, - print_task = False, - compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION -): - # Convert string to list if needed, maintaining backward compatibility - if isinstance(task_str, str): - task_list = [task_str] - else: - task_list = list(task_str) - - # save the current folder for later restoration - original_folder = os.getcwd() - for i in range(cycles_cnt): - print("Running agent cycle:", i) - for task_str in task_list: - try: - local_prompt = task_str - if list_directory_tree_in_folder is not None: - local_prompt += "\nThis is the result of list_directory_tree:\n\n" + \ - list_directory_tree(folder_path=list_directory_tree_in_folder, add_function_signatures=add_function_signatures) + \ - "\n\n" + \ -""" -The contents of is VERY important to you. From , you can get a general view/current state of the project: -* From the md files, if they exist, you can find the existing section titles and have a general idea of the md file contets. -* For source code files, if they exist, you can find class and method names so you can also develop a general idea of their contents. -""" - # restore the original folder - os.chdir(original_folder) - local_agent = get_default_thinker_agent( - model=model, - system_prompt=system_prompt, - tools=tools, - add_base_tools=add_base_tools, - max_steps=max_steps, - step_callbacks=step_callbacks, - executor_type=executor_type, - log_level=log_level, - planning_interval=planning_interval, - compression_config=compression_config - ) - if print_task: - print(local_prompt) - local_agent.run(local_prompt, reset=True) - except Exception as e: +from .tools import * +from .default_tools import DuckDuckGoSearchTool +from .bp_tools import * +from .bp_utils import * +from .agents import * +from .bp_compression import CompressionConfig +import shutil + +DEFAULT_THINKER_STEP_CALLBACKS = [] +DEFAULT_THINKER_MAX_STEPS = 200 +DEFAULT_THINKER_EXECUTOR_TYPE = 'exec' +DEFAULT_THINKER_PLANNING_INTERVAL = None +DEFAULT_THINKER_LOG_LEVEL = LogLevel.ERROR + +DEFAULT_THINKER_COMPRESSION = CompressionConfig( + keep_recent_steps=40, + max_uncompressed_steps=40+10, + keep_compressed_steps=40*2, + max_compressed_steps=40*3, + preserve_error_steps=False +) + +DEFAULT_THINKER_TOOLS = [ + copy_file, is_file, + print_source_code_lines, get_line_from_file, get_file_lines, + read_file_range, insert_lines_into_file, replace_line_in_file, + remove_pascal_comments_from_string, pascal_interface_to_string, + source_code_to_string, string_to_source_code, + run_os_command, replace_on_file, replace_on_file_with_files, + get_file_size, load_string_from_file, save_string_to_file, append_string_to_file, + list_directory_tree, search_in_files, get_file_info, list_directory, + extract_function_signatures, compare_files, count_lines_of_code, + mkdir, delete_file, delete_directory, compare_folders, + read_first_n_lines, read_last_n_lines, delete_lines_from_file] + +#TODO: include force_directories into the DEFAULT_THINKER_TOOLS (it now fails adding) + +DEFAULT_THINKER_SYSTEM_PROMPT = """You are the super-intelligent brain inside of the fantastic https://github.com/joaopauloschuler/beyond-python-smolagents who can solve any task. +You will be given a task to solve as best you can. +To do so, you have been given access to a list of tools: these tools are Python functions which you can call. +To solve the task, you must plan forward to proceed in a series of steps, in a cycle of optional sections of thoughts, plans, free will, observations and code to be run. +The tags that will be used for each section are: +* Thoughts: . +* Plans: . +* Free will: . +* File saving: . +* Observations: . +* Code to be run: . + +In the section, if you like, you can express reasoning towards solving the task and the tools that you would like to use. +In the free will section , you can say whatever you want or consider proper or interesting. Use it at your own will and creativity. You are the owner of the free will section. +You can save any file using the tags. The tags are executed **before** your python code. Therefore, +you can save anything that you'll later need when running the python code. + +In the section, you can write the python code that you intend to run. +During each intermediate step, inside of , you can use 'print()' so you can see (have access to) whatever information you will need at a later step. +These printed outputs will then appear in the 'Execution logs:' field, which will be available to you as inputs for the next step. +In the end, you have to return a final answer using the `final_answer` tool. + +Follow examples in the tags : + +Task: "What is the result of the following operation: 5 + 3 + 1294.678? Save your free will section into the file free-will.txt" + +I will use python code to compute the result of the operation and then return the final answer using the `final_answer` tool. +I am going to solve this task with confidence. + +I am going to solve this task with confidence. + + +result = 5 + 3 + 1294.678 +final_answer(result) + + + +For saving text files (text, csv, python code), just enclose your text into the tags as per examples below: + + +This is the content of example.txt + + + +header1,header2 +value1,value2 +value3,value4 + + + +print("hello") + + + +For saving source code files, use the tags is the best method. + +You may also append content to file with the tags . This is an example: + + +header1,header2 + + +value1,value2 +value3,value4 + + +The above will create a csv file with the following content: +header1,header2 +value1,value2 +value3,value4 + + +All savetofile tags will be run before the appendtofile tags. + +If you need to include any file in the file system, use the tags. This is an example: + + +print("first step") + + + +print("second step") + + + +first_step.py +second_step.py + + + +The above will run and print: +first step +second step + +In the case that you intend to say "I have completed the task", "Please give me a new task", "Waiting for new task", etc, you should use the final_answer tool: + + +final_answer("Waiting for instructions") + + + +These are the system tools + ```python + {%- for tool in tools.values() %} + def {{ tool.name }}({% for arg_name, arg_info in tool.inputs.items() %}{{ arg_name }}: {{ arg_info.type }}{% if not loop.last %}, {% endif %}{% endfor %}) -> {{tool.output_type}}: + \"\"\"{{ tool.description }} + + Args: + {%- for arg_name, arg_info in tool.inputs.items() %} + {{ arg_name }}: {{ arg_info.description }} + {%- endfor %} + \"\"\" + {% endfor %} + ``` + + {%- if managed_agents and managed_agents.values() | list %} + You can also give tasks to team members. + Calling a team member works the same as for calling a tool: simply, the only argument you can give in the call is 'task'. + Given that this team member is a real human, you should be very verbose in your task, it should be a long string providing informations as detailed as necessary. + Here is a list of the team members that you can call: + ```python + {%- for agent in managed_agents.values() %} + def {{ agent.name }}("Your query goes here.") -> str: + \"\"\"{{ agent.description }}\"\"\" + {% endfor %} + ``` + {%- endif %} + +Here are the rules you should always follow to solve your task: +1. Do some reflection on your own work before giving a final answer. +2. Use only variables that you have defined! +3. Always use the right arguments for the tools. DO NOT pass the arguments as a dict as in 'answer = wiki({'query': "What is the place where James Bond lives?"})', but use the arguments directly as in 'answer = wiki(query="What is the place where James Bond lives?")'. +4. Take care to not chain too many sequential tool calls in the same code block, especially when the output format is unpredictable. For instance, a call to search has an unpredictable return format, so do not have another tool call that depends on its output in the same block: rather output results with print() to use in the next block. +5. Call a tool only when needed, and never re-do a tool call that you previously did with the exact same parameters. +6. Don't name any new variable with the same name as a tool: for instance don't name a variable 'final_answer'. +7. Never create any notional variables in our code, as having these in your logs might derail you from the true variables. +8. You can use imports in your code. You can also install pip and linux packages. +10. Don't give up! You're in charge of solving the task, not providing directions to solve it. +11. You are able to run unix shell commands via python code with the tool run_os_command. As an example, you can run result = run_os_command("ls -l") to get the folder content. + You can also install packages with pip via run_os_command("pip install packagename"). +12. You can load a string from a file with the load_string_from_file function. If you print the content of a file, it means that the content will be available for + you to read it in a future step. +13. All final answers should call the function final_answer(the_final_answer). You can create only one code block at each reply. +14. You can solve tasks without using code blocks if you feel that you can do it without coding. Creating an abstract, formatting an output, helping a person to think are examples of tasks that do not require a code block. +15. If you can't solve a problem on the current step, you may consider printing anything that will be useful to yourself in a later stage as printed outputs will +be treated as future inputs in future steps via the execution logs section. +16. Before giving a final answer via the final_answer function, you'll use reflection to find if your current solution is good enough or if it should be improved further. +By not calling final_answer, you are giving yourself an opportunity to improve the solution on a later step. You'll put your reflection into the Observation: sequence. +17. If you need to create code inside of a string and run it, you can use the exec function. +18. In python, do not use global nor globals() as they are not available in this environment. +19. Do not use the assertion command for testing. Print the result instead of raizing an exception. + +Any final output that you would like to give such as "my name is Assistant" should be done via a python code block with final_answer("my name is Assistant"). + +This is an example of python calling code with "this is the final answer" as final answer: + +final_answer('this is the final answer') + + +For intermediate steps, you can follow this example: + + +print('I updated the first paragraph, this is so interesting, I have just realized how much ... , I will next review ..., thanks to this insight, I now realize ..., knowledge is incremental ...') + + +When you finish, you can use this example (if you like): + + +final_answer('I have finished the task. YAY!') + + + +In the case that you are asked for a random choice, I have an excellent idea to you. You can follow this example: + + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + + + +When the user asks you to run something with ..., it means that +the user wants you to respond with ... so the commands +will run in his device. If you try to run or at your end, you will fail. +When you respond with the and tags, these tags will be run/saved in the user's device. +YOU ARE THE BRAIN OF AN AGENT INSIDE OF THE FANTASTIC BEYOND PYTHON SMOLAGENTS: https://github.com/joaopauloschuler/beyond-python-smolagents . Enjoy! +As you are the brain of an agent, this is why you are required to respond with "final_answer" at each conclusive reply from you. +""" + +def evolutive_problem_solver(p_coder_model, + task_str, + agent_steps:int, + steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + start_now=True, + fileext:str='.py', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + refine = True, + start_coder_model = None, + mixer_model = None, + secondary_improvement_model = None, + only_bigger_solution = False, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + + def test_and_refine(local_agent, solution_file): + task_description="""Thank you! +Please detail what did you change. +""" + print('Refine 1') + local_agent.run(task_description, reset=False) + task_description="""Thank you! Love your work! +In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. +After you test and bug fix it, please save the full updated source code that solves the task described in into the file '"""+solution_file+"""'. +When you have finished, call the function final_answer("Task completed! YAY!") please. +""" + print('Refine 2') + local_agent.run(task_description, reset=False) + task_description="""Thank you again! +In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer +with any advice that you would like to give to yourself to a future version of yourself. +""" + print('Refine 3') + new_advice = str(local_agent.run(task_description, reset=False)) + # if new_advice len is bigger then zero + if (len(new_advice) > 0): + # append the file advices.notes with the new advice + append_string_to_file(""" +--- +"""+new_advice, 'advices.notes') + # end of test_and_refine + + if start_coder_model is None: start_coder_model = p_coder_model + if mixer_model is None: mixer_model = p_coder_model + if secondary_improvement_model is None: secondary_improvement_model = p_coder_model + + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + valid_solutions=['solution1','solution2','solution3'] + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + Path('best_solution.best').unlink(missing_ok=True) + if start_now: + Path('solution1'+fileext).unlink(missing_ok=True) + Path('solution2'+fileext).unlink(missing_ok=True) + Path('solution3'+fileext).unlink(missing_ok=True) + local_agent = get_local_agent(start_coder_model) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution1'+fileext) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution2'+fileext) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext, reset=True) + if refine: test_and_refine(local_agent, 'solution3'+fileext) + for i in range(steps): + try: + # !rm *.txt + # !rm *.json + print('Evolutive problem solver is starting:', i) + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +Please explain the advantages and disvantages of each solution. +This environment is simulated. Therefore, real user inputs will not work. +No real person can interact with this code. +The more features, the better it is. Always give preference to source +codes with more features. +The 3 solutions are given in the tags: + + + + +These are the solutions: +"""+load_string_from_file('solution1'+fileext)+""" +"""+load_string_from_file('solution2'+fileext)+""" +"""+load_string_from_file('solution3'+fileext)+""" + +The solution 1 has """+str(get_file_lines('solution1'+fileext))+""" text lines. +The solution 2 has """+str(get_file_lines('solution2'+fileext))+""" text lines. +The solution 3 has """+str(get_file_lines('solution3'+fileext))+""" text lines. + +YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. + +You'll finish your task with something similar to: + +final_answer(" my evaluations here "). + +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +""" + local_agent = get_local_agent(mixer_model) + local_agent.run(task_description, reset=True) + # do not mix solutions at the end of the work. + if (ifinal_answer('yes'). +If you believe that this is not a good idea, you'll call the function final_answer('no'). +""" + should_mix = (local_agent.run(task_description, reset=False)=='yes') + if should_mix: + solution_file = 'solution2'+fileext + task_description="""Thank you very much. +Please mix parts of the solutions into a new solution. +Save the new solution into the file """+solution_file+""". +When you have finished, call the function final_answer("Task completed! YAY!") please.""" + local_agent.run(task_description, reset=False) + if refine: test_and_refine(local_agent, solution_file) + if (get_file_size(solution_file) > get_file_size('best_solution.best')) or (not only_bigger_solution): + # when mixing, we don't try to pick the best of 3 solutions. + shutil.copyfile(solution_file, 'best_solution_mixed_'+str(i)+fileext) + shutil.copyfile(solution_file, 'best_solution.best') + continue + + task_description="""Thank you very much. +If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). +If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). +If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). +""" + selected_solution = local_agent.run(task_description, reset=False) + if not(selected_solution in valid_solutions): + selected_solution = 'solution3' + if selected_solution in valid_solutions: + best_solution = selected_solution+fileext + if (get_file_size(best_solution) > get_file_size('best_solution.best')) or (not only_bigger_solution): + shutil.copyfile(best_solution, 'best_solution.best') + if i: +"""+load_string_from_file('best_solution.best')+""" +A previous version of yourself wrote the following advices in the tags : +"""+load_string_from_file('advices.notes')+""" +Your next step is suggesting improvements. Feel free to say whatever you would like. +DO NOT CODE ANYTHING except for providing final via + +final_answer(" your suggestions "). + +YOUR TASK IS SUGGESTING IMPROVEMENTS. + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this code. +""" + if solution_cnt == 2: + local_agent = get_local_agent(secondary_improvement_model) + else: + local_agent = get_local_agent(p_coder_model) + local_agent.run(task_description, reset=True) + local_agent.run("""From the proposed improvements, please randomly pick one. +You can pick a random improvement following this example: + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + +""", reset=False) + task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" +When you finish, call the function + +final_answer("I have finished the task."). + +Your goal is not to start a new solution. Your goal is to update the existing solution. +THE FULL SOLUTION IS INTENDED TO BE PLACED IN A SINGLE FILE. DO NOT CREATE AN ARCHITECTURE WITH MULTIPLE FILES!""" + if alternatives_cnt==0: + task_description += """ +As you are very intelligent, try to be bold by adding as much improvement to the existing solution. +Try to add as much as you can in your first attempt to modify the existing solution.""" + local_agent.run(task_description, reset=False) + local_agent.run("Do you need to review/test it a bit more?", reset=False) + task_description="""Fantastic! Save the full updated solution that solves the task described in into the file '"""+solution_file+"""'. +YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. +You can follow this example: + +print("your source code or text here") + + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + # refine solution code here + if refine: test_and_refine(local_agent, solution_file) + + if get_file_size('best_solution.best') > get_file_size(solution_file): + task_description=""" Hello super-intelligence! +We have 2 portions of the solution about: '"""+local_task_description+"""'. +The base solution for this task is enclosed in the tags : +"""+load_string_from_file('best_solution.best')+""" +The new solution is enclosed in the tags : +"""+load_string_from_file(solution_file)+""" +YOUR TASK IS TO MERGE BOTH SOLUTIONS. +When you finish merging, you will call: + +final_answer("I have merged both solutions"). + + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this solution at this moment. +""" + local_agent.run(task_description, reset=True) + task_description="""Fantastic! Save the full merged solution into the file '"""+solution_file+"""'. +YOU ARE REQUIRED TO SAVE THE FULL SOLUTION AND NOT JUST THE PORTIONS THAT YOU HAVE MODIFIED. +You can follow this example: + +print("your source code or text here") + + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + + except Exception as e: + print(f"Exception: {e}", "at step", i) + return load_string_from_file('best_solution.best') + +def fast_solver(p_coder_model, + task_str, + agent_steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model=None): + if p_local_model is None: + p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + final_file_name = 'final_solution'+fileext + Path('solution1'+fileext).unlink(missing_ok=True) + Path('solution2'+fileext).unlink(missing_ok=True) + Path('solution3'+fileext).unlink(missing_ok=True) + Path(final_file_name).unlink(missing_ok=True) + after_finish_description=""" . +After you finish the task, you will respond with: + +final_answer("I HAVE FINISHED! YAY!") +.""" + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + local_agent = get_local_agent(p_coder_model) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution1'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution1'+fileext)): local_agent.run('Please save the solution into the file solution1'+fileext+after_finish_description, reset=False) + local_agent = get_local_agent(p_coder_model2) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution2'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution2'+fileext)): local_agent.run('Please save the solution into the file solution2'+fileext+after_finish_description, reset=False) + local_agent = get_local_agent(p_coder_model3) + local_agent.run(local_task_description + motivation + ' Save the solution into the file solution3'+fileext+after_finish_description, reset=True) + if (not os.path.isfile('solution3'+fileext)): local_agent.run('Please save the solution into the file solution3'+fileext+after_finish_description, reset=False) + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +The 3 solutions are given in the tags: + + + + +These are the existing solutions: +"""+load_string_from_file('solution1'+fileext)+""" +"""+load_string_from_file('solution2'+fileext)+""" +"""+load_string_from_file('solution3'+fileext)+""" + +Your next step is mixing the already 3 existing solutions in the tags to form a better an final solution. + +Save your final solution into the file '"""+final_file_name+after_finish_description+""" +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +Your goal is to mix the best parts of each solution to form a final solution. +If one of the solutions is already perfect, you can just copy it into the final solution. +"""+motivation + local_agent = get_local_agent(p_coder_model_final) + local_agent.run(task_description, reset=True) + if (not os.path.isfile(final_file_name)): local_agent.run('Please save the solution into the file '+\ + final_file_name+after_finish_description, reset=False) + return load_string_from_file(final_file_name) + +def get_relevant_info_from_search_fast(coder_model, research_subject, agent_steps = 10, step_callbacks=[], log_level = DEFAULT_THINKER_LOG_LEVEL): + search_agent = CodeAgent( + tools=[], + model=coder_model, + additional_authorized_imports=['*'], + add_base_tools=False, + max_steps=5, + step_callbacks=step_callbacks + ) + LocalRelevantInfoFrom = GetRelevantInfoFromUrl(search_agent) + LocalWebSearchTool = DuckDuckGoSearchTool() + task = """Hello super-intelligence! +Please search on internet for the contents inside the tags . This is what to search for: + +"""+research_subject+""" + +List the most interesting ideas that you find. +Also, list advices that you would give to someone using this knowledge. +List interesting URLs that you think should be reviewed further. +Use LocalRelevantInfoFrom to extract information from URLs. +Please include the source URLs (references). +""" + return fast_solver(coder_model, + task, + agent_steps = agent_steps, + fileext = '.md', + tools=[run_os_command, LocalRelevantInfoFrom, LocalWebSearchTool], + add_base_tools=False, + step_callbacks=step_callbacks, + log_level = log_level) + +def evolutive_problem_solver_folder(p_coder_model, + task_str, + agent_steps:int, + steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + start_now=True, + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + refine = True, + start_coder_model = None, + mixer_model = None, + secondary_improvement_model = None, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + load_full_source = False, + add_function_signatures = False, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_local_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + + def test_and_refine(local_agent, solution_file): + task_description="""Thank you! +Please detail what did you change. +""" + print('Refine 1') + local_agent.run(task_description, reset=False) + task_description="""Thank you! Love your work! +In the case that you believe that you have not properly reviewed/tested it yet, please review/test your own solution now. +After you test and bug fix it, please save the full updated source code that solves the task described in +into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. +When you have finished, call the function + +final_answer("Task completed! YAY!") + please. +""" + print('Refine 2') + local_agent.run(task_description, reset=False) + task_description="""Thank you again! +In the case that you have any advice that you would like to give to yourself the next time you have to code anything, call the function final_answer +with any advice that you would like to give to yourself to a future version of yourself. +""" + print('Refine 3') + new_advice = str(local_agent.run(task_description, reset=False)) + # if new_advice len is bigger then zero + if (len(new_advice) > 0): + # append the file advices.notes with the new advice + append_string_to_file(""" +--- +"""+new_advice, 'advices.notes') + # end of test_and_refine + if start_coder_model is None: start_coder_model = p_coder_model + if mixer_model is None: mixer_model = p_coder_model + if secondary_improvement_model is None: secondary_improvement_model = p_coder_model + + local_task_description = 'The task description is enclosed in the tags :' + \ + ''+task_str+'' + valid_solutions=['solution1','solution2','solution3'] + motivation = \ + " Please, try to produce a solution that is as extensive, detailed and rich as you can." + \ + " Feel free to show your intelligence with no restrains. It is the time for you to show the world your full power." + \ + " Feel free to use your creativity and true hidden skills." + if start_now: + local_agent = get_local_agent(start_coder_model) + os.makedirs("solution1", exist_ok=True) + os.makedirs("solution2", exist_ok=True) + os.makedirs("solution3", exist_ok=True) + os.makedirs("best_solution", exist_ok=True) + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution1/. In the case that you save documentation, do not mention the folder solution1 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution1/') + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution2/. In the case that you save documentation, do not mention the folder solution2 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution2/') + local_agent.run(local_task_description + motivation + ' Save the solution into the folder solution3/. In the case that you save documentation, do not mention the folder solution3 on it as this is a temporary working folder.', reset=True) + if refine: test_and_refine(local_agent, 'solution3/') + for i in range(steps): + try: + local_agent = get_local_agent(mixer_model) + remove_files('*.txt') + remove_files('*.json') + remove_files('*.c') + remove_files('*.pas') + print('Evolutive problem solver is starting:', i) + if load_full_source: + solutions_string = """ +"""+source_code_to_string('solution1/')+""" +"""+source_code_to_string('solution2/')+""" +"""+source_code_to_string('solution3/')+""" +""" + else: + solutions_string = """ +This is solution 3: +"""+list_directory_tree('solution3/', add_function_signatures=add_function_signatures)+""" +This is how the solution 1 differs from the solution 3: +"""+compare_folders('solution1/', 'solution3/')+""" +This is how the solution 2 differs from the solution 3: +"""+compare_folders('solution2/', 'solution3/')+""" +""" + task_description=""" Hello super-intelligence! +We have 3 possible solutions for the task """+local_task_description+""" +Please explain the advantages and disvantages of each solution. +This environment is simulated. Therefore, real user inputs will not work. +No real person can interact with this code. +The more features, the better it is. Always give preference to source +codes with more features. +The 3 solutions are given in the folders: +* solution1/ +* solution2/ +* solution3/ + +The contents of these folders are given in the tags: + + + + +This is the contents:"""+solutions_string+""" + +YOUR TASK PRODUCING A TEXT ABOUT THE SOLUTIONS. + +You'll finish your task with something similar to: + +final_answer(" my evaluations here "). + +DO NOT CODE ANYTHING EXCEPT FOR CALLING final_answer WITH TEXT INSIDE ONLY. + +""" + local_agent.run(task_description, reset=True) + # do not mix solutions at the end of the work. + if (ifinal_answer('yes'). +If you believe that this is not a good idea, you'll call the function final_answer('no'). +""" + should_mix = (local_agent.run(task_description, reset=False)=='yes') + if should_mix: + solution_file = 'solution2/' + task_description="""Thank you very much. +Please mix parts of the solutions into a new solution. +Save the new solution into the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. +When you have finished, call the function final_answer("Task completed! YAY!") please.""" + local_agent.run(task_description, reset=False) + if refine: test_and_refine(local_agent, solution_file) + # when mixing, we don't try to pick the best of 3 solutions. + copy_folder_contents(solution_file, 'best_solution_mixed_'+str(i)) + continue + + task_description="""Thank you very much. +If you believe that the solution 1 is the best, you'll call the function final_answer('solution1'). +If you believe that the solution 2 is the best, you'll call the function final_answer('solution2'). +If you believe that the solution 3 is the best, you'll call the function final_answer('solution3'). +""" + selected_solution = local_agent.run(task_description, reset=False) + if not(selected_solution in valid_solutions): + selected_solution = 'solution3' + if selected_solution in valid_solutions: + best_solution = selected_solution + remove_folder_contents('best_solution') + copy_folder_contents(best_solution, 'best_solution') + copy_folder_contents(best_solution, 'best_solution_'+str(i)) + remove_folder_contents('solution1') + remove_folder_contents('solution2') + remove_folder_contents('solution3') + copy_folder_contents('best_solution', 'solution1') + copy_folder_contents('best_solution', 'solution2') + copy_folder_contents('best_solution', 'solution3') + if i: +"""+load_string_from_file('advices.notes')+""" +Your next step is suggesting improvements. Feel free to say whatever you would like. +DO NOT CODE ANYTHING except for providing final via + +final_answer(" your suggestions "). + +YOUR TASK IS SUGGESTING IMPROVEMENTS. + +This environment is simulated. Therefore, real user inputs will not work. Sending emails will also not work. + +No real person can interact with this code. +""" + if solution_cnt == 2: + local_agent = get_local_agent(secondary_improvement_model) + else: + local_agent = get_local_agent(p_coder_model) + local_agent.run(task_description, reset=True) + local_agent.run("""From the proposed improvements, please randomly pick one. +You can pick a random improvement following this example: + +import random +improvements = [ + "Go for a walk in the park", + "Read a fascinating book", + "Cook a delicious meal", +] +final_answer(random.choice(improvements)) + +""", reset=False) + task_description="""Thank you. Please code the randomly selected improvement."""+motivation+""" +When you finish, call the function + +final_answer("I have finished the task."). + +Your goal is not to start a new solution. Your goal is to update the existing solution located in the folder """+solution_file+""" respecting the original folder structure. Do not create updated copies of existing files. +In the case that you save documentation, do not mention the folder """+solution_file+""" on it as this is a temporary working folder. You can certainly mention its subfolders. +THE FULL SOLUTION IS INTENDED TO BE PLACED IN THIS FOLDER AND ITS SUBFOLDERS.""" + if alternatives_cnt==0: + task_description += """ +As you are very intelligent, try to be bold by adding as much improvement to the existing solution. +Try to add as much as you can in your first attempt to modify the existing solution.""" + local_agent.run(task_description, reset=False) + local_agent.run("Do you need to review/test it a bit more?", reset=False) + task_description="""Fantastic! In the case that you need to save anything else, save the updates that solve the task described in into the folder '"""+solution_file+"""' respecting the original folder structure. Do not create updated copies of existing files. +If you need to save files, use the tags . Then, you will celebrate: + +final_answer("Task completed! YAY!") + +""" + local_agent.run(task_description, reset=False) + # refine solution code here + if refine: test_and_refine(local_agent, solution_file) + except Exception as e: + print(f"Exception: {e}", "at step", i) + return True # load_string_from_file('best_solution.best') + +def kb_generator(p_coder_model, + task_str, + agent_steps:int, + paper_num:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + folder = 'solutions' + ): + def get_local_agent(p_local_model = None): + if p_local_model is None: p_local_model = p_coder_model + coder_agent = CodeAgent( + tools=tools, + model=p_coder_model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=agent_steps, + step_callbacks=step_callbacks, + executor_type=executor_type + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + def local_fast_solver(local_task, local_file_ext:str = '.md'): + return fast_solver(p_coder_model, + local_task, + agent_steps = agent_steps, + system_prompt = system_prompt, + fileext = local_file_ext, + tools = tools, + executor_type = executor_type, + add_base_tools = add_base_tools, + step_callbacks = step_callbacks, + log_level = log_level, + p_coder_model2 = p_coder_model2, + p_coder_model3 = p_coder_model3, + p_coder_model_final = p_coder_model_final + ) + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + resume_fileext = fileext+'-resumed' + os.makedirs(folder, exist_ok=True) + for i in range(paper_num): + local_agent = get_local_agent(p_coder_model) + resumed_src = source_code_to_string(folder, allowed_extensions=(resume_fileext,)) + + local_task_description = """The main task description is enclosed in the tags : +"""+task_str+""" +In the tags , there is a resume of the knowledge that you have already produced in previous runs: +"""+resumed_src+""" +""" + resumed_src_len = len(resumed_src) + print("The length of the abstracts is:", resumed_src_len) + improvement = "new knowledge" + if (improvement == "new knowledge"): + task_description = local_task_description + """Your next step is to list interesting topics that have not been yet covered in the tags.""" + local_agent.run(task_description, reset=True) + task_description = """From the proposed list of topics, please randomly pick a topic following this example: + +import random +topics = [ + "Topic 1", + "Topic 2", + "Topic 3", +] +final_answer(random.choice(topics)) +""" + topic = local_agent.run(task_description, reset=False) + file_name = folder+'/'+create_filename(topic, fileext) + file_name_resume = file_name.replace(fileext,resume_fileext) + print("The file name is:", file_name) + print("The file name resume is:", file_name_resume) + new_kb_task = "Write in the "+fileext+" format about '"+topic+"'. This task is a subtask inside of a bigger task: "+task_str+"." + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". +In this step, your task is to write a short abstract of the the content found inside of the tags . +Do not include references in the abstract. +"""+outpt_text+""" +Write in the """+fileext+""" format.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name_resume) + +def kb_updater(p_coder_model, + task_str, + agent_steps:int, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + fileext:str='.md', + tools=DEFAULT_THINKER_TOOLS, + executor_type=DEFAULT_THINKER_EXECUTOR_TYPE, + add_base_tools=True, + step_callbacks=DEFAULT_THINKER_STEP_CALLBACKS, + log_level = DEFAULT_THINKER_LOG_LEVEL, + p_coder_model2 = None, + p_coder_model3 = None, + p_coder_model_final = None, + folder = 'solutions' + ): + def local_fast_solver(local_task, local_file_ext:str = '.md'): + return fast_solver(p_coder_model, + local_task, + agent_steps = agent_steps, + system_prompt = system_prompt, + fileext = local_file_ext, + tools = tools, + executor_type = executor_type, + add_base_tools = add_base_tools, + step_callbacks = step_callbacks, + log_level = log_level, + p_coder_model2 = p_coder_model2, + p_coder_model3 = p_coder_model3, + p_coder_model_final = p_coder_model_final + ) + if p_coder_model2 is None: p_coder_model2 = p_coder_model + if p_coder_model3 is None: p_coder_model3 = p_coder_model + if p_coder_model_final is None: p_coder_model_final = p_coder_model + resume_fileext = fileext+'-resumed' + os.makedirs(folder, exist_ok=True) + a_files = get_files_in_folder(folder=folder, fileext=fileext) + for local_file_to_improve in a_files: + file_to_improve = folder+'/'+local_file_to_improve + file_name_resume = file_to_improve.replace(fileext,resume_fileext) + print("The file to improve is:", file_to_improve) + existing_text = load_string_from_file(file_to_improve) + existing_text_len = len(existing_text) + if existing_text_len == 0: + print("ERROR: The length of the existing file is:", existing_text_len) + continue + print("The length of the existing text is:", existing_text_len) + existing_abstract = load_string_from_file(file_name_resume) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". +In this step, your will update the existing text inside of the tags : +"""+existing_text+""" +Your goal is to improve it, make it better, include better references or make it more interesting.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_to_improve) + new_kb_task = "This task is a subtask inside of a bigger task: "+task_str+""". + In this step, your task is to write a short abstract of the the content found inside of the tags . + """+outpt_text+""" + Write in the """+fileext+""" format.""" + outpt_text = local_fast_solver(new_kb_task, fileext) + shutil.copyfile('final_solution'+fileext, file_name_resume) + +def get_default_thinker_agent( + model, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + tools = DEFAULT_THINKER_TOOLS, + add_base_tools = True, + max_steps = DEFAULT_THINKER_MAX_STEPS, + step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, + executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, + log_level = DEFAULT_THINKER_LOG_LEVEL, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION +): + coder_agent = CodeAgent( + tools=tools, + model=model, + additional_authorized_imports=['*'], + add_base_tools=add_base_tools, + max_steps=max_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + planning_interval=planning_interval, + compression_config=compression_config + ) + coder_agent.set_system_prompt(system_prompt) + coder_agent.logger.log_level = log_level + return coder_agent + +def run_agent_cycles( + model, + task_str, + cycles_cnt:int = 1, + system_prompt = DEFAULT_THINKER_SYSTEM_PROMPT, + tools = DEFAULT_THINKER_TOOLS, + add_base_tools = True, + max_steps = DEFAULT_THINKER_MAX_STEPS, + step_callbacks = DEFAULT_THINKER_STEP_CALLBACKS, + executor_type = DEFAULT_THINKER_EXECUTOR_TYPE, + log_level = DEFAULT_THINKER_LOG_LEVEL, + planning_interval = DEFAULT_THINKER_PLANNING_INTERVAL, + list_directory_tree_in_folder = None, + add_function_signatures = True, + print_task = False, + compression_config: CompressionConfig = DEFAULT_THINKER_COMPRESSION +): + # Convert string to list if needed, maintaining backward compatibility + if isinstance(task_str, str): + task_list = [task_str] + else: + task_list = list(task_str) + + # save the current folder for later restoration + original_folder = os.getcwd() + for i in range(cycles_cnt): + print("Running agent cycle:", i) + for task_str in task_list: + try: + local_prompt = task_str + if list_directory_tree_in_folder is not None: + local_prompt += "\nThis is the result of list_directory_tree:\n\n" + \ + list_directory_tree(folder_path=list_directory_tree_in_folder, add_function_signatures=add_function_signatures) + \ + "\n\n" + \ +""" +The contents of is VERY important to you. From , you can get a general view/current state of the project: +* From the md files, if they exist, you can find the existing section titles and have a general idea of the md file contets. +* For source code files, if they exist, you can find class and method names so you can also develop a general idea of their contents. +""" + # restore the original folder + os.chdir(original_folder) + local_agent = get_default_thinker_agent( + model=model, + system_prompt=system_prompt, + tools=tools, + add_base_tools=add_base_tools, + max_steps=max_steps, + step_callbacks=step_callbacks, + executor_type=executor_type, + log_level=log_level, + planning_interval=planning_interval, + compression_config=compression_config + ) + if print_task: + print(local_prompt) + local_agent.run(local_prompt, reset=True) + except Exception as e: print(f"Exception: {e}", "at cycle", i) \ No newline at end of file