cathub/LocalChatGPT
0
1# -*- coding:utf-8 -*-2import os3import logging4import sys5 6import gradio as gr7 8from modules.utils import *9from modules.presets import *10from modules.overwrites import *11from modules.chat_func import *12from modules.openai_func import get_usage13 14logging.basicConfig(15 level=logging.DEBUG,16 format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",17)18 19my_api_key = "" # 在这里输入你的 API 密钥20 21# if we are running in Docker22if os.environ.get("dockerrun") == "yes":23 dockerflag = True24else:25 dockerflag = False26 27authflag = False28auth_list = []29 30if not my_api_key:31 my_api_key = os.environ.get("my_api_key")32if dockerflag:33 if my_api_key == "empty":34 logging.error("Please give a api key!")35 sys.exit(1)36 # auth37 username = os.environ.get("USERNAME")38 password = os.environ.get("PASSWORD")39 if not (isinstance(username, type(None)) or isinstance(password, type(None))):40 auth_list.append((os.environ.get("USERNAME"), os.environ.get("PASSWORD")))41 authflag = True42else:43 if (44 not my_api_key45 and os.path.exists("api_key.txt")46 and os.path.getsize("api_key.txt")47 ):48 with open("api_key.txt", "r") as f:49 my_api_key = f.read().strip()50 if os.path.exists("auth.json"):51 authflag = True52 with open("auth.json", "r", encoding='utf-8') as f:53 auth = json.load(f)54 for _ in auth:55 if auth[_]["username"] and auth[_]["password"]:56 auth_list.append((auth[_]["username"], auth[_]["password"]))57 else:58 logging.error("请检查auth.json文件中的用户名和密码!")59 sys.exit(1)60 61gr.Chatbot.postprocess = postprocess62PromptHelper.compact_text_chunks = compact_text_chunks63 64with open("assets/custom.css", "r", encoding="utf-8") as f:65 customCSS = f.read()66 67with gr.Blocks(css=customCSS, theme=small_and_beautiful_theme) as demo:68 history = gr.State([])69 token_count = gr.State([])70 promptTemplates = gr.State(load_template(get_template_names(plain=True)[0], mode=2))71 user_api_key = gr.State(my_api_key)72 user_question = gr.State("")73 outputing = gr.State(False)74 topic = gr.State("未命名对话历史记录")75 76 with gr.Row():77 with gr.Column(scale=1):78 gr.HTML(title)79 with gr.Column(scale=4):80 gr.HTML('<center><a href="https://huggingface.co/spaces/JohnSmith9982/ChuanhuChatGPT?duplicate=true"><img src="https://bit.ly/3gLdBN6" alt="Duplicate Space"></a>Duplicate the Space and run securely with your OpenAI API Key</center>')81 with gr.Column(scale=4):82 status_display = gr.Markdown(get_geoip(), elem_id="status_display")83 84 with gr.Row().style(equal_height=True):85 with gr.Column(scale=5):86 with gr.Row():87 chatbot = gr.Chatbot(elem_id="chuanhu_chatbot").style(height="100%")88 with gr.Row():89 with gr.Column(scale=12):90 user_input = gr.Textbox(91 show_label=False, placeholder="在这里输入"92 ).style(container=False)93 with gr.Column(min_width=70, scale=1):94 submitBtn = gr.Button("发送", variant="primary")95 cancelBtn = gr.Button("取消", variant="secondary", visible=False)96 with gr.Row():97 emptyBtn = gr.Button(98 "🧹 新的对话",99 )100 retryBtn = gr.Button("🔄 重新生成")101 delFirstBtn = gr.Button("🗑️ 删除最旧对话")102 delLastBtn = gr.Button("🗑️ 删除最新对话")103 reduceTokenBtn = gr.Button("♻️ 总结对话")104 105 with gr.Column():106 with gr.Column(min_width=50, scale=1):107 with gr.Tab(label="ChatGPT"):108 keyTxt = gr.Textbox(109 show_label=True,110 placeholder=f"OpenAI API-key...",111 value=hide_middle_chars(my_api_key),112 type="password",113 visible=not HIDE_MY_KEY,114 label="API-Key",115 )116 usageTxt = gr.Markdown("**发送消息** 或 **提交key** 以显示额度", elem_id="usage_display")117 model_select_dropdown = gr.Dropdown(118 label="选择模型", choices=MODELS, multiselect=False, value=MODELS[0]119 )120 use_streaming_checkbox = gr.Checkbox(121 label="实时传输回答", value=True, visible=enable_streaming_option122 )123 use_websearch_checkbox = gr.Checkbox(label="使用在线搜索", value=False)124 language_select_dropdown = gr.Dropdown(125 label="选择回复语言(针对搜索&索引功能)",126 choices=REPLY_LANGUAGES,127 multiselect=False,128 value=REPLY_LANGUAGES[0],129 )130 index_files = gr.Files(label="上传索引文件", type="file", multiple=True)131 132 with gr.Tab(label="Prompt"):133 systemPromptTxt = gr.Textbox(134 show_label=True,135 placeholder=f"在这里输入System Prompt...",136 label="System prompt",137 value=initial_prompt,138 lines=10,139 ).style(container=False)140 with gr.Accordion(label="加载Prompt模板", open=True):141 with gr.Column():142 with gr.Row():143 with gr.Column(scale=6):144 templateFileSelectDropdown = gr.Dropdown(145 label="选择Prompt模板集合文件",146 choices=get_template_names(plain=True),147 multiselect=False,148 value=get_template_names(plain=True)[0],149 ).style(container=False)150 with gr.Column(scale=1):151 templateRefreshBtn = gr.Button("🔄 刷新")152 with gr.Row():153 with gr.Column():154 templateSelectDropdown = gr.Dropdown(155 label="从Prompt模板中加载",156 choices=load_template(157 get_template_names(plain=True)[0], mode=1158 ),159 multiselect=False,160 value=load_template(161 get_template_names(plain=True)[0], mode=1162 )[0],163 ).style(container=False)164 165 with gr.Tab(label="保存/加载"):166 with gr.Accordion(label="保存/加载对话历史记录", open=True):167 with gr.Column():168 with gr.Row():169 with gr.Column(scale=6):170 historyFileSelectDropdown = gr.Dropdown(171 label="从列表中加载对话",172 choices=get_history_names(plain=True),173 multiselect=False,174 value=get_history_names(plain=True)[0],175 )176 with gr.Column(scale=1):177 historyRefreshBtn = gr.Button("🔄 刷新")178 with gr.Row():179 with gr.Column(scale=6):180 saveFileName = gr.Textbox(181 show_label=True,182 placeholder=f"设置文件名: 默认为.json,可选为.md",183 label="设置保存文件名",184 value="对话历史记录",185 ).style(container=True)186 with gr.Column(scale=1):187 saveHistoryBtn = gr.Button("💾 保存对话")188 exportMarkdownBtn = gr.Button("📝 导出为Markdown")189 gr.Markdown("默认保存于history文件夹")190 with gr.Row():191 with gr.Column():192 downloadFile = gr.File(interactive=True)193 194 with gr.Tab(label="高级"):195 gr.Markdown("# ⚠️ 务必谨慎更改 ⚠️\n\n如果无法使用请恢复默认设置")196 default_btn = gr.Button("🔙 恢复默认设置")197 198 with gr.Accordion("参数", open=False):199 top_p = gr.Slider(200 minimum=-0,201 maximum=1.0,202 value=1.0,203 step=0.05,204 interactive=True,205 label="Top-p",206 )207 temperature = gr.Slider(208 minimum=-0,209 maximum=2.0,210 value=1.0,211 step=0.1,212 interactive=True,213 label="Temperature",214 )215 216 with gr.Accordion("网络设置", open=False, visible=False):217 apiurlTxt = gr.Textbox(218 show_label=True,219 placeholder=f"在这里输入API地址...",220 label="API地址",221 value="https://api.openai.com/v1/chat/completions",222 lines=2,223 )224 changeAPIURLBtn = gr.Button("🔄 切换API地址")225 proxyTxt = gr.Textbox(226 show_label=True,227 placeholder=f"在这里输入代理地址...",228 label="代理地址(示例:http://127.0.0.1:10809)",229 value="",230 lines=2,231 )232 changeProxyBtn = gr.Button("🔄 设置代理地址")233 234 gr.Markdown(description)235 gr.HTML(footer.format(versions=versions_html()), elem_id="footer")236 chatgpt_predict_args = dict(237 fn=predict,238 inputs=[239 user_api_key,240 systemPromptTxt,241 history,242 user_question,243 chatbot,244 token_count,245 top_p,246 temperature,247 use_streaming_checkbox,248 model_select_dropdown,249 use_websearch_checkbox,250 index_files,251 language_select_dropdown,252 ],253 outputs=[chatbot, history, status_display, token_count],254 show_progress=True,255 )256 257 start_outputing_args = dict(258 fn=start_outputing,259 inputs=[],260 outputs=[submitBtn, cancelBtn],261 show_progress=True,262 )263 264 end_outputing_args = dict(265 fn=end_outputing, inputs=[], outputs=[submitBtn, cancelBtn]266 )267 268 reset_textbox_args = dict(269 fn=reset_textbox, inputs=[], outputs=[user_input]270 )271 272 transfer_input_args = dict(273 fn=transfer_input, inputs=[user_input], outputs=[user_question, user_input, submitBtn, cancelBtn], show_progress=True274 )275 276 get_usage_args = dict(277 fn=get_usage, inputs=[user_api_key], outputs=[usageTxt], show_progress=False278 )279 280 281 # Chatbot282 cancelBtn.click(cancel_outputing, [], [])283 284 user_input.submit(**transfer_input_args).then(**chatgpt_predict_args).then(**end_outputing_args)285 user_input.submit(**get_usage_args)286 287 submitBtn.click(**transfer_input_args).then(**chatgpt_predict_args).then(**end_outputing_args)288 submitBtn.click(**get_usage_args)289 290 emptyBtn.click(291 reset_state,292 outputs=[chatbot, history, token_count, status_display],293 show_progress=True,294 )295 emptyBtn.click(**reset_textbox_args)296 297 retryBtn.click(**start_outputing_args).then(298 retry,299 [300 user_api_key,301 systemPromptTxt,302 history,303 chatbot,304 token_count,305 top_p,306 temperature,307 use_streaming_checkbox,308 model_select_dropdown,309 language_select_dropdown,310 ],311 [chatbot, history, status_display, token_count],312 show_progress=True,313 ).then(**end_outputing_args)314 retryBtn.click(**get_usage_args)315 316 delFirstBtn.click(317 delete_first_conversation,318 [history, token_count],319 [history, token_count, status_display],320 )321 322 delLastBtn.click(323 delete_last_conversation,324 [chatbot, history, token_count],325 [chatbot, history, token_count, status_display],326 show_progress=True,327 )328 329 reduceTokenBtn.click(330 reduce_token_size,331 [332 user_api_key,333 systemPromptTxt,334 history,335 chatbot,336 token_count,337 top_p,338 temperature,339 gr.State(sum(token_count.value[-4:])),340 model_select_dropdown,341 language_select_dropdown,342 ],343 [chatbot, history, status_display, token_count],344 show_progress=True,345 )346 reduceTokenBtn.click(**get_usage_args)347 348 # ChatGPT349 keyTxt.change(submit_key, keyTxt, [user_api_key, status_display]).then(**get_usage_args)350 keyTxt.submit(**get_usage_args)351 352 # Template353 templateRefreshBtn.click(get_template_names, None, [templateFileSelectDropdown])354 templateFileSelectDropdown.change(355 load_template,356 [templateFileSelectDropdown],357 [promptTemplates, templateSelectDropdown],358 show_progress=True,359 )360 templateSelectDropdown.change(361 get_template_content,362 [promptTemplates, templateSelectDropdown, systemPromptTxt],363 [systemPromptTxt],364 show_progress=True,365 )366 367 # S&L368 saveHistoryBtn.click(369 save_chat_history,370 [saveFileName, systemPromptTxt, history, chatbot],371 downloadFile,372 show_progress=True,373 )374 saveHistoryBtn.click(get_history_names, None, [historyFileSelectDropdown])375 exportMarkdownBtn.click(376 export_markdown,377 [saveFileName, systemPromptTxt, history, chatbot],378 downloadFile,379 show_progress=True,380 )381 historyRefreshBtn.click(get_history_names, None, [historyFileSelectDropdown])382 historyFileSelectDropdown.change(383 load_chat_history,384 [historyFileSelectDropdown, systemPromptTxt, history, chatbot],385 [saveFileName, systemPromptTxt, history, chatbot],386 show_progress=True,387 )388 downloadFile.change(389 load_chat_history,390 [downloadFile, systemPromptTxt, history, chatbot],391 [saveFileName, systemPromptTxt, history, chatbot],392 )393 394 # Advanced395 default_btn.click(396 reset_default, [], [apiurlTxt, proxyTxt, status_display], show_progress=True397 )398 changeAPIURLBtn.click(399 change_api_url,400 [apiurlTxt],401 [status_display],402 show_progress=True,403 )404 changeProxyBtn.click(405 change_proxy,406 [proxyTxt],407 [status_display],408 show_progress=True,409 )410 411logging.info(412 colorama.Back.GREEN413 + "\n川虎的温馨提示:访问 http://localhost:7860 查看界面"414 + colorama.Style.RESET_ALL415)416# 默认开启本地服务器,默认可以直接从IP访问,默认不创建公开分享链接417demo.title = "川虎ChatGPT 🚀"418 419if __name__ == "__main__":420 reload_javascript()421 # if running in Docker422 if dockerflag:423 if authflag:424 demo.queue(concurrency_count=CONCURRENT_COUNT).launch(425 server_name="0.0.0.0",426 server_port=7860,427 auth=auth_list,428 favicon_path="./assets/favicon.ico",429 )430 else:431 demo.queue(concurrency_count=CONCURRENT_COUNT).launch(432 server_name="0.0.0.0",433 server_port=7860,434 share=False,435 favicon_path="./assets/favicon.ico",436 )437 # if not running in Docker438 else:439 if authflag:440 demo.queue(concurrency_count=CONCURRENT_COUNT).launch(441 share=False,442 auth=auth_list,443 favicon_path="./assets/favicon.ico",444 inbrowser=True,445 )446 else:447 demo.queue(concurrency_count=CONCURRENT_COUNT).launch(448 share=False, favicon_path="./assets/favicon.ico", inbrowser=True449 ) # 改为 share=True 可以创建公开分享链接450 # demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=7860, share=False) # 可自定义端口451 # demo.queue(concurrency_count=CONCURRENT_COUNT).launch(server_name="0.0.0.0", server_port=7860,auth=("在这里填写用户名", "在这里填写密码")) # 可设置用户名与密码452 # demo.queue(concurrency_count=CONCURRENT_COUNT).launch(auth=("在这里填写用户名", "在这里填写密码")) # 适合Nginx反向代理453 