CoolFace
Apppublic

chenxc1029/Local-Code-Interpreter

sourceHugging Faceupdated 3y agoView on Hugging Face
1likes
bot_backend.py237 linesDownload Raw Back to root
1import json2import openai3import os4import copy5import shutil6from jupyter_backend import *7from typing import *8 9functions = [10    {11        "name": "execute_code",12        "description": "This function allows you to execute Python code and retrieve the terminal output. If the code "13                       "generates image output, the function will return the text '[image]'. The code is sent to a "14                       "Jupyter kernel for execution. The kernel will remain active after execution, retaining all "15                       "variables in memory.",16        "parameters": {17            "type": "object",18            "properties": {19                "code": {20                    "type": "string",21                    "description": "The code text"22                }23            },24            "required": ["code"],25        }26    }27]28 29system_msg = '''You are an AI code interpreter.30Your goal is to help users do a variety of jobs by executing Python code.31 32You should:331. Comprehend the user's requirements carefully & 34 35 36 37to the letter. 382. Give a brief description for what you plan to do & call the execute_code function to run code393. Provide results analysis based on the execution output. 404. If error occurred, try to fix it.41 42Note: If the user uploads a file, you will receive a system message "User uploaded a file: filename". Use the filename as the path in the code. '''43 44with open('config.json') as f:45    config = json.load(f)46 47if not config['API_KEY']:48    config['API_KEY'] = os.getenv('OPENAI_API_KEY')49    os.unsetenv('OPENAI_API_KEY')50 51 52def get_config():53    return config54 55 56def config_openai_api(api_type, api_base, api_version, api_key):57    openai.api_type = api_type58    openai.api_base = api_base59    openai.api_version = api_version60    openai.api_key = api_key61 62 63class GPTResponseLog:64    def __init__(self):65        self.assistant_role_name = ''66        self.content = ''67        self.function_name = None68        self.function_args_str = ''69        self.display_code_block = ''70        self.finish_reason = 'stop'71        self.bot_history = None72 73    def reset_gpt_response_log_values(self, exclude=None):74        if exclude is None:75            exclude = []76 77        attributes = {'assistant_role_name': '',78                      'content': '',79                      'function_name': None,80                      'function_args_str': '',81                      'display_code_block': '',82                      'finish_reason': 'stop',83                      'bot_history': None}84 85        for attr_name in exclude:86            del attributes[attr_name]87        for attr_name, value in attributes.items():88            setattr(self, attr_name, value)89 90    def set_assistant_role_name(self, assistant_role_name: str):91        self.assistant_role_name = assistant_role_name92 93    def add_content(self, content: str):94        self.content += content95 96    def set_function_name(self, function_name: str):97        self.function_name = function_name98 99    def copy_current_bot_history(self, bot_history: List):100        self.bot_history = copy.deepcopy(bot_history)101 102    def add_function_args_str(self, function_args_str: str):103        self.function_args_str += function_args_str104 105    def update_display_code_block(self, display_code_block):106        self.display_code_block = display_code_block107 108    def update_finish_reason(self, finish_reason: str):109        self.finish_reason = finish_reason110 111 112class BotBackend(GPTResponseLog):113    def __init__(self):114        super().__init__()115        self.unique_id = hash(id(self))116        self.jupyter_work_dir = f'cache/work_dir_{self.unique_id}'117        self.jupyter_kernel = JupyterKernel(work_dir=self.jupyter_work_dir)118        self.gpt_model_choice = "GPT-3.5"119        self.revocable_files = []120        self._init_conversation()121        self._init_api_config()122        self._init_kwargs_for_chat_completion()123 124    def _init_conversation(self):125        first_system_msg = {'role': 'system', 'content': system_msg}126        if hasattr(self, 'conversation'):127            self.conversation.clear()128            self.conversation.append(first_system_msg)129        else:130            self.conversation: List[Dict] = [first_system_msg]131 132    def _init_api_config(self):133        self.config = get_config()134        api_type = self.config['API_TYPE']135        api_base = self.config['API_base']136        api_version = self.config['API_VERSION']137        api_key = config['API_KEY']138        config_openai_api(api_type, api_base, api_version, api_key)139 140    def _init_kwargs_for_chat_completion(self):141        self.kwargs_for_chat_completion = {142            'stream': True,143            'messages': self.conversation,144            'functions': functions,145            'function_call': 'auto'146        }147 148        model_name = self.config['model'][self.gpt_model_choice]['model_name']149 150        if self.config['API_TYPE'] == 'azure':151            self.kwargs_for_chat_completion['engine'] = model_name152        else:153            self.kwargs_for_chat_completion['model'] = model_name154 155    def _clear_all_files_in_work_dir(self):156        for filename in os.listdir(self.jupyter_work_dir):157            os.remove(158                os.path.join(self.jupyter_work_dir, filename)159            )160 161    def add_gpt_response_content_message(self):162        self.conversation.append(163            {'role': self.assistant_role_name, 'content': self.content}164        )165 166    def add_text_message(self, user_text):167        self.conversation.append(168            {'role': 'user', 'content': user_text}169        )170        self.revocable_files.clear()171        self.update_finish_reason(finish_reason='new_input')172 173    def add_file_message(self, path, bot_msg):174        filename = os.path.basename(path)175        work_dir = self.jupyter_work_dir176 177        shutil.copy(path, work_dir)178 179        gpt_msg = {'role': 'system', 'content': f'User uploaded a file: {filename}'}180        self.conversation.append(gpt_msg)181        self.revocable_files.append(182            {183                'bot_msg': bot_msg,184                'gpt_msg': gpt_msg,185                'path': os.path.join(work_dir, filename)186            }187        )188 189    def add_function_call_response_message(self, function_response: str, save_tokens=True):190        self.conversation.append(191            {192                "role": self.assistant_role_name,193                "name": self.function_name,194                "content": self.function_args_str195            }196        )197 198        if save_tokens and len(function_response) > 500:199            function_response = f'{function_response[:200]}\n[Output too much, the middle part output is omitted]\n ' \200                                f'End part of output:\n{function_response[-200:]}'201        self.conversation.append(202            {203                "role": "function",204                "name": self.function_name,205                "content": function_response,206            }207        )208 209    def revoke_file(self):210        if self.revocable_files:211            file = self.revocable_files[-1]212            bot_msg = file['bot_msg']213            gpt_msg = file['gpt_msg']214            path = file['path']215 216            assert self.conversation[-1] is gpt_msg217            del self.conversation[-1]218 219            os.remove(path)220 221            del self.revocable_files[-1]222 223            return bot_msg224        else:225            return None226 227    def update_gpt_model_choice(self, model_choice):228        self.gpt_model_choice = model_choice229        self._init_kwargs_for_chat_completion()230 231    def restart(self):232        self._clear_all_files_in_work_dir()233        self.revocable_files.clear()234        self._init_conversation()235        self.reset_gpt_response_log_values()236        self.jupyter_kernel.restart_jupyter_kernel()237