feat: Refactor DpmOverlays to use ShowCard for rendering cards and add ToolStatusToast for operation status notifications
- Moved card rendering logic from DpmOverlays to a new ShowCard component for better reusability. - Introduced ToolStatusToast to display real-time operation statuses in the top right corner. - Updated PageHeader to conditionally render credits based on the current path. - Modified PromptPanel to change tool names and update prompt titles. - Enhanced ScreenLayout to include ToolStatusToast. - Updated styles for new components and adjusted existing styles for consistency. - Implemented statusBus utility for dispatching tool status events. - Updated useMqttControl to integrate tool status notifications during navigation and card display actions.
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""知识库入库脚本:分块 → LLM 生成问答 → 双路向量索引 → 落盘 kb_index.json / kb_qa.json。
|
||||
|
||||
知识源 = backend/knowledge/ 下全部 *.md(park.md / opc.md / park_data.md …)。
|
||||
- 幂等:缓存有效时直接加载(不重新构建);--force 强制删除缓存重建。
|
||||
- 首次运行会调用 DashScope(text-embedding-v4 向量化 + qwen-plus 生成问答),
|
||||
耗时约数分钟,仅构建一次,之后命中缓存秒开。
|
||||
|
||||
用法(在 backend/ 目录下执行):
|
||||
python scripts/ingest_kb.py # 有缓存则加载,无缓存则构建
|
||||
python scripts/ingest_kb.py --force # 强制重建(任一知识文件变更后)
|
||||
"""
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BACKEND_DIR = Path(__file__).resolve().parent.parent
|
||||
if str(BACKEND_DIR) not in sys.path:
|
||||
sys.path.insert(0, str(BACKEND_DIR))
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="知识库入库(分块 + 问答 + 双路向量索引)")
|
||||
parser.add_argument("--force", action="store_true", help="删除缓存并强制重建")
|
||||
parser.add_argument("--dry", action="store_true", help="只做分块预览,不调 API、不落盘")
|
||||
args = parser.parse_args()
|
||||
|
||||
from app import rag
|
||||
|
||||
if args.dry:
|
||||
chunks = rag._chunk_md(rag._kb_text())
|
||||
print(f"[dry] 知识源 {len(list(rag.KB_DIR.glob(rag.KB_GLOB)))} 个文件,全库 "
|
||||
f"{len(rag._kb_text())} 字 → {len(chunks)} 块(最长 {max(map(len, chunks))} 字)")
|
||||
return
|
||||
|
||||
if args.force:
|
||||
for p in (rag.META_FILE, rag.VECTOR_FILE, rag.QA_FILE, rag.LEGACY_INDEX_FILE):
|
||||
if p.exists():
|
||||
p.unlink()
|
||||
print(f"[ingest] 已删除缓存 {p.name}")
|
||||
|
||||
print("[ingest] 知识源:")
|
||||
for f in sorted(rag.KB_DIR.glob(rag.KB_GLOB)):
|
||||
print(f" - {f.name} ({f.stat().st_size} B)")
|
||||
|
||||
idx = rag._load_index()
|
||||
n_chunk = len(idx["chunks"])
|
||||
n_vec = len(idx["embed_texts"])
|
||||
dim = idx["embeddings"].shape[1]
|
||||
n_q = sum(1 for qs in idx["questions"] for _ in qs)
|
||||
print("[ingest] 入库完成:")
|
||||
print(f" - 分块数: {n_chunk}")
|
||||
print(f" - 生成问句数: {n_q}")
|
||||
print(f" - 向量数: {n_vec}(dim={dim},含原句+问句双路)")
|
||||
print(f" - 向量矩阵: {rag.VECTOR_FILE}")
|
||||
print(f" - 元数据: {rag.META_FILE}")
|
||||
print(f" - 问答缓存: {rag.QA_FILE}")
|
||||
print("[ingest] 成功。")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user