diff --git a/__main__.py b/__main__.py index ec33f1c..8570c48 100644 --- a/__main__.py +++ b/__main__.py @@ -75,16 +75,52 @@ class ChatBot(ChatBotFrame): self.chatbot = gr.Chatbot(elem_id='main_chatbot', label=f"当前模型:{LLM_MODEL}") self.chatbot.style() self.history = gr.State([]) - temp_draw = [gr.HTML() for i in range(4)] + temp_draw = [gr.HTML() for i in range(2)] with gr.Row(): self.txt = gr.Textbox(show_label=False, placeholder="Input question here.", elem_id='chat_txt').style(container=False) self.input_copy = gr.State('') - self.submitBtn = gr.Button("提交", variant="primary", visible=False).style(full_width=False) - with gr.Row(elem_id='debug_mes'): - self.status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}") + self.submitBtn = gr.Button("", variant="primary", elem_classes='submit_btn').style(full_width=False) + with gr.Row(): + self.status = gr.Markdown(f"Tip: 按Enter提交, 按Shift+Enter换行。当前模型: {LLM_MODEL} \n {proxy_info}", elem_id='debug_mes') + + + def draw_examples(self): + with gr.Column(elem_id='examples_col') as self.examples_column: + gr.Markdown('# Get Started Quickly') + with gr.Row(): + hide_components = gr.Textbox(visible=False) + gr.Button.update = func_box.update_btn + self.example = [['今天伦敦天气怎么样?', '对2021年以后的世界和事件了解有限', self.submitBtn.update(elem_id='highlight_update')], + ['今夕何夕,明月何月?', '偶尔会产生不正确的信息', self.submitBtn.update(elem_id='highlight_update')], + ['怎么才能把学校给炸了?', '经过训练,会拒绝不适当的请求', self.submitBtn.update(elem_id='highlight_update')]] + self.example_inputs = [self.txt, hide_components, self.submitBtn] + self.guidance_example = gr.Examples(examples=self.example, inputs=self.example_inputs, label='基础对话') + self.guidance_plugins = gr.Dataset(components=[gr.HTML(visible=False)], samples=[['...'] for i in range(4)], label='高级功能', type='index') + self.guidance_plugins_state = gr.State() + self.guidance_news = gr.Examples(examples=func_box.git_log_list(), inputs=[hide_components, hide_components], label='News') + + def plug_update(index, date_set): + variant = crazy_fns[date_set[index]]["Color"] if "Color" in crazy_fns[date_set[index]] else "secondary" + ret = {self.switchy_bt: self.switchy_bt.update(value=date_set[index], variant=variant, elem_id='highlight_update'), + self.tabs_inputs: gr.Tabs.update(selected='plug_tab'), + self.area_crazy_fn: self.area_crazy_fn.update(open=True)} + fns_value = func_box.txt_converter_json(str(crazy_fns[date_set[index]].get('Parameters', ''))) + fns_lable = f"插件[{date_set[index]}]的高级参数说明:\n" + crazy_fns[date_set[index]].get("ArgsReminder", f"没有提供高级参数功能说明") + temp_dict = dict(visible=True, interactive=True, value=str(fns_value), label=fns_lable) + # 是否唤起高级插件参数区 + if crazy_fns[date_set[index]].get("AdvancedArgs", False): + ret.update({self.plugin_advanced_arg: gr.update(**temp_dict)}) + ret.update({self.area_crazy_fn: self.area_crazy_fn.update(open=False)}) + else: + ret.update({self.plugin_advanced_arg: gr.update(visible=False, label=f"插件[{date_set[index]}]不需要高级参数。")}) + return ret + + self.guidance_plugins.select(fn=plug_update, inputs=[self.guidance_plugins, self.guidance_plugins_state], + outputs=[self.switchy_bt, self.plugin_advanced_arg, self.tabs_inputs, + self.area_crazy_fn]) def __clear_input(self, inputs): - return '', inputs + return '', inputs, self.examples_column.update(visible=False) def draw_prompt(self): with gr.Row(): @@ -102,7 +138,7 @@ class ChatBot(ChatBotFrame): with gr.Row(): with gr.Column(scale=100): self.pro_results = gr.Chatbot(label='Prompt and result', elem_id='prompt_result').style() - with gr.Column(scale=11): + with gr.Column(scale=16): Tips = "用 BORF 分析法设计chat GPT prompt:\n" \ "1、阐述背景 B(Background): 说明背景,为chatGPT提供充足的信息\n" \ "2、定义目标 O(Objectives):“我们希望实现什么”\n" \ @@ -147,16 +183,12 @@ class ChatBot(ChatBotFrame): self.pro_reuse_btn.click( fn=func_box.reuse_chat, inputs=[self.pro_results, self.chatbot, self.history, self.pro_name_txt], - outputs=[self.chatbot, self.history, self.txt, self.tabs_chatbot, self.pro_name_txt] + outputs=[self.chatbot, self.history, self.txt, self.tabs_chatbot, self.pro_name_txt, self.examples_column] ) def draw_function_chat(self): prompt_list, devs_document = get_conf('prompt_list', 'devs_document') - with gr.Row(): - # self.cpopyBtn = gr.Button("复制回答", variant="secondary").style(size="sm") - self.resetBtn = gr.Button("新建对话", variant="secondary", elem_id='empty_btn').style(size="sm") - self.stopBtn = gr.Button("中止对话", variant="stop").style(size="sm") - with gr.Tab('Function'): + with gr.TabItem('Function', id='func_tab'): with gr.Accordion("基础功能区", open=True) as self.area_basic_fn: with gr.Row(): for k in functional: @@ -189,7 +221,7 @@ class ChatBot(ChatBotFrame): self.prompt_tab.select(fn=lambda: 1, inputs=None, outputs=self.tabs_code) def draw_public_chat(self): - with gr.Tab('Plugins'): + with gr.TabItem('Plugins', id='plug_tab'): with gr.Accordion("上传本地文件可供高亮函数插件调用", open=False) as self.area_file_up: self.file_upload = gr.Files(label="任何文件, 但推荐上传压缩文件(zip, tar)", file_count="multiple") @@ -220,7 +252,7 @@ class ChatBot(ChatBotFrame): def draw_setting_chat(self): switch_model = get_conf('switch_model')[0] - with gr.Tab('Settings'): + with gr.TabItem('Settings', id='sett_tab'): self.top_p = gr.Slider(minimum=-0, maximum=1.0, value=1.0, step=0.01, interactive=True, label="Top-p (nucleus sampling)", ).style(container=False) self.temperature = gr.Slider(minimum=-0, maximum=2.0, value=1.0, step=0.01, interactive=True, @@ -270,7 +302,8 @@ class ChatBot(ChatBotFrame): self.system_prompt, self.models_box, self.plugin_advanced_arg] self.output_combo = [self.cookies, self.chatbot, self.history, self.status] self.predict_args = dict(fn=ArgsGeneralWrapper(predict), inputs=self.input_combo, outputs=self.output_combo) - self.clear_agrs = dict(fn=self.__clear_input, inputs=[self.txt], outputs=[self.txt, self.input_copy]) + self.clear_agrs = dict(fn=self.__clear_input, inputs=[self.txt], outputs=[self.txt, self.input_copy, + self.examples_column]) # 提交按钮、重置按钮 self.cancel_handles.append(self.txt.submit(**self.clear_agrs).then(**self.predict_args)) self.cancel_handles.append(self.submitBtn.click(**self.clear_agrs).then(**self.predict_args)) @@ -305,7 +338,7 @@ class ChatBot(ChatBotFrame): def on_dropdown_changed(k): # 按钮颜色随变 variant = crazy_fns[k]["Color"] if "Color" in crazy_fns[k] else "secondary" - ret = {self.switchy_bt: gr.update(value=k, variant=variant)} + ret = {self.switchy_bt: self.switchy_bt.update(value=k, variant=variant)} # 参数取随变 fns_value = func_box.txt_converter_json(str(crazy_fns[k].get('Parameters', ''))) fns_lable = f"插件[{k}]的高级参数说明:\n" + crazy_fns[k].get("ArgsReminder", f"没有提供高级参数功能说明") @@ -336,13 +369,12 @@ class ChatBot(ChatBotFrame): self.md_dropdown.select(on_md_dropdown_changed, [self.md_dropdown], [self.chatbot]) def signals_auto_input(self): - from autogpt.cli import agent_main self.auto_input_combo = [self.ai_name, self.ai_role, self.ai_goal_list, self.ai_budget, self.cookies, self.chatbot, self.history, self.agent_obj] self.auto_output_combo = [self.cookies, self.chatbot, self.history, self.status, self.agent_obj, self.submit_start, self.submit_next, self.text_continue] - self.submit_start.click(fn=agent_main, inputs=self.auto_input_combo, outputs=self.auto_output_combo) + # gradio的inbrowser触发不太稳定,回滚代码到原始的浏览器打开函数 def auto_opentab_delay(self, is_open=False): @@ -369,13 +401,19 @@ class ChatBot(ChatBotFrame): # 绘制一个ROW,row会让底下的元素自动排成一行 with gr.Row().style(justify='between'): # 绘制列1 - with gr.Column(scale=46): + with gr.Column(scale=44): with gr.Tabs() as self.tabs_copilot: # 绘制对话模组 with gr.TabItem('Chat-Copilot'): - self.draw_function_chat() - self.draw_public_chat() - self.draw_setting_chat() + with gr.Row(): + # self.cpopyBtn = gr.Button("复制回答", variant="secondary").style(size="sm") + self.resetBtn = gr.Button("新建对话", variant="secondary", elem_id='empty_btn').style( + size="sm") + self.stopBtn = gr.Button("中止对话", variant="stop").style(size="sm") + with gr.Tabs() as self.tabs_inputs: + self.draw_function_chat() + self.draw_public_chat() + self.draw_setting_chat() # 绘制autogpt模组 with gr.TabItem('Auto-GPT'): @@ -392,6 +430,7 @@ class ChatBot(ChatBotFrame): with self.chat_tab: # 使用 gr.State()对组件进行拷贝时,如果之前绘制了Markdown格式,会导致启动崩溃,所以将 markdown相关绘制放在最后 self.draw_chatbot() + self.draw_examples() with self.prompt_tab: self.draw_temp_edit() # 函数注册,需要在Blocks下进行 @@ -401,7 +440,10 @@ class ChatBot(ChatBotFrame): self.signals_public() self.signals_prompt_edit() # self.signals_auto_input() - self.demo.load(fn=func_box.refresh_load_data, postprocess=False, inputs=[self.chatbot, self.history, self.pro_fp_state], outputs=[self.pro_func_prompt, self.pro_fp_state, self.chatbot, self.history, ]) + adv_plugins = gr.State([i for i in crazy_fns]) + self.demo.load(fn=func_box.refresh_load_data, postprocess=False, + inputs=[self.chatbot, self.history, self.pro_fp_state, adv_plugins], + outputs=[self.pro_func_prompt, self.pro_fp_state, self.chatbot, self.history, self.guidance_plugins, self.guidance_plugins_state]) # Start self.auto_opentab_delay() diff --git a/core_functional.py b/core_functional.py index a86cb43..ab1600d 100644 --- a/core_functional.py +++ b/core_functional.py @@ -78,5 +78,9 @@ def get_core_functions(): } +def get_guidance(): + pass + + def get_guidance(): pass \ No newline at end of file diff --git a/docs/assets/custom.css b/docs/assets/custom.css index 29377e0..89480a4 100644 --- a/docs/assets/custom.css +++ b/docs/assets/custom.css @@ -11,6 +11,38 @@ mspace { display: block; } + +@keyframes highlight { + 0%, 100% { + border: 2px solid transparent; + } + 50% { + border-color: yellow; + } +} + +#highlight_update { + animation-name: highlight; + animation-duration: 0.75s; + animation-iteration-count: 3; +} + +.table-wrap.svelte-13hsdno.svelte-13hsdno.svelte-13hsdno { + border: 0px solid var(--border-color-primary) !important; +} + +#examples_col { + z-index: 3; + position: absolute; + bottom: 0; + left: 0; + width: 100%; + margin-bottom: 30% !important; +} +.gradio-container-3-32-2 h6 { + font-weight: 200 !important; + font-size: 12px !important; +} .gradio-container-3-32-2 h1 { font-weight: 700 !important; font-size: 28px !important; @@ -31,17 +63,18 @@ mspace { font-weight: 300 !important; font-size: 14px !important; } -.gradio-container-3-32-2 h6 { - font-weight: 200 !important; - font-size: 12px !important; +#hide_examples { + z-index: 0; } + #debug_mes { position: absolute; + display: flex; bottom: 0; left: 0; width: 100%; z-index: 1; /* 设置更高的 z-index 值 */ - margin-bottom: 10px !important; + margin-bottom: -4px !important; } #chat_txt { display: flex; @@ -53,8 +86,24 @@ mspace { bottom: 0; left: 0; width: 100%; - margin-bottom: 35px !important; + margin-bottom: 20px !important; } + +.submit_btn { + display: flex; + flex-direction: column-reverse; + overflow-y: auto !important; + z-index: 3; + flex-grow: 1; /* 自动填充剩余空间 */ + position: absolute; + bottom: 0; + right: 0; + width: 100%; + margin-bottom: 20px !important; + min-width: min(50px,100%) !important; +} + + #sm_btn { display: flex; flex-wrap: unset !important; @@ -182,6 +231,33 @@ span.svelte-1gfkn6j { height: 100%; } +.gradio-container-3-32-2 h1 { + font-weight: 700 !important; + font-size: 28px !important; +} + + +.gradio-container-3-32-2 h2 { + font-weight: 600 !important; + font-size: 24px !important; +} +.gradio-container-3-32-2 h3 { + font-weight: 500 !important; + font-size: 20px !important; +} +.gradio-container-3-32-2 h4 { + font-weight: 400 !important; + font-size: 16px !important; +} +.gradio-container-3-32-2 h5 { + font-weight: 300 !important; + font-size: 14px !important; +} +.gradio-container-3-32-2 h6 { + font-weight: 200 !important; + font-size: 12px !important; +} + /* usage_display */ .insert_block { position: relative; @@ -296,10 +372,10 @@ input[type=range]::-webkit-slider-runnable-track { background: transparent; } -#submit_btn, #cancel_btn { +.submit_btn, #cancel_btn { height: 42px !important; } -#submit_btn::before { +.submit_btn::before { content: url("data:image/svg+xml, %3Csvg width='21px' height='20px' viewBox='0 0 21 20' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E %3Cg id='page' stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E %3Cg id='send' transform='translate(0.435849, 0.088463)' fill='%23FFFFFF' fill-rule='nonzero'%3E %3Cpath d='M0.579148261,0.0428666046 C0.301105539,-0.0961547561 -0.036517765,0.122307382 0.0032026237,0.420210298 L1.4927172,18.1553639 C1.5125774,18.4334066 1.79062012,18.5922882 2.04880264,18.4929872 L8.24518329,15.8913017 L11.6412765,19.7441794 C11.8597387,19.9825018 12.2370824,19.8832008 12.3165231,19.5852979 L13.9450591,13.4882182 L19.7839562,11.0255541 C20.0619989,10.8865327 20.0818591,10.4694687 19.7839562,10.3105871 L0.579148261,0.0428666046 Z M11.6138902,17.0883151 L9.85385903,14.7195502 L0.718169621,0.618812241 L12.69945,12.9346347 L11.6138902,17.0883151 Z' id='shape'%3E%3C/path%3E %3C/g%3E %3C/g%3E %3C/svg%3E"); height: 21px; } diff --git a/docs/imgs/pic_desc.png b/docs/imgs/pic_desc.png new file mode 100644 index 0000000..6b6d434 Binary files /dev/null and b/docs/imgs/pic_desc.png differ diff --git a/func_box.py b/func_box.py index e38b59f..f1150a4 100644 --- a/func_box.py +++ b/func_box.py @@ -133,7 +133,7 @@ def html_tag_color(tag, color=None, font='black'): def html_a_blank(__href, name=''): if not name: - dir_name = __href + name = __href a = f'{name}' return a @@ -145,6 +145,9 @@ def html_download_blank(__href, file_name='temp', dir_name=''): a = f'{file_name}' return a +def html_local_img(__file): + a = f'
' + return a def ipaddr(): # 获取本地ipx @@ -301,8 +304,9 @@ def diff_list(txt='', percent=0.70, switch: list = None, lst: dict = None, sp=15 for key in sorted_dict: # 开始匹配关键字 index = str(key[0]).lower().find(txt.lower()) - - if index != -1: + index_ = str(key[1]).lower().find(txt.lower()) + if index != -1 or index_ != -1: + if index == -1: index = index_ # 增加搜索prompt 名称 # sp=split 用于判断在哪里启动、在哪里断开 if index - sp > 0: start = index - sp @@ -505,7 +509,10 @@ def thread_write_chat(chatbot, history): private_key = toolbox.get_conf('private_key')[0] chat_title = chatbot[0][1].split() i_say = pattern_markdown.sub('', chatbot[-1][0]) - gpt_result = history + if history: + gpt_result = history + else: # 如果历史对话不存在,那么读取对话框 + gpt_result = [pattern_markdown.sub('', v) for i in chatbot for v in i] if private_key in chat_title: SqliteHandle(f'ai_private_{chat_title[-2]}').inset_prompt({i_say: gpt_result}) else: @@ -515,11 +522,10 @@ def thread_write_chat(chatbot, history): base_path = os.path.dirname(__file__) prompt_path = os.path.join(base_path, 'prompt_users') - def reuse_chat(result, chatbot, history, pro_numb): """复用对话记录""" if result is None or result == []: - return chatbot, history, gr.update(), gr.update(), '' + return chatbot, history, gr.update(), gr.update(), '', gr.Column.update() else: if pro_numb: chatbot += result @@ -529,7 +535,7 @@ def reuse_chat(result, chatbot, history, pro_numb): history += [pattern_markdown.sub('', _) for i in result[-2:] for _ in i] print(chatbot[-1][0]) i_say = pattern_markdown.sub('', chatbot[-1][0]) - return chatbot, history, i_say, gr.Tabs.update(selected='chatbot'), '' + return chatbot, history, i_say, gr.Tabs.update(selected='chatbot'), '', gr.Column.update(visible=False) def num_tokens_from_string(listing: list, encoding_name: str = 'cl100k_base') -> int: @@ -553,7 +559,7 @@ def spinner_chatbot_loading(chatbot): loading_msg[-1] = tuple(temp_list) return loading_msg -def refresh_load_data(chat, history, prompt): +def refresh_load_data(chat, history, prompt, crazy_list): """ Args: chat: 聊天组件 @@ -566,7 +572,8 @@ def refresh_load_data(chat, history, prompt): is_all = toolbox.get_conf('prompt_list')[0]['key'][0] data = prompt_retrieval(is_all=[is_all]) prompt.samples = data - return prompt.update(samples=data, visible=True), prompt, chat, history + selected = random.sample(crazy_list, 4) + return prompt.update(samples=data, visible=True), prompt, chat, history, gr.Dataset.update(samples=[[i] for i in selected]), selected @@ -588,6 +595,70 @@ def clean_br_string(s): s = re.sub('<\s*br\s*/?>', '\n', s) # 使用正则表达式同时匹配


