Compare commits

..

3 Commits

Author SHA1 Message Date
Soulter
e9be8cf69f chore: bump version to 4.7.4 2025-12-01 18:42:07 +08:00
Soulter
31d53edb9d refactor: standardize provider test method implementation
- Updated the `test` method in all provider classes to remove return values and raise exceptions for failure cases, enhancing clarity and consistency.
- Adjusted related logic in the dashboard and command routes to align with the new `test` method behavior, simplifying error handling.
2025-12-01 18:37:08 +08:00
Soulter
2ba0460f19 feat: introduce file extract capability (#3870)
* feat: introduce file extract capability

powered by MoonshotAI

* fix: correct indentation in default configuration file

* fix: add error handling for file extract application in InternalAgentSubStage

* fix: update file name handling in InternalAgentSubStage to correctly associate file names with extracted content

* feat: add condition settings for local agent runner in default configuration

* fix: enhance file naming logic in File component and update prompt handling in InternalAgentSubStage
2025-12-01 18:12:39 +08:00
7 changed files with 73 additions and 108 deletions

View File

@@ -1 +1 @@
__version__ = "4.7.3" __version__ = "4.7.4"

View File

@@ -4,7 +4,7 @@ import os
from astrbot.core.utils.astrbot_path import get_astrbot_data_path from astrbot.core.utils.astrbot_path import get_astrbot_data_path
VERSION = "4.7.3" VERSION = "4.7.4"
DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db") DB_PATH = os.path.join(get_astrbot_data_path(), "data_v4.db")
# 默认配置 # 默认配置
@@ -2422,36 +2422,36 @@ CONFIG_METADATA_3 = {
"provider_settings.enable": True, "provider_settings.enable": True,
}, },
}, },
"file_extract": { # "file_extract": {
"description": "文档解析能力", # "description": "文档解析能力 [beta]",
"type": "object", # "type": "object",
"items": { # "items": {
"provider_settings.file_extract.enable": { # "provider_settings.file_extract.enable": {
"description": "启用文档解析能力", # "description": "启用文档解析能力",
"type": "bool", # "type": "bool",
}, # },
"provider_settings.file_extract.provider": { # "provider_settings.file_extract.provider": {
"description": "文档解析提供商", # "description": "文档解析提供商",
"type": "string", # "type": "string",
"options": ["moonshotai"], # "options": ["moonshotai"],
"condition": { # "condition": {
"provider_settings.file_extract.enable": True, # "provider_settings.file_extract.enable": True,
}, # },
}, # },
"provider_settings.file_extract.moonshotai_api_key": { # "provider_settings.file_extract.moonshotai_api_key": {
"description": "Moonshot AI API Key", # "description": "Moonshot AI API Key",
"type": "string", # "type": "string",
"condition": { # "condition": {
"provider_settings.file_extract.provider": "moonshotai", # "provider_settings.file_extract.provider": "moonshotai",
"provider_settings.file_extract.enable": True, # "provider_settings.file_extract.enable": True,
}, # },
}, # },
}, # },
"condition": { # "condition": {
"provider_settings.agent_runner_type": "local", # "provider_settings.agent_runner_type": "local",
"provider_settings.enable": True, # "provider_settings.enable": True,
}, # },
}, # },
"others": { "others": {
"description": "其他配置", "description": "其他配置",
"type": "object", "type": "object",

View File

@@ -45,13 +45,13 @@ class AbstractProvider(abc.ABC):
) )
return meta return meta
async def test(self) -> bool: async def test(self):
"""test the provider is a """test the provider is a
Returns: raises:
bool: the provider is available Exception: if the provider is not available
""" """
return True ...
class Provider(AbstractProvider): class Provider(AbstractProvider):
@@ -175,15 +175,11 @@ class Provider(AbstractProvider):
return dicts return dicts
async def test(self, timeout: float = 45.0) -> bool: async def test(self, timeout: float = 45.0):
try: await asyncio.wait_for(
response = await asyncio.wait_for( self.text_chat(prompt="REPLY `PONG` ONLY"),
self.text_chat(prompt="REPLY `PONG` ONLY"), timeout=timeout,
timeout=timeout, )
)
return response is not None
except Exception:
return False
class STTProvider(AbstractProvider): class STTProvider(AbstractProvider):
@@ -197,19 +193,13 @@ class STTProvider(AbstractProvider):
"""获取音频的文本""" """获取音频的文本"""
raise NotImplementedError raise NotImplementedError
async def test(self) -> bool: async def test(self):
try: sample_audio_path = os.path.join(
sample_audio_path = os.path.join( get_astrbot_path(),
get_astrbot_path(), "samples",
"samples", "stt_health_check.wav",
"stt_health_check.wav", )
) await self.get_text(sample_audio_path)
if not os.path.exists(sample_audio_path):
return False
text_result = await self.get_text(sample_audio_path)
return isinstance(text_result, str) and bool(text_result)
except Exception:
return False
class TTSProvider(AbstractProvider): class TTSProvider(AbstractProvider):
@@ -223,12 +213,8 @@ class TTSProvider(AbstractProvider):
"""获取文本的音频,返回音频文件路径""" """获取文本的音频,返回音频文件路径"""
raise NotImplementedError raise NotImplementedError
async def test(self) -> bool: async def test(self):
try: await self.get_audio("hi")
audio_result = await self.get_audio("hi")
return isinstance(audio_result, str) and bool(audio_result)
except Exception:
return False
class EmbeddingProvider(AbstractProvider): class EmbeddingProvider(AbstractProvider):
@@ -252,14 +238,8 @@ class EmbeddingProvider(AbstractProvider):
"""获取向量的维度""" """获取向量的维度"""
... ...
async def test(self) -> bool: async def test(self):
try: await self.get_embedding("astrbot")
embedding_result = await self.get_embedding("health_check")
return isinstance(embedding_result, list) and (
not embedding_result or isinstance(embedding_result[0], float)
)
except Exception:
return False
async def get_embeddings_batch( async def get_embeddings_batch(
self, self,
@@ -345,9 +325,7 @@ class RerankProvider(AbstractProvider):
"""获取查询和文档的重排序分数""" """获取查询和文档的重排序分数"""
... ...
async def test(self) -> bool: async def test(self):
try: result = await self.rerank("Apple", documents=["apple", "banana"])
await self.rerank("Apple", documents=["apple", "banana"]) if not result:
return True raise Exception("Rerank provider test failed, no results returned")
except Exception:
return False

View File

@@ -354,17 +354,11 @@ class ConfigRoute(Route):
) )
try: try:
result = await provider.test() await provider.test()
if result: status_info["status"] = "available"
status_info["status"] = "available" logger.info(
logger.info( f"Provider {status_info['name']} (ID: {status_info['id']}) is available.",
f"Provider {status_info['name']} (ID: {status_info['id']}) is available.", )
)
else:
status_info["error"] = "Provider test returned False."
logger.warning(
f"Provider {status_info['name']} (ID: {status_info['id']}) test returned False.",
)
except Exception as e: except Exception as e:
error_message = str(e) error_message = str(e)
status_info["error"] = error_message status_info["error"] = error_message

