From 4805e83c1211713b7b6d64fa74cd2514d709575b Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Mon, 16 Oct 2023 22:39:04 +0800 Subject: [PATCH 1/7] add_or_update->upsert --- erniebot/auth.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/erniebot/auth.py b/erniebot/auth.py index 00062e2bc..28293ca5a 100644 --- a/erniebot/auth.py +++ b/erniebot/auth.py @@ -69,11 +69,10 @@ def retrieve_entry(self, api_type: str, return key, val - def add_or_update_entry( - self, - api_type: str, - key: Hashable, - value: Union[str, Callable[[], str]]) -> Optional[str]: + def upsert_entry(self, + api_type: str, + key: Hashable, + value: Union[str, Callable[[], str]]) -> Optional[str]: with self._cond: self._writes += 1 while self._reads > 0 or self._is_writing: @@ -167,7 +166,7 @@ def _retrieve_from_cache(self) -> Optional[str]: self._cache_key)[1] def _update_cache(self, init: bool) -> str: - token = _GlobalAuthCache().add_or_update_entry( + token = _GlobalAuthCache().upsert_entry( self.api_type.name, self._cache_key, functools.partial( From 5b71fdbd12c3b0ad2e579ff6511960b08ccfed55 Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Tue, 17 Oct 2023 17:03:14 +0800 Subject: [PATCH 2/7] Remove unused fs --- examples/function_calling/function_calling_demo.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/function_calling/function_calling_demo.py b/examples/function_calling/function_calling_demo.py index fb33cf972..028a81b80 100644 --- a/examples/function_calling/function_calling_demo.py +++ b/examples/function_calling/function_calling_demo.py @@ -613,7 +613,8 @@ def generate_response( context.append(message) name2function = state['name2function'] functions = [name2function[name].desc for name in candidates] - data = { + params = { + 'model': ernie_model, 'messages': context, 'top_p': top_p, 'temperature': temperature, @@ -624,12 +625,11 @@ def generate_response( resp_stream = create_chat_completion( _config_={k: v for k, v in auth_config.items() if v}, - model=ernie_model, - **data, + **params, stream=True, ) except eb.errors.TokenUpdateFailedError as e: - handle_exception(e, f"鉴权参数无效,请重新填写", raise_=False) + handle_exception(e, "鉴权参数无效,请重新填写", raise_=False) yield get_fallback_return() return except eb.errors.EBError as e: @@ -846,7 +846,7 @@ def make_custom_function(code, desc_str): def call_function(state, candidates, func_name, func_args): name2function = state['name2function'] if text_is_empty(func_name): - gr.Warning(f"函数名称不能为空") + gr.Warning("函数名称不能为空") return None if func_name not in name2function: gr.Warning(f"函数`{func_name}`不存在") From 6a5611bc32d91015419d6ef9ee2012a793903e1b Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Tue, 17 Oct 2023 23:08:59 +0800 Subject: [PATCH 3/7] Fix function calling demo bugs --- .../function_calling/function_calling_demo.py | 659 ++++++++---------- 1 file changed, 308 insertions(+), 351 deletions(-) diff --git a/examples/function_calling/function_calling_demo.py b/examples/function_calling/function_calling_demo.py index 028a81b80..1a8a39aa3 100644 --- a/examples/function_calling/function_calling_demo.py +++ b/examples/function_calling/function_calling_demo.py @@ -185,283 +185,285 @@ def create_components(functions): raw_context_json = gr.JSON( label=f"最近{MAX_CONTEXT_LINES_TO_SHOW}条消息", scale=1) - api_type.change( - update_api_type, - inputs=[ - auth_state, - api_type, - ], - outputs=[ - auth_state, - access_key, - secret_key, - ], - ).success( - reset_conversation, - inputs=state, - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - ], - ) - access_key.change( - make_state_updater( - key='ak', strip=True), - inputs=[ - auth_state, - access_key, - ], - outputs=auth_state, - ) - secret_key.change( - make_state_updater( - key='sk', strip=True), - inputs=[ - auth_state, - secret_key, - ], - outputs=auth_state, - ) - access_token.change( - make_state_updater( - key='access_token', strip=True), - inputs=[ - auth_state, - access_token, - ], - outputs=auth_state, - ) + api_type.change( + update_api_type, + inputs=[ + auth_state, + api_type, + ], + outputs=[ + auth_state, + access_key, + secret_key, + ], + ).success( + reset_conversation, + inputs=state, + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + ], + ) + access_key.change( + make_state_updater( + key='ak', strip=True), + inputs=[ + auth_state, + access_key, + ], + outputs=auth_state, + ) + secret_key.change( + make_state_updater( + key='sk', strip=True), + inputs=[ + auth_state, + secret_key, + ], + outputs=auth_state, + ) + access_token.change( + make_state_updater( + key='access_token', strip=True), + inputs=[ + auth_state, + access_token, + ], + outputs=auth_state, + ) - disable_chat_input_args = { - 'fn': - lambda: replicate_gradio_update(6, interactive=False), - 'inputs': None, - 'outputs': [ - input_text, - clear_btn, - recall_btn, - regen_btn, - send_text_btn, - send_res_btn, - ], - 'show_progress': False, - 'queue': False, - } - enable_chat_input_args = { - 'fn': lambda: replicate_gradio_update(6, interactive=True), - 'inputs': None, - 'outputs': [ - input_text, - clear_btn, - recall_btn, - regen_btn, - send_text_btn, - send_res_btn, - ], - 'show_progress': False, - 'queue': False, - } - input_text.submit(**disable_chat_input_args).then( - generate_response_for_text, - inputs=[ - state, - chosen_func_names, - auth_state, - ernie_model, - input_text, - top_p, - temperature, - ], - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - func_call_accord, - ], - show_progress=False, - ).then(**enable_chat_input_args) - send_text_btn.click(**disable_chat_input_args).then( - generate_response_for_text, - inputs=[ - state, - chosen_func_names, - auth_state, - ernie_model, - input_text, - top_p, - temperature, - ], - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - func_call_accord, - ], - show_progress=False, - ).then(**enable_chat_input_args) - regen_btn.click(**disable_chat_input_args).then( - lambda history: (history and history[:-1], gr.update(interactive=False)), - inputs=context_chatbot, - outputs=[ - context_chatbot, - regen_btn, - ], - show_progress=False, - queue=False, - ).then( - regenerate_response, - inputs=[ - state, - chosen_func_names, - auth_state, - ernie_model, - top_p, - temperature, - ], - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - func_call_accord, - ], - show_progress=False, - ).then(**enable_chat_input_args) - recall_btn.click(**disable_chat_input_args).then( - recall_message, - inputs=state, - outputs=[state, context_chatbot, raw_context_json], - show_progress=False, - ).then(**enable_chat_input_args) - clear_btn.click(**disable_chat_input_args).then( - reset_conversation, - inputs=state, - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - ], - ).then(**enable_chat_input_args) - - chosen_func_names.select( - try_update_candidates, - inputs=[ - state, - chosen_func_names, - custom_func_code, - custom_func_desc, - ], - outputs=[ - state, - chosen_func_names, - ], - ) + disable_chat_input_args = { + 'fn': + lambda: replicate_gradio_update(6, interactive=False), + 'inputs': None, + 'outputs': [ + input_text, + clear_btn, + recall_btn, + regen_btn, + send_text_btn, + send_res_btn, + ], + 'show_progress': False, + 'queue': False, + } + enable_chat_input_args = { + 'fn': lambda: replicate_gradio_update(6, interactive=True), + 'inputs': None, + 'outputs': [ + input_text, + clear_btn, + recall_btn, + regen_btn, + send_text_btn, + send_res_btn, + ], + 'show_progress': False, + 'queue': False, + } + input_text.submit(**disable_chat_input_args).then( + generate_response_for_text, + inputs=[ + state, + chosen_func_names, + auth_state, + ernie_model, + input_text, + top_p, + temperature, + ], + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + func_call_accord, + ], + show_progress=False, + ).then(**enable_chat_input_args) + send_text_btn.click(**disable_chat_input_args).then( + generate_response_for_text, + inputs=[ + state, + chosen_func_names, + auth_state, + ernie_model, + input_text, + top_p, + temperature, + ], + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + func_call_accord, + ], + show_progress=False, + ).then(**enable_chat_input_args) + regen_btn.click(**disable_chat_input_args).then( + lambda history: (history and history[:-1], gr.update(interactive=False)), + inputs=context_chatbot, + outputs=[ + context_chatbot, + regen_btn, + ], + show_progress=False, + queue=False, + ).then( + regenerate_response, + inputs=[ + state, + chosen_func_names, + auth_state, + ernie_model, + top_p, + temperature, + ], + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + func_call_accord, + ], + show_progress=False, + ).then(**enable_chat_input_args) + recall_btn.click(**disable_chat_input_args).then( + recall_message, + inputs=state, + outputs=[state, context_chatbot, raw_context_json], + show_progress=False, + ).then(**enable_chat_input_args) + clear_btn.click(**disable_chat_input_args).then( + reset_conversation, + inputs=state, + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + ], + ).then(**enable_chat_input_args) + + chosen_func_names.select( + try_update_candidates, + inputs=[ + state, + chosen_func_names, + custom_func_code, + custom_func_desc, + ], + outputs=[ + state, + chosen_func_names, + ], + show_progress=False, + ) - custom_func_code.change( - remove_old_custom_function, - inputs=[ - state, - chosen_func_names, - ], - outputs=[ - state, - chosen_func_names, - ], - show_progress=False, - ) - custom_func_desc.change( - remove_old_custom_function, - inputs=[ - state, - chosen_func_names, - ], - outputs=[ - state, - chosen_func_names, - ], - show_progress=False, - ) - update_func_desc_btn.click( - try_update_custom_func_desc, - inputs=[ - custom_func_code, - custom_func_desc, - ], - outputs=custom_func_desc, - ) + custom_func_code.change( + remove_old_custom_function, + inputs=[ + state, + chosen_func_names, + ], + outputs=[ + state, + chosen_func_names, + ], + show_progress=False, + ) + custom_func_desc.change( + remove_old_custom_function, + inputs=[ + state, + chosen_func_names, + ], + outputs=[ + state, + chosen_func_names, + ], + show_progress=False, + ) + update_func_desc_btn.click( + update_custom_func_desc, + inputs=[ + custom_func_code, + custom_func_desc, + ], + outputs=custom_func_desc, + show_progress=False, + ) - call_func_btn.click( - lambda: gr.update(interactive=False), - outputs=call_func_btn, - show_progress=False, - queue=False, - ).then( - call_function, - inputs=[ - state, - chosen_func_names, - func_name, - func_in_params, - ], - outputs=func_out_params, - ).then( - lambda: gr.update(interactive=True), - outputs=call_func_btn, - show_progress=False, - queue=False, - ) - send_res_btn.click(**disable_chat_input_args).then( - generate_response_for_function, - inputs=[ - state, - chosen_func_names, - auth_state, - ernie_model, - func_name, - func_out_params, - top_p, - temperature, - ], - outputs=[ - state, - context_chatbot, - input_text, - raw_context_json, - func_name, - func_in_params, - func_out_params, - ], - show_progress=False, - ).then(**enable_chat_input_args) - reset_func_btn.click( - lambda: (None, None, None), - outputs=[ - func_name, - func_in_params, - func_out_params, - ], - show_progress=False, - ) + call_func_btn.click( + lambda: gr.update(interactive=False), + outputs=call_func_btn, + show_progress=False, + queue=False, + ).then( + call_function, + inputs=[ + state, + chosen_func_names, + func_name, + func_in_params, + ], + outputs=func_out_params, + show_progress=False, + ).then( + lambda: gr.update(interactive=True), + outputs=call_func_btn, + show_progress=False, + queue=False, + ) + send_res_btn.click(**disable_chat_input_args).then( + generate_response_for_function, + inputs=[ + state, + chosen_func_names, + auth_state, + ernie_model, + func_name, + func_out_params, + top_p, + temperature, + ], + outputs=[ + state, + context_chatbot, + input_text, + raw_context_json, + func_name, + func_in_params, + func_out_params, + ], + show_progress=False, + ).then(**enable_chat_input_args) + reset_func_btn.click( + lambda: (None, None, None), + outputs=[ + func_name, + func_in_params, + func_out_params, + ], + ) def create_function_tab(function): @@ -508,13 +510,9 @@ def generate_response_for_function( temperature, ): if text_is_empty(func_name): - gr.Warning("函数名称不能为空") - yield get_fallback_return() - return + raise gr.Error("函数名称不能为空") if func_res is None: - gr.Warning("无法获取函数响应参数,请调用函数") - yield get_fallback_return() - return + raise gr.Error("无法获取函数响应参数,请调用函数") message = { 'role': 'function', 'name': func_name, @@ -542,9 +540,7 @@ def generate_response_for_text( temperature, ): if text_is_empty(content): - gr.Warning("消息内容不能为空") - yield get_fallback_return() - return + raise gr.Error("消息内容不能为空") content = content.strip().replace('
', '\n') message = {'role': 'user', 'content': content} yield from generate_response( @@ -561,8 +557,7 @@ def generate_response_for_text( def recall_message(state): context = state['context'] if len(context) < 2: - gr.Warning("请至少进行一轮对话") - return replicate_gradio_update(3) + raise gr.Error("请至少进行一轮对话") context = context[:-2] history = extract_history(context) state['context'] = context @@ -579,9 +574,7 @@ def regenerate_response( ): context = state['context'] if len(context) < 2: - gr.Warning("请至少进行一轮对话") - yield get_fallback_return() - return + raise gr.Error("请至少进行一轮对话") context.pop() user_message = context.pop() yield from generate_response( @@ -629,13 +622,9 @@ def generate_response( stream=True, ) except eb.errors.TokenUpdateFailedError as e: - handle_exception(e, "鉴权参数无效,请重新填写", raise_=False) - yield get_fallback_return() - return + raise gr.Error("鉴权参数无效,请重新填写") from e except eb.errors.EBError as e: - handle_exception(e, f"请求失败。错误信息如下:{str(e)}", raise_=False) - yield get_fallback_return() - return + raise gr.Error(f"请求失败。错误信息如下:{str(e)}") from e context.append({'role': 'assistant', 'content': None}) history = None @@ -664,33 +653,30 @@ def generate_response( gr.update(open=True), ) break else: - if context[-1]['content'] is None: - context[-1]['content'] = resp.result - else: - context[-1]['content'] += resp.result if history is None: old_content = "" + history = extract_history(context) + if history[-1][1] is None: + history[-1][1] = "" else: old_content = history[-1][1] - history = extract_history(context, history) - new_content = history[-1][1] - temp_history = copy.copy(history) - # Partial deep copy - temp_history[-1] = history[-1][:] + if context[-1]['content'] is None: + context[-1]['content'] = resp.result + else: + context[-1]['content'] += resp.result + new_content = context[-1]['content'] for content in stream_output_smoother( old_content, new_content, - min_num_chars=1, - max_num_chars=4, - delay=0.1, ): - temp_history[-1][1] = content + history[-1][1] = content yield ( state, - temp_history, + history, None, *replicate_gradio_update(5), ) else: + history = extract_history(context) state['context'] = context yield ( state, @@ -700,28 +686,9 @@ def generate_response( *replicate_gradio_update(4), ) -def extract_history(context, old_history=None): - if old_history is not None: - history = old_history - else: - history = [] - - len_history = len(history) - len_context = len(context) - diff = len_history - (len(context) + 1) // 2 - if diff > 0: - for _ in range(diff): - history.pop() - return history - - if diff == 0: - if len_history > 0: - history.pop() - start = len_context - 1 - (len_context % 2 == 0) - else: - start = len_history * 2 - - for round_idx in range(start, len_context, 2): +def extract_history(context): + history = [] + for round_idx in range(0, len(context), 2): user_message = context[round_idx] pair = [] if user_message['role'] == 'function': @@ -748,20 +715,15 @@ def extract_history(context, old_history=None): assert len(pair) == 2 history.append(pair) - return history -def get_fallback_return(): - return replicate_gradio_update(8) - - def stream_output_smoother(old_content, new_content, *, min_num_chars=1, - max_num_chars=16, - delay=0.03, + max_num_chars=4, + delay=0.1, add_cursor=True): end = len(new_content) pos = len(old_content) @@ -799,7 +761,7 @@ def remove_old_custom_function(state, candidates): return state, candidates -def try_update_custom_func_desc(custom_func_code, custom_func_desc_str): +def update_custom_func_desc(custom_func_code, custom_func_desc_str): try: func = code_to_function(custom_func_code, CUSTOM_FUNC_NAME) sig = inspect.signature(func) @@ -827,8 +789,7 @@ def try_update_custom_func_desc(custom_func_code, custom_func_desc_str): new_params_desc['properties'][name] = param_desc custom_func_desc['parameters'] = new_params_desc except Exception as e: - handle_exception(e, f"更新函数描述失败,错误信息如下:{str(e)}", raise_=False) - return gr.update() + raise gr.Error(f"更新函数描述失败,错误信息如下:{str(e)}") from e else: return to_pretty_json(custom_func_desc) @@ -846,25 +807,21 @@ def make_custom_function(code, desc_str): def call_function(state, candidates, func_name, func_args): name2function = state['name2function'] if text_is_empty(func_name): - gr.Warning("函数名称不能为空") - return None + raise gr.Error("函数名称不能为空") if func_name not in name2function: - gr.Warning(f"函数`{func_name}`不存在") - return None + raise gr.Error(f"函数`{func_name}`不存在") if func_name not in candidates: - gr.Warning(f"函数`{func_name}`不是候选函数") - return None + raise gr.Error(f"函数`{func_name}`不是候选函数") func = name2function[func_name].func if text_is_empty(func_args): func_args = '{}' func_args = json_to_obj(func_args) if not isinstance(func_args, dict): - gr.Warning(f"无法将{reprlib.repr(func_args)}解析为字典") - return None + raise gr.Error(f"无法将{reprlib.repr(func_args)}解析为字典") try: res = func(**func_args) except Exception as e: - handle_exception(e, f"函数{func_name}调用失败,错误信息如下:{str(e)}", raise_=True) + raise gr.Error(f"函数{func_name}调用失败,错误信息如下:{str(e)}") from e return to_pretty_json(res, from_json=False) @@ -1053,11 +1010,11 @@ def to_pretty_json(obj, *, from_json=False): def handle_exception(exception, message, *, raise_=False): - traceback.print_exception( - type(exception), exception, exception.__traceback__) if raise_: raise gr.Error(message) else: + traceback.print_exception( + type(exception), exception, exception.__traceback__) gr.Warning(message) From faf61f94b0abd1e25e62c35fd29e24788feeea9e Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Wed, 18 Oct 2023 00:01:08 +0800 Subject: [PATCH 4/7] Update dependencies --- examples/function_calling/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/function_calling/requirements.txt b/examples/function_calling/requirements.txt index 7ed01b87a..ee8b1a6f8 100644 --- a/examples/function_calling/requirements.txt +++ b/examples/function_calling/requirements.txt @@ -1 +1 @@ -gradio >= 3.44.3 +gradio >= 3.48.0 From 037bed38f0d06abd8525b73ff348fd93296489f9 Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Wed, 18 Oct 2023 16:47:53 +0800 Subject: [PATCH 5/7] Refactor output smoother --- .../function_calling/function_calling_demo.py | 41 ++++++------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/examples/function_calling/function_calling_demo.py b/examples/function_calling/function_calling_demo.py index 1a8a39aa3..7af42e4f8 100644 --- a/examples/function_calling/function_calling_demo.py +++ b/examples/function_calling/function_calling_demo.py @@ -21,7 +21,6 @@ import inspect import json import operator -import random import reprlib import sys major = sys.version_info.major @@ -640,6 +639,7 @@ def generate_response( # formatted JSON. In this case we use the raw string. func_args = function_call['arguments'] context[-1]['function_call'] = function_call + assert history is None history = extract_history(context) state['context'] = context yield ( @@ -654,20 +654,15 @@ def generate_response( break else: if history is None: - old_content = "" history = extract_history(context) - if history[-1][1] is None: - history[-1][1] = "" - else: - old_content = history[-1][1] if context[-1]['content'] is None: - context[-1]['content'] = resp.result - else: - context[-1]['content'] += resp.result - new_content = context[-1]['content'] + context[-1]['content'] = "" + old_content = context[-1]['content'] + delta = resp.result + context[-1]['content'] += delta for content in stream_output_smoother( old_content, - new_content, + delta, ): history[-1][1] = content yield ( @@ -675,8 +670,8 @@ def generate_response( history, None, *replicate_gradio_update(5), ) + assert history[-1][1] == context[-1]['content'] else: - history = extract_history(context) state['context'] = context yield ( state, @@ -718,22 +713,12 @@ def extract_history(context): return history -def stream_output_smoother(old_content, - new_content, - *, - min_num_chars=1, - max_num_chars=4, - delay=0.1, - add_cursor=True): - end = len(new_content) - pos = len(old_content) - while pos < end: - offset = random.randint(min_num_chars, max_num_chars) - pos += offset - curr = new_content[:pos] - if add_cursor: - curr += "▌" - yield curr +def stream_output_smoother(old_content, delta, *, delay=0.03): + content = old_content + yield content + for char in delta: + content += char + yield content time.sleep(delay) From f120928fda94b57825b239267ddea1d9c80792e9 Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Thu, 19 Oct 2023 13:44:04 +0800 Subject: [PATCH 6/7] Fix demos --- examples/function_calling/function_calling_demo.py | 1 + examples/quick_start/gradio_demo.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/function_calling/function_calling_demo.py b/examples/function_calling/function_calling_demo.py index 7af42e4f8..800d3524e 100644 --- a/examples/function_calling/function_calling_demo.py +++ b/examples/function_calling/function_calling_demo.py @@ -52,6 +52,7 @@ def create_ui_and_launch(args): title="ERNIE Bot SDK Function Calling Demo", theme=gr.themes.Soft( spacing_size='sm', text_size='md')) as block: + gr.Markdown("# ERNIE Bot SDK函数调用功能演示") create_components(functions=get_predefined_functions()) block.queue( diff --git a/examples/quick_start/gradio_demo.py b/examples/quick_start/gradio_demo.py index 8541a62a4..6b2c2e41b 100644 --- a/examples/quick_start/gradio_demo.py +++ b/examples/quick_start/gradio_demo.py @@ -39,8 +39,7 @@ def parse_setup_args(): def create_ui_and_launch(args): with gr.Blocks(title="ERNIE Bot SDK", theme=gr.themes.Soft()) as block: - with gr.Row(): - gr.Markdown("# ERNIE Bot SDK") + gr.Markdown("# ERNIE Bot SDK基础功能演示") create_chat_completion_tab() create_embedding_tab() create_image_tab() @@ -167,8 +166,7 @@ def _get_history(context): rollback_btn = gr.Button("撤回") regen_btn = gr.Button("重新生成") send_btn = gr.Button("发送") - with gr.Row(): - raw_context_json = gr.JSON(label="原始对话上下文信息") + raw_context_json = gr.JSON(label="原始对话上下文信息") api_type.change( lambda api_type: { From 6483c82f19b0c0cfc088e787c8ee235d4fe21f5d Mon Sep 17 00:00:00 2001 From: Bobholamovic Date: Fri, 20 Oct 2023 11:41:37 +0800 Subject: [PATCH 7/7] ABCs are not necessarily protocols --- erniebot/resources/abc/cancellable.py | 9 ++++----- erniebot/resources/abc/creatable.py | 9 ++++----- erniebot/resources/abc/queryable.py | 9 ++++----- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/erniebot/resources/abc/cancellable.py b/erniebot/resources/abc/cancellable.py index 3cf97329a..4010844ac 100644 --- a/erniebot/resources/abc/cancellable.py +++ b/erniebot/resources/abc/cancellable.py @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import abc from typing import (Any, Dict, Optional, Tuple) -from typing_extensions import Protocol, runtime_checkable - from erniebot.response import EBResponse from erniebot.types import (ParamsType, HeadersType) from .protocol import Resource -@runtime_checkable -class Cancellable(Resource, Protocol): - """Cancellable resource protocol.""" +class Cancellable(Resource): + """Cancellable resource.""" @classmethod def cancel(cls, **kwargs: Any) -> EBResponse: @@ -68,6 +66,7 @@ async def acancel_resource(self, **cancel_kwargs: Any) -> EBResponse: resp = self._postprocess_cancel(resp) return resp + @abc.abstractmethod def _prepare_cancel(self, kwargs: Dict[str, Any]) -> Tuple[str, Optional[ParamsType], diff --git a/erniebot/resources/abc/creatable.py b/erniebot/resources/abc/creatable.py index cd0a08786..341ac0faf 100644 --- a/erniebot/resources/abc/creatable.py +++ b/erniebot/resources/abc/creatable.py @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import abc from typing import (Any, AsyncIterator, Dict, Iterator, Optional, Tuple, Union) -from typing_extensions import Protocol, runtime_checkable - from erniebot.response import EBResponse from erniebot.types import (ParamsType, HeadersType, FilesType, ResponseT) from .protocol import Resource -@runtime_checkable -class Creatable(Resource, Protocol): - """Creatable resource protocol.""" +class Creatable(Resource): + """Creatable resource.""" @classmethod def create(cls, **kwargs: Any) -> Union[EBResponse, Iterator[EBResponse]]: @@ -76,6 +74,7 @@ async def acreate_resource( resp = self._postprocess_create(resp) # type: ignore return resp + @abc.abstractmethod def _prepare_create(self, kwargs: Dict[str, Any]) -> Tuple[str, Optional[ParamsType], diff --git a/erniebot/resources/abc/queryable.py b/erniebot/resources/abc/queryable.py index fcb99beb4..c2f1e0b38 100644 --- a/erniebot/resources/abc/queryable.py +++ b/erniebot/resources/abc/queryable.py @@ -12,18 +12,16 @@ # See the License for the specific language governing permissions and # limitations under the License. +import abc from typing import (Any, Dict, Optional, Tuple) -from typing_extensions import Protocol, runtime_checkable - from erniebot.response import EBResponse from erniebot.types import (ParamsType, HeadersType) from .protocol import Resource -@runtime_checkable -class Queryable(Resource, Protocol): - """Queryable resource protocol.""" +class Queryable(Resource): + """Queryable resource.""" @classmethod def query(cls, **kwargs: Any) -> EBResponse: @@ -68,6 +66,7 @@ async def aquery_resource(self, **query_kwargs: Any) -> EBResponse: resp = self._postprocess_query(resp) return resp + @abc.abstractmethod def _prepare_query(self, kwargs: Dict[str, Any]) -> Tuple[str, Optional[ParamsType],