2
2
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
3
3
// See the LICENSE file in the project root for more information.
4
4
5
- using System . Collections . Generic ;
6
- using System . Linq ;
5
+ using System . Text . Json ;
7
6
using System . Text . Json . Nodes ;
8
7
9
8
using Elastic . Clients . Elasticsearch ;
10
9
using Elastic . Transport . Extensions ;
11
10
11
+ using Microsoft . Extensions . AI ;
12
12
using Microsoft . Extensions . VectorData ;
13
+ using Microsoft . Extensions . VectorData . ConnectorSupport ;
13
14
using Microsoft . SemanticKernel ;
14
15
15
16
namespace Elastic . SemanticKernel . Connectors . Elasticsearch ;
16
17
17
18
/// <summary>
18
- /// A mapper that maps between the generic Semantic Kernel data model and the model that the data is stored under,
19
- /// within Elasticsearch.
19
+ /// A mapper that maps between the generic Semantic Kernel data model and the model that the data is stored under,
20
+ /// within Elasticsearch.
20
21
/// </summary>
21
- internal sealed class ElasticsearchDataModelMapper < TRecord > :
22
- IVectorStoreRecordMapper < TRecord , ( string ? id , JsonObject document ) >
22
+ internal sealed class ElasticsearchDataModelMapper < TKey , TRecord > :
23
+ IElasticsearchVectorStoreRecordMapper < TRecord , ( string ? id , JsonObject document ) >
24
+ where TKey : notnull
25
+ where TRecord : notnull
23
26
{
24
- /// <summary>The Elasticsearch client settings.</summary>
25
- private readonly IElasticsearchClientSettings _elasticsearchClientSettings ;
27
+ /// <summary>
28
+ /// A model representing a record in a vector store collection.
29
+ /// </summary>
30
+ private readonly VectorStoreRecordModel _model ;
26
31
27
- /// <summary>A mapping from <see cref="VectorStoreRecordDefinition" /> to storage model property name.</summary>
28
- private readonly Dictionary < VectorStoreRecordProperty , string > _propertyToStorageName ;
32
+ /// <summary>
33
+ /// The Elasticsearch client settings.
34
+ /// </summary>
35
+ private readonly IElasticsearchClientSettings _elasticsearchClientSettings ;
29
36
30
37
/// <summary>
31
- /// Initializes a new instance of the <see cref="ElasticsearchGenericDataModelMapper" /> class.
38
+ /// Initializes a new instance of the <see cref="ElasticsearchGenericDataModelMapper" /> class.
32
39
/// </summary>
33
- /// <param name="propertyToStorageName ">A mapping from <see cref="VectorStoreRecordDefinition" /> to storage model property name .</param>
40
+ /// <param name="model ">A model representing a record in a vector store collection .</param>
34
41
/// <param name="elasticsearchClientSettings">The Elasticsearch client settings to use.</param>
35
42
public ElasticsearchDataModelMapper (
36
- Dictionary < VectorStoreRecordProperty , string > propertyToStorageName ,
43
+ VectorStoreRecordModel model ,
37
44
IElasticsearchClientSettings elasticsearchClientSettings )
38
45
{
39
- Verify . NotNull ( propertyToStorageName ) ;
46
+ Verify . NotNull ( model ) ;
40
47
Verify . NotNull ( elasticsearchClientSettings ) ;
41
48
42
49
// Assign.
50
+ _model = model ;
43
51
_elasticsearchClientSettings = elasticsearchClientSettings ;
44
- _propertyToStorageName = propertyToStorageName ;
45
52
}
46
53
47
54
/// <inheritdoc />
48
- public ( string ? id , JsonObject document ) MapFromDataToStorageModel ( TRecord dataModel )
55
+ public ( string ? id , JsonObject document ) MapFromDataToStorageModel ( TRecord dataModel , Embedding < float > ? [ ] ? generatedEmbeddings )
49
56
{
50
- // Serialize the whole record to JsonObject.
57
+ Verify . NotNull ( dataModel ) ;
51
58
52
- var document = SerializeSource ( dataModel , _elasticsearchClientSettings ) ! ;
59
+ // Serialize the whole record to JsonObject.
53
60
54
- // Extract key property.
61
+ var document = SerializeSource ( dataModel , _elasticsearchClientSettings ) ;
55
62
56
- var keyProperty = _propertyToStorageName . Single ( x => x . Key is VectorStoreRecordKeyProperty ) ;
57
- var keyValue = document [ keyProperty . Value ] ! . AsValue ( ) ;
63
+ // Extract key property and remove it from document.
58
64
59
- var id = keyValue . GetValue < string ? > ( ) ;
65
+ var keyProperty = _model . KeyProperty ;
66
+ var id = ( TKey ? ) keyProperty . GetValueAsObject ( dataModel ) ;
67
+ document . Remove ( keyProperty . StorageName ) ;
60
68
61
- // Remove key property from document .
69
+ // Update vector properties with generated embeddings .
62
70
63
- document . Remove ( keyProperty . Value ) ;
71
+ if ( generatedEmbeddings is not null )
72
+ {
73
+ for ( var i = 0 ; i < _model . VectorProperties . Count ; ++ i )
74
+ {
75
+ if ( generatedEmbeddings [ i ] is not { } embedding )
76
+ {
77
+ continue ;
78
+ }
79
+
80
+ var vectorProperty = _model . VectorProperties [ i ] ;
81
+ document [ vectorProperty . StorageName ] = JsonValue . Create ( embedding . Vector ) ;
82
+ }
83
+ }
64
84
65
- return ( id , document ) ;
85
+ return ( ( id is null ) ? null : ElasticsearchVectorStoreRecordFieldMapping . KeyToElasticsearchId ( id ) , document ) ;
66
86
}
67
87
68
88
/// <inheritdoc />
@@ -71,19 +91,19 @@ public TRecord MapFromStorageToDataModel((string? id, JsonObject document) stora
71
91
{
72
92
// Add key property to document.
73
93
74
- var keyProperty = _propertyToStorageName . Single ( x => x . Key is VectorStoreRecordKeyProperty ) ;
75
- storageModel . document . Add ( keyProperty . Value , storageModel . id ) ;
94
+ var keyProperty = _model . KeyProperty ;
95
+ storageModel . document . Add ( keyProperty . StorageName , JsonValue . Create ( ElasticsearchVectorStoreRecordFieldMapping . ElasticsearchIdToKey < TKey > ( storageModel . id ! ) ) ) ;
76
96
77
97
// Serialize the whole model into the user-defined record type.
78
98
79
99
return _elasticsearchClientSettings . SourceSerializer . Deserialize < TRecord > ( storageModel . document ) ! ;
80
100
}
81
101
82
- private static JsonObject ? SerializeSource < T > ( T ? obj , IElasticsearchClientSettings settings )
102
+ private static JsonObject SerializeSource < T > ( T obj , IElasticsearchClientSettings settings )
83
103
{
84
- if ( obj is null )
104
+ if ( settings . SourceSerializer . TryGetJsonSerializerOptions ( out var options ) )
85
105
{
86
- return null ;
106
+ return ( JsonObject ) JsonSerializer . SerializeToNode ( obj , options ) ! ;
87
107
}
88
108
89
109
using var stream = settings . MemoryStreamFactory . Create ( ) ;
0 commit comments