Skip to content

Commit d542550

Browse files
authored
fix business knowledge vector filters (#569)
1 parent 217cee8 commit d542550

6 files changed

Lines changed: 68 additions & 7 deletions

File tree

‎data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/business/BusinessKnowledgeServiceImpl.java‎

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,17 +184,42 @@ public void deleteKnowledge(Long id) {
184184
}
185185

186186
private void doDelVector(BusinessKnowledge knowledge) {
187-
agentVectorStoreService.deleteDocumentsByMetadata(knowledge.getAgentId().toString(), vectorMetadata(knowledge));
187+
Map<String, Object> metadata = vectorMetadata(knowledge);
188+
boolean currentMetadataDeleted = deleteDocumentsByMetadata(knowledge, metadata);
189+
190+
// Compatibility cleanup for documents embedded before businessTermId was
191+
// normalized to String metadata.
192+
Map<String, Object> legacyNumericMetadata = new HashMap<>(metadata);
193+
legacyNumericMetadata.put(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, knowledge.getId());
194+
boolean legacyNumericMetadataDeleted = deleteDocumentsByMetadata(knowledge, legacyNumericMetadata);
195+
196+
if (!currentMetadataDeleted && !legacyNumericMetadataDeleted) {
197+
throw new IllegalStateException(
198+
"Failed to delete business knowledge from vector store: " + knowledge.getId());
199+
}
188200
}
189201

190202
private Map<String, Object> vectorMetadata(BusinessKnowledge knowledge) {
191203
Map<String, Object> metadata = new HashMap<>();
192204
metadata.put(Constant.AGENT_ID, knowledge.getAgentId().toString());
193-
metadata.put(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, knowledge.getId());
205+
metadata.put(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, knowledge.getId().toString());
194206
metadata.put(DocumentMetadataConstant.VECTOR_TYPE, DocumentMetadataConstant.BUSINESS_TERM);
195207
return metadata;
196208
}
197209

210+
private boolean deleteDocumentsByMetadata(BusinessKnowledge knowledge, Map<String, Object> metadata) {
211+
try {
212+
return Boolean.TRUE
213+
.equals(agentVectorStoreService.deleteDocumentsByMetadata(knowledge.getAgentId().toString(), metadata));
214+
}
215+
catch (RuntimeException ex) {
216+
Object businessTermId = metadata.get(DocumentMetadataConstant.DB_BUSINESS_TERM_ID);
217+
log.debug("Vector store rejected businessTermId metadata type {}",
218+
businessTermId.getClass().getSimpleName(), ex);
219+
return false;
220+
}
221+
}
222+
198223
@Override
199224
@Transactional(rollbackFor = Exception.class)
200225
public void recallKnowledge(Long id, Boolean isRecall) {

‎data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/service/vectorstore/DynamicFilterService.java‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,17 @@ public Filter.Expression buildDynamicFilter(String agentId, String vectorType) {
7373
return null;
7474
}
7575
else {
76-
// 添加 ID 过滤
76+
String[] stringIds = recalledBusinessKnowledgeIds.stream()
77+
.map(String::valueOf)
78+
.toArray(String[]::new);
79+
Filter.Expression stringIdFilter = b
80+
.in(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, (Object[]) stringIds)
81+
.build();
82+
Filter.Expression legacyNumericIdFilter = b
83+
.in(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, recalledBusinessKnowledgeIds.toArray())
84+
.build();
7785
conditions
78-
.add(b.in(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, recalledBusinessKnowledgeIds.toArray())
79-
.build());
86+
.add(new Filter.Expression(Filter.ExpressionType.OR, stringIdFilter, legacyNumericIdFilter));
8087
}
8188
break;
8289

‎data-agent-management/src/main/java/com/alibaba/cloud/ai/dataagent/util/DocumentConverterUtil.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public static Document convertBusinessKnowledgeToDocument(BusinessKnowledge busi
116116
Map<String, Object> metadata = new HashMap<>();
117117
metadata.put(DocumentMetadataConstant.VECTOR_TYPE, DocumentMetadataConstant.BUSINESS_TERM);
118118
metadata.put(Constant.AGENT_ID, businessKnowledge.getAgentId().toString());
119-
metadata.put(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, businessKnowledge.getId());
119+
metadata.put(DocumentMetadataConstant.DB_BUSINESS_TERM_ID, businessKnowledge.getId().toString());
120120

121121
return new Document(content, metadata);
122122
}

‎data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/business/BusinessKnowledgeServiceImplTest.java‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package com.alibaba.cloud.ai.dataagent.service.business;
1717

18+
import com.alibaba.cloud.ai.dataagent.constant.DocumentMetadataConstant;
1819
import com.alibaba.cloud.ai.dataagent.converter.BusinessKnowledgeConverter;
1920
import com.alibaba.cloud.ai.dataagent.dto.knowledge.businessknowledge.CreateBusinessKnowledgeDTO;
2021
import com.alibaba.cloud.ai.dataagent.dto.knowledge.businessknowledge.UpdateBusinessKnowledgeDTO;
@@ -229,7 +230,10 @@ void deleteKnowledge_found() {
229230
when(businessKnowledgeMapper.logicalDelete(1L, 1)).thenReturn(1);
230231

231232
service.deleteKnowledge(1L);
232-
verify(agentVectorStoreService).deleteDocumentsByMetadata(anyString(), anyMap());
233+
verify(agentVectorStoreService).deleteDocumentsByMetadata(anyString(),
234+
argThat(metadata -> "1".equals(metadata.get(DocumentMetadataConstant.DB_BUSINESS_TERM_ID))));
235+
verify(agentVectorStoreService).deleteDocumentsByMetadata(anyString(),
236+
argThat(metadata -> Long.valueOf(1L).equals(metadata.get(DocumentMetadataConstant.DB_BUSINESS_TERM_ID))));
233237
}
234238

235239
@Test

‎data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/service/vectorstore/DynamicFilterServiceTest.java‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import org.mockito.junit.jupiter.MockitoExtension;
2626
import org.mockito.junit.jupiter.MockitoSettings;
2727
import org.mockito.quality.Strictness;
28+
import org.springframework.ai.document.Document;
29+
import org.springframework.ai.embedding.EmbeddingModel;
30+
import org.springframework.ai.vectorstore.SearchRequest;
2831
import org.springframework.ai.vectorstore.filter.Filter;
2932

3033
import java.util.ArrayList;
@@ -33,8 +36,10 @@
3336
import java.util.Map;
3437

3538
import static org.junit.jupiter.api.Assertions.*;
39+
import static org.mockito.ArgumentMatchers.any;
3640
import static org.mockito.ArgumentMatchers.anyInt;
3741
import static org.mockito.ArgumentMatchers.anyLong;
42+
import static org.mockito.Mockito.mock;
3843
import static org.mockito.Mockito.when;
3944

4045
@ExtendWith(MockitoExtension.class)
@@ -84,6 +89,25 @@ void buildDynamicFilter_businessTerm_withValidIds_returnsFilterExpression() {
8489
assertNotNull(result);
8590
}
8691

92+
@Test
93+
void buildDynamicFilter_businessTerm_matchesStringMetadataInSimpleVectorStore() {
94+
when(businessKnowledgeMapper.selectRecalledKnowledgeIds(anyLong())).thenReturn(List.of(10L));
95+
EmbeddingModel embeddingModel = mock(EmbeddingModel.class);
96+
when(embeddingModel.dimensions()).thenReturn(2);
97+
when(embeddingModel.embed(any(Document.class))).thenReturn(new float[] { 1.0f, 0.0f });
98+
when(embeddingModel.embed(any(String.class))).thenReturn(new float[] { 1.0f, 0.0f });
99+
MetadataAwareSimpleVectorStore store = new MetadataAwareSimpleVectorStore(embeddingModel);
100+
store.add(List.of(new Document("term", Map.of("agentId", "1", DocumentMetadataConstant.VECTOR_TYPE,
101+
DocumentMetadataConstant.BUSINESS_TERM, DocumentMetadataConstant.DB_BUSINESS_TERM_ID, "10"))));
102+
103+
Filter.Expression filter = dynamicFilterService.buildDynamicFilter("1",
104+
DocumentMetadataConstant.BUSINESS_TERM);
105+
List<Document> result = store.similaritySearch(
106+
SearchRequest.builder().query("default").filterExpression(filter).topK(10).similarityThreshold(0).build());
107+
108+
assertEquals(1, result.size());
109+
}
110+
87111
@Test
88112
void buildDynamicFilter_businessTerm_noValidIds_returnsNull() {
89113
when(businessKnowledgeMapper.selectRecalledKnowledgeIds(anyLong())).thenReturn(new ArrayList<>());

‎data-agent-management/src/test/java/com/alibaba/cloud/ai/dataagent/util/DocumentConverterUtilTest.java‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ void testConvertBusinessKnowledgeToDocument() {
149149
assertTrue(doc.getText().contains("Gross Merchandise Value"));
150150
assertEquals(DocumentMetadataConstant.BUSINESS_TERM,
151151
doc.getMetadata().get(DocumentMetadataConstant.VECTOR_TYPE));
152+
assertEquals("1", doc.getMetadata().get(DocumentMetadataConstant.DB_BUSINESS_TERM_ID));
152153
}
153154

154155
@Test

0 commit comments

Comments
 (0)