From dd75f98d85d8ef1d09e3e679c70d9e2950ece775 Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Fri, 4 Aug 2023 18:41:04 +0800 Subject: [PATCH 01/11] =?UTF-8?q?feat:=20=E4=B8=96=E7=95=8C=E4=B8=8A?= =?UTF-8?q?=E6=9C=80=E5=85=88=E8=BF=9B=E7=9A=84=E8=B0=83=E7=94=A8=E6=B5=81?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/openai/api/chat_completion.py | 18 +++++++++++------- pkg/openai/session.py | 20 ++++++++++++-------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/pkg/openai/api/chat_completion.py b/pkg/openai/api/chat_completion.py index 4c375f7e..1ea46ac6 100644 --- a/pkg/openai/api/chat_completion.py +++ b/pkg/openai/api/chat_completion.py @@ -30,7 +30,7 @@ class ChatCompletionRequest(RequestBase): ) self.pending_msg = "" - def append_message(self, role: str, content: str, name: str=None): + def append_message(self, role: str, content: str, name: str=None, function_call: dict=None): msg = { "role": role, "content": content @@ -39,6 +39,9 @@ class ChatCompletionRequest(RequestBase): if name is not None: msg['name'] = name + if function_call is not None: + msg['function_call'] = function_call + self.messages.append(msg) def __init__( @@ -87,16 +90,17 @@ class ChatCompletionRequest(RequestBase): choice0 = resp["choices"][0] # 如果不是函数调用,且finish_reason为stop,则停止迭代 - if 'function_call' not in choice0['message']: # and choice0["finish_reason"] == "stop" + if choice0['finish_reason'] == 'stop': # and choice0["finish_reason"] == "stop" self.stopped = True if 'function_call' in choice0['message']: self.pending_func_call = choice0['message']['function_call'] - # self.append_message( - # role="assistant", - # content="function call: "+json.dumps(self.pending_func_call, ensure_ascii=False) - # ) + self.append_message( + role="assistant", + content=None, + function_call=choice0['message']['function_call'] + ) return { "id": resp["id"], @@ -106,7 +110,7 @@ class ChatCompletionRequest(RequestBase): "message": { "role": "assistant", "type": "function_call", - "content": None, + "content": choice0['message']['content'], "function_call": choice0['message']['function_call'] }, "finish_reason": "function_call" diff --git a/pkg/openai/session.py b/pkg/openai/session.py index 1ab3fd88..2b8a145b 100644 --- a/pkg/openai/session.py +++ b/pkg/openai/session.py @@ -259,17 +259,21 @@ class Session: finish_reason = resp['choices'][0]['finish_reason'] - if resp['choices'][0]['message']['type'] == 'text': # 普通回复 - res_text += resp['choices'][0]['message']['content'] + if resp['choices'][0]['message']['role'] == "assistant" and resp['choices'][0]['message']['content'] != None: # 包含纯文本响应 + + res_text += resp['choices'][0]['message']['content'] + "\n" total_tokens += resp['usage']['total_tokens'] - pending_msgs.append( - { - "role": "assistant", - "content": resp['choices'][0]['message']['content'] - } - ) + msg = { + "role": "assistant", + "content": resp['choices'][0]['message']['content'] + } + + if 'function_call' in resp['choices'][0]['message']: + msg['function_call'] = resp['choices'][0]['message']['function_call'] + + pending_msgs.append(msg) elif resp['choices'][0]['message']['type'] == 'function_call': # self.prompt.append( From 054d0839acff84edf992e84c7d3359a0471a376b Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Fri, 4 Aug 2023 19:08:48 +0800 Subject: [PATCH 02/11] =?UTF-8?q?fix:=20=E6=9C=AA=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E7=9A=84function=5Fcall=E5=B1=9E=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/openai/modelmgr.py | 1 + pkg/openai/session.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/openai/modelmgr.py b/pkg/openai/modelmgr.py index 0b287752..cdc51297 100644 --- a/pkg/openai/modelmgr.py +++ b/pkg/openai/modelmgr.py @@ -112,6 +112,7 @@ def count_completion_tokens(messages: list, model: str) -> int: def count_tokens(messages: list, model: str): + if model in CHAT_COMPLETION_MODELS: return count_chat_completion_tokens(messages, model) elif model in COMPLETION_MODELS: diff --git a/pkg/openai/session.py b/pkg/openai/session.py index 2b8a145b..1400a8c6 100644 --- a/pkg/openai/session.py +++ b/pkg/openai/session.py @@ -271,7 +271,7 @@ class Session: } if 'function_call' in resp['choices'][0]['message']: - msg['function_call'] = resp['choices'][0]['message']['function_call'] + msg['function_call'] = json.dumps(resp['choices'][0]['message']['function_call']) pending_msgs.append(msg) From 3586cd941f7d2bf83fb71bc46d94b1e6c2322cb1 Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sat, 5 Aug 2023 21:44:11 +0800 Subject: [PATCH 03/11] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E8=B7=9F?= =?UTF-8?q?=E8=B8=AA=E5=87=BD=E6=95=B0=E8=B0=83=E7=94=A8=E8=BF=87=E7=A8=8B?= =?UTF-8?q?=E5=B9=B6=E9=BB=98=E8=AE=A4=E5=90=AF=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-template.py | 5 +++++ pkg/openai/api/chat_completion.py | 2 +- pkg/openai/session.py | 30 ++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/config-template.py b/config-template.py index 987e63da..4e6082ec 100644 --- a/config-template.py +++ b/config-template.py @@ -239,6 +239,11 @@ image_api_params = { "size": "256x256", # 图片尺寸,支持256x256, 512x512, 1024x1024 } +# 跟踪函数调用 +# 为True时,在每次GPT进行Function Calling时都会输出发送一条回复给用户 +# 同时,一次提问内所有的Function Calling和普通回复消息都会单独发送给用户 +trace_function_calls = True + # 群内回复消息时是否引用原消息 quote_origin = True diff --git a/pkg/openai/api/chat_completion.py b/pkg/openai/api/chat_completion.py index 1ea46ac6..032e14bc 100644 --- a/pkg/openai/api/chat_completion.py +++ b/pkg/openai/api/chat_completion.py @@ -98,7 +98,7 @@ class ChatCompletionRequest(RequestBase): self.append_message( role="assistant", - content=None, + content=choice0['message']['content'], function_call=choice0['message']['function_call'] ) diff --git a/pkg/openai/session.py b/pkg/openai/session.py index 1400a8c6..dd2b0d21 100644 --- a/pkg/openai/session.py +++ b/pkg/openai/session.py @@ -255,13 +255,33 @@ class Session: funcs = [] + trace_func_calls = config.trace_function_calls + botmgr = pkg.utils.context.get_qqbot_manager() + + session_name_spt: list[str] = self.name.split("_") + + pending_res_text = "" + + # TODO 对不起,我知道这样非常非常屎山,但我之后会重构的 for resp in pkg.utils.context.get_openai_manager().request_completion(prompts): + if pending_res_text != "": + botmgr.adapter.send_message( + session_name_spt[0], + session_name_spt[1], + pending_res_text + ) + pending_res_text = "" + finish_reason = resp['choices'][0]['finish_reason'] if resp['choices'][0]['message']['role'] == "assistant" and resp['choices'][0]['message']['content'] != None: # 包含纯文本响应 - res_text += resp['choices'][0]['message']['content'] + "\n" + if not trace_func_calls: + res_text += resp['choices'][0]['message']['content'] + "\n" + else: + res_text = resp['choices'][0]['message']['content'] + pending_res_text = resp['choices'][0]['message']['content'] total_tokens += resp['usage']['total_tokens'] @@ -275,13 +295,19 @@ class Session: pending_msgs.append(msg) - elif resp['choices'][0]['message']['type'] == 'function_call': + if resp['choices'][0]['message']['type'] == 'function_call': # self.prompt.append( # { # "role": "assistant", # "content": "function call: "+json.dumps(resp['choices'][0]['message']['function_call']) # } # ) + if trace_func_calls: + botmgr.adapter.send_message( + session_name_spt[0], + session_name_spt[1], + "调用函数 "+resp['choices'][0]['message']['function_call']['name'] + "..." + ) total_tokens += resp['usage']['total_tokens'] elif resp['choices'][0]['message']['type'] == 'function_return': From 89bb364b1613a78d27f8b3462a3d2d10d6bde1ad Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sat, 5 Aug 2023 13:44:30 +0000 Subject: [PATCH 04/11] Update override-all.json --- override-all.json | 1 + 1 file changed, 1 insertion(+) diff --git a/override-all.json b/override-all.json index e46e1c90..4f659de7 100644 --- a/override-all.json +++ b/override-all.json @@ -65,6 +65,7 @@ "image_api_params": { "size": "256x256" }, + "trace_function_calls": true, "quote_origin": true, "at_sender": false, "include_image_description": true, From 080e53d9a9a754e4f489eb47e72dfb50a6141291 Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sat, 5 Aug 2023 21:51:28 +0800 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20=E5=88=AA=E9=99=A4continue?= =?UTF-8?q?=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/cmds/session/continue.py | 27 --------------------------- res/wiki/功能使用.md | 1 - 2 files changed, 28 deletions(-) delete mode 100644 pkg/qqbot/cmds/session/continue.py diff --git a/pkg/qqbot/cmds/session/continue.py b/pkg/qqbot/cmds/session/continue.py deleted file mode 100644 index 6f5cc45b..00000000 --- a/pkg/qqbot/cmds/session/continue.py +++ /dev/null @@ -1,27 +0,0 @@ -from ..aamgr import AbstractCommandNode, Context - - -@AbstractCommandNode.register( - parent=None, - name="continue", - description="继续未完成的响应", - usage="!continue", - aliases=[], - privilege=1 -) -class ContinueCommand(AbstractCommandNode): - @classmethod - def process(cls, ctx: Context) -> tuple[bool, list]: - import pkg.openai.session - import config - session_name = ctx.session_name - - reply = [] - - session = pkg.openai.session.get_session(session_name) - - text, _, _ = session.append() - - reply = [text] - - return True, reply diff --git a/res/wiki/功能使用.md b/res/wiki/功能使用.md index 67b7ce89..df469bcf 100644 --- a/res/wiki/功能使用.md +++ b/res/wiki/功能使用.md @@ -180,7 +180,6 @@ !draw <提示语> 进行绘图 !version 查看当前版本并检查更新 !resend 重新回复上一个问题 -!continue 继续响应未完成的回合(通常用于内容函数继续调用) !plugin 用法请查看插件使用页的`管理`章节 !default 查看可用的情景预设值 ``` From 7979a8e97fa3cbec8f3ba53500df135b3961d732 Mon Sep 17 00:00:00 2001 From: GitHub Actions Bot Date: Sat, 5 Aug 2023 13:52:03 +0000 Subject: [PATCH 06/11] Update cmdpriv-template.json --- res/templates/cmdpriv-template.json | 1 - 1 file changed, 1 deletion(-) diff --git a/res/templates/cmdpriv-template.json b/res/templates/cmdpriv-template.json index e0944bda..33603878 100644 --- a/res/templates/cmdpriv-template.json +++ b/res/templates/cmdpriv-template.json @@ -8,7 +8,6 @@ "plugin.del": 2, "plugin.off": 2, "plugin.on": 2, - "continue": 1, "default": 1, "default.set": 2, "del": 1, From 1b0ae8da58d8a438c306b5d892773dc4f0e0be3c Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sat, 5 Aug 2023 22:00:32 +0800 Subject: [PATCH 07/11] =?UTF-8?q?refactor:=20session=20append=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E4=B8=BAquery?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/openai/session.py | 2 +- pkg/qqbot/message.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/openai/session.py b/pkg/openai/session.py index dd2b0d21..6bf13dca 100644 --- a/pkg/openai/session.py +++ b/pkg/openai/session.py @@ -194,7 +194,7 @@ class Session: # 请求回复 # 这个函数是阻塞的 - def append(self, text: str=None) -> tuple[str, str, list[str]]: + def query(self, text: str=None) -> tuple[str, str, list[str]]: """向session中添加一条消息,返回接口回复 Args: diff --git a/pkg/qqbot/message.py b/pkg/qqbot/message.py index 354c818a..309632f7 100644 --- a/pkg/qqbot/message.py +++ b/pkg/qqbot/message.py @@ -40,7 +40,7 @@ def process_normal_message(text_message: str, mgr, config, launcher_type: str, try: prefix = "[GPT]" if config.show_prefix else "" - text, finish_reason, funcs = session.append(text_message) + text, finish_reason, funcs = session.query(text_message) # 触发插件事件 args = { From 1aef81e38fc28d19813f6d85135e626dc51eb412 Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sun, 6 Aug 2023 12:17:04 +0800 Subject: [PATCH 08/11] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E7=BD=91?= =?UTF-8?q?=E7=BB=9C=E9=97=AE=E9=A2=98=E6=97=B6=E7=9A=84=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/qqbot/message.py b/pkg/qqbot/message.py index 309632f7..8fe168ae 100644 --- a/pkg/qqbot/message.py +++ b/pkg/qqbot/message.py @@ -68,7 +68,7 @@ def process_normal_message(text_message: str, mgr, config, launcher_type: str, except openai.error.APIConnectionError as e: err_msg = str(e) if err_msg.__contains__('Error communicating with OpenAI'): - reply = handle_exception("{}会话调用API失败:{}\n请尝试关闭网络代理来解决此问题。".format(session_name, e), + reply = handle_exception("{}会话调用API失败:{}\n您的网络无法访问OpenAI接口或网络代理不正常".format(session_name, e), "[bot]err:调用API失败,请重试或联系管理员,或等待修复") else: reply = handle_exception("{}会话调用API失败:{}".format(session_name, e), "[bot]err:调用API失败,请重试或联系管理员,或等待修复") From 3d40909c02ac1f3931207936fbebd4a1d17d71f4 Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sun, 6 Aug 2023 14:40:35 +0800 Subject: [PATCH 09/11] =?UTF-8?q?feat:=20=E4=B8=8D=E5=86=8D=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E5=90=AF=E7=94=A8trace=5Ffunction=5Fcalls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config-template.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config-template.py b/config-template.py index 4e6082ec..c3e6490c 100644 --- a/config-template.py +++ b/config-template.py @@ -242,7 +242,7 @@ image_api_params = { # 跟踪函数调用 # 为True时,在每次GPT进行Function Calling时都会输出发送一条回复给用户 # 同时,一次提问内所有的Function Calling和普通回复消息都会单独发送给用户 -trace_function_calls = True +trace_function_calls = False # 群内回复消息时是否引用原消息 quote_origin = True From 549e4dc02ee6704c324189ff9d29f89a67f994d0 Mon Sep 17 00:00:00 2001 From: GitHub Actions Date: Sun, 6 Aug 2023 06:41:00 +0000 Subject: [PATCH 10/11] Update override-all.json --- override-all.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/override-all.json b/override-all.json index 4f659de7..738264b1 100644 --- a/override-all.json +++ b/override-all.json @@ -65,7 +65,7 @@ "image_api_params": { "size": "256x256" }, - "trace_function_calls": true, + "trace_function_calls": false, "quote_origin": true, "at_sender": false, "include_image_description": true, From 33efb9401340b5e08611e19c1e0c9922e9d41e7c Mon Sep 17 00:00:00 2001 From: RockChinQ <1010553892@qq.com> Date: Sun, 6 Aug 2023 14:42:23 +0800 Subject: [PATCH 11/11] =?UTF-8?q?feat:=20=E5=BA=94=E7=94=A8cmdpriv?= =?UTF-8?q?=E6=97=B6=E5=BF=BD=E7=95=A5=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84?= =?UTF-8?q?=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/qqbot/cmds/aamgr.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/qqbot/cmds/aamgr.py b/pkg/qqbot/cmds/aamgr.py index 2f535102..cfc95b5a 100644 --- a/pkg/qqbot/cmds/aamgr.py +++ b/pkg/qqbot/cmds/aamgr.py @@ -327,6 +327,10 @@ def apply_privileges(): for path, priv in data.items(): if path == 'comment': continue + + if path not in __command_list__: + continue + if __command_list__[path]['privilege'] != priv: logging.debug('应用权限: {} -> {}(default: {})'.format(path, priv, __command_list__[path]['privilege']))