diff --git a/crazy_functions/全项目切换英文.py b/crazy_functions/全项目切换英文.py new file mode 100644 index 0000000..8015f55 --- /dev/null +++ b/crazy_functions/全项目切换英文.py @@ -0,0 +1,59 @@ +import threading +from predict import predict_no_ui_long_connection +from toolbox import CatchException, write_results_to_file + + + +@CatchException +def 全项目切换英文(txt, top_p, temperature, chatbot, history, sys_prompt, WEB_PORT): + history = [] # 清空历史,以免输入溢出 + # 集合文件 + import time, glob, os + file_manifest = [f for f in glob.glob('./**/*.py', recursive=True) if ('test_project' not in f) and ('gpt_log' not in f)] + i_say_show_user_buffer = [] + + # 随便显示点什么防止卡顿 + for index, fp in enumerate(file_manifest): + # if 'test_project' in fp: continue + with open(fp, 'r', encoding='utf-8') as f: + file_content = f.read() + i_say_show_user =f'[{index}/{len(file_manifest)}] 接下来请将以下代码中包含的所有中文转化为英文,只输出代码: {os.path.abspath(fp)}' + i_say_show_user_buffer.append(i_say_show_user) + chatbot.append((i_say_show_user, "[Local Message] 等待多线程操作,中间过程不予显示.")) + yield chatbot, history, '正常' + + # 任务函数 + mutable_return = [None for _ in file_manifest] + def thread_worker(fp,index): + with open(fp, 'r', encoding='utf-8') as f: + file_content = f.read() + i_say = f'接下来请将以下代码中包含的所有中文转化为英文,只输出代码,文件名是{fp},文件代码是 ```{file_content}```' + # ** gpt request ** + gpt_say = predict_no_ui_long_connection(inputs=i_say, top_p=top_p, temperature=temperature, history=history, sys_prompt=sys_prompt) + mutable_return[index] = gpt_say + + # 所有线程同时开始执行任务函数 + handles = [threading.Thread(target=thread_worker, args=(fp,index)) for index, fp in enumerate(file_manifest)] + for h in handles: + h.daemon = True + h.start() + + # 等待各个线程逐一完成 + for index, h in enumerate(handles): + h.join() + fp = file_manifest[index] + gpt_say = mutable_return[index] + i_say_show_user = i_say_show_user_buffer[index] + os.makedirs('gpt_log/generated_english_version', exist_ok=True) + os.makedirs('gpt_log/generated_english_version/crazy_functions', exist_ok=True) + where_to_relocate = f'gpt_log/generated_english_version/{fp}' + with open(where_to_relocate, 'w+', encoding='utf-8') as f: f.write(gpt_say.lstrip('```').rstrip('```')) + chatbot.append((i_say_show_user, f'[Local Message] 已完成{os.path.abspath(fp)}的转化,\n\n存入{os.path.abspath(where_to_relocate)}')) + history.append(i_say_show_user); history.append(gpt_say) + yield chatbot, history, '正常' + time.sleep(2) + + # 结束 + res = write_results_to_file(history) + chatbot.append(("完成了吗?", res)) + yield chatbot, history, '正常' diff --git a/functional_crazy.py b/functional_crazy.py index 15fcf79..0c3480d 100644 --- a/functional_crazy.py +++ b/functional_crazy.py @@ -7,11 +7,16 @@ def get_crazy_functionals(): from crazy_functions.解析项目源代码 import 解析一个C项目的头文件 from crazy_functions.解析项目源代码 import 解析一个C项目 from crazy_functions.高级功能函数模板 import 高阶功能模板函数 + from crazy_functions.全项目切换英文 import 全项目切换英文 return { "[实验] 请解析并解构此项目本身": { "Function": 解析项目本身 }, + "[实验] 把此项目代码切换成全英文": { + "Color": "stop", # 按钮颜色 + "Function": 全项目切换英文 + }, "[实验] 解析整个py项目(配合input输入框)": { "Color": "stop", # 按钮颜色 "Function": 解析一个Python项目 diff --git a/predict.py b/predict.py index cda511e..fb1eb26 100644 --- a/predict.py +++ b/predict.py @@ -25,7 +25,7 @@ def get_full_error(chunk, stream_response): break return chunk -def predict_no_ui(inputs, top_p, temperature, history=[]): +def predict_no_ui(inputs, top_p, temperature, history=[], sys_prompt=""): """ 发送至chatGPT,等待回复,一次性完成,不显示中间过程。 predict函数的简化版。 @@ -36,7 +36,7 @@ def predict_no_ui(inputs, top_p, temperature, history=[]): history 是之前的对话列表 (注意无论是inputs还是history,内容太长了都会触发token数量溢出的错误,然后raise ConnectionAbortedError) """ - headers, payload = generate_payload(inputs, top_p, temperature, history, system_prompt="", stream=False) + headers, payload = generate_payload(inputs, top_p, temperature, history, system_prompt=sys_prompt, stream=False) retry = 0 while True: @@ -47,8 +47,8 @@ def predict_no_ui(inputs, top_p, temperature, history=[]): except requests.exceptions.ReadTimeout as e: retry += 1 traceback.print_exc() - if MAX_RETRY!=0: print(f'请求超时,正在重试 ({retry}/{MAX_RETRY}) ……') if retry > MAX_RETRY: raise TimeoutError + if MAX_RETRY!=0: print(f'请求超时,正在重试 ({retry}/{MAX_RETRY}) ……') try: result = json.loads(response.text)["choices"][0]["message"]["content"] @@ -58,6 +58,40 @@ def predict_no_ui(inputs, top_p, temperature, history=[]): raise ConnectionAbortedError("Json解析不合常规,可能是文本过长" + response.text) +def predict_no_ui_long_connection(inputs, top_p, temperature, history=[], sys_prompt=""): + """ + 发送至chatGPT,等待回复,一次性完成,不显示中间过程。但内部用stream的方法避免有人中途掐网线。 + """ + headers, payload = generate_payload(inputs, top_p, temperature, history, system_prompt=sys_prompt, stream=True) + + retry = 0 + while True: + try: + # make a POST request to the API endpoint, stream=False + response = requests.post(API_URL, headers=headers, proxies=proxies, + json=payload, stream=True, timeout=TIMEOUT_SECONDS); break + except requests.exceptions.ReadTimeout as e: + retry += 1 + traceback.print_exc() + if retry > MAX_RETRY: raise TimeoutError + if MAX_RETRY!=0: print(f'请求超时,正在重试 ({retry}/{MAX_RETRY}) ……') + + stream_response = response.iter_lines() + result = '' + while True: + try: chunk = next(stream_response).decode() + except StopIteration: break + if len(chunk)==0: continue + if not chunk.startswith('data:'): + raise ConnectionAbortedError("OpenAI返回了错误:" + chunk) + delta = json.loads(chunk.lstrip('data:'))['choices'][0]["delta"] + if len(delta) == 0: break + if "role" in delta: continue + if "content" in delta: result += delta["content"]; print(delta["content"], end='') + else: raise RuntimeError("意外Json结构:"+delta) + return result + + def predict(inputs, top_p, temperature, chatbot=[], history=[], system_prompt='', stream = True, additional_fn=None): """ diff --git a/toolbox.py b/toolbox.py index 12e6524..9c420d1 100644 --- a/toolbox.py +++ b/toolbox.py @@ -2,7 +2,7 @@ import markdown, mdtex2html, threading from show_math import convert as convert_math from functools import wraps -def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temperature, history=[]): +def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temperature, history=[], sys_prompt=''): """ 调用简单的predict_no_ui接口,但是依然保留了些许界面心跳功能,当对话太长时,会自动采用二分法截断 """ @@ -17,7 +17,7 @@ def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temp def mt(i_say, history): while True: try: - mutable[0] = predict_no_ui(inputs=i_say, top_p=top_p, temperature=temperature, history=history) + mutable[0] = predict_no_ui(inputs=i_say, top_p=top_p, temperature=temperature, history=history, sys_prompt=sys_prompt) break except ConnectionAbortedError as e: if len(history) > 0: @@ -27,7 +27,8 @@ def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temp i_say = i_say[:len(i_say)//2] mutable[1] = 'Warning! Input file is too long, cut into half. ' except TimeoutError as e: - mutable[0] = '[Local Message] Failed with timeout' + mutable[0] = '[Local Message] Failed with timeout.' + raise TimeoutError # 创建新线程发出http请求 thread_name = threading.Thread(target=mt, args=(i_say, history)); thread_name.start() # 原来的线程则负责持续更新UI,实现一个超时倒计时,并等待新线程的任务完成 @@ -39,6 +40,7 @@ def predict_no_ui_but_counting_down(i_say, i_say_show_user, chatbot, top_p, temp time.sleep(1) # 把gpt的输出从mutable中取出来 gpt_say = mutable[0] + if gpt_say=='[Local Message] Failed with timeout.': raise TimeoutError return gpt_say def write_results_to_file(history, file_name=None):