vector_store.py 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. from typing import Any
  2. from uuid import uuid4
  3. from qdrant_client import QdrantClient
  4. from qdrant_client.http import models as qmodels
  5. from sentence_transformers import SentenceTransformer
  6. from app.config import settings
  7. class VectorStore:
  8. def __init__(self) -> None:
  9. self.client = QdrantClient(url=settings.qdrant_url)
  10. self.embedder = SentenceTransformer(settings.embedding_model_name)
  11. self.collection = settings.qdrant_collection
  12. self._ensure_collection()
  13. def _ensure_collection(self) -> None:
  14. collections = self.client.get_collections().collections
  15. exists = any(c.name == self.collection for c in collections)
  16. if not exists:
  17. self.client.create_collection(
  18. collection_name=self.collection,
  19. vectors_config=qmodels.VectorParams(size=384, distance=qmodels.Distance.COSINE),
  20. )
  21. def add_case_vector(self, case_id: int, text: str, metadata: dict[str, Any]) -> None:
  22. vector = self.embedder.encode(text).tolist()
  23. self.client.upsert(
  24. collection_name=self.collection,
  25. points=[
  26. qmodels.PointStruct(
  27. id=str(uuid4()),
  28. vector=vector,
  29. payload={"case_id": case_id, **metadata},
  30. )
  31. ],
  32. )
  33. def search_similar(self, text: str, limit: int = 5) -> list[dict[str, Any]]:
  34. query_vector = self.embedder.encode(text).tolist()
  35. hits = self.client.search(
  36. collection_name=self.collection,
  37. query_vector=query_vector,
  38. limit=limit,
  39. with_payload=True,
  40. )
  41. return [
  42. {
  43. "score": hit.score,
  44. "case_id": hit.payload.get("case_id") if hit.payload else None,
  45. "case_name": hit.payload.get("case_name") if hit.payload else None,
  46. }
  47. for hit in hits
  48. ]