import re from sqlalchemy.orm import Session from app.models import CaseRecord def _tokens(text: str) -> set[str]: if not text: return set() chunk = text[:8000] return set(re.findall(r"[\w\u4e00-\u9fff]+", chunk)) def _jaccard(a: set[str], b: set[str]) -> float: if not a or not b: return 0.0 inter = len(a & b) union = len(a | b) return inter / union if union else 0.0 def find_similar(db: Session, exclude_case_id: int, query_text: str, limit: int = 5) -> list[dict]: """ 不依赖向量库:用词集合 Jaccard 与库里历史案件粗排相似度(适合毕业设计演示)。 """ q = _tokens(query_text) rows = db.query(CaseRecord).filter(CaseRecord.id != exclude_case_id).all() scored: list[tuple[float, CaseRecord]] = [] for row in rows: s = _jaccard(q, _tokens(row.raw_text or "")) scored.append((s, row)) scored.sort(key=lambda x: x[0], reverse=True) return [ {"score": float(s), "case_id": row.id, "case_name": row.case_name} for s, row in scored[:limit] if s > 0 ]