# import gradio as gr import gradio # import lmdb # import base64 # import io # import random # import time import json import copy # import sqlite3 from urllib.parse import urljoin import openai DEFAULT_PROMPT = [ ["system", "You(assistant) are a helpful AI assistant."], ] # def get_settings(old_state): # db_path = './my_app_state' # env = lmdb.open(db_path, max_dbs=2*1024*1024) # # print(env.stat()) # txn = env.begin() # saved_api_key = txn.get(key=b'api_key').decode('utf-8') or '' # txn.commit() # env.close() # new_state = copy.deepcopy(old_state) or {} # new_state['api_key'] = saved_api_key # return new_state, saved_api_key # def save_settings(old_state, api_key_text): # db_path = './my_app_state' # env = lmdb.open(db_path, max_dbs=2*1024*1024) # # print(env.stat()) # txn = env.begin(write=True) # txn.put(key=b'api_key', value=api_key_text.encode('utf-8')) # # 提交事务 # txn.commit() # return get_settings(old_state) def on_click_send_btn( global_state_json, api_key_text, chat_input_role, chat_input, prompt_table, chat_use_prompt, chat_use_history, chat_log, chat_model, temperature, top_p, choices_num, stream, max_tokens, presence_penalty, frequency_penalty, logit_bias, ): old_state = json.loads(global_state_json or "{}") print('\n\n\n\n\n') print(prompt_table) prompt_table = prompt_table or [] chat_log = chat_log or [] chat_log_md = '' if chat_use_prompt: chat_log_md += '
(prompt)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", prompt_table)]) chat_log_md += '\n---\n' if True: chat_log_md += '
(history)
\n\n' if chat_use_history else '
(not used history)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", chat_log)]) chat_log_md += '\n---\n' # if chat_input=='': # return json.dumps(old_state), chat_log, chat_log_md, chat_log_md, None, None, chat_input print('\n') print(chat_input) print('') try: logit_bias_json = json.dumps(logit_bias) if logit_bias else None except: return json.dumps(old_state), chat_log, chat_log_md, chat_log_md, None, None, chat_input new_state = copy.deepcopy(old_state) or {} req_hist = copy.deepcopy(prompt_table) if chat_use_prompt else [] if chat_use_history: for hh in (chat_log or []): req_hist.append(hh) if chat_input and chat_input!="": req_hist.append([(chat_input_role or 'user'), chat_input]) openai.api_key = api_key_text props = { 'model': chat_model, 'messages': [xx for xx in map(lambda it: {'role':it[0], 'content':it[1]}, req_hist)], 'temperature': temperature, 'top_p': top_p, 'n': choices_num, 'stream': stream, 'presence_penalty': presence_penalty, 'frequency_penalty': frequency_penalty, } if max_tokens>0: props['max_tokens'] = max_tokens if logit_bias_json is not None: props['logit_bias'] = logit_bias_json props_json = json.dumps(props) try: completion = openai.ChatCompletion.create(**props) print('') chat_log_md = '' if chat_use_prompt: chat_log_md += '
(prompt)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", prompt_table)]) chat_log_md += '\n---\n' if True: chat_log_md += '
(history)
\n\n' if chat_use_history else '
(not used history)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", chat_log)]) chat_log_md += '\n---\n' if chat_input and chat_input!="": chat_log.append([(chat_input_role or 'user'), chat_input]) chat_log_md += f"##### `{(chat_input_role or 'user')}`\n\n{chat_input}\n\n" partial_words = "" counter=0 if stream: the_response = '' the_response_role = '' for chunk in completion: #Skipping first chunk if counter == 0: the_response_role = chunk.choices[0].delta.role chat_log_md += f"##### `{the_response_role}`\n\n" counter += 1 continue # print(('chunk', chunk)) if chunk.choices[0].finish_reason is None: the_response_chunk = chunk.choices[0].delta.content the_response += the_response_chunk chat_log_md += f"{the_response_chunk}" yield json.dumps(new_state), chat_log, chat_log_md, chat_log_md, "{}", props_json, '' else: chat_log.append([the_response_role, the_response]) chat_log_md += f"\n\n" yield json.dumps(new_state), chat_log, chat_log_md, chat_log_md, '{"msg": "stream模式不支持显示"}', props_json, '' # chat_last_resp = json.dumps(completion.__dict__) # chat_last_resp_dict = json.loads(chat_last_resp) # chat_last_resp_dict['api_key'] = "hidden by UI" # chat_last_resp_dict['organization'] = "hidden by UI" # chat_last_resp = json.dumps(chat_last_resp_dict) else: the_response_role = completion.choices[0].message.role the_response = completion.choices[0].message.content print(the_response) print('') chat_log.append([the_response_role, the_response]) chat_log_md += f"##### `{the_response_role}`\n\n{the_response}\n\n" chat_last_resp = json.dumps(completion.__dict__) chat_last_resp_dict = json.loads(chat_last_resp) chat_last_resp_dict['api_key'] = "hidden by UI" chat_last_resp_dict['organization'] = "hidden by UI" chat_last_resp = json.dumps(chat_last_resp_dict) return json.dumps(new_state), chat_log, chat_log_md, chat_log_md, chat_last_resp, props_json, '' except Exception as error: print(error) print('error!!!!!!') chat_log_md = '' if chat_use_prompt: chat_log_md += '
(prompt)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", prompt_table)]) chat_log_md += '\n---\n' if True: chat_log_md += '
(history)
\n\n' if chat_use_history else '
(not used history)
\n\n' chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", chat_log)]) chat_log_md += '\n---\n' # chat_log_md = '' # chat_log_md = "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", prompt_table)]) if chat_use_prompt else '' # chat_log_md += "\n".join([xx for xx in map(lambda it: f"##### `{it[0]}`\n\n{it[1]}\n\n", hist)]) chat_log_md += "\n" chat_log_md += str(error) return json.dumps(new_state), chat_log, chat_log_md, chat_log_md, None, props_json, chat_input def clear_history(): return [], "" def copy_history(txt): # print('\n\n copying') # print(txt) # print('\n\n') pass def update_saved_prompt_titles(global_state_json, selected_saved_prompt_title): print('') global_state = json.loads(global_state_json or "{}") print(global_state) print(selected_saved_prompt_title) saved_prompts = global_state.get('saved_prompts') or [] print(saved_prompts) the_choices = [(it.get('title') or '[untitled]') for it in saved_prompts] print(the_choices) print('') return gradio.Dropdown.update(choices=the_choices) def save_prompt(global_state_json, saved_prompts, prompt_title, prompt_table): the_choices = [] global_state = json.loads(global_state_json or "{}") saved_prompts = global_state.get('saved_prompts') or [] if len(saved_prompts): the_choices = [it.get('title') or '[untitled]' for it in saved_prompts] pass return global_state_json, gradio.Dropdown.update(choices=the_choices, value=prompt_title), prompt_title, prompt_table def load_saved_prompt(title): pass css = """ .table-wrap .cell-wrap input {min-width:80%} #api-key-textbox textarea {filter:blur(8px); transition: filter 0.25s} #api-key-textbox textarea:focus {filter:none} #chat-log-md hr {margin-top: 1rem; margin-bottom: 1rem;} """ with gradio.Blocks(title="ChatGPT", css=css) as demo: global_state_json = gradio.Textbox(visible=False) # https://gradio.app/docs # https://platform.openai.com/docs/api-reference/chat/create with gradio.Tab("ChatGPT"): with gradio.Row(): with gradio.Box(): with gradio.Column(scale=12): with gradio.Row(): api_key_text = gradio.Textbox(label="Your API key", elem_id="api-key-textbox") with gradio.Row(): with gradio.Column(scale=2): api_key_refresh_btn = gradio.Button("🔄 Load from browser storage") api_key_refresh_btn.click( # get_settings, None, inputs=[], outputs=[api_key_text], api_name="load-settings", _js="""()=>{ const the_api_key = localStorage?.getItem?.('[gradio][chat-gpt-ui][api_key_text]') ?? ''; return the_api_key; }""", ) with gradio.Column(scale=2): api_key_save_btn = gradio.Button("💾 Save to browser storage") api_key_save_btn.click( # save_settings, None, inputs=[api_key_text], outputs=[api_key_text], api_name="save-settings", _js="""(api_key_text)=>{ localStorage.setItem('[gradio][chat-gpt-ui][api_key_text]', api_key_text); return api_key_text; }""", ) with gradio.Row(): gradio.Markdown("Go to https://platform.openai.com/account/api-keys to get your API key.") with gradio.Row(): with gradio.Box(): gradio.Markdown("**Prompt**") with gradio.Column(scale=12): with gradio.Row(): with gradio.Column(scale=6): prompt_title = gradio.Textbox(label='Prompt title (only for saving)') with gradio.Column(scale=6): selected_saved_prompt_title = gradio.Dropdown(label='Select prompt from saved list (click ♻️ then 🔄)') with gradio.Row(): with gradio.Column(scale=1, min_width=100): saved_prompts_refresh_btn = gradio.Button("♻️") with gradio.Column(scale=1, min_width=100): saved_prompts_save_btn = gradio.Button("💾") with gradio.Column(scale=1, min_width=100): saved_prompts_delete_btn = gradio.Button("🗑") with gradio.Column(scale=1, min_width=100): saved_prompts_list_refresh_btn = gradio.Button("🔄") with gradio.Column(scale=1, min_width=100): copy_prompt = gradio.Button("📑") with gradio.Column(scale=1, min_width=100): paste_prompt = gradio.Button("📋") with gradio.Row(): gradio.Markdown("""Buttons above: ♻️ then 🔄: Load prompts from browser storage. 💾 then 🔄: Save current prompt to browser storage, overwrite the prompt with the same title. 🗑 then 🔄: Delete prompt with the same title from browser storage. 🔄 : Update the selector list. 📑 : Copy current prompt to clipboard. 📋 : Paste prompt from clipboard (need [permission](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText#browser_compatibility)).""") with gradio.Row(): prompt_table = gradio.Dataframe( type='array', label='Prompt content', col_count=(2, 'fixed'), max_cols=2, value=DEFAULT_PROMPT, headers=['role', 'content'], interactive=True, ) with gradio.Row(): gradio.Markdown("The Table above is editable. The content will be added to the beginning of the conversation (if you check 'send with prompt' as `√`). See https://platform.openai.com/docs/guides/chat/introduction .") copy_prompt.click(None, inputs=[prompt_title, prompt_table], outputs=[prompt_title, prompt_table], _js="""(prompt_title, prompt_table)=>{ try { const txt = JSON.stringify({ title: prompt_title, content: prompt_table, }, null, 2); console.log(txt); const promise = navigator?.clipboard?.writeText?.(txt); } catch(error) {console?.log?.(error);}; return [prompt_title, prompt_table]; }""") paste_prompt.click(None, inputs=[prompt_title, prompt_table], outputs=[prompt_title, prompt_table], _js="""async (prompt_title, prompt_table)=>{ console.log("flag1"); try { const promise = navigator?.clipboard?.readText?.(); console.log(promise); console.log("flag1 p"); const result = await promise?.then?.((txt)=>{ console.log("flag1 t"); const json = JSON.parse(txt); const title = json?.title ?? ""; console.log("flag1 0"); console.log(title); const content = json?.content ?? {data: [], headers: ['role', 'content']}; console.log(content); const result = [title, content]; console.log("flag1 1"); console.log(result); console.log("flag1 2"); return result; }); console.log("flag1 3"); if (result!=null) { return result; }; } catch(error) {console?.log?.(error);}; console.log("flag2"); try { const promise = navigator?.clipboard?.read?.(); console.log(promise); promise?.then?.((data)=>{ console.log(data); }); } catch(error) {console?.log?.(error);}; console.log("flag3"); return [prompt_title, prompt_table]; }""") saved_prompts_refresh_btn.click(None, inputs=[global_state_json, selected_saved_prompt_title], outputs=[global_state_json, selected_saved_prompt_title], _js="""(global_state_json, saved_prompts)=>{ try { if(global_state_json=="") {global_state_json=null;}; console.log('global_state_json:\\n', global_state_json); const global_state = JSON.parse(global_state_json??"{ }")??{ }; const saved = (JSON.parse(localStorage?.getItem?.('[gradio][chat-gpt-ui][prompts]') ?? '[]')); console.log('saved:\\n', saved); global_state['saved_prompts'] = saved; global_state['selected_saved_prompt_title'] = saved.map(it=>it?.title??"[untitled]")[0]; const results = [JSON.stringify(global_state), global_state['selected_saved_prompt_title']]; console.log(results); return results; } catch(error) { console.log(error); return ["{ }", ""]; }; }""") saved_prompts_list_refresh_btn.click( update_saved_prompt_titles, inputs=[global_state_json, selected_saved_prompt_title], outputs=[selected_saved_prompt_title], ) selected_saved_prompt_title.change(None, inputs=[global_state_json, selected_saved_prompt_title], outputs=[global_state_json, prompt_title, prompt_table], _js="""(global_state_json, selected_saved_prompt_title)=>{ if(global_state_json=="") {global_state_json=null;}; const global_state = JSON.parse(global_state_json??"{ }")??{ }; const found = (global_state?.['saved_prompts']??[]).find(it=>it?.title==selected_saved_prompt_title); return [JSON.stringify(global_state), found?.title??'', found?.content??{data:[], headers:["role", "content"]}]; }""") saved_prompts_delete_btn.click(None, inputs=[global_state_json, selected_saved_prompt_title, prompt_title, prompt_table], outputs=[global_state_json, selected_saved_prompt_title, prompt_title, prompt_table], _js="""(global_state_json, saved_prompts, prompt_title, prompt_table)=>{ if(prompt_title==""||!prompt_title){ return [global_state_json, selected_saved_prompt_title, prompt_title, prompt_table]; }; console.log('global_state_json:\\n', global_state_json); if(global_state_json=="") {global_state_json=null;}; const global_state = JSON.parse(global_state_json??"{ }")??{ }; console.log(global_state); const saved = (JSON.parse(localStorage?.getItem?.('[gradio][chat-gpt-ui][prompts]') ?? '[]')); console.log('saved:\\n', saved); global_state['saved_prompts'] = saved?.filter?.(it=>it.title!=prompt_title)??[]; global_state['selected_saved_prompt_title'] = ""; console.log(global_state); localStorage?.setItem?.('[gradio][chat-gpt-ui][prompts]', JSON.stringify(global_state['saved_prompts'])); return [JSON.stringify(global_state), "", "", {data: [], headers: ['role', 'content']}]; }""") saved_prompts_save_btn.click(None, inputs=[global_state_json, selected_saved_prompt_title, prompt_title, prompt_table], outputs=[global_state_json, selected_saved_prompt_title, prompt_title, prompt_table], _js="""(global_state_json, saved_prompts, prompt_title, prompt_table)=>{ if(prompt_title==""||!prompt_title){ return [global_state_json, selected_saved_prompt_title, prompt_title, prompt_table]; }; console.log('global_state_json:\\n', global_state_json); if(global_state_json=="") {global_state_json=null;}; const global_state = JSON.parse(global_state_json??"{ }")??{ }; console.log(global_state); const saved = (JSON.parse(localStorage?.getItem?.('[gradio][chat-gpt-ui][prompts]') ?? '[]')); console.log('saved:\\n', saved); const new_prompt_obj = { title: prompt_title, content: prompt_table, }; global_state['saved_prompts'] = saved?.filter?.(it=>it.title!=prompt_title)??[]; global_state['saved_prompts'].unshift(new_prompt_obj); global_state['selected_saved_prompt_title'] = prompt_title; console.log(global_state); localStorage?.setItem?.('[gradio][chat-gpt-ui][prompts]', JSON.stringify(global_state['saved_prompts'])); return [JSON.stringify(global_state), prompt_title, prompt_title, prompt_table]; }""") with gradio.Row(): with gradio.Column(scale=4): with gradio.Box(): gradio.Markdown("See https://platform.openai.com/docs/api-reference/chat/create .") chat_model = gradio.Dropdown(label="model", choices=[ "gpt-3.5-turbo", "gpt-3.5-turbo-0301", "gpt-4", "gpt-4-0314", "gpt-4-32k", "gpt-4-32k-0314", ], value="gpt-3.5-turbo") chat_temperature = gradio.Slider(label="temperature", value=1, minimum=0, maximum=2) chat_top_p = gradio.Slider(label="top_p", value=1, minimum=0, maximum=1) chat_choices_num = gradio.Slider(label="choices num(n)", value=1, minimum=1, maximum=20) chat_stream = gradio.Checkbox(label="stream", value=True, visible=True) chat_max_tokens = gradio.Slider(label="max_tokens", value=-1, minimum=-1, maximum=4096) chat_presence_penalty = gradio.Slider(label="presence_penalty", value=0, minimum=-2, maximum=2) chat_frequency_penalty = gradio.Slider(label="frequency_penalty", value=0, minimum=-2, maximum=2) chat_logit_bias = gradio.Textbox(label="logit_bias", visible=False) pass with gradio.Column(scale=8): with gradio.Row(): with gradio.Column(scale=10): chat_log = gradio.State() with gradio.Box(): with gradio.Column(scale=10): chat_log_box = gradio.Markdown(label='chat history', value="
(empty)
", elem_id="chat-log-md") real_md_box = gradio.Textbox(value="", visible=False) with gradio.Row(): chat_copy_history_btn = gradio.Button("Copy all (as HTML)") chat_copy_history_md_btn = gradio.Button("Copy all (as Markdown)") chat_copy_history_btn.click( copy_history, inputs=[chat_log_box], _js="""(txt)=>{ console.log(txt); try {let promise = navigator?.clipboard?.writeText?.(txt);} catch(error) {console?.log?.(error);}; }""", ) chat_copy_history_md_btn.click( copy_history, inputs=[real_md_box], _js="""(txt)=>{ console.log(txt); try {let promise = navigator?.clipboard?.writeText?.(txt);} catch(error) {console?.log?.(error);}; }""", ) chat_input_role = gradio.Dropdown(label='role', choices=['user', 'system', 'assistant'], value='user') chat_input = gradio.Textbox(lines=4, label='input') with gradio.Row(): chat_clear_history_btn = gradio.Button("clear history") chat_clear_history_btn.click(clear_history, inputs=[], outputs=[chat_log, chat_log_box]) chat_use_prompt = gradio.Checkbox(label='send with prompt', value=True) chat_use_history = gradio.Checkbox(label='send with history', value=True) chat_send_btn = gradio.Button("send") pass with gradio.Row(): chat_last_req = gradio.JSON(label='last request') chat_last_resp = gradio.JSON(label='last response') chat_send_btn.click( on_click_send_btn, inputs=[ global_state_json, api_key_text, chat_input_role, chat_input, prompt_table, chat_use_prompt, chat_use_history, chat_log, chat_model, chat_temperature, chat_top_p, chat_choices_num, chat_stream, chat_max_tokens, chat_presence_penalty, chat_frequency_penalty, chat_logit_bias, ], outputs=[global_state_json, chat_log, chat_log_box, real_md_box, chat_last_resp, chat_last_req, chat_input], api_name="click-send-btn", ) pass with gradio.Tab("Settings"): gradio.Markdown('Currently nothing.') pass if __name__ == "__main__": demo.queue(concurrency_count=20).launch()