GH-1826 Fix EmbeddingModel's usage on Document#embedding
- Since the Document object's reference to the `embedding` is deprecated and will be removed, the VectorStore implementations require a way to store the embedding of the corresponding Document objects
- One way to fix this is, to have the EmbeddingModel#embed to return the embeddings in the same order as that of the Documents passed to it.
- Since both the Document and embedding collections use the List object, their iteration operation will make sure to keep them in line with the same order.
- A fix is required to preserve the order when batching strategy is applied.
- Updated the Javadoc for BatchingStrategy
- Fixed the Document List order in TokenCountBatchingStrategy
- Refactored the vector store implementations to update this change
Resolves #GH-1826
This commit is contained in:
committed by
Christian Tzolov
parent
6cfe5e79e8
commit
ebd29e0959
@@ -196,10 +196,11 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini
|
||||
|
||||
@Override
|
||||
public void doAdd(List<Document> documents) {
|
||||
this.embeddingModel.embed(documents, EmbeddingOptionsBuilder.builder().build(), this.batchingStrategy);
|
||||
List<float[]> embeddings = this.embeddingModel.embed(documents, EmbeddingOptionsBuilder.builder().build(),
|
||||
this.batchingStrategy);
|
||||
|
||||
List<List<Document>> batchedDocuments = batchDocuments(documents);
|
||||
batchedDocuments.forEach(this::insertOrUpdateBatch);
|
||||
batchedDocuments.forEach(batchDocument -> insertOrUpdateBatch(batchDocument, documents, embeddings));
|
||||
}
|
||||
|
||||
private List<List<Document>> batchDocuments(List<Document> documents) {
|
||||
@@ -210,7 +211,7 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini
|
||||
return batches;
|
||||
}
|
||||
|
||||
private void insertOrUpdateBatch(List<Document> batch) {
|
||||
private void insertOrUpdateBatch(List<Document> batch, List<Document> documents, List<float[]> embeddings) {
|
||||
String sql = "INSERT INTO " + getFullyQualifiedTableName()
|
||||
+ " (id, content, metadata, embedding) VALUES (?, ?, ?::jsonb, ?) " + "ON CONFLICT (id) DO "
|
||||
+ "UPDATE SET content = ? , metadata = ?::jsonb , embedding = ? ";
|
||||
@@ -223,7 +224,7 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini
|
||||
var document = batch.get(i);
|
||||
var content = document.getContent();
|
||||
var json = toJson(document.getMetadata());
|
||||
var embedding = document.getEmbedding();
|
||||
var embedding = embeddings.get(documents.indexOf(document));
|
||||
var pGvector = new PGvector(embedding);
|
||||
|
||||
StatementCreatorUtils.setParameterValue(ps, 1, SqlTypeValue.TYPE_UNKNOWN,
|
||||
@@ -499,23 +500,18 @@ public class PgVectorStore extends AbstractObservationVectorStore implements Ini
|
||||
String id = rs.getString(COLUMN_ID);
|
||||
String content = rs.getString(COLUMN_CONTENT);
|
||||
PGobject pgMetadata = rs.getObject(COLUMN_METADATA, PGobject.class);
|
||||
PGobject embedding = rs.getObject(COLUMN_EMBEDDING, PGobject.class);
|
||||
Float distance = rs.getFloat(COLUMN_DISTANCE);
|
||||
|
||||
Map<String, Object> metadata = toMap(pgMetadata);
|
||||
metadata.put(DocumentMetadata.DISTANCE.value(), distance);
|
||||
|
||||
// @formatter:off
|
||||
return Document.builder()
|
||||
.id(id)
|
||||
.content(content)
|
||||
.metadata(metadata)
|
||||
.score(1.0 - distance)
|
||||
.embedding(toFloatArray(embedding))
|
||||
.build();
|
||||
}
|
||||
|
||||
private float[] toFloatArray(PGobject embedding) throws SQLException {
|
||||
return new PGvector(embedding.getValue()).toArray();
|
||||
.build(); // @formatter:on
|
||||
}
|
||||
|
||||
private Map<String, Object> toMap(PGobject pgObject) {
|
||||
|
||||
@@ -146,9 +146,6 @@ class PgVectorStoreWithChatMemoryAdvisorIT {
|
||||
EmbeddingModel embeddingModel = mock(EmbeddingModel.class);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
Object[] arguments = invocationOnMock.getArguments();
|
||||
List<Document> documents = (List<Document>) arguments[0];
|
||||
documents.forEach(d -> d.setEmbedding(this.embed));
|
||||
return List.of(this.embed, this.embed);
|
||||
}).when(embeddingModel).embed(ArgumentMatchers.any(), any(), any());
|
||||
given(embeddingModel.embed(any(String.class))).willReturn(this.embed);
|
||||
|
||||
Reference in New Issue
Block a user