Files
park-desktop/backend/scripts/ingest_kb.py
T
Pine b681eac2df feat: 大屏后端(FastAPI+MQTT+sim_engine)
- REST :10085 / MQTT 控制 / SSE 回退 / AI+语音
- 数据源规划:接核心服务端 + 算力引擎真实数据
2026-08-23 22:35:05 +08:00

64 lines
2.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()