Compare commits

..

4 Commits

Author SHA1 Message Date
Soulter
dba1ed1e19 v3.4.30 2025-02-21 01:31:36 +08:00
Soulter
a24514876b fix: 修复 dify 无法使用事件钩子的问题以及出现 GeneratorExit 的问题 #533 #264 2025-02-21 01:14:13 +08:00
Soulter
466a1c1c41 🐛 fix: 修复某些情况下导致插件报错 AttributeError 的问题 #549 2025-02-21 00:38:08 +08:00
Soulter
a2d5e9f40f feat: add xAI template 2025-02-20 16:34:32 +08:00
9 changed files with 99 additions and 64 deletions

View File

@@ -2,7 +2,7 @@
如需修改配置,请在 `data/cmd_config.json` 中修改或者在管理面板中可视化修改。
"""
VERSION = "3.4.29"
VERSION = "3.4.30"
DB_PATH = "data/data_v3.db"
# 默认配置
@@ -409,6 +409,17 @@ CONFIG_METADATA_2 = {
"model": "gpt-4o-mini",
},
},
"xAI": {
"id": "xai",
"type": "openai_chat_completion",
"enable": True,
"key": [],
"api_base": "https://api.x.ai/v1",
"timeout": 120,
"model_config": {
"model": "grok-2-latest",
},
},
"ollama": {
"id": "ollama_default",
"type": "openai_chat_completion",

View File

@@ -11,6 +11,7 @@ from astrbot.core.message.components import Image
from astrbot.core import logger
from astrbot.core.utils.metrics import Metric
from astrbot.core.provider.entites import ProviderRequest
from astrbot.core.star.star_handler import star_handlers_registry, EventType
class DifyRequestSubStage(Stage):
@@ -48,17 +49,40 @@ class DifyRequestSubStage(Stage):
return
req.session_id = event.unified_msg_origin
# 执行请求 LLM 前事件钩子。
# 装饰 system_prompt 等功能
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnLLMRequestEvent)
for handler in handlers:
try:
await handler.handler(event, req)
except BaseException:
logger.error(traceback.format_exc())
try:
logger.debug(f"Dify 请求 Payload: {req.__dict__}")
llm_response = await provider.text_chat(**req.__dict__) # 请求 LLM
await Metric.upload(llm_tick=1, model_name=provider.get_model(), provider_type=provider.meta().type)
# 执行 LLM 响应后的事件。
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnLLMResponseEvent)
for handler in handlers:
try:
await handler.handler(event, llm_response)
except BaseException:
logger.error(traceback.format_exc())
if llm_response.role == 'assistant':
# text completion
event.set_result(MessageEventResult().message(llm_response.completion_text)
.set_result_content_type(ResultContentType.LLM_RESULT))
yield # rick roll
return
elif llm_response.role == 'err':
event.set_result(MessageEventResult().message(f"AstrBot 请求失败。\n错误信息: {llm_response.completion_text}"))
return
elif llm_response.role == 'tool':
event.set_result(MessageEventResult().message(f"Dify 暂不支持工具调用。"))
yield
except BaseException as e:
logger.error(traceback.format_exc())

View File

@@ -69,9 +69,7 @@ class LLMRequestSubStage(Stage):
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnLLMRequestEvent)
for handler in handlers:
try:
wrapper = self._call_handler(self.ctx, event, handler.handler, req)
async for ret in wrapper:
yield ret
await handler.handler(event, req)
except BaseException:
logger.error(traceback.format_exc())
@@ -88,9 +86,7 @@ class LLMRequestSubStage(Stage):
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnLLMResponseEvent)
for handler in handlers:
try:
wrapper = self._call_handler(self.ctx, event, handler.handler, llm_response)
async for ret in wrapper:
yield ret
await handler.handler(event, llm_response)
except BaseException:
logger.error(traceback.format_exc())

View File

@@ -90,9 +90,7 @@ class RespondStage(Stage):
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnAfterMessageSentEvent)
for handler in handlers:
try:
wrapper = self._call_handler(self.ctx, event, handler.handler)
async for ret in wrapper:
yield ret
await handler.handler(event)
except BaseException:
logger.error(traceback.format_exc())

View File

@@ -63,13 +63,10 @@ class ResultDecorateStage(Stage):
handlers = star_handlers_registry.get_handlers_by_event_type(EventType.OnDecoratingResultEvent)
for handler in handlers:
try:
wrapper = self._call_handler(self.ctx, event, handler.handler)
async for ret in wrapper:
yield ret
await handler.handler(event)
except BaseException:
logger.error(traceback.format_exc())
# 需要再获取一次。插件可能直接对 chain 进行了替换。
result = event.get_result()
if result is None:

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
import abc
import inspect
from astrbot.api import logger
from typing import List, AsyncGenerator, Union, Awaitable
from astrbot.core.platform.astr_message_event import AstrMessageEvent
from .context import PipelineContext
@@ -46,6 +47,7 @@ class Stage(abc.ABC):
ready_to_call = handler(event, *args, **kwargs)
except TypeError as e:
# 向下兼容
logger.debug(str(e))
ready_to_call = handler(event, ctx.plugin_manager.context, *args, **kwargs)
if isinstance(ready_to_call, AsyncGenerator):

View File

@@ -75,52 +75,57 @@ class ProviderDify(Provider):
session_vars = sp.get("session_variables", {})
session_var = session_vars.get(session_id, {})
match self.api_type:
case "chat" | "agent":
async for chunk in self.api_client.chat_messages(
inputs={
**session_var
},
query=prompt,
user=session_id,
conversation_id=conversation_id,
files=files_payload,
timeout=self.timeout
):
logger.debug(f"dify resp chunk: {chunk}")
if chunk['event'] == "message" or \
chunk['event'] == "agent_message":
result += chunk['answer']
if not conversation_id:
self.conversation_ids[session_id] = chunk['conversation_id']
conversation_id = chunk['conversation_id']
case "workflow":
async for chunk in self.api_client.workflow_run(
inputs={
self.dify_query_input_key: prompt,
"astrbot_session_id": session_id,
**session_var
},
user=session_id,
files=files_payload,
timeout=self.timeout
):
match chunk['event']:
case "workflow_started":
logger.info(f"Dify 工作流(ID: {chunk['workflow_run_id']})开始运行。")
case "node_finished":
logger.debug(f"Dify 工作流节点(ID: {chunk['data']['node_id']} Title: {chunk['data'].get('title', '')})运行结束。")
case "workflow_finished":
logger.info(f"Dify 工作流(ID: {chunk['workflow_run_id']})运行结束。")
if chunk['data']['error']:
logger.error(f"Dify 工作流出现错误:{chunk['data']['error']}")
raise Exception(f"Dify 工作流出现错误:{chunk['data']['error']}")
if self.workflow_output_key not in chunk['data']['outputs']:
raise Exception(f"Dify 工作流的输出不包含指定的键名:{self.workflow_output_key}")
result = chunk['data']['outputs'][self.workflow_output_key]
case _:
raise Exception(f"未知的 Dify API 类型:{self.api_type}")
try:
match self.api_type:
case "chat" | "agent":
async for chunk in self.api_client.chat_messages(
inputs={
**session_var
},
query=prompt,
user=session_id,
conversation_id=conversation_id,
files=files_payload,
timeout=self.timeout
):
logger.debug(f"dify resp chunk: {chunk}")
if chunk['event'] == "message" or \
chunk['event'] == "agent_message":
result += chunk['answer']
if not conversation_id:
self.conversation_ids[session_id] = chunk['conversation_id']
conversation_id = chunk['conversation_id']
case "workflow":
async for chunk in self.api_client.workflow_run(
inputs={
self.dify_query_input_key: prompt,
"astrbot_session_id": session_id,
**session_var
},
user=session_id,
files=files_payload,
timeout=self.timeout
):
match chunk['event']:
case "workflow_started":
logger.info(f"Dify 工作流(ID: {chunk['workflow_run_id']})开始运行。")
case "node_finished":
logger.debug(f"Dify 工作流节点(ID: {chunk['data']['node_id']} Title: {chunk['data'].get('title', '')})运行结束。")
case "workflow_finished":
logger.info(f"Dify 工作流(ID: {chunk['workflow_run_id']})运行结束。")
if chunk['data']['error']:
logger.error(f"Dify 工作流出现错误:{chunk['data']['error']}")
raise Exception(f"Dify 工作流出现错误:{chunk['data']['error']}")
if self.workflow_output_key not in chunk['data']['outputs']:
raise Exception(f"Dify 工作流的输出不包含指定的键名:{self.workflow_output_key}")
result = chunk['data']['outputs'][self.workflow_output_key]
case _:
raise Exception(f"未知的 Dify API 类型:{self.api_type}")
except Exception as e:
logger.error(f"Dify 请求失败:{str(e)}")
return LLMResponse(role="err", completion_text=f"Dify 请求失败:{str(e)}")
return LLMResponse(role="assistant", completion_text=result)
async def forget(self, session_id):

View File

@@ -110,9 +110,6 @@ class CommandFilter(HandlerFilter):
message_str = message_str[len(_full):].strip()
ok = True
break
print(message_str, self.command_name, self.alias, self.parent_command_names, ok)
if not ok:
return False

5
changelogs/v3.4.30.md Normal file
View File

@@ -0,0 +1,5 @@
# What's Changed
1. ‼️🐛 修复: 修复某些情况下导致插件报错 AttributeError 的问题 #549
2. ✨ 新增: add xAI template
3. 🐛 修复: 修复 dify 无法使用事件钩子的问题以及出现 GeneratorExit 的问题 #533 #264