Source code for agentscope.service._code.exec_notebook
# -*- coding: utf-8 -*-# pylint: disable=C0301"""Service for executing jupyter notebooks interactivelyPartially referenced the implementation ofhttps://github.com/geekan/MetaGPT/blob/main/metagpt/actions/di/execute_nb_code.py"""importbase64importasynciofromloguruimportloggertry:importnbclientimportnbformatexceptImportError:nbclient=Nonenbformat=Nonefrom...managerimportFileManagerfrom..service_statusimportServiceExecStatusfrom..service_responseimportServiceResponse
[docs]classNoteBookExecutor:""" Class for executing jupyter notebooks block interactively. To use the service function, you should first init the class, then call the run_code_on_notebook function. Example: ```ipython from agentscope.service.service_toolkit import * from agentscope.service._code.exec_notebook import * nbe = NoteBookExecutor() code = "print('helloworld')" # calling directly nbe.run_code_on_notebook(code) >>> Executing function run_code_on_notebook with arguments: >>> code: print('helloworld') >>> END # calling with service toolkit service_toolkit = ServiceToolkit() service_toolkit.add(nbe.run_code_on_notebook) input_obs = [{"name": "run_code_on_notebook", "arguments":{"code": code}}] res_of_string_input = service_toolkit.parse_and_call_func(input_obs) "1. Execute function run_code_on_notebook\n [ARGUMENTS]:\n code: print('helloworld')\n [STATUS]: SUCCESS\n [RESULT]: ['helloworld\\n']\n" ``` """# noqadef__init__(self,timeout:int=300,)->None:""" The construct function of the NoteBookExecutor. Args: timeout (Optional`int`): The timeout for each cell execution. Default to 300. """ifnbclientisNoneornbformatisNone:raiseImportError("The package nbclient or nbformat is not found. Please ""install it by `pip install notebook nbclient nbformat`",)self.nb=nbformat.v4.new_notebook()self.nb_client=nbclient.NotebookClient(nb=self.nb)self.timeout=timeoutasyncio.run(self._start_client())def_output_parser(self,output:dict)->str:"""Parse the output of the notebook cell and return str"""ifoutput["output_type"]=="stream":returnoutput["text"]elifoutput["output_type"]=="execute_result":returnoutput["data"]["text/plain"]elifoutput["output_type"]=="display_data":if"image/png"inoutput["data"]:file_path=self._save_image(output["data"]["image/png"])returnf"Displayed image saved to {file_path}"else:return"Unsupported display type"elifoutput["output_type"]=="error":returnoutput["traceback"]else:logger.info(f"Unsupported output encountered: {output}")return"Unsupported output encountered"asyncdef_start_client(self)->None:"""start notebook client"""ifself.nb_client.kcisNoneornotawaitself.nb_client.kc.is_alive():self.nb_client.create_kernel_manager()self.nb_client.start_new_kernel()self.nb_client.start_new_kernel_client()asyncdef_kill_client(self)->None:"""kill notebook client"""if(self.nb_client.kmisnotNoneandawaitself.nb_client.km.is_alive()):awaitself.nb_client.km.shutdown_kernel(now=True)awaitself.nb_client.km.cleanup_resources()self.nb_client.kc.stop_channels()self.nb_client.kc=Noneself.nb_client.km=Noneasyncdef_restart_client(self)->None:"""Restart the notebook client"""awaitself._kill_client()self.nb_client=nbclient.NotebookClient(self.nb,timeout=self.timeout)awaitself._start_client()asyncdef_run_cell(self,cell_index:int)->ServiceResponse:"""Run a cell in the notebook by its index"""try:self.nb_client.execute_cell(self.nb.cells[cell_index],cell_index)returnServiceResponse(status=ServiceExecStatus.SUCCESS,content=[self._output_parser(output)foroutputinself.nb.cells[cell_index].outputs],)exceptnbclient.exceptions.DeadKernelError:awaitself.reset()returnServiceResponse(status=ServiceExecStatus.ERROR,content="DeadKernelError when executing cell, reset kernel",)exceptnbclient.exceptions.CellTimeoutError:assertself.nb_client.kmisnotNoneawaitself.nb_client.km.interrupt_kernel()returnServiceResponse(status=ServiceExecStatus.ERROR,content=("CellTimeoutError when executing cell"", code execution timeout"),)exceptExceptionase:returnServiceResponse(status=ServiceExecStatus.ERROR,content=str(e),)@propertydefcells_length(self)->int:"""return cell length"""returnlen(self.nb.cells)
[docs]asyncdefasync_run_code_on_notebook(self,code:str)->ServiceResponse:""" Run the code on interactive notebook """self.nb.cells.append(nbformat.v4.new_code_cell(code))cell_index=self.cells_length-1returnawaitself._run_cell(cell_index)
[docs]defrun_code_on_notebook(self,code:str)->ServiceResponse:""" Run the code on interactive jupyter notebook. Args: code (`str`): The Python code to be executed in the interactive notebook. Returns: `ServiceResponse`: whether the code execution was successful, and the output of the code execution. """returnasyncio.run(self.async_run_code_on_notebook(code))
[docs]defreset_notebook(self)->ServiceResponse:""" Reset the notebook """asyncio.run(self._restart_client())returnServiceResponse(status=ServiceExecStatus.SUCCESS,content="Reset notebook",)
def_save_image(self,image_base64:str)->str:"""Save image data to a file. The image name is generated randomly here"""image_data=base64.b64decode(image_base64)file_manager=FileManager.get_instance()returnfile_manager.save_image(image_data)