Download vetcopilot-backend/scripts/init_knowledge_base.py from WWsCa/VetNet-LCPS: direct link, hf CLI and curl.
- Browser
- Download file 4.85 kB
-
https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-backend/scripts/init_knowledge_base.py
- Command line
-
hf download hf://WWsCa/VetNet-LCPS/vetcopilot-backend/scripts/init_knowledge_base.py
-
curl -L -o init_knowledge_base.py https://huggingface.co/WWsCa/VetNet-LCPS/resolve/main/vetcopilot-backend/scripts/init_knowledge_base.py
4.85 kB
| """ | |
| 知识库初始化脚本 - 递归扫描 veterinary_articles 目录下所有 PDF | |
| 使用方法: | |
| py -3.12 scripts/init_knowledge_base.py | |
| """ | |
| import os | |
| import sys | |
| import shutil | |
| import time | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) | |
| from app.database import SessionLocal, init_db | |
| from app.models.knowledge import KnowledgeDocument, KnowledgeChunk | |
| from app.services import knowledge_service as ks | |
| from app.config import settings | |
| from app.utils.logger import logger | |
| # 扫描目录:本地 veterinary_articles(含 site1/site2/site3) | |
| ARTICLES_DIR = Path(r"C:\Users\HP\Documents\666666666666666666\veterinary_articles") | |
| PDF_DEST_DIR = Path(settings.UPLOAD_DIR) / "knowledge_pdfs" | |
| EXCLUDE_PATTERNS = [ | |
| "cover", "index", "contents", "front", "preface", "acknowledg", | |
| "abbreviat", "glossary", "appendi", "reference", "bibliograph", | |
| ] | |
| def should_include(filename: str) -> bool: | |
| name_lower = filename.lower() | |
| for pattern in EXCLUDE_PATTERNS: | |
| if pattern in name_lower: | |
| return False | |
| return True | |
| def main(): | |
| if not ARTICLES_DIR.exists(): | |
| print(f"错误:目录不存在: {ARTICLES_DIR}") | |
| return | |
| # 确保目标目录存在 | |
| PDF_DEST_DIR.mkdir(parents=True, exist_ok=True) | |
| # 初始化数据库 | |
| print("初始化数据库...") | |
| init_db() | |
| # 初始化 FAISS 索引 | |
| print("初始化 FAISS 索引...") | |
| ks.init_faiss_index() | |
| # 递归扫描所有 PDF | |
| print(f"\n扫描目录: {ARTICLES_DIR}") | |
| pdf_files = sorted(ARTICLES_DIR.rglob("*.pdf")) | |
| pdf_files = [f for f in pdf_files if not f.name.startswith("_")] | |
| print(f"发现 {len(pdf_files)} 个 PDF 文件") | |
| # 过滤 | |
| pdf_files = [f for f in pdf_files if should_include(f.name)] | |
| print(f"过滤后剩余 {len(pdf_files)} 个文件待导入\n") | |
| # 按站点分组统计 | |
| from collections import Counter | |
| site_counts = Counter() | |
| for f in pdf_files: | |
| parts = f.parts | |
| for p in parts: | |
| if p.startswith("site"): | |
| site_counts[p] += 1 | |
| break | |
| else: | |
| site_counts["other"] += 1 | |
| print("按站点分布:") | |
| for site, cnt in site_counts.most_common(): | |
| print(f" {site}: {cnt} 个") | |
| # 检查已存在 | |
| db = SessionLocal() | |
| try: | |
| existing_hashes = set() | |
| all_docs = db.query(KnowledgeDocument).all() | |
| for d in all_docs: | |
| existing_hashes.add(d.file_hash) | |
| imported = 0 | |
| skipped = 0 | |
| failed = 0 | |
| total = len(pdf_files) | |
| for idx, pdf_path in enumerate(pdf_files): | |
| file_hash = ks._compute_sha256(pdf_path) | |
| if file_hash in existing_hashes: | |
| if (idx + 1) % 100 == 0: | |
| print(f" [{idx+1}/{total}] 已导入={imported} 跳过={skipped} 失败={failed}") | |
| skipped += 1 | |
| continue | |
| # 复制到知识库 PDF 目录 | |
| dest_name = pdf_path.name | |
| dest_path = PDF_DEST_DIR / dest_name | |
| # 处理重名 | |
| counter = 1 | |
| while dest_path.exists(): | |
| stem = pdf_path.stem | |
| dest_name = f"{stem}_{counter}.pdf" | |
| dest_path = PDF_DEST_DIR / dest_name | |
| counter += 1 | |
| shutil.copy2(pdf_path, dest_path) | |
| try: | |
| result = ks.upload_document(dest_path, dest_name) | |
| if result.get("duplicate"): | |
| skipped += 1 | |
| continue | |
| doc_id = result["id"] | |
| # 同步处理(大文件可能需要较长时间) | |
| ks.process_document(doc_id) | |
| doc = db.query(KnowledgeDocument).filter( | |
| KnowledgeDocument.id == doc_id | |
| ).first() | |
| if doc and doc.status == "ready": | |
| imported += 1 | |
| else: | |
| status = doc.status if doc else "unknown" | |
| error = doc.error_message if doc else "" | |
| failed += 1 | |
| if idx < 5: | |
| print(f" [失败] {pdf_path.name}: status={status} error={error[:80]}") | |
| except Exception as e: | |
| failed += 1 | |
| if idx < 5: | |
| print(f" [异常] {pdf_path.name}: {e}") | |
| if (idx + 1) % 50 == 0 or idx < 5: | |
| print(f" [{idx+1}/{total}] 已导入={imported} 跳过={skipped} 失败={failed}") | |
| print(f"\n{'='*50}") | |
| print(f"导入完成!") | |
| print(f" 成功导入: {imported}") | |
| print(f" 跳过(已存在): {skipped}") | |
| print(f" 失败: {failed}") | |
| print(f"{'='*50}") | |
| finally: | |
| db.close() | |
| if __name__ == "__main__": | |
| main() | |