Skip to content

Commit 7e2d0c6

Browse files
committed
Merge branch 'feat/add-plugin-readme-buttom' of https://github.com/VanillaNahida/AstrBot into feat/add-plugin-readme-buttom
2 parents d655d3a + bdacdf6 commit 7e2d0c6

27 files changed

Lines changed: 1004 additions & 53 deletions

File tree

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
1212
ca-certificates \
1313
bash \
1414
ffmpeg \
15+
libavcodec-extra \
1516
curl \
1617
gnupg \
1718
git \

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ Connect AstrBot to your favorite chat platform.
184184
| Coze | LLMOps Platforms |
185185
| OpenAI Whisper | Speech-to-Text Services |
186186
| SenseVoice | Speech-to-Text Services |
187+
| Xiaomi MiMo Omni | Speech-to-Text Services |
187188
| OpenAI TTS | Text-to-Speech Services |
188189
| Gemini TTS | Text-to-Speech Services |
189190
| GPT-Sovits-Inference | Text-to-Speech Services |
@@ -193,6 +194,7 @@ Connect AstrBot to your favorite chat platform.
193194
| Alibaba Cloud Bailian TTS | Text-to-Speech Services |
194195
| Azure TTS | Text-to-Speech Services |
195196
| Minimax TTS | Text-to-Speech Services |
197+
| Xiaomi MiMo TTS | Text-to-Speech Services |
196198
| Volcano Engine TTS | Text-to-Speech Services |
197199

198200
## ❤️ Sponsors

README_fr.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ Connectez AstrBot à vos plateformes de chat préférées.
184184
| Coze | Plateformes LLMOps |
185185
| OpenAI Whisper | Services de reconnaissance vocale |
186186
| SenseVoice | Services de reconnaissance vocale |
187+
| Xiaomi MiMo Omni | Services de reconnaissance vocale |
187188
| OpenAI TTS | Services de synthèse vocale |
188189
| Gemini TTS | Services de synthèse vocale |
189190
| GPT-Sovits-Inference | Services de synthèse vocale |
@@ -193,6 +194,7 @@ Connectez AstrBot à vos plateformes de chat préférées.
193194
| Alibaba Cloud Bailian TTS | Services de synthèse vocale |
194195
| Azure TTS | Services de synthèse vocale |
195196
| Minimax TTS | Services de synthèse vocale |
197+
| Xiaomi MiMo TTS | Services de synthèse vocale |
196198
| Volcano Engine TTS | Services de synthèse vocale |
197199

198200
## ❤️ Contribuer

README_ja.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ AstrBot をよく使うチャットプラットフォームに接続できます
185185
| Coze | LLMOps プラットフォーム |
186186
| OpenAI Whisper | 音声認識サービス |
187187
| SenseVoice | 音声認識サービス |
188+
| Xiaomi MiMo Omni | 音声認識サービス |
188189
| OpenAI TTS | 音声合成サービス |
189190
| Gemini TTS | 音声合成サービス |
190191
| GPT-Sovits-Inference | 音声合成サービス |
@@ -194,6 +195,7 @@ AstrBot をよく使うチャットプラットフォームに接続できます
194195
| Alibaba Cloud 百炼 TTS | 音声合成サービス |
195196
| Azure TTS | 音声合成サービス |
196197
| Minimax TTS | 音声合成サービス |
198+
| Xiaomi MiMo TTS | 音声合成サービス |
197199
| Volcano Engine TTS | 音声合成サービス |
198200

199201
## ❤️ コントリビューション

README_ru.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ yay -S astrbot-git
184184
| Coze | Платформы LLMOps |
185185
| OpenAI Whisper | Сервисы распознавания речи |
186186
| SenseVoice | Сервисы распознавания речи |
187+
| Xiaomi MiMo Omni | Сервисы распознавания речи |
187188
| OpenAI TTS | Сервисы синтеза речи |
188189
| Gemini TTS | Сервисы синтеза речи |
189190
| GPT-Sovits-Inference | Сервисы синтеза речи |
@@ -193,6 +194,7 @@ yay -S astrbot-git
193194
| Alibaba Cloud Bailian TTS | Сервисы синтеза речи |
194195
| Azure TTS | Сервисы синтеза речи |
195196
| Minimax TTS | Сервисы синтеза речи |
197+
| Xiaomi MiMo TTS | Сервисы синтеза речи |
196198
| Volcano Engine TTS | Сервисы синтеза речи |
197199

198200
## ❤️ Вклад в проект

README_zh-TW.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ yay -S astrbot-git
184184
| Coze | LLMOps 平台 |
185185
| OpenAI Whisper | 語音轉文字服務 |
186186
| SenseVoice | 語音轉文字服務 |
187+
| Xiaomi MiMo Omni | 語音轉文字服務 |
187188
| OpenAI TTS | 文字轉語音服務 |
188189
| Gemini TTS | 文字轉語音服務 |
189190
| GPT-Sovits-Inference | 文字轉語音服務 |
@@ -193,6 +194,7 @@ yay -S astrbot-git
193194
| 阿里雲百煉 TTS | 文字轉語音服務 |
194195
| Azure TTS | 文字轉語音服務 |
195196
| Minimax TTS | 文字轉語音服務 |
197+
| Xiaomi MiMo TTS | 文字轉語音服務 |
196198
| 火山引擎 TTS | 文字轉語音服務 |
197199

