Files
cdsl-cad/backend/app/services/library.py
T
2026-08-19 19:34:30 +08:00

75 lines
2.5 KiB
Python

from __future__ import annotations
import json
import re
from pathlib import Path
from typing import Any
from app.settings import Settings
TOKEN_PATTERN = re.compile(r"[a-zA-Z0-9_]+")
def tokens(value: str) -> set[str]:
return {token.lower() for token in TOKEN_PATTERN.findall(value)}
class CdslLibrary:
def __init__(self, settings: Settings) -> None:
self.settings = settings
self.index_path = settings.library_root / "index" / "catalog.json"
def _records(self) -> list[dict[str, Any]]:
if not self.index_path.is_file():
return []
payload = json.loads(self.index_path.read_text(encoding="utf-8"))
return payload.get("samples", [])
def count(self) -> int:
return len(self._records())
def search(self, query: str, limit: int = 5) -> list[dict[str, Any]]:
query_tokens = tokens(query)
if not query_tokens:
return [
{
"part_id": record["part_id"],
"profiles": record.get("profiles", []),
"features": record.get("features", []),
"summary": record.get("summary", ""),
}
for record in self._records()[:limit]
]
scored: list[tuple[int, dict[str, Any]]] = []
for record in self._records():
corpus = " ".join([
record.get("part_id", ""),
record.get("source_name", ""),
" ".join(record.get("profiles", [])),
" ".join(record.get("features", [])),
" ".join(record.get("parameters", [])),
])
score = len(query_tokens & tokens(corpus))
if score:
scored.append((score, record))
scored.sort(key=lambda item: (-item[0], item[1]["part_id"]))
return [
{
"part_id": record["part_id"],
"profiles": record.get("profiles", []),
"features": record.get("features", []),
"summary": record.get("summary", ""),
}
for _, record in scored[:limit]
]
def read_sample(self, part_id: str) -> dict[str, Any]:
for record in self._records():
if record.get("part_id") == part_id:
source = self.settings.library_root / "samples" / part_id / "model.cdsl.json"
if not source.is_file():
break
return json.loads(source.read_text(encoding="utf-8"))
raise ValueError(f"CDSL sample not found: {part_id}")