|
6 | 6 |
|
7 | 7 | from eaa.core.message_proc import ( |
8 | 8 | generate_openai_message, |
9 | | - purge_context_images, |
10 | | - print_message, |
11 | 9 | ) |
12 | 10 | from eaa.api.llm_config import LLMConfig |
13 | 11 | from eaa.api.memory import MemoryManagerConfig |
14 | 12 | from eaa.core.exceptions import MaxRoundsReached |
15 | | -from eaa.core.tooling.base import ToolReturnType, BaseTool |
| 13 | +from eaa.core.tooling.base import BaseTool |
16 | 14 |
|
17 | 15 | from eaa.tool.imaging.acquisition import AcquireImage |
18 | 16 | from eaa.tool.imaging.param_tuning import SetParameters |
@@ -543,222 +541,3 @@ def run_from_checkpoint(self) -> None: |
543 | 541 | self.run_feedback_loop_from_checkpoint( |
544 | 542 | hook_functions=self.active_feedback_hook_functions, |
545 | 543 | ) |
546 | | - |
547 | | - |
548 | | -class ParameterTuningTaskManager(BaseParameterTuningTaskManager): |
549 | | - |
550 | | - def __init__( |
551 | | - self, |
552 | | - llm_config: LLMConfig = None, |
553 | | - memory_config: Optional[MemoryManagerConfig] = None, |
554 | | - param_setting_tool: SetParameters = None, |
555 | | - acquisition_tool: AcquireImage = None, |
556 | | - initial_parameters: dict[str, float] = None, |
557 | | - parameter_ranges: list[tuple[float, ...], tuple[float, ...]] = None, |
558 | | - session_db_path: Optional[str] = "session.sqlite", |
559 | | - build: bool = True, |
560 | | - *args, **kwargs |
561 | | - ) -> None: |
562 | | - """An agent that searches for the best setup parameters |
563 | | - for an imaging system. |
564 | | -
|
565 | | - Parameters |
566 | | - ---------- |
567 | | - llm_config : LLMConfig |
568 | | - The configuration for the LLM. |
569 | | - memory_config : MemoryManagerConfig, optional |
570 | | - Memory configuration forwarded to the agent. |
571 | | - param_setting_tool : SetParameters |
572 | | - The tool to use to set the parameters. |
573 | | - acquisition_tool : SimulatedAcquireImage, optional |
574 | | - The tool to use to acquire images. This tool will |
575 | | - not be called by AI; it is executed automatically |
576 | | - following each parameter adjustment. |
577 | | - initial_parameters : dict[str, float], optional |
578 | | - The initial parameters given as a dictionary of |
579 | | - parameter names and values. |
580 | | - parameter_ranges : list[tuple[float, ...], tuple[float, ...]] |
581 | | - The ranges of the parameters. It should be given as a list of |
582 | | - 2 tuples, where the first tuple gives the lower bounds and the |
583 | | - second tuple gives the upper bounds. The order of the parameters |
584 | | - should match the order of the initial parameters. |
585 | | - session_db_path : Optional[str] |
586 | | - If provided, the entire chat history will be stored in |
587 | | - a SQLite database at the given path. This is essential |
588 | | - if you want to use the WebUI, which polls the database |
589 | | - for new messages. |
590 | | - """ |
591 | | - if "tools" in kwargs.keys(): |
592 | | - raise ValueError( |
593 | | - "`tools` should not be provided to `ParameterTuningTaskManager`. Instead, " |
594 | | - "provide the `param_setting_tool` and `acquisition_tool`." |
595 | | - ) |
596 | | - |
597 | | - self.acquisition_tool = acquisition_tool |
598 | | - |
599 | | - super().__init__( |
600 | | - llm_config=llm_config, |
601 | | - memory_config=memory_config, |
602 | | - param_setting_tool=param_setting_tool, |
603 | | - additional_tools=[param_setting_tool], |
604 | | - initial_parameters=initial_parameters, |
605 | | - parameter_ranges=parameter_ranges, |
606 | | - session_db_path=session_db_path, |
607 | | - build=build, |
608 | | - *args, **kwargs |
609 | | - ) |
610 | | - |
611 | | - def prerun_check(self, *args, **kwargs) -> bool: |
612 | | - if self.initial_parameters is None: |
613 | | - raise ValueError("initial_parameters must be provided.") |
614 | | - return super().prerun_check(*args, **kwargs) |
615 | | - |
616 | | - def run( |
617 | | - self, |
618 | | - acquisition_tool_kwargs: dict = {}, |
619 | | - n_last_images_to_keep: int = 3, |
620 | | - max_iters: int = 10, |
621 | | - initial_prompt: Optional[str] = None, |
622 | | - additional_prompt: Optional[str] = None, |
623 | | - ) -> None: |
624 | | - """Run the parameter tuning task. |
625 | | - |
626 | | - Parameters |
627 | | - ---------- |
628 | | - acquisition_tool_kwargs : dict |
629 | | - The arguments for the acquisition tool. These arguments will be |
630 | | - used to acquire images for evaluation. |
631 | | - n_last_images_to_keep : int, optional |
632 | | - The number of most recent images to keep in the context. Having past |
633 | | - images in the context allows to agent to "remember" images it |
634 | | - has seen before; however, it also increases the context size |
635 | | - and inference cost. |
636 | | - max_iters : int, optional |
637 | | - The maximum number of iterations to run. |
638 | | - initial_prompt : str, optional |
639 | | - If provided, this prompt will override the default initial prompt. |
640 | | - additional_prompt : str, optional |
641 | | - If provided, this prompt will be added to the initial prompt (either |
642 | | - the default one or the one provided by `initial_prompt`). |
643 | | - """ |
644 | | - self.prerun_check() |
645 | | - |
646 | | - initial_parameter_values = list(self.initial_parameters.values()) |
647 | | - self.param_setting_tool.set_parameters(initial_parameter_values) |
648 | | - last_img_path = self.acquisition_tool.acquire_image(**acquisition_tool_kwargs) |
649 | | - |
650 | | - bounds_str = "" |
651 | | - for i, param in enumerate(self.parameter_names): |
652 | | - bounds_str += f"{param}: {self.parameter_ranges[0][i]} to {self.parameter_ranges[1][i]}\n" |
653 | | - |
654 | | - if initial_prompt is None: |
655 | | - initial_prompt = ( |
656 | | - f"You are tuning the parameters of a microscope to attain the best " |
657 | | - f"image sharpness. The parameters are {list(self.parameter_names)}, " |
658 | | - f"and their current values are {initial_parameter_values}. An image acquired " |
659 | | - f"with the current parameters is shown below.\n\n" |
660 | | - f"<img {last_img_path}>\n\n" |
661 | | - f"Here are the tunable ranges of the parameters:\n" |
662 | | - f"{bounds_str}\n" |
663 | | - f"You can change the parameters using your parameter setting tool. " |
664 | | - f"An image acquired with the new parameters will be given to you " |
665 | | - f"after each parameter change. Here are some detailed instructions:\n\n" |
666 | | - f"- Tune parameters one by one. Start with the first parameter, tweak it " |
667 | | - f"to attain the sharpest possible image, then move on to the next parameter. " |
668 | | - f"Do not change more than one parameter at a time.\n" |
669 | | - f"- The sharpness of the image is convex with regards to the parameters. There " |
670 | | - f"is only one optimal point; assume there is no local maximum. As such, if " |
671 | | - f"you find the image comes more blurry when changing a parameter in a direction, " |
672 | | - f"you should consider changing it the other way; if you find the image comes " |
673 | | - f"sharper when changing a parameter in a direction, you are on the right track.\n" |
674 | | - f"- For each parameter, first get a coarse estimate of the optimal value, then " |
675 | | - f"fine-tune it. To get a coarse estimate, look for a peak in the sharpness. In " |
676 | | - f"other words, find a parameter value that gives a sharper image than the value " |
677 | | - f"immediately before and after it. For example, if the image becomes sharper when " |
678 | | - f"you increase the parameter from 4 to 5, but becomes blurrier when you increase " |
679 | | - f"it from 5 to 6, then the optimal value is around 5.\n" |
680 | | - f"- Choose the step size for changing parameters wisely. For each parameter, start " |
681 | | - f"with a large step size, and decrease it as you get closer to the optimal point.\n" |
682 | | - f"- Only call the parameter setting tool one at a time. Do not call it multiple times " |
683 | | - f"in one response.\n\n" |
684 | | - f"When you finish or when you need human input, add \"TERMINATE\" to your response." |
685 | | - ) |
686 | | - if additional_prompt is not None: |
687 | | - initial_prompt += "\nAdditional instructions:\n" + additional_prompt |
688 | | - |
689 | | - round = 0 |
690 | | - response, outgoing = self.agent.receive( |
691 | | - initial_prompt, |
692 | | - context=self.context, |
693 | | - image_path=last_img_path, |
694 | | - return_outgoing_message=True |
695 | | - ) |
696 | | - self.update_message_history(outgoing, update_context=True, update_full_history=True) |
697 | | - self.update_message_history(response, update_context=True, update_full_history=True) |
698 | | - while round < max_iters: |
699 | | - if response["content"] is not None and "TERMINATE" in response["content"]: |
700 | | - message = self.get_user_input( |
701 | | - "Termination condition triggered. What to do next? Type \"/exit\" to exit. " |
702 | | - ) |
703 | | - if message.lower() == "/exit": |
704 | | - return |
705 | | - else: |
706 | | - response, outgoing = self.agent.receive( |
707 | | - message, |
708 | | - context=self.context, |
709 | | - image_path=None, |
710 | | - return_outgoing_message=True |
711 | | - ) |
712 | | - self.update_message_history(outgoing, update_context=True, update_full_history=True) |
713 | | - self.update_message_history(response, update_context=True, update_full_history=True) |
714 | | - continue |
715 | | - |
716 | | - tool_responses, tool_response_types = self.agent.handle_tool_call(response, return_tool_return_types=True) |
717 | | - if len(tool_responses) == 1: |
718 | | - tool_response = tool_responses[0] |
719 | | - tool_response_type = tool_response_types[0] |
720 | | - # Just save the tool response, but don't send yet. We will send it |
721 | | - # together with the image later. |
722 | | - print_message(tool_response) |
723 | | - self.update_message_history(tool_response, update_context=True, update_full_history=True) |
724 | | - |
725 | | - if tool_response_type == ToolReturnType.EXCEPTION: |
726 | | - response, outgoing = self.agent.receive( |
727 | | - "The tool returned an exception. Please fix the exception and try again.", |
728 | | - image_path=None, |
729 | | - context=self.context, |
730 | | - return_outgoing_message=True |
731 | | - ) |
732 | | - else: |
733 | | - # Acquire an image with the new parameters. |
734 | | - last_img_path = self.acquisition_tool.acquire_image(**acquisition_tool_kwargs) |
735 | | - response, outgoing = self.agent.receive( |
736 | | - "An image acquired with the new parameters is shown below.", |
737 | | - image_path=last_img_path, |
738 | | - context=self.context, |
739 | | - return_outgoing_message=True |
740 | | - ) |
741 | | - self.context = purge_context_images(self.context, keep_first_n=1, keep_last_n=n_last_images_to_keep - 1) |
742 | | - self.update_message_history(outgoing, update_context=True, update_full_history=True) |
743 | | - self.update_message_history(response, update_context=True, update_full_history=True) |
744 | | - elif len(tool_responses) > 1: |
745 | | - response, outgoing = self.agent.receive( |
746 | | - "There are more than one tool calls in your response. " |
747 | | - "Make sure you only make one call at a time. Please redo " |
748 | | - "your tool calls.", |
749 | | - image_path=None, |
750 | | - context=self.context, |
751 | | - return_outgoing_message=True |
752 | | - ) |
753 | | - self.update_message_history(outgoing, update_context=True, update_full_history=True) |
754 | | - self.update_message_history(response, update_context=True, update_full_history=True) |
755 | | - else: |
756 | | - response, outgoing = self.agent.receive( |
757 | | - "There is no tool call in the response. Make sure you call the tool correctly.", |
758 | | - image_path=None, |
759 | | - context=self.context, |
760 | | - return_outgoing_message=True |
761 | | - ) |
762 | | - self.update_message_history(outgoing, update_context=True, update_full_history=True) |
763 | | - self.update_message_history(response, update_context=True, update_full_history=True) |
764 | | - round += 1 |
0 commit comments