AstrBot 4.3.5__py3-none-any.whl → 4.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. astrbot/core/agent/runners/tool_loop_agent_runner.py +31 -2
  2. astrbot/core/astrbot_config_mgr.py +23 -51
  3. astrbot/core/config/default.py +92 -12
  4. astrbot/core/conversation_mgr.py +36 -1
  5. astrbot/core/core_lifecycle.py +24 -5
  6. astrbot/core/db/migration/migra_45_to_46.py +44 -0
  7. astrbot/core/db/vec_db/base.py +33 -2
  8. astrbot/core/db/vec_db/faiss_impl/document_storage.py +310 -52
  9. astrbot/core/db/vec_db/faiss_impl/embedding_storage.py +31 -3
  10. astrbot/core/db/vec_db/faiss_impl/vec_db.py +81 -23
  11. astrbot/core/file_token_service.py +6 -1
  12. astrbot/core/initial_loader.py +6 -3
  13. astrbot/core/knowledge_base/chunking/__init__.py +11 -0
  14. astrbot/core/knowledge_base/chunking/base.py +24 -0
  15. astrbot/core/knowledge_base/chunking/fixed_size.py +57 -0
  16. astrbot/core/knowledge_base/chunking/recursive.py +155 -0
  17. astrbot/core/knowledge_base/kb_db_sqlite.py +299 -0
  18. astrbot/core/knowledge_base/kb_helper.py +348 -0
  19. astrbot/core/knowledge_base/kb_mgr.py +287 -0
  20. astrbot/core/knowledge_base/models.py +114 -0
  21. astrbot/core/knowledge_base/parsers/__init__.py +15 -0
  22. astrbot/core/knowledge_base/parsers/base.py +50 -0
  23. astrbot/core/knowledge_base/parsers/markitdown_parser.py +25 -0
  24. astrbot/core/knowledge_base/parsers/pdf_parser.py +100 -0
  25. astrbot/core/knowledge_base/parsers/text_parser.py +41 -0
  26. astrbot/core/knowledge_base/parsers/util.py +13 -0
  27. astrbot/core/knowledge_base/retrieval/__init__.py +16 -0
  28. astrbot/core/knowledge_base/retrieval/hit_stopwords.txt +767 -0
  29. astrbot/core/knowledge_base/retrieval/manager.py +273 -0
  30. astrbot/core/knowledge_base/retrieval/rank_fusion.py +138 -0
  31. astrbot/core/knowledge_base/retrieval/sparse_retriever.py +130 -0
  32. astrbot/core/pipeline/process_stage/method/llm_request.py +29 -7
  33. astrbot/core/pipeline/process_stage/utils.py +80 -0
  34. astrbot/core/platform/astr_message_event.py +8 -7
  35. astrbot/core/platform/sources/misskey/misskey_adapter.py +380 -44
  36. astrbot/core/platform/sources/misskey/misskey_api.py +581 -45
  37. astrbot/core/platform/sources/misskey/misskey_event.py +76 -41
  38. astrbot/core/platform/sources/misskey/misskey_utils.py +254 -43
  39. astrbot/core/platform/sources/qqofficial_webhook/qo_webhook_server.py +2 -1
  40. astrbot/core/platform/sources/satori/satori_adapter.py +27 -1
  41. astrbot/core/platform/sources/satori/satori_event.py +270 -99
  42. astrbot/core/provider/manager.py +14 -9
  43. astrbot/core/provider/provider.py +67 -0
  44. astrbot/core/provider/sources/anthropic_source.py +4 -4
  45. astrbot/core/provider/sources/dashscope_source.py +10 -9
  46. astrbot/core/provider/sources/dify_source.py +6 -8
  47. astrbot/core/provider/sources/gemini_embedding_source.py +1 -2
  48. astrbot/core/provider/sources/openai_embedding_source.py +1 -2
  49. astrbot/core/provider/sources/openai_source.py +18 -15
  50. astrbot/core/provider/sources/openai_tts_api_source.py +1 -1
  51. astrbot/core/star/context.py +3 -0
  52. astrbot/core/star/star.py +6 -0
  53. astrbot/core/star/star_manager.py +13 -7
  54. astrbot/core/umop_config_router.py +81 -0
  55. astrbot/core/updator.py +1 -1
  56. astrbot/core/utils/io.py +23 -12
  57. astrbot/dashboard/routes/__init__.py +2 -0
  58. astrbot/dashboard/routes/config.py +137 -9
  59. astrbot/dashboard/routes/knowledge_base.py +1065 -0
  60. astrbot/dashboard/routes/plugin.py +24 -5
  61. astrbot/dashboard/routes/update.py +1 -1
  62. astrbot/dashboard/server.py +6 -0
  63. astrbot/dashboard/utils.py +161 -0
  64. {astrbot-4.3.5.dist-info → astrbot-4.5.0.dist-info}/METADATA +29 -13
  65. {astrbot-4.3.5.dist-info → astrbot-4.5.0.dist-info}/RECORD +68 -44
  66. {astrbot-4.3.5.dist-info → astrbot-4.5.0.dist-info}/WHEEL +0 -0
  67. {astrbot-4.3.5.dist-info → astrbot-4.5.0.dist-info}/entry_points.txt +0 -0
  68. {astrbot-4.3.5.dist-info → astrbot-4.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,80 @@
1
+ from ..context import PipelineContext
2
+ from astrbot.core.provider.entities import ProviderRequest
3
+ from astrbot.api import logger, sp
4
+
5
+
6
+ async def inject_kb_context(
7
+ umo: str,
8
+ p_ctx: PipelineContext,
9
+ req: ProviderRequest,
10
+ ) -> None:
11
+ """inject knowledge base context into the provider request
12
+
13
+ Args:
14
+ umo: Unique message object (session ID)
15
+ p_ctx: Pipeline context
16
+ req: Provider request
17
+ """
18
+
19
+ kb_mgr = p_ctx.plugin_manager.context.kb_manager
20
+
21
+ # 1. 优先读取会话级配置
22
+ session_config = await sp.session_get(umo, "kb_config", default={})
23
+
24
+ if session_config and "kb_ids" in session_config:
25
+ # 会话级配置
26
+ kb_ids = session_config.get("kb_ids", [])
27
+
28
+ # 如果配置为空列表,明确表示不使用知识库
29
+ if not kb_ids:
30
+ logger.info(f"[知识库] 会话 {umo} 已被配置为不使用知识库")
31
+ return
32
+
33
+ top_k = session_config.get("top_k", 5)
34
+
35
+ # 将 kb_ids 转换为 kb_names
36
+ kb_names = []
37
+ invalid_kb_ids = []
38
+ for kb_id in kb_ids:
39
+ kb_helper = await kb_mgr.get_kb(kb_id)
40
+ if kb_helper:
41
+ kb_names.append(kb_helper.kb.kb_name)
42
+ else:
43
+ logger.warning(f"[知识库] 知识库不存在或未加载: {kb_id}")
44
+ invalid_kb_ids.append(kb_id)
45
+
46
+ if invalid_kb_ids:
47
+ logger.warning(
48
+ f"[知识库] 会话 {umo} 配置的以下知识库无效: {invalid_kb_ids}"
49
+ )
50
+
51
+ if not kb_names:
52
+ return
53
+
54
+ logger.debug(f"[知识库] 使用会话级配置,知识库数量: {len(kb_names)}")
55
+ else:
56
+ kb_names = p_ctx.astrbot_config.get("kb_names", [])
57
+ top_k = p_ctx.astrbot_config.get("kb_final_top_k", 5)
58
+ logger.debug(f"[知识库] 使用全局配置,知识库数量: {len(kb_names)}")
59
+
60
+ top_k_fusion = p_ctx.astrbot_config.get("kb_fusion_top_k", 20)
61
+
62
+ if not kb_names:
63
+ return
64
+
65
+ logger.debug(f"[知识库] 开始检索知识库,数量: {len(kb_names)}, top_k={top_k}")
66
+ kb_context = await kb_mgr.retrieve(
67
+ query=req.prompt,
68
+ kb_names=kb_names,
69
+ top_k_fusion=top_k_fusion,
70
+ top_m_final=top_k,
71
+ )
72
+
73
+ if not kb_context:
74
+ return
75
+
76
+ formatted = kb_context.get("context_text", "")
77
+ if formatted:
78
+ results = kb_context.get("results", [])
79
+ logger.debug(f"[知识库] 为会话 {umo} 注入了 {len(results)} 条相关知识块")
80
+ req.system_prompt = f"{formatted}\n\n{req.system_prompt or ''}"
@@ -4,7 +4,7 @@ import re
4
4
  import hashlib
5
5
  import uuid
6
6
 
7
- from typing import List, Union, Optional, AsyncGenerator, TypeVar, Any
7
+ from typing import List, Union, Optional, AsyncGenerator, Any
8
8
 
9
9
  from astrbot import logger
10
10
  from astrbot.core.db.po import Conversation
@@ -26,8 +26,6 @@ from .astrbot_message import AstrBotMessage, Group
26
26
  from .platform_metadata import PlatformMetadata
27
27
  from .message_session import MessageSession, MessageSesion # noqa
28
28
 
29
- _VT = TypeVar("_VT")
30
-
31
29
 
32
30
  class AstrMessageEvent(abc.ABC):
33
31
  def __init__(
@@ -92,8 +90,10 @@ class AstrMessageEvent(abc.ABC):
92
90
  """
93
91
  return self.message_str
94
92
 
95
- def _outline_chain(self, chain: List[BaseMessageComponent]) -> str:
93
+ def _outline_chain(self, chain: Optional[List[BaseMessageComponent]]) -> str:
96
94
  outline = ""
95
+ if not chain:
96
+ return outline
97
97
  for i in chain:
98
98
  if isinstance(i, Plain):
99
99
  outline += i.text
@@ -175,9 +175,7 @@ class AstrMessageEvent(abc.ABC):
175
175
  """
176
176
  self._extras[key] = value
177
177
 
178
- def get_extra(
179
- self, key: str | None = None, default: _VT = None
180
- ) -> dict[str, Any] | _VT:
178
+ def get_extra(self, key: str | None = None, default=None) -> Any:
181
179
  """
182
180
  获取额外的信息。
183
181
  """
@@ -265,6 +263,9 @@ class AstrMessageEvent(abc.ABC):
265
263
  """
266
264
  if isinstance(result, str):
267
265
  result = MessageEventResult().message(result)
266
+ # 兼容外部插件或调用方传入的 chain=None 的情况,确保为可迭代列表
267
+ if isinstance(result, MessageEventResult) and result.chain is None:
268
+ result.chain = []
268
269
  self._result = result
269
270
 
270
271
  def stop_event(self):