aphilippov/python-server-api
0
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 