diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index 397c49fe..7181f918 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -11,9 +11,12 @@ body:
- 其他(或暂未使用)
- Nakuru(go-cqhttp)
- aiocqhttp(使用 OneBot 协议接入的)
- - qq-botpy(QQ官方API)
+ - qq-botpy(QQ官方API WebSocket)
+ - qqofficial(QQ官方API Webhook)
- lark(飞书)
- wecom(企业微信)
+ - gewechat(个人微信)
+ - discord
validations:
required: true
- type: input
diff --git a/README.md b/README.md
index fc78032c..2921bf23 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
-

+
项目主页 |
功能介绍 |
diff --git a/pkg/core/notes/n003_print_version.py b/pkg/core/notes/n003_print_version.py
new file mode 100644
index 00000000..6eed21d6
--- /dev/null
+++ b/pkg/core/notes/n003_print_version.py
@@ -0,0 +1,21 @@
+from __future__ import annotations
+
+import typing
+import os
+import sys
+import logging
+
+from .. import note, app
+
+
+@note.note_class("PrintVersion", 3)
+class PrintVersion(note.LaunchNote):
+ """打印版本信息
+ """
+
+ async def need_show(self) -> bool:
+ return True
+
+ async def yield_note(self) -> typing.AsyncGenerator[typing.Tuple[str, int], None]:
+
+ yield f"当前版本:{self.ap.ver_mgr.get_current_version()}", logging.INFO
diff --git a/pkg/core/stages/show_notes.py b/pkg/core/stages/show_notes.py
index 91cdbf01..63d8f580 100644
--- a/pkg/core/stages/show_notes.py
+++ b/pkg/core/stages/show_notes.py
@@ -1,7 +1,7 @@
from __future__ import annotations
from .. import stage, app, note
-from ..notes import n001_classic_msgs, n002_selection_mode_on_windows
+from ..notes import n001_classic_msgs, n002_selection_mode_on_windows, n003_print_version
@stage.stage_class("ShowNotesStage")
diff --git a/pkg/pipeline/wrapper/wrapper.py b/pkg/pipeline/wrapper/wrapper.py
index 1ffb3147..a06e4a80 100644
--- a/pkg/pipeline/wrapper/wrapper.py
+++ b/pkg/pipeline/wrapper/wrapper.py
@@ -102,7 +102,7 @@ class ResponseWrapper(stage.PipelineStage):
new_query=query
)
- if result.tool_calls is not None: # 有函数调用
+ if result.tool_calls is not None and len(result.tool_calls) > 0: # 有函数调用
function_names = [tc.function.name for tc in result.tool_calls]
diff --git a/pkg/platform/sources/qqofficial.py b/pkg/platform/sources/qqofficial.py
index 924e7ba0..7993062a 100644
--- a/pkg/platform/sources/qqofficial.py
+++ b/pkg/platform/sources/qqofficial.py
@@ -47,6 +47,7 @@ class QQOfficialMessageConverter(adapter.MessageConverter):
yiri_msg_list.append(
platform_message.Image(base64=base64_url)
)
+
yiri_msg_list.append(platform_message.Plain(text=message))
chain = platform_message.MessageChain(yiri_msg_list)
return chain
diff --git a/pkg/provider/modelmgr/requesters/chatcmpl.py b/pkg/provider/modelmgr/requesters/chatcmpl.py
index 9e3014af..0b1c4cf2 100644
--- a/pkg/provider/modelmgr/requesters/chatcmpl.py
+++ b/pkg/provider/modelmgr/requesters/chatcmpl.py
@@ -8,6 +8,7 @@ from typing import AsyncGenerator
import openai
import openai.types.chat.chat_completion as chat_completion
+import openai.types.chat.chat_completion_message_tool_call as chat_completion_message_tool_call
import httpx
import aiohttp
import async_lru
@@ -40,6 +41,7 @@ class OpenAIChatCompletions(requester.LLMAPIRequester):
timeout=self.requester_cfg['timeout'],
http_client=httpx.AsyncClient(
trust_env=True,
+ timeout=self.requester_cfg['timeout']
)
)
@@ -47,7 +49,67 @@ class OpenAIChatCompletions(requester.LLMAPIRequester):
self,
args: dict,
) -> chat_completion.ChatCompletion:
- return await self.client.chat.completions.create(**args)
+ args["stream"] = True
+
+ chunk = None
+
+ pending_content = ""
+
+ tool_calls = []
+
+ resp_gen: openai.AsyncStream = await self.client.chat.completions.create(**args)
+
+ async for chunk in resp_gen:
+ # print(chunk)
+ if not chunk:
+ continue
+
+ if chunk.choices[0].delta.content is not None:
+ pending_content += chunk.choices[0].delta.content
+
+ if chunk.choices[0].delta.tool_calls is not None:
+ for tool_call in chunk.choices[0].delta.tool_calls:
+ for tc in tool_calls:
+ if tc.index == tool_call.index:
+ tc.function.arguments += tool_call.function.arguments
+ break
+ else:
+ tool_calls.append(tool_call)
+
+ real_tool_calls = []
+
+ for tc in tool_calls:
+ function = chat_completion_message_tool_call.Function(
+ name=tc.function.name,
+ arguments=tc.function.arguments
+ )
+ real_tool_calls.append(chat_completion_message_tool_call.ChatCompletionMessageToolCall(
+ id=tc.id,
+ function=function,
+ type="function"
+ ))
+
+ return chat_completion.ChatCompletion(
+ id=chunk.id,
+ object="chat.completion",
+ created=chunk.created,
+ choices=[
+ chat_completion.Choice(
+ index=0,
+ message=chat_completion.ChatCompletionMessage(
+ role="assistant",
+ content=pending_content,
+ tool_calls=real_tool_calls if len(real_tool_calls) > 0 else None
+ ),
+ finish_reason=chunk.choices[0].finish_reason if hasattr(chunk.choices[0], 'finish_reason') and chunk.choices[0].finish_reason is not None else 'stop',
+ logprobs=chunk.choices[0].logprobs,
+ )
+ ],
+ model=chunk.model,
+ service_tier=chunk.service_tier if hasattr(chunk, 'service_tier') else None,
+ system_fingerprint=chunk.system_fingerprint if hasattr(chunk, 'system_fingerprint') else None,
+ usage=chunk.usage if hasattr(chunk, 'usage') else None
+ ) if chunk else None
async def _make_msg(
self,
diff --git a/pkg/provider/modelmgr/requesters/deepseekchatcmpl.py b/pkg/provider/modelmgr/requesters/deepseekchatcmpl.py
index bf414745..7b8c9ca8 100644
--- a/pkg/provider/modelmgr/requesters/deepseekchatcmpl.py
+++ b/pkg/provider/modelmgr/requesters/deepseekchatcmpl.py
@@ -46,6 +46,9 @@ class DeepseekChatCompletions(chatcmpl.OpenAIChatCompletions):
# 发送请求
resp = await self._req(args)
+ if resp is None:
+ raise errors.RequesterError('接口返回为空,请确定模型提供商服务是否正常')
+
# 处理请求结果
message = await self._make_msg(resp)
diff --git a/pkg/utils/constants.py b/pkg/utils/constants.py
index 0dce973c..61ed497b 100644
--- a/pkg/utils/constants.py
+++ b/pkg/utils/constants.py
@@ -1,4 +1,4 @@
-semantic_version = "v3.4.6"
+semantic_version = "v3.4.6.2"
debug_mode = False
diff --git a/web/package-lock.json b/web/package-lock.json
index d692c64b..331b2815 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -4410,14 +4410,14 @@
}
},
"node_modules/jsonpath-plus": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.1.0.tgz",
- "integrity": "sha512-gHfV1IYqH8uJHYVTs8BJX1XKy2/rR93+f8QQi0xhx95aCiXn1ettYAd5T+7FU6wfqyDoX/wy0pm/fL3jOKJ9Lg==",
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.2.0.tgz",
+ "integrity": "sha512-T9V+8iNYKFL2n2rF+w02LBOT2JjDnTjioaNFrxRy0Bv1y/hNsqR/EBK7Ojy2ythRHwmz2cRIls+9JitQGZC/sw==",
"license": "MIT",
"dependencies": {
- "@jsep-plugin/assignment": "^1.2.1",
- "@jsep-plugin/regex": "^1.0.3",
- "jsep": "^1.3.9"
+ "@jsep-plugin/assignment": "^1.3.0",
+ "@jsep-plugin/regex": "^1.0.4",
+ "jsep": "^1.4.0"
},
"bin": {
"jsonpath": "bin/jsonpath-cli.js",