Team Ai
Apppublic

aphilippov/python-server-api

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
0likes
agent_builder.py765 linesDownload Raw Back to contrib
1import autogen2import time3import subprocess as sp4import socket5import json6import hashlib7from typing import Optional, List, Dict, Tuple8 9 10def _config_check(config: Dict):11    # check config loading12    assert config.get("coding", None) is not None, 'Missing "coding" in your config.'13    assert config.get("default_llm_config", None) is not None, 'Missing "default_llm_config" in your config.'14    assert config.get("code_execution_config", None) is not None, 'Missing "code_execution_config" in your config.'15 16    for agent_config in config["agent_configs"]:17        assert agent_config.get("name", None) is not None, 'Missing agent "name" in your agent_configs.'18        assert agent_config.get("model", None) is not None, 'Missing agent "model" in your agent_configs.'19        assert (20            agent_config.get("system_message", None) is not None21        ), 'Missing agent "system_message" in your agent_configs.'22        assert agent_config.get("description", None) is not None, 'Missing agent "description" in your agent_configs.'23 24 25class AgentBuilder:26    """27    AgentBuilder can help user build an automatic task solving process powered by multi-agent system.28    Specifically, our building pipeline includes initialize and build.29    In build(), we prompt a LLM to create multiple participant agents, and specify whether this task need programming to solve.30    User can save the built agents' config by calling save(), and load the saved configs by load(), which can skip the31        building process.32    """33 34    online_server_name = "online"35 36    CODING_PROMPT = """Does the following task need programming (i.e., access external API or tool by coding) to solve,37    or coding may help the following task become easier?38 39    TASK: {task}40 41    Hint:42    # Answer only YES or NO.43    """44 45    AGENT_NAME_PROMPT = """To complete the following task, what positions/jobs should be set to maximize efficiency?46 47    TASK: {task}48 49    Hint:50    # Considering the effort, the position in this task should be no more than {max_agents}; less is better.51    # These positions' name should include enough information that can help a group chat manager know when to let this position speak.52    # The position name should be as specific as possible. For example, use "python_programmer" instead of "programmer".53    # Do not use ambiguous position name, such as "domain expert" with no specific description of domain or "technical writer" with no description of what it should write.54    # Each position should have a unique function and the position name should reflect this.55    # The positions should relate to the task and significantly different in function.56    # Add ONLY ONE programming related position if the task needs coding.57    # Generated agent's name should follow the format of ^[a-zA-Z0-9_-]{{1,64}}$, use "_" to split words.58    # Answer the names of those positions/jobs, separated names by commas.59    # Only return the list of positions.60    """61 62    AGENT_SYS_MSG_PROMPT = """Considering the following position and task:63 64    TASK: {task}65    POSITION: {position}66 67    Modify the following position requirement, making it more suitable for the above task and position:68 69    REQUIREMENT: {default_sys_msg}70 71    Hint:72    # Your answer should be natural, starting from "You are now in a group chat. You need to complete a task with other participants. As a ...".73    # [IMPORTANT] You should let them reply "TERMINATE" when they think the task is completed (the user's need has actually been satisfied).74    # The modified requirement should not contain the code interpreter skill.75    # You should remove the related skill description when the position is not a programmer or developer.76    # Coding skill is limited to Python.77    # Your answer should omit the word "REQUIREMENT".78    # People with the above position can doubt previous messages or code in the group chat (for example, if there is no79output after executing the code) and provide a corrected answer or code.80    # People in the above position should ask for help from the group chat manager when confused and let the manager select another participant.81    """82 83    AGENT_DESCRIPTION_PROMPT = """Considering the following position:84 85    POSITION: {position}86 87    What requirements should this position be satisfied?88 89    Hint:90    # This description should include enough information that can help a group chat manager know when to let this position speak.91    # People with the above position can doubt previous messages or code in the group chat (for example, if there is no92output after executing the code) and provide a corrected answer or code.93    # Your answer should be in at most three sentences.94    # Your answer should be natural, starting from "[POSITION's name] is a ...".95    # Your answer should include the skills that this position should have.96    # Your answer should not contain coding-related skills when the position is not a programmer or developer.97    # Coding skills should be limited to Python.98    """99 100    AGENT_SEARCHING_PROMPT = """Considering the following task:101 102    TASK: {task}103 104    What following agents should be involved to the task?105 106    AGENT LIST:107    {agent_list}108 109    Hint:110    # You should consider if the agent's name and profile match the task.111    # Considering the effort, you should select less then {max_agents} agents; less is better.112    # Separate agent names by commas and use "_" instead of space. For example, Product_manager,Programmer113    # Only return the list of agent names.114    """115 116    def __init__(117        self,118        config_file_or_env: Optional[str] = "OAI_CONFIG_LIST",119        config_file_location: Optional[str] = "",120        builder_model: Optional[str] = "gpt-4",121        agent_model: Optional[str] = "gpt-4",122        host: Optional[str] = "localhost",123        endpoint_building_timeout: Optional[int] = 600,124        max_tokens: Optional[int] = 945,125        max_agents: Optional[int] = 5,126    ):127        """128        (These APIs are experimental and may change in the future.)129        Args:130            config_file_or_env: path or environment of the OpenAI api configs.131            builder_model: specify a model as the backbone of build manager.132            agent_model: specify a model as the backbone of participant agents.133            host: endpoint host.134            endpoint_building_timeout: timeout for building up an endpoint server.135            max_tokens: max tokens for each agent.136            max_agents: max agents for each task.137        """138        self.host = host139        self.builder_model = builder_model140        self.agent_model = agent_model141        self.config_file_or_env = config_file_or_env142        self.config_file_location = config_file_location143        self.endpoint_building_timeout = endpoint_building_timeout144 145        self.building_task: str = None146        self.agent_configs: List[Dict] = []147        self.open_ports: List[str] = []148        self.agent_procs: Dict[str, Tuple[sp.Popen, str]] = {}149        self.agent_procs_assign: Dict[str, Tuple[autogen.ConversableAgent, str]] = {}150        self.cached_configs: Dict = {}151 152        self.max_tokens = max_tokens153        self.max_agents = max_agents154 155        for port in range(8000, 65535):156            if self._is_port_open(host, port):157                self.open_ports.append(str(port))158 159    def set_builder_model(self, model: str):160        self.builder_model = model161 162    def set_agent_model(self, model: str):163        self.agent_model = model164 165    @staticmethod166    def _is_port_open(host, port):167        """Check if a tcp port is open."""168        try:169            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)170            s.settimeout(10)171            s.bind((host, int(port)))172            s.close()173            return True174        except OSError:175            return False176 177    def _create_agent(178        self,179        agent_name: str,180        model_name_or_hf_repo: str,181        llm_config: dict,182        system_message: Optional[str] = autogen.AssistantAgent.DEFAULT_SYSTEM_MESSAGE,183        description: Optional[str] = autogen.AssistantAgent.DEFAULT_DESCRIPTION,184        use_oai_assistant: Optional[bool] = False,185        world_size: Optional[int] = 1,186    ) -> autogen.AssistantAgent:187        """188        Create a group chat participant agent.189 190        If the agent rely on an open-source model, this function will automatically set up an endpoint for that agent.191        The API address of that endpoint will be "localhost:{free port}".192 193        Args:194            agent_name: the name that identify the function of the agent (e.g., Coder, Product Manager,...)195            model_name_or_hf_repo: the name of the model or the huggingface repo.196            llm_config: specific configs for LLM (e.g., config_list, seed, temperature, ...).197            system_message: system prompt use to format an agent's behavior.198            description: a brief description of the agent. This will improve the group chat performance.199            use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.200            world_size: the max size of parallel tensors (in most of the cases, this is identical to the amount of GPUs).201 202        Returns:203            agent: a set-up agent.204        """205        from huggingface_hub import HfApi206        from huggingface_hub.utils import GatedRepoError, RepositoryNotFoundError207 208        config_list = autogen.config_list_from_json(209            self.config_file_or_env,210            file_location=self.config_file_location,211            filter_dict={"model": [model_name_or_hf_repo]},212        )213        if len(config_list) == 0:214            raise RuntimeError(215                f"Fail to initialize agent {agent_name}: {model_name_or_hf_repo} does not exist in {self.config_file_or_env}.\n"216                f'If you would like to change this model, please specify the "agent_model" in the constructor.\n'217                f"If you load configs from json, make sure the model in agent_configs is in the {self.config_file_or_env}."218            )219        try:220            hf_api = HfApi()221            hf_api.model_info(model_name_or_hf_repo)222            model_name = model_name_or_hf_repo.split("/")[-1]223            server_id = f"{model_name}_{self.host}"224        except GatedRepoError as e:225            raise e226        except RepositoryNotFoundError:227            server_id = self.online_server_name228 229        if server_id != self.online_server_name:230            # The code in this block is uncovered by tests because online environment does not support gpu use.231            if self.agent_procs.get(server_id, None) is None:232                while True:233                    port = self.open_ports.pop()234                    if self._is_port_open(self.host, port):235                        break236 237                # Use vLLM to set up a server with OpenAI API support.238                agent_proc = sp.Popen(239                    [240                        "python",241                        "-m",242                        "vllm.entrypoints.openai.api_server",243                        "--host",244                        f"{self.host}",245                        "--port",246                        f"{port}",247                        "--model",248                        f"{model_name_or_hf_repo}",249                        "--tensor-parallel-size",250                        f"{world_size}",251                    ],252                    stdout=sp.PIPE,253                    stderr=sp.STDOUT,254                )255                timeout_start = time.time()256 257                while True:258                    server_stdout = agent_proc.stdout.readline()259                    if server_stdout != b"":260                        print(server_stdout)261                    timeout_end = time.time()262                    if b"running" in server_stdout:263                        print(264                            f"Running {model_name_or_hf_repo} on http://{self.host}:{port} "265                            f"with tensor parallel size {world_size}."266                        )267                        break268                    elif b"address already in use" in server_stdout:269                        raise RuntimeError(270                            f"{self.host}:{port} already in use. Fail to set up the endpoint for "271                            f"{model_name_or_hf_repo} on {self.host}:{port}."272                        )273                    elif timeout_end - timeout_start > self.endpoint_building_timeout:274                        raise RuntimeError(275                            f"Timeout exceed. Fail to set up the endpoint for "276                            f"{model_name_or_hf_repo} on {self.host}:{port}."277                        )278                self.agent_procs[server_id] = (agent_proc, port)279            else:280                port = self.agent_procs[server_id][1]281 282            config_list[0]["base_url"] = f"http://{self.host}:{port}/v1"283 284        current_config = llm_config.copy()285        current_config.update(286            {"config_list": config_list, "model": model_name_or_hf_repo, "max_tokens": self.max_tokens}287        )288        if use_oai_assistant:289            from autogen.agentchat.contrib.gpt_assistant_agent import GPTAssistantAgent290 291            agent = GPTAssistantAgent(292                name=agent_name,293                llm_config={**current_config, "assistant_id": None},294                instructions=system_message,295                overwrite_instructions=False,296            )297        else:298            agent = autogen.AssistantAgent(299                name=agent_name,300                llm_config=current_config.copy(),301                system_message=system_message,302                description=description,303            )304        self.agent_procs_assign[agent_name] = (agent, server_id)305        return agent306 307    def clear_agent(self, agent_name: str, recycle_endpoint: Optional[bool] = True):308        """309        Clear a specific agent by name.310 311        Args:312            agent_name: the name of agent.313            recycle_endpoint: trigger for recycle the endpoint server. If true, the endpoint will be recycled314                when there is no agent depending on.315        """316        _, server_id = self.agent_procs_assign[agent_name]317        del self.agent_procs_assign[agent_name]318        if recycle_endpoint:319            if server_id == self.online_server_name:320                return321            else:322                for _, iter_sid in self.agent_procs_assign.values():323                    if server_id == iter_sid:324                        return325                self.agent_procs[server_id][0].terminate()326                self.open_ports.append(server_id.split("_")[-1])327        print(f"Agent {agent_name} has been cleared.")328 329    def clear_all_agents(self, recycle_endpoint: Optional[bool] = True):330        """331        Clear all cached agents.332        """333        for agent_name in [agent_name for agent_name in self.agent_procs_assign.keys()]:334            self.clear_agent(agent_name, recycle_endpoint)335        print("All agents have been cleared.")336 337    def build(338        self,339        building_task: str,340        default_llm_config: Dict,341        coding: Optional[bool] = None,342        code_execution_config: Optional[Dict] = None,343        use_oai_assistant: Optional[bool] = False,344        **kwargs,345    ) -> Tuple[List[autogen.ConversableAgent], Dict]:346        """347        Auto build agents based on the building task.348 349        Args:350            building_task: instruction that helps build manager (gpt-4) to decide what agent should be built.351            coding: use to identify if the user proxy (a code interpreter) should be added.352            code_execution_config: specific configs for user proxy (e.g., last_n_messages, work_dir, ...).353            default_llm_config: specific configs for LLM (e.g., config_list, seed, temperature, ...).354            use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.355 356        Returns:357            agent_list: a list of agents.358            cached_configs: cached configs.359        """360        if code_execution_config is None:361            code_execution_config = {362                "last_n_messages": 2,363                "work_dir": "groupchat",364                "use_docker": False,365                "timeout": 60,366            }367 368        agent_configs = []369        self.building_task = building_task370 371        config_list = autogen.config_list_from_json(372            self.config_file_or_env,373            file_location=self.config_file_location,374            filter_dict={"model": [self.builder_model]},375        )376        if len(config_list) == 0:377            raise RuntimeError(378                f"Fail to initialize build manager: {self.builder_model} does not exist in {self.config_file_or_env}. "379                f'If you want to change this model, please specify the "builder_model" in the constructor.'380            )381        build_manager = autogen.OpenAIWrapper(config_list=config_list)382 383        print("==> Generating agents...")384        resp_agent_name = (385            build_manager.create(386                messages=[387                    {388                        "role": "user",389                        "content": self.AGENT_NAME_PROMPT.format(task=building_task, max_agents=self.max_agents),390                    }391                ]392            )393            .choices[0]394            .message.content395        )396        agent_name_list = [agent_name.strip().replace(" ", "_") for agent_name in resp_agent_name.split(",")]397        print(f"{agent_name_list} are generated.")398 399        print("==> Generating system message...")400        agent_sys_msg_list = []401        for name in agent_name_list:402            print(f"Preparing system message for {name}")403            resp_agent_sys_msg = (404                build_manager.create(405                    messages=[406                        {407                            "role": "user",408                            "content": self.AGENT_SYS_MSG_PROMPT.format(409                                task=building_task,410                                position=name,411                                default_sys_msg=autogen.AssistantAgent.DEFAULT_SYSTEM_MESSAGE,412                            ),413                        }414                    ]415                )416                .choices[0]417                .message.content418            )419            agent_sys_msg_list.append(resp_agent_sys_msg)420 421        print("==> Generating description...")422        agent_description_list = []423        for name in agent_name_list:424            print(f"Preparing description for {name}")425            resp_agent_description = (426                build_manager.create(427                    messages=[428                        {429                            "role": "user",430                            "content": self.AGENT_DESCRIPTION_PROMPT.format(position=name),431                        }432                    ]433                )434                .choices[0]435                .message.content436            )437            agent_description_list.append(resp_agent_description)438 439        for name, sys_msg, description in list(zip(agent_name_list, agent_sys_msg_list, agent_description_list)):440            agent_configs.append(441                {"name": name, "model": self.agent_model, "system_message": sys_msg, "description": description}442            )443 444        if coding is None:445            resp = (446                build_manager.create(447                    messages=[{"role": "user", "content": self.CODING_PROMPT.format(task=building_task)}]448                )449                .choices[0]450                .message.content451            )452            coding = True if resp == "YES" else False453 454        self.cached_configs.update(455            {456                "building_task": building_task,457                "agent_configs": agent_configs,458                "coding": coding,459                "default_llm_config": default_llm_config,460                "code_execution_config": code_execution_config,461            }462        )463 464        return self._build_agents(use_oai_assistant, **kwargs)465 466    def build_from_library(467        self,468        building_task: str,469        library_path_or_json: str,470        default_llm_config: Dict,471        coding: Optional[bool] = True,472        code_execution_config: Optional[Dict] = None,473        use_oai_assistant: Optional[bool] = False,474        embedding_model: Optional[str] = None,475        **kwargs,476    ) -> Tuple[List[autogen.ConversableAgent], Dict]:477        """478        Build agents from a library.479        The library is a list of agent configs, which contains the name and system_message for each agent.480        We use a build manager to decide what agent in that library should be involved to the task.481 482        Args:483            building_task: instruction that helps build manager (gpt-4) to decide what agent should be built.484            library_path_or_json: path or JSON string config of agent library.485            default_llm_config: specific configs for LLM (e.g., config_list, seed, temperature, ...).486            coding: use to identify if the user proxy (a code interpreter) should be added.487            code_execution_config: specific configs for user proxy (e.g., last_n_messages, work_dir, ...).488            use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.489            embedding_model: a Sentence-Transformers model use for embedding similarity to select agents from library.490                if None, an openai model will be prompted to select agents. As reference, chromadb use "all-mpnet-base-491                v2" as default.492 493        Returns:494            agent_list: a list of agents.495            cached_configs: cached configs.496        """497        import chromadb498        from chromadb.utils import embedding_functions499 500        if code_execution_config is None:501            code_execution_config = {502                "last_n_messages": 2,503                "work_dir": "groupchat",504                "use_docker": False,505                "timeout": 60,506            }507 508        agent_configs = []509 510        config_list = autogen.config_list_from_json(511            self.config_file_or_env,512            file_location=self.config_file_location,513            filter_dict={"model": [self.builder_model]},514        )515        if len(config_list) == 0:516            raise RuntimeError(517                f"Fail to initialize build manager: {self.builder_model} does not exist in {self.config_file_or_env}. "518                f'If you want to change this model, please specify the "builder_model" in the constructor.'519            )520        build_manager = autogen.OpenAIWrapper(config_list=config_list)521 522        try:523            agent_library = json.loads(library_path_or_json)524        except json.decoder.JSONDecodeError:525            with open(library_path_or_json, "r") as f:526                agent_library = json.load(f)527 528        print("==> Looking for suitable agents in library...")529        if embedding_model is not None:530            chroma_client = chromadb.Client()531            collection = chroma_client.create_collection(532                name="agent_list",533                embedding_function=embedding_functions.SentenceTransformerEmbeddingFunction(model_name=embedding_model),534            )535            collection.add(536                documents=[agent["profile"] for agent in agent_library],537                metadatas=[{"source": "agent_profile"} for _ in range(len(agent_library))],538                ids=[f"agent_{i}" for i in range(len(agent_library))],539            )540            agent_profile_list = collection.query(query_texts=[building_task], n_results=self.max_agents)["documents"][541                0542            ]543 544            # search name from library545            agent_name_list = []546            for profile in agent_profile_list:547                for agent in agent_library:548                    if agent["profile"] == profile:549                        agent_name_list.append(agent["name"])550                        break551            chroma_client.delete_collection(collection.name)552            print(f"{agent_name_list} are selected.")553        else:554            agent_profiles = [555                f"No.{i + 1} AGENT's NAME: {agent['name']}\nNo.{i + 1} AGENT's PROFILE: {agent['profile']}\n\n"556                for i, agent in enumerate(agent_library)557            ]558            resp_agent_name = (559                build_manager.create(560                    messages=[561                        {562                            "role": "user",563                            "content": self.AGENT_SEARCHING_PROMPT.format(564                                task=building_task, agent_list="".join(agent_profiles), max_agents=self.max_agents565                            ),566                        }567                    ]568                )569                .choices[0]570                .message.content571            )572            agent_name_list = [agent_name.strip().replace(" ", "_") for agent_name in resp_agent_name.split(",")]573 574            # search profile from library575            agent_profile_list = []576            for name in agent_name_list:577                for agent in agent_library:578                    if agent["name"] == name:579                        agent_profile_list.append(agent["profile"])580                        break581            print(f"{agent_name_list} are selected.")582 583        print("==> Generating system message...")584        # generate system message from profile585        agent_sys_msg_list = []586        for name, profile in list(zip(agent_name_list, agent_profile_list)):587            print(f"Preparing system message for {name}...")588            resp_agent_sys_msg = (589                build_manager.create(590                    messages=[591                        {592                            "role": "user",593                            "content": self.AGENT_SYS_MSG_PROMPT.format(594                                task=building_task,595                                position=f"{name}\nPOSITION PROFILE: {profile}",596                                default_sys_msg=autogen.AssistantAgent.DEFAULT_SYSTEM_MESSAGE,597                            ),598                        }599                    ]600                )601                .choices[0]602                .message.content603            )604            agent_sys_msg_list.append(resp_agent_sys_msg)605 606        for name, sys_msg, description in list(zip(agent_name_list, agent_sys_msg_list, agent_profile_list)):607            agent_configs.append(608                {"name": name, "model": self.agent_model, "system_message": sys_msg, "description": description}609            )610 611        if coding is None:612            resp = (613                build_manager.create(614                    messages=[{"role": "user", "content": self.CODING_PROMPT.format(task=building_task)}]615                )616                .choices[0]617                .message.content618            )619            coding = True if resp == "YES" else False620 621        self.cached_configs.update(622            {623                "building_task": building_task,624                "agent_configs": agent_configs,625                "coding": coding,626                "default_llm_config": default_llm_config,627                "code_execution_config": code_execution_config,628            }629        )630 631        return self._build_agents(use_oai_assistant, **kwargs)632 633    def _build_agents(634        self, use_oai_assistant: Optional[bool] = False, **kwargs635    ) -> Tuple[List[autogen.ConversableAgent], Dict]:636        """637        Build agents with generated configs.638 639        Args:640            use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.641 642        Returns:643            agent_list: a list of agents.644            cached_configs: cached configs.645        """646        agent_configs = self.cached_configs["agent_configs"]647        default_llm_config = self.cached_configs["default_llm_config"]648        coding = self.cached_configs["coding"]649        code_execution_config = self.cached_configs["code_execution_config"]650 651        print("==> Creating agents...")652        for config in agent_configs:653            print(f"Creating agent {config['name']} with backbone {config['model']}...")654            self._create_agent(655                config["name"],656                config["model"],657                default_llm_config,658                system_message=config["system_message"],659                description=config["description"],660                use_oai_assistant=use_oai_assistant,661                **kwargs,662            )663        agent_list = [agent_config[0] for agent_config in self.agent_procs_assign.values()]664 665        if coding is True:666            print("Adding user console proxy...")667            agent_list = (668                [669                    autogen.UserProxyAgent(670                        name="User_console_and_code_interpreter",671                        is_termination_msg=lambda x: "TERMINATE" in x.get("content"),672                        system_message="User console with a python code interpreter interface.",673                        description="""A user console with a code interpreter interface.674It can provide the code execution results. Select this player when other players provide some code that needs to be executed.675DO NOT SELECT THIS PLAYER WHEN NO CODE TO EXECUTE; IT WILL NOT ANSWER ANYTHING.""",676                        code_execution_config=code_execution_config,677                        human_input_mode="NEVER",678                    )679                ]680                + agent_list681            )682 683        return agent_list, self.cached_configs.copy()684 685    def save(self, filepath: Optional[str] = None) -> str:686        """687        Save building configs. If the filepath is not specific, this function will create a filename by encrypt the688        building_task string by md5 with "save_config_" prefix, and save config to the local path.689 690        Args:691            filepath: save path.692 693        Return:694            filepath: path save.695        """696        if filepath is None:697            filepath = f'./save_config_{hashlib.md5(self.building_task.encode("utf-8")).hexdigest()}.json'698        with open(filepath, "w") as save_file:699            json.dump(self.cached_configs, save_file, indent=4)700        print(f"Building config saved to {filepath}")701 702        return filepath703 704    def load(705        self,706        filepath: Optional[str] = None,707        config_json: Optional[str] = None,708        use_oai_assistant: Optional[bool] = False,709        **kwargs,710    ) -> Tuple[List[autogen.ConversableAgent], Dict]:711        """712        Load building configs and call the build function to complete building without calling online LLMs' api.713 714        Args:715            filepath: filepath or JSON string for the save config.716            config_json: JSON string for the save config.717            use_oai_assistant: use OpenAI assistant api instead of self-constructed agent.718 719        Returns:720            agent_list: a list of agents.721            cached_configs: cached configs.722        """723        # load json string.724        if config_json is not None:725            print("Loading config from JSON...")726            cached_configs = json.loads(config_json)727 728        # load from path.729        if filepath is not None:730            print(f"Loading config from {filepath}")731            with open(filepath) as f:732                cached_configs = json.load(f)733 734        _config_check(cached_configs)735 736        agent_configs = cached_configs["agent_configs"]737        default_llm_config = cached_configs["default_llm_config"]738        coding = cached_configs["coding"]739 740        if kwargs.get("code_execution_config", None) is not None:741            # for test742            self.cached_configs.update(743                {744                    "building_task": cached_configs["building_task"],745                    "agent_configs": agent_configs,746                    "coding": coding,747                    "default_llm_config": default_llm_config,748                    "code_execution_config": kwargs["code_execution_config"],749                }750            )751            del kwargs["code_execution_config"]752            return self._build_agents(use_oai_assistant, **kwargs)753        else:754            code_execution_config = cached_configs["code_execution_config"]755            self.cached_configs.update(756                {757                    "building_task": cached_configs["building_task"],758                    "agent_configs": agent_configs,759                    "coding": coding,760                    "default_llm_config": default_llm_config,761                    "code_execution_config": code_execution_config,762                }763            )764            return self._build_agents(use_oai_assistant, **kwargs)765