Coverage for src / lexigram / contracts / data / vector / protocols.py: 0%

30 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-15 18:57 +0800

1"""Vector store protocol definitions.""" 

2 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable 

6 

7if TYPE_CHECKING: 

8 from lexigram.contracts.core.health import HealthCheckResult 

9 from lexigram.contracts.data.vector.enums import DistanceMetric 

10 from lexigram.contracts.data.vector.filters import ( 

11 MetadataCondition, 

12 MetadataConditionGroup, 

13 ) 

14 from lexigram.contracts.data.vector.types import ( 

15 CollectionConfig, 

16 CollectionInfo, 

17 DeleteResult, 

18 SearchQuery, 

19 SearchResult, 

20 UpsertResult, 

21 VectorRecord, 

22 ) 

23 

24 

25@runtime_checkable 

26class VectorStoreProtocol(Protocol): 

27 """Top-level vector store lifecycle and collection management. 

28 

29 Implementations manage connections, collection CRUD, and delegate 

30 vector operations to ``VectorCollectionProtocol`` instances. 

31 """ 

32 

33 async def connect(self) -> None: 

34 """Establish connection to the vector store.""" 

35 ... 

36 

37 async def disconnect(self) -> None: 

38 """Close all connections and release resources.""" 

39 ... 

40 

41 async def health_check(self, timeout: float = 5.0) -> HealthCheckResult: 

42 """Check store connectivity and readiness.""" 

43 ... 

44 

45 async def list_collections(self) -> list[CollectionInfo]: 

46 """List all collections with metadata.""" 

47 ... 

48 

49 async def create_collection(self, config: CollectionConfig) -> None: 

50 """Create a new vector collection. 

51 

52 Raises: 

53 CollectionAlreadyExistsError: If collection name is taken. 

54 VectorConfigError: If config is invalid for this backend. 

55 """ 

56 ... 

57 

58 async def delete_collection(self, name: str) -> None: 

59 """Delete a collection and all its vectors. 

60 

61 Raises: 

62 CollectionNotFoundError: If collection does not exist. 

63 """ 

64 ... 

65 

66 async def collection_exists(self, name: str) -> bool: 

67 """Check whether a collection exists.""" 

68 ... 

69 

70 async def get_collection(self, name: str) -> VectorCollectionProtocol: 

71 """Get a handle to an existing collection. 

72 

73 Raises: 

74 CollectionNotFoundError: If collection does not exist. 

75 """ 

76 ... 

77 

78 async def add_texts( 

79 self, 

80 texts: list[str], 

81 embeddings: list[list[float]] | None = None, 

82 metadatas: list[dict[str, Any]] | None = None, 

83 collection_name: str | None = None, 

84 ) -> UpsertResult: 

85 """Add texts to a collection. 

86 

87 Convenience method that handles collection routing. If embeddings 

88 are not provided, the implementation may compute them internally 

89 or raise an error. 

90 """ 

91 ... 

92 

93 

94@runtime_checkable 

95class VectorCollectionProtocol(Protocol): 

96 """Vector operations within a single collection. 

97 

98 All similarity search, upsert, and delete operations operate 

99 on vectors within a named, dimensioned collection. 

100 """ 

101 

102 @property 

103 def name(self) -> str: 

104 """Collection name.""" 

105 ... 

106 

107 @property 

108 def dimension(self) -> int: 

109 """Vector dimensionality.""" 

110 ... 

111 

112 @property 

113 def distance_metric(self) -> DistanceMetric: 

114 """Distance function used for similarity.""" 

115 ... 

116 

117 async def upsert(self, records: list[VectorRecord]) -> UpsertResult: 

118 """Insert or update vectors. 

119 

120 If a record with the same ID exists, it is replaced. 

121 

122 Raises: 

123 DimensionMismatchError: If any vector has wrong dimensionality. 

124 """ 

125 ... 

126 

127 async def search(self, query: SearchQuery) -> list[SearchResult]: 

128 """Find the most similar vectors to the query vector. 

129 

130 Returns results ordered by similarity (best first), 

131 limited to ``query.top_k``. 

132 

133 Raises: 

134 DimensionMismatchError: If query vector has wrong dimensionality. 

135 """ 

136 ... 

137 

138 async def get(self, ids: list[str]) -> list[VectorRecord]: 

139 """Retrieve vectors by their IDs. 

140 

141 Returns only records that exist — missing IDs are silently skipped. 

142 """ 

143 ... 

144 

145 async def delete(self, ids: list[str]) -> DeleteResult: 

146 """Delete vectors by their IDs.""" 

147 ... 

148 

149 async def delete_by_filter( 

150 self, 

151 filter: MetadataCondition | MetadataConditionGroup, 

152 ) -> DeleteResult: 

153 """Delete all vectors matching a metadata filter.""" 

154 ... 

155 

156 async def count(self) -> int: 

157 """Return the number of vectors in this collection.""" 

158 ... 

159 

160 async def update_metadata( 

161 self, 

162 id: str, 

163 metadata: dict[str, Any], 

164 ) -> bool: 

165 """Update metadata for a single vector without re-uploading the vector. 

166 

167 Returns True if the record existed and was updated. 

168 """ 

169 ... 

170 

171 async def add_texts( 

172 self, 

173 texts: list[str], 

174 embeddings: list[list[float]], 

175 metadatas: list[dict[str, Any]] | None = None, 

176 ids: list[str] | None = None, 

177 ) -> UpsertResult: 

178 """Add texts with pre-computed embeddings. 

179 

180 This is a convenience method that wraps upsert for common use cases. 

181 """ 

182 ... 

183 

184 

185__all__ = [ 

186 "VectorCollectionProtocol", 

187 "VectorStoreProtocol", 

188]