Spaces:
Paused
Paused
| from __future__ import annotations | |
| import json | |
| from pathlib import Path | |
| from threading import Lock | |
| from typing import Any | |
| BASE_DIR = Path(__file__).resolve().parent | |
| SEED_FILE = BASE_DIR / "seed_data.json" | |
| _LOCK = Lock() | |
| def _ensure_seed_file() -> None: | |
| if not SEED_FILE.exists(): | |
| SEED_FILE.write_text("[] | |
| ", encoding="utf-8") | |
| def load_entries() -> list[dict[str, Any]]: | |
| _ensure_seed_file() | |
| with SEED_FILE.open("r", encoding="utf-8") as handle: | |
| data = json.load(handle) | |
| if not isinstance(data, list): | |
| raise ValueError("Knowledge base seed_data.json must contain a list") | |
| return [entry for entry in data if isinstance(entry, dict)] | |
| def _save_entries(entries: list[dict[str, Any]]) -> None: | |
| tmp = SEED_FILE.with_suffix(".json.tmp") | |
| with tmp.open("w", encoding="utf-8") as handle: | |
| json.dump(entries, handle, indent=2, ensure_ascii=False) | |
| handle.write(" | |
| ") | |
| tmp.replace(SEED_FILE) | |
| def next_entry_id(entries: list[dict[str, Any]]) -> str: | |
| max_num = 0 | |
| for entry in entries: | |
| entry_id = str(entry.get("id", "")) | |
| if entry_id.startswith("kb_"): | |
| suffix = entry_id[3:] | |
| if suffix.isdigit(): | |
| max_num = max(max_num, int(suffix)) | |
| return f"kb_{max_num + 1:03d}" | |
| def normalize_entry(entry: dict[str, Any]) -> dict[str, Any]: | |
| required = ["topic", "title", "content", "source", "tags"] | |
| missing = [key for key in required if not entry.get(key)] | |
| if missing: | |
| raise ValueError(f"Missing required knowledge base fields: {', '.join(missing)}") | |
| tags = entry.get("tags") | |
| if not isinstance(tags, list): | |
| raise ValueError("tags must be a list of strings") | |
| return { | |
| "id": str(entry.get("id") or "").strip(), | |
| "topic": str(entry["topic"]).strip(), | |
| "title": str(entry["title"]).strip(), | |
| "content": str(entry["content"]).strip(), | |
| "source": str(entry["source"]).strip(), | |
| "tags": [str(tag).strip() for tag in tags if str(tag).strip()], | |
| } | |
| def append_entry(entry: dict[str, Any]) -> dict[str, Any]: | |
| with _LOCK: | |
| entries = load_entries() | |
| normalized = normalize_entry(entry) | |
| if not normalized["id"]: | |
| normalized["id"] = next_entry_id(entries) | |
| entries.append(normalized) | |
| _save_entries(entries) | |
| return normalized | |
| def update_entries(entries: list[dict[str, Any]]) -> None: | |
| with _LOCK: | |
| _save_entries(entries) | |