SearchEntityFiles 根据实体名称搜索向量库,返回命中的文件ID列表和分数
(eid int64, name string, topK int)
| 165 | |
| 166 | // SearchEntityFiles 根据实体名称搜索向量库,返回命中的文件ID列表和分数 |
| 167 | func (s *EntityVectorService) SearchEntityFiles(eid int64, name string, topK int) ([]EntitySearchHit, error) { |
| 168 | if s.vectorDB == nil { |
| 169 | return nil, fmt.Errorf("vector store unavailable") |
| 170 | } |
| 171 | if topK <= 0 { |
| 172 | topK = 10 |
| 173 | } |
| 174 | |
| 175 | // 1. 生成搜索向量 |
| 176 | configService := NewChunkConfigService(s.db) |
| 177 | config, err := configService.GetConfig(eid, nil, model.ChunkTypeDefault) |
| 178 | if err != nil { |
| 179 | return nil, err |
| 180 | } |
| 181 | if config.EmbeddingChannelID == nil { |
| 182 | return nil, fmt.Errorf("未配置向量化渠道") |
| 183 | } |
| 184 | |
| 185 | // 实体向量内容格式为 "Type:Name",由于输入只有 name,我们搜索时也按此逻辑 |
| 186 | // 如果需要更精准,可以考虑只针对 Name 生成向量,或者尝试匹配所有可能的 Type |
| 187 | // 这里目前采用通用的关键词 Embedding |
| 188 | queryVec64, err := s.embedding.GetQueryEmbedding(eid, name, *config.EmbeddingChannelID, config) |
| 189 | if err != nil { |
| 190 | return nil, err |
| 191 | } |
| 192 | queryVec := make([]float32, len(queryVec64)) |
| 193 | for i, v := range queryVec64 { |
| 194 | queryVec[i] = float32(v) |
| 195 | } |
| 196 | |
| 197 | // 2. 向量库搜索 |
| 198 | req := vectorstore.SearchRequest{ |
| 199 | Collection: model.GetEntityVectorCollectionName(eid), |
| 200 | Vector: queryVec, |
| 201 | TopK: topK, |
| 202 | ScoreThreshold: 0, |
| 203 | } |
| 204 | ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) |
| 205 | res, err := s.vectorDB.Search(ctx, req) |
| 206 | cancel() |
| 207 | if err != nil { |
| 208 | // 如果集合不存在,说明没有索引数据,直接返回空 |
| 209 | if vectorstore.IsNotFoundError(err) { |
| 210 | return []EntitySearchHit{}, nil |
| 211 | } |
| 212 | return nil, err |
| 213 | } |
| 214 | if res == nil { |
| 215 | return nil, fmt.Errorf("search result is nil") |
| 216 | } |
| 217 | |
| 218 | // 3. 聚合结果并查询关联的文件ID |
| 219 | var hits []EntitySearchHit |
| 220 | for _, r := range res.Results { |
| 221 | if r.Metadata == nil { |
| 222 | continue |
| 223 | } |
| 224 |
no test coverage detected