{"repo": "b-lala/gpt-v1.0", "files": {"toolbox.py": {"cf3f571b334e0f6d47a3d7ad9522a38c39d966cc": {"t": 1785768952.798555, "n": 46921, "h": "ce3433cbb5a987ca", "c": "import markdown\nimport importlib\nimport time\nimport inspect\nimport re\nimport os\nimport base64\nimport gradio\nimport shutil\nimport glob\nimport math\nfrom latex2mathml.converter import convert as tex2mathml\nfrom functools import wraps, lru_cache\npj = os.path.join\ndefault_user_name = 'default_user'\n\"\"\"\n========================================================================\n第一部分\n函数插件输入输出接驳区\n - ChatBotWithCookies: 带Cookies的Chatbot类,为实现更多强大的功能做基础\n - ArgsGeneralWrapper: 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构\n - update_ui: 刷新界面用 yield from update_ui(chatbot, history)\n - CatchException: 将插件中出的所有问题显示在界面上\n - HotReload: 实现插件的热更新\n - trimmed_format_exc: 打印traceback,为了安全而隐藏绝对地址\n========================================================================\n\"\"\"\n\nclass ChatBotWithCookies(list):\n def __init__(self, cookie):\n \"\"\"\n cookies = {\n 'top_p': top_p,\n 'temperature': temperature,\n 'lock_plugin': bool,\n \"files_to_promote\": [\"file1\", \"file2\"],\n \"most_recent_uploaded\": {\n \"path\": \"uploaded_path\",\n \"time\": time.time(),\n \"time_str\": \"timestr\",\n }\n }\n \"\"\"\n self._cookies = cookie\n\n def write_list(self, list):\n for t in list:\n self.append(t)\n\n def get_list(self):\n return [t for t in self]\n\n def get_cookies(self):\n return self._cookies\n\n\ndef ArgsGeneralWrapper(f):\n \"\"\"\n 装饰器函数,用于重组输入参数,改变输入参数的顺序与结构。\n \"\"\"\n def decorated(request: gradio.Request, cookies, max_length, llm_model, txt, txt2, top_p, temperature, chatbot, history, system_prompt, plugin_advanced_arg, *args):\n txt_passon = txt\n if txt == \"\" and txt2 != \"\": txt_passon = txt2\n # 引入一个有cookie的chatbot\n if request.username is not None:\n user_name = request.username\n else:\n user_name = default_user_name\n cookies.update({\n 'top_p':top_p,\n 'api_key': cookies['api_key'],\n 'llm_model': llm_model,\n 'temperature':temperature,\n 'user_name': user_name,\n })\n llm_kwargs = {\n 'api_key': cookies['api_key'],\n 'llm_model': llm_model,\n 'top_p':top_p,\n 'max_length': max_length,\n 'temperature':temperature,\n 'client_ip': request.client.host,\n 'most_recent_uploaded': cookies.get('most_recent_uploaded')\n }\n plugin_kwargs = {\n \"advanced_arg\": plugin_advanced_arg,\n }\n chatbot_with_cookie = ChatBotWithCookies(cookies)\n chatbot_with_cookie.write_list(chatbot)\n \n if cookies.get('lock_plugin', None) is None:\n # 正常状态\n if len(args) == 0: # 插件通道\n yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, request)\n else: # 对话通道,或者基础功能通道\n yield from f(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, *args)\n else:\n # 处理少数情况下的特殊插件的锁定状态\n module, fn_name = cookies['lock_plugin'].split('->')\n f_hot_reload = getattr(importlib.import_module(module, fn_name), fn_name)\n yield from f_hot_reload(txt_passon, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, system_prompt, request)\n # 判断一下用户是否错误地通过对话通道进入,如果是,则进行提醒\n final_cookies = chatbot_with_cookie.get_cookies()\n # len(args) != 0 代表“提交”键对话通道,或者基础功能通道\n if len(args) != 0 and 'files_to_promote' in final_cookies and len(final_cookies['files_to_promote']) > 0:\n chatbot_with_cookie.append([\"检测到**滞留的缓存文档**,请及时处理。\", \"请及时点击“**保存当前对话**”获取所有滞留文档。\"])\n yield from update_ui(chatbot_with_cookie, final_cookies['history'], msg=\"检测到被滞留的缓存文档\")\n return decorated\n\n\ndef update_ui(chatbot, history, msg='正常', **kwargs): # 刷新界面\n \"\"\"\n 刷新用户界面\n \"\"\"\n assert isinstance(chatbot, ChatBotWithCookies), \"在传递chatbot的过程中不要将其丢弃。必要时, 可用clear将其清空, 然后用for+append循环重新赋值。\"\n cookies = chatbot.get_cookies()\n # 备份一份History作为记录\n cookies.update({'history': history})\n # 解决插件锁定时的界面显示问题\n if cookies.get('lock_plugin', None):\n label = cookies.get('llm_model', \"\") + \" | \" + \"正在锁定插件\" + cookies.get('lock_plugin', None)\n chatbot_gr = gradio.update(value=chatbot, label=label)\n if cookies.get('label', \"\") != label: cookies['label'] = label # 记住当前的label\n elif cookies.get('label', None):\n chatbot_gr = gradio.update(value=chatbot, label=cookies.get('llm_model', \"\"))\n cookies['label'] = None # 清空label\n else:\n chatbot_gr = chatbot\n\n yield cookies, chatbot_gr, history, msg\n\ndef update_ui_lastest_msg(lastmsg, chatbot, history, delay=1): # 刷新界面\n \"\"\"\n 刷新用户界面\n \"\"\"\n if len(chatbot) == 0: chatbot.append([\"update_ui_last_msg\", lastmsg])\n chatbot[-1] = list(chatbot[-1])\n chatbot[-1][-1] = lastmsg\n yield from update_ui(chatbot=chatbot, history=history)\n time.sleep(delay)\n\n\ndef trimmed_format_exc():\n import os, traceback\n str = traceback.format_exc()\n current_path = os.getcwd()\n replace_path = \".\"\n return str.replace(current_path, replace_path)\n\ndef CatchException(f):\n \"\"\"\n 装饰器函数,捕捉函数f中的异常并封装到一个生成器中返回,并显示到聊天当中。\n \"\"\"\n\n @wraps(f)\n def decorated(main_input, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, *args, **kwargs):\n try:\n yield from f(main_input, llm_kwargs, plugin_kwargs, chatbot_with_cookie, history, *args, **kwargs)\n except Exception as e:\n from check_proxy import check_proxy\n from toolbox import get_conf\n proxies = get_conf('proxies')\n tb_str = '```\\n' + trimmed_format_exc() + '```'\n if len(chatbot_with_cookie) == 0:\n chatbot_with_cookie.clear()\n chatbot_with_cookie.append([\"插件调度异常\", \"异常原因\"])\n chatbot_with_cookie[-1] = (chatbot_with_cookie[-1][0],\n f\"[Local Message] 插件调用出错: \\n\\n{tb_str} \\n\\n当前代理可用性: \\n\\n{check_proxy(proxies)}\")\n yield from update_ui(chatbot=chatbot_with_cookie, history=history, msg=f'异常 {e}') # 刷新界面\n return decorated\n\n\ndef HotReload(f):\n \"\"\"\n HotReload的装饰器函数,用于实现Python函数插件的热更新。\n 函数热更新是指在不停止程序运行的情况下,更新函数代码,从而达到实时更新功能。\n 在装饰器内部,使用wraps(f)来保留函数的元信息,并定义了一个名为decorated的内部函数。\n 内部函数通过使用importlib模块的reload函数和inspect模块的getmodule函数来重新加载并获取函数模块,\n 然后通过getattr函数获取函数名,并在新模块中重新加载函数。\n 最后,使用yield from语句返回重新加载过的函数,并在被装饰的函数上执行。\n 最终,装饰器函数返回内部函数。这个内部函数可以将函数的原始定义更新为最新版本,并执行函数的新版本。\n \"\"\"\n if get_conf('PLUGIN_HOT_RELOAD'):\n @wraps(f)\n def decorated(*args, **kwargs):\n fn_name = f.__name__\n f_hot_reload = getattr(importlib.reload(inspect.getmodule(f)), fn_name)\n yield from f_hot_reload(*args, **kwargs)\n return decorated\n else:\n return f\n\n\n\"\"\"\n========================================================================\n第二部分\n其他小工具:\n - write_history_to_file: 将结果写入markdown文件中\n - regular_txt_to_markdown: 将普通文本转换为Markdown格式的文本。\n - report_exception: 向chatbot中添加简单的意外错误信息\n - text_divide_paragraph: 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。\n - markdown_convertion: 用多种方式组合,将markdown转化为好看的html\n - format_io: 接管gradio默认的markdown处理方式\n - on_file_uploaded: 处理文件的上传(自动解压)\n - on_report_generated: 将生成的报告自动投射到文件上传区\n - clip_history: 当历史上下文过长时,自动截断\n - get_conf: 获取设置\n - select_api_key: 根据当前的模型类别,抽取可用的api-key\n========================================================================\n\"\"\"\n\ndef get_reduce_token_percent(text):\n \"\"\"\n * 此函数未来将被弃用\n \"\"\"\n try:\n # text = \"maximum context length is 4097 tokens. However, your messages resulted in 4870 tokens\"\n pattern = r\"(\\d+)\\s+tokens\\b\"\n match = re.findall(pattern, text)\n EXCEED_ALLO = 500 # 稍微留一点余地,否则在回复时会因余量太少出问题\n max_limit = float(match[0]) - EXCEED_ALLO\n current_tokens = float(match[1])\n ratio = max_limit/current_tokens\n assert ratio > 0 and ratio < 1\n return ratio, str(int(current_tokens-max_limit))\n except:\n return 0.5, '不详'\n\n\ndef write_history_to_file(history, file_basename=None, file_fullname=None, auto_caption=True):\n \"\"\"\n 将对话记录history以Markdown格式写入文件中。如果没有指定文件名,则使用当前时间生成文件名。\n \"\"\"\n import os\n import time\n if file_fullname is None:\n if file_basename is not None:\n file_fullname = pj(get_log_folder(), file_basename)\n else:\n file_fullname = pj(get_log_folder(), f'GPT-Academic-{gen_time_str()}.md')\n os.makedirs(os.path.dirname(file_fullname), exist_ok=True)\n with open(file_fullname, 'w', encoding='utf8') as f:\n f.write('# GPT-Academic Report\\n')\n for i, content in enumerate(history):\n try: \n if type(content) != str: content = str(content)\n except:\n continue\n if i % 2 == 0 and auto_caption:\n f.write('## ')\n try:\n f.write(content)\n except:\n # remove everything that cannot be handled by utf8\n f.write(content.encode('utf-8', 'ignore').decode())\n f.write('\\n\\n')\n res = os.path.abspath(file_fullname)\n return res\n\n\ndef regular_txt_to_markdown(text):\n \"\"\"\n 将普通文本转换为Markdown格式的文本。\n \"\"\"\n text = text.replace('\\n', '\\n\\n')\n text = text.replace('\\n\\n\\n', '\\n\\n')\n text = text.replace('\\n\\n\\n', '\\n\\n')\n return text\n\n\n\n\ndef report_exception(chatbot, history, a, b):\n \"\"\"\n 向chatbot中添加错误信息\n \"\"\"\n chatbot.append((a, b))\n history.extend([a, b])\n\n\ndef text_divide_paragraph(text):\n \"\"\"\n 将文本按照段落分隔符分割开,生成带有段落标签的HTML代码。\n \"\"\"\n pre = '