7
changelogs/v4.7.4.md Normal file
View File

@@ -0,0 +1,7 @@
## What's Changed
1. 修复assistant message 中 tool_call 存在但 content 不存在时,导致验证错误的问题 ([#3862](https://github.com/AstrBotDevs/AstrBot/issues/3862))
2. 修复fix: aiocqhttp 适配器 NapCat 文件名获取为空 ([#3853](https://github.com/AstrBotDevs/AstrBot/issues/3853))
3. 新增:升级所有插件按钮
4. 新增:/provider 指令支持同时测试提供商可用性
5. 优化:主动回复的 prompt

View File

@@ -34,25 +34,11 @@ class ProviderCommands:
provider_capability_type = meta.provider_type provider_capability_type = meta.provider_type
try: try:
result = await provider.test() await provider.test()
if result: return True, None, None
return True, None, None except Exception as e:
err_code = "TEST_FAILED" err_code = "TEST_FAILED"
err_reason = "Provider test returned False" err_reason = str(e)
self._log_reachability_failure(
provider, provider_capability_type, err_code, err_reason
)
return False, err_code, err_reason
except Exception as exc:
err_code = (
getattr(exc, "status_code", None)
or getattr(exc, "code", None)
or getattr(exc, "error_code", None)
)
err_reason = str(exc)
if not err_code:
err_code = exc.__class__.__name__
self._log_reachability_failure( self._log_reachability_failure(
provider, provider_capability_type, err_code, err_reason provider, provider_capability_type, err_code, err_reason
) )

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "AstrBot" name = "AstrBot"
version = "4.7.3" version = "4.7.4"
description = "Easy-to-use multi-platform LLM chatbot and development framework" description = "Easy-to-use multi-platform LLM chatbot and development framework"
readme = "README.md" readme = "README.md"
requires-python = ">=3.10" requires-python = ">=3.10"