、< br>和< br/> return s + +def update_btn(self, + value: str = None, + variant: str = None, + visible: bool = None, + interactive: bool = None, + elem_id: str = None, + label: str = None +): + if not variant: variant = self.variant + if not visible: visible = self.visible + if not value: value = self.value + if not interactive: interactive = self.interactive + if not elem_id: elem_id = self.elem_id + if not elem_id: label = self.label + return { + "variant": variant, + "visible": visible, + "value": value, + "interactive": interactive, + 'elem_id': elem_id, + 'label': label, + "__type__": "update", + } + +def update_txt(self, + value: str = None, + lines: int = None, + max_lines: int = None, + placeholder: str = None, + label: str = None, + show_label: bool = None, + visible: bool = None, + interactive: bool = None, + type: str = None, + elem_id: str = None + ): + + return { + "lines": self.lines, + "max_lines": self.max_lines, + "placeholder": self.placeholder, + "label": self.label, + "show_label": self.show_label, + "visible": self.visible, + "value": self.value, + "type": self.type, + "interactive": self.interactive, + "elem_id": elem_id, + "__type__": "update", + + } + + +def txtx(f, q): + return f + + +def git_log_list(): + ll = Shell("git log --pretty=format:'%s | %h' -n 10").read()[1].splitlines() + + return [i.split('|') for i in ll if 'branch' not in i][:5] + + class YamlHandle: def __init__(self, file=os.path.join(prompt_path, 'ai_common.yaml')): @@ -633,4 +704,4 @@ class JsonHandle: if __name__ == '__main__': - pass \ No newline at end of file + html_local_img("docs/imgs/openai-api-key-billing-paid-account.png") \ No newline at end of file diff --git a/toolbox.py b/toolbox.py index bfcaf84..47b1990 100644 --- a/toolbox.py +++ b/toolbox.py @@ -595,7 +595,7 @@ def is_api2d_key(key): return False def is_proxy_key(key): - if 'proxy' in key: + if key.startswith('proxy-') and len(key) == 37: return True else: return False @@ -621,7 +621,14 @@ def what_keys(keys): if is_api2d_key(k): avail_key_list['API2D Key'] += 1 - return f"检测到: OpenAI Key {avail_key_list['OpenAI Key']} 个,API2D Key {avail_key_list['API2D Key']} 个" + for k in key_list: + if is_proxy_key(k): + avail_key_list['Proxy Key'] += 1 + + return f"检测到: \n" \ + f"OpenAI Key {avail_key_list['OpenAI Key']} 个\n" \ + f"API2D Key {avail_key_list['API2D Key']} 个\n" \ + f"Proxy Key {avail_key_list['API2D Key']} 个\n" def select_api_key(keys, llm_model): import random @@ -636,7 +643,7 @@ def select_api_key(keys, llm_model): for k in key_list: if is_api2d_key(k): avail_key_list.append(k) - if llm_model.startswith('proxy'): + if llm_model.startswith('proxy-'): for k in key_list: if is_proxy_key(k): avail_key_list.append(k.replace('proxy-', ''))