198200
## ❤️ 貢獻

README_zh.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ yay -S astrbot-git
185185
| Coze | LLMOps 平台 |
186186
| OpenAI Whisper | 语音转文本 |
187187
| SenseVoice | 语音转文本 |
188+
| Xiaomi MiMo Omni | 语音转文本 |
188189
| OpenAI TTS | 文本转语音 |
189190
| Gemini TTS | 文本转语音 |
190191
| GPT-Sovits-Inference | 文本转语音 |
@@ -194,6 +195,7 @@ yay -S astrbot-git
194195
| 阿里云百炼 TTS | 文本转语音 |
195196
| Azure TTS | 文本转语音 |
196197
| Minimax TTS | 文本转语音 |
198+
| Xiaomi MiMo TTS | 文本转语音 |
197199
| 火山引擎 TTS | 文本转语音 |
198200

199201
## ❤️ 贡献

astrbot/core/config/default.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,9 +4040,9 @@ class ChatProviderTemplate(TypedDict):
40404040
"hint": "时区设置。请填写 IANA 时区名称, 如 Asia/Shanghai, 为空时使用系统默认时区。所有时区请查看: https://data.iana.org/time-zones/tzdb-2021a/zone1970.tab",
40414041
},
40424042
"http_proxy": {
4043-
"description": "HTTP 代理",
4043+
"description": "代理",
40444044
"type": "string",
4045-
"hint": "启用后,会以添加环境变量的方式设置代理。格式为 `http://ip:port`",
4045+
"hint": "启用后,会以添加环境变量的方式设置代理。支持 http://、https://、socks5:// 格式,例如:http://127.0.0.1:7890 或 socks5://127.0.0.1:7891",
40464046
},
40474047
"no_proxy": {
40484048
"description": "直连地址列表",

astrbot/core/knowledge_base/kb_helper.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ async def _repair_and_translate_chunk_with_retry(
108108
class KBHelper:
109109
vec_db: BaseVecDB
110110
kb: KnowledgeBase
111+
init_error: str | None
111112

112113
def __init__(
113114
self,
@@ -122,6 +123,7 @@ def __init__(
122123
self.prov_mgr = provider_manager
123124
self.kb_root_dir = kb_root_dir
124125
self.chunker = chunker
126+
self.init_error = None
125127

126128
self.kb_dir = Path(self.kb_root_dir) / self.kb.kb_id
127129
self.kb_medias_dir = Path(self.kb_dir) / "medias" / self.kb.kb_id
@@ -148,21 +150,28 @@ async def get_ep(self) -> EmbeddingProvider:
148150
async def get_rp(self) -> RerankProvider | None:
149151
if not self.kb.rerank_provider_id:
150152
return None
151-
rp: RerankProvider = await self.prov_mgr.get_provider_by_id(
153+
rp: RerankProvider | None = await self.prov_mgr.get_provider_by_id(
152154
self.kb.rerank_provider_id,
153155
) # type: ignore
154156
if not rp:
155-
raise ValueError(
156-
f"无法找到 ID 为 {self.kb.rerank_provider_id} 的 Rerank Provider",
157+
logger.warning(
158+
f"知识库 {self.kb.kb_name}({self.kb.kb_id}) 的 Rerank Provider({self.kb.rerank_provider_id}) 不可用,将跳过重排序。",
157159
)
160+
return None
158161
return rp
159162

160163
async def _ensure_vec_db(self) -> FaissVecDB:
161164
if not self.kb.embedding_provider_id:
162165
raise ValueError(f"知识库 {self.kb.kb_name} 未配置 Embedding Provider")
163166

164167
ep = await self.get_ep()
165-
rp = await self.get_rp()
168+
rp: RerankProvider | None = None
169+
try:
170+
rp = await self.get_rp()
171+
except Exception as e:
172+
logger.warning(
173+
f"知识库 {self.kb.kb_name}({self.kb.kb_id}) 初始化重排序能力失败,将跳过重排序: {e}",
174+
)
166175

167176
vec_db = FaissVecDB(
168177
doc_store_path=str(self.kb_dir / "doc.db"),
@@ -172,6 +181,8 @@ async def _ensure_vec_db(self) -> FaissVecDB:
172181
)
173182
await vec_db.initialize()
174183
self.vec_db = vec_db
184+
# Clear stale init_error once initialization succeeds.
185+
self.init_error = None
175186
return vec_db
176187

177188
async def delete_vec_db(self) -> None:
@@ -183,7 +194,7 @@ async def delete_vec_db(self) -> None:
183194
shutil.rmtree(self.kb_dir)
184195

185196
async def terminate(self) -> None:
186-
if self.vec_db:
197+
if hasattr(self, "vec_db") and self.vec_db:
187198
await self.vec_db.close()
188199

189200
async def upload_document(

astrbot/core/knowledge_base/kb_mgr.py

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import traceback
21
from pathlib import Path
32

43
from astrbot.core import logger
@@ -56,8 +55,7 @@ async def initialize(self) -> None:
5655
logger.error(f"知识库模块导入失败: {e}")
5756
logger.warning("请确保已安装所需依赖: pypdf, aiofiles, Pillow, rank-bm25")
5857
except Exception as e:
59-
logger.error(f"知识库模块初始化失败: {e}")
60-
logger.error(traceback.format_exc())
58+
logger.error(f"知识库模块初始化失败: {e}", exc_info=True)
6159

6260
async def _init_kb_database(self) -> None:
6361
self.kb_db = KBSQLiteDatabase(DB_PATH.as_posix())
@@ -76,7 +74,14 @@ async def load_kbs(self) -> None:
7674
kb_root_dir=FILES_PATH,
7775
chunker=CHUNKER,
7876
)
79-
await kb_helper.initialize()
77+
try:
78+
await kb_helper.initialize()
79+
except Exception as e:
80+
kb_helper.init_error = str(e)
81+
logger.error(
82+
f"知识库 {record.kb_name}({record.kb_id}) 初始化失败: {e}",
83+
exc_info=True,
84+
)
8085
self.kb_insts[record.kb_id] = kb_helper
8186

8287
async def create_kb(
@@ -179,6 +184,20 @@ async def update_kb(
179184
return None
180185

181186
kb = kb_helper.kb
187+
previous_state = {
188+
"kb_name": kb.kb_name,
189+
"description": kb.description,
190+
"emoji": kb.emoji,
191+
"embedding_provider_id": kb.embedding_provider_id,
192+
"rerank_provider_id": kb.rerank_provider_id,
193+
"chunk_size": kb.chunk_size,
194+
"chunk_overlap": kb.chunk_overlap,
195+
"top_k_dense": kb.top_k_dense,
196+
"top_k_sparse": kb.top_k_sparse,
197+
"top_m_final": kb.top_m_final,
198+
}
199+
previous_init_error = kb_helper.init_error
200+
182201
if kb_name is not None:
183202
kb.kb_name = kb_name
184203
if description is not None:
@@ -198,12 +217,47 @@ async def update_kb(
198217
kb.top_k_sparse = top_k_sparse
199218
if top_m_final is not None:
200219
kb.top_m_final = top_m_final
220+
221+
# Build a new helper first. Keep current vec_db alive until new init succeeds.
222+
new_helper = KBHelper(
223+
kb_db=self.kb_db,
224+
kb=kb,
225+
provider_manager=self.provider_manager,
226+
kb_root_dir=FILES_PATH,
227+
chunker=CHUNKER,
228+
)
229+
230+
try:
231+
await new_helper.initialize()
232+
except Exception as e:
233+
# Roll back in-memory settings and keep current helper available.
234+
kb.kb_name = previous_state["kb_name"]
235+
kb.description = previous_state["description"]
236+
kb.emoji = previous_state["emoji"]
237+
kb.embedding_provider_id = previous_state["embedding_provider_id"]
238+
kb.rerank_provider_id = previous_state["rerank_provider_id"]
239+
kb.chunk_size = previous_state["chunk_size"]
240+
kb.chunk_overlap = previous_state["chunk_overlap"]
241+
kb.top_k_dense = previous_state["top_k_dense"]
242+
kb.top_k_sparse = previous_state["top_k_sparse"]
243+
kb.top_m_final = previous_state["top_m_final"]
244+
kb_helper.init_error = previous_init_error
245+
logger.error(
246+
f"知识库 {kb.kb_name}({kb.kb_id}) 重新初始化失败,继续使用旧实例: {e}",
247+
exc_info=True,
248+
)
249+
return kb_helper
250+
201251
async with self.kb_db.get_db() as session:
202252
session.add(kb)
203253
await session.commit()
204254
await session.refresh(kb)
205255

206-
return kb_helper
256+
old_helper = kb_helper
257+
self.kb_insts[kb_id] = new_helper
258+
await old_helper.terminate()
259+
new_helper.init_error = None
260+
return new_helper
207261

208262
async def retrieve(
209263
self,
@@ -215,11 +269,21 @@ async def retrieve(
215269
"""从指定知识库中检索相关内容"""
216270
kb_ids = []
217271
kb_id_helper_map = {}
272+
unavailable_kbs = []
218273
for kb_name in kb_names:
219274
if kb_helper := await self.get_kb_by_name(kb_name):
275+
if kb_helper.init_error:
276+
unavailable_kbs.append((kb_name, kb_helper.init_error))
277+
logger.warning(f"知识库 {kb_name} 不可用: {kb_helper.init_error}")
278+
continue
220279
kb_ids.append(kb_helper.kb.kb_id)
221280
kb_id_helper_map[kb_helper.kb.kb_id] = kb_helper
222281

282+
# all requested KBs are unavailable
283+
if not kb_ids and unavailable_kbs:
284+
errors = "; ".join(f"{n}: {e}" for n, e in unavailable_kbs)
285+
raise ValueError(f"所有请求的知识库均不可用: {errors}")
286+
223287
if not kb_ids:
224288
return {}
225289

0 commit comments

Comments
 (0)