knowledge_service.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. from __future__ import annotations
  2. from difflib import SequenceMatcher
  3. from sqlalchemy.orm import Session
  4. from app.db.models.knowledge import KnowledgeItem
  5. from app.db.repositories import knowledge as knowledge_repo
  6. from app.schemas.knowledge import KnowledgeSearchRequest
  7. def _score(item: KnowledgeItem, query: str) -> float:
  8. normalized = query.strip().lower()
  9. if not normalized:
  10. return 0
  11. title = item.title.lower()
  12. summary = item.summary.lower()
  13. content = item.content.lower()
  14. if normalized == title:
  15. return 100
  16. if normalized in title:
  17. base = 90
  18. elif normalized in summary:
  19. base = 78
  20. elif normalized in content:
  21. base = 65
  22. else:
  23. base = 0
  24. ratio = max(
  25. SequenceMatcher(None, normalized, title).ratio(),
  26. SequenceMatcher(None, normalized, summary[:300]).ratio(),
  27. )
  28. return round(min(100, base + ratio * 10), 2)
  29. def search_knowledge(
  30. db: Session,
  31. payload: KnowledgeSearchRequest,
  32. ) -> list[dict]:
  33. items, _ = knowledge_repo.list_knowledge(
  34. db,
  35. mine_id=payload.mine_id,
  36. knowledge_type=payload.knowledge_type,
  37. category=payload.category,
  38. keyword=payload.query,
  39. page=1,
  40. page_size=payload.limit,
  41. )
  42. hits = [
  43. {
  44. "item": item,
  45. "score": _score(item, payload.query),
  46. "highlight": item.summary or item.content[:160],
  47. }
  48. for item in items
  49. ]
  50. hits.sort(key=lambda item: item["score"], reverse=True)
  51. return hits