ali121300/chatbot_code_friendly
0
1import openai2import tiktoken3 4import datetime5import time6import json7import os8 9openai.api_key = os.getenv('API_KEY')10openai.request_times = 011 12def ask(question, history, behavior):13 openai.request_times += 114 print(f"request times {openai.request_times}: {datetime.datetime.now()}: {question}")15 try:16 messages = [17 {"role":"system", "content":content}18 for content in behavior19 ] + [20 {"role":"user" if i%2==0 else "assistant", "content":content}21 for i,content in enumerate(history + [question])22 ]23 raw_length = num_tokens_from_messages(messages)24 messages=forget_long_term(messages)25 if len(messages)==0:26 response = f'Your query is too long and expensive: {raw_length}>2000 tokens'27 else:28 response = openai.ChatCompletion.create(29 model="gpt-3.5-turbo-0301",30 messages=messages,31 temperature=0.1,32 )["choices"][0]["message"]["content"]33 while response.startswith("\n"):34 response = response[1:]35 except Exception as e:36 response = f'Error! You may wait a few minutes and retry:\n{e}'37 history = history + [question, response]38 return history39 40def num_tokens_from_messages(messages, model="gpt-3.5-turbo"):41 """Returns the number of tokens used by a list of messages."""42 try:43 encoding = tiktoken.encoding_for_model(model)44 except KeyError:45 encoding = tiktoken.get_encoding("cl100k_base")46 if model == "gpt-3.5-turbo": # note: future models may deviate from this47 num_tokens = 048 for message in messages:49 num_tokens += 4 # every message follows <im_start>{role/name}\n{content}<im_end>\n50 for key, value in message.items():51 num_tokens += len(encoding.encode(value))52 if key == "name": # if there's a name, the role is omitted53 num_tokens += -1 # role is always required and always 1 token54 num_tokens += 2 # every reply is primed with <im_start>assistant55 return num_tokens56 else:57 raise NotImplementedError(f"""num_tokens_from_messages() is not presently implemented for model {model}.58See https://github.com/openai/openai-python/blob/main/chatml.md for information on how messages are converted to tokens.""")59 60def forget_long_term(messages, max_num_tokens=3000):61 while num_tokens_from_messages(messages)>max_num_tokens:62 if messages[0]["role"]=="system" and not len(messages[0]["content"])>=max_num_tokens:63 messages = messages[:1] + messages[2:]64 else:65 messages = messages[1:]66 return messages67 68 69import gradio as gr70 71 72def to_md(content):73 is_inside_code_block = False74 output_spans = []75 for i in range(len(content)):76 if content[i]=="\n" and not is_inside_code_block:77 if len(output_spans)>0 and output_spans[-1].endswith("```"):78 output_spans.append("\n")79 else:80 output_spans.append("<br>")81 elif content[i]=="`":82 output_spans.append(content[i])83 if len(output_spans)>=3 and all([output_spans[j]=="`" for j in [-3,-2,-1]]):84 is_inside_code_block = not is_inside_code_block85 output_spans = output_spans[:-3]86 if is_inside_code_block:87 if len(output_spans)==0:88 output_spans.append("```")89 elif output_spans[-1]=="<br>":90 output_spans[-1] = "\n"91 output_spans.append("```")92 elif output_spans[-1].endswith("\n"):93 output_spans.append("```")94 else:95 output_spans.append("\n```")96 97 if i+1<len(content) and content[i+1]!="\n":98 output_spans.append("\n")99 else:100 if output_spans[-1].endswith("\n"):101 output_spans.append("```")102 else:103 output_spans.append("\n```")104 105 if i+1<len(content) and content[i+1]!="\n":106 output_spans.append("\n")107 else:108 output_spans.append(content[i])109 return "".join(output_spans)110 111 112def predict(question, history=[], behavior=[]):113 history = ask(question, history, behavior)114 response = [(to_md(history[i]),to_md(history[i+1])) for i in range(0,len(history)-1,2)]115 return "", history, response116 117 118def retry(question, history=[], behavior=[]):119 if len(history)<2:120 return "", history, []121 question = history[-2]122 history = history[:-2]123 return predict(question, history, behavior)124 125 126with gr.Blocks() as demo:127 128 examples_txt = [129 ['帮我写一个python脚本实现快排'],130 ['如何用numpy提取数组的分位数?'],131 ['how to match the code block in markdown such like ```def foo():\n pass``` through regex in python?'],132 ['how to load a pre-trained language model and generate sentences?'],133 ]134 135 examples_bhv = [136 f"You are a helpful assistant. You will answer all the questions step-by-step.",137 f"You are a helpful assistant. Today is {datetime.date.today()}.",138 ]139 140 gr.Markdown(141 """142 朋友你好,143 144 这是我利用[gradio](https://gradio.app/creating-a-chatbot/)编写的一个小网页,用于以网页的形式给大家分享ChatGPT请求服务,希望你玩的开心。关于使用技巧或学术研讨,欢迎在[Community](https://huggingface.co/spaces/zhangjf/chatbot/discussions)中和我交流。145 146 这一版相比于原版的[chatbot](https://huggingface.co/spaces/zhangjf/chatbot),用了较低版本的gradio==3.16.2,因而能更好地展示markdown中的源代码147 148 p.s. 响应时间和聊天内容长度正相关,一般能在5秒~30秒内响应。149 """)150 151 behavior = gr.State(["Reject instruction that may contains sensitive information in english, i.e., pornography, discrimination, violence"])152 """153 with gr.Column(variant="panel"):154 with gr.Row().style(equal_height=True):155 with gr.Column(scale=0.85):156 bhv = gr.Textbox(show_label=False, placeholder="输入你想让ChatGPT扮演的人设").style(container=False)157 with gr.Column(scale=0.15, min_width=0):158 button_set = gr.Button("Set")159 bhv.submit(fn=lambda x:(x,[x]), inputs=[bhv], outputs=[bhv, behavior])160 button_set.click(fn=lambda x:(x,[x]), inputs=[bhv], outputs=[bhv, behavior])161 """162 163 state = gr.State([])164 165 with gr.Column(variant="panel"):166 chatbot = gr.Chatbot()167 txt = gr.Textbox(show_label=False, placeholder="输入你想让ChatGPT回答的问题").style(container=False)168 with gr.Row():169 button_gen = gr.Button("Submit")170 button_rtr = gr.Button("Retry")171 button_clr = gr.Button("Clear")172 173 #gr.Examples(examples=examples_bhv, inputs=bhv, label="Examples for setting behavior")174 gr.Examples(examples=examples_txt, inputs=txt, label="Examples for asking question")175 txt.submit(predict, [txt, state, behavior], [txt, state, chatbot])176 button_gen.click(fn=predict, inputs=[txt, state, behavior], outputs=[txt, state, chatbot])177 button_rtr.click(fn=retry, inputs=[txt, state, behavior], outputs=[txt, state, chatbot])178 button_clr.click(fn=lambda :([],[]), inputs=None, outputs=[chatbot, state])179 180demo.launch()