Skip to content

Commit 51dcfb4

Browse files
authored
Merge branch 'main' into feature_single_agent_patterns_nochat
2 parents a495eac + 4f945a3 commit 51dcfb4

File tree

5 files changed

+81
-49
lines changed

5 files changed

+81
-49
lines changed

dotnet/src/Connectors/Connectors.Memory.SqlServer/SqlServerClient.cs

+21-7
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,31 @@ public SqlServerClient(SqlConnection connection, string schema)
3333
this._schema = schema;
3434
}
3535

36+
private async Task<bool> HasJsonNativeTypeAsync(CancellationToken cancellationToken = default)
37+
{
38+
using (await this.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
39+
{
40+
using var cmd = this._connection.CreateCommand();
41+
cmd.CommandText = "select [name] from sys.types where system_type_id = 244 and user_type_id = 244";
42+
var typeName = (string)await cmd.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
43+
return string.Equals(typeName, "json", StringComparison.OrdinalIgnoreCase);
44+
}
45+
}
46+
3647
/// <inheritdoc/>
3748
public async Task CreateTableAsync(string tableName, CancellationToken cancellationToken = default)
3849
{
3950
var fullTableName = this.GetSanitizedFullTableName(tableName);
51+
var metadataType = await this.HasJsonNativeTypeAsync(cancellationToken).ConfigureAwait(false) ? "json" : "nvarchar(max)";
52+
4053
using (await this.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
4154
{
4255
using var cmd = this._connection.CreateCommand();
4356
cmd.CommandText = $"""
4457
IF OBJECT_ID(N'{fullTableName}', N'U') IS NULL
4558
CREATE TABLE {fullTableName} (
4659
[key] nvarchar(255) collate latin1_general_bin2 not null,
47-
[metadata] nvarchar(max) not null,
60+
[metadata] {metadataType} not null,
4861
[embedding] varbinary(8000),
4962
[timestamp] datetimeoffset,
5063
PRIMARY KEY NONCLUSTERED ([key]),
@@ -138,9 +151,9 @@ WHEN NOT MATCHED THEN
138151
/// <inheritdoc/>
139152
public async IAsyncEnumerable<SqlServerMemoryEntry> ReadBatchAsync(string tableName, IEnumerable<string> keys, bool withEmbeddings = false, [EnumeratorCancellation] CancellationToken cancellationToken = default)
140153
{
141-
var queryColumns = withEmbeddings
142-
? "[key], [metadata], [timestamp], VECTOR_TO_JSON_ARRAY([embedding]) AS [embedding]"
143-
: "[key], [metadata], [timestamp]";
154+
var queryColumns = "[key], [metadata], [timestamp]" +
155+
(withEmbeddings ? ", VECTOR_TO_JSON_ARRAY([embedding]) AS [embedding]" : string.Empty);
156+
144157
var fullTableName = this.GetSanitizedFullTableName(tableName);
145158
var keysList = keys.ToList();
146159
var keysParams = string.Join(", ", keysList.Select((_, i) => $"@k{i}"));
@@ -189,9 +202,8 @@ WHERE [key] IN ({keysParams})
189202
/// <inheritdoc/>
190203
public async IAsyncEnumerable<(SqlServerMemoryEntry, double)> GetNearestMatchesAsync(string tableName, ReadOnlyMemory<float> embedding, int limit, double minRelevanceScore = 0, bool withEmbeddings = false, [EnumeratorCancellation] CancellationToken cancellationToken = default)
191204
{
192-
var queryColumns = withEmbeddings
193-
? "[key], [metadata], [timestamp], 1 - VECTOR_DISTANCE('cosine', [embedding], JSON_ARRAY_TO_VECTOR(@e)) AS [cosine_similarity], VECTOR_TO_JSON_ARRAY([embedding]) AS [embedding]"
194-
: "[key], [metadata], [timestamp], 1 - VECTOR_DISTANCE('cosine', [embedding], JSON_ARRAY_TO_VECTOR(@e)) AS [cosine_similarity]";
205+
var queryColumns = "[key], [metadata], [timestamp], 1 - VECTOR_DISTANCE('cosine', [embedding], JSON_ARRAY_TO_VECTOR(@e)) AS [cosine_similarity]" +
206+
(withEmbeddings ? ", VECTOR_TO_JSON_ARRAY([embedding]) AS [embedding]" : string.Empty);
195207
var fullTableName = this.GetSanitizedFullTableName(tableName);
196208
using (await this.OpenConnectionAsync(cancellationToken).ConfigureAwait(false))
197209
{
@@ -221,6 +233,7 @@ ORDER BY [cosine_similarity] DESC
221233
private string GetSanitizedFullTableName(string tableName) => $"{DelimitIdentifier(this._schema)}.{DelimitIdentifier(tableName)}";
222234

223235
private string SerializeEmbedding(ReadOnlyMemory<float> embedding) => JsonSerializer.Serialize(embedding);
236+
224237
private ReadOnlyMemory<float> DeserializeEmbedding(string embedding) => JsonSerializer.Deserialize<ReadOnlyMemory<float>>(embedding);
225238

226239
private SqlServerMemoryEntry ReadEntry(SqlDataReader reader, bool hasEmbedding)
@@ -247,6 +260,7 @@ private async Task<IDisposable> OpenConnectionAsync(CancellationToken cancellati
247260
}
248261

249262
private static string DelimitIdentifier(string identifier) => $"[{EscapeIdentifier(identifier)}]";
263+
250264
private static string EscapeIdentifier(string identifier) => identifier.Replace("]", "]]");
251265

252266
private readonly struct Closer(SqlServerClient client, bool shouldClose) : IDisposable

dotnet/src/Connectors/Connectors.Memory.Sqlite/Database.cs

+21
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,27 @@ DELETE FROM {TableName}
168168
return cmd.ExecuteNonQueryAsync(cancellationToken);
169169
}
170170

171+
public Task DeleteBatchAsync(SqliteConnection conn, string collectionName, string[] keys, CancellationToken cancellationToken = default)
172+
{
173+
using SqliteCommand cmd = conn.CreateCommand();
174+
var keyParameters = keys.Select((key, index) => $"@key{index}");
175+
var parameters = string.Join(", ", keyParameters);
176+
177+
#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
178+
cmd.CommandText = $@"
179+
DELETE FROM {TableName}
180+
WHERE collection=@collection
181+
AND key IN ({parameters})";
182+
#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
183+
184+
cmd.Parameters.Add(new SqliteParameter("@collection", collectionName));
185+
for (int i = 0; i < keys.Length; i++)
186+
{
187+
cmd.Parameters.Add(new SqliteParameter($"@key{i}", keys[i]));
188+
}
189+
return cmd.ExecuteNonQueryAsync(cancellationToken);
190+
}
191+
171192
public Task DeleteEmptyAsync(SqliteConnection conn, string collectionName, CancellationToken cancellationToken = default)
172193
{
173194
using SqliteCommand cmd = conn.CreateCommand();

dotnet/src/Connectors/Connectors.Memory.Sqlite/SqliteMemoryStore.cs

+2-3
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public async Task RemoveAsync(string collectionName, string key, CancellationTok
113113
/// <inheritdoc/>
114114
public async Task RemoveBatchAsync(string collectionName, IEnumerable<string> keys, CancellationToken cancellationToken = default)
115115
{
116-
await Task.WhenAll(keys.Select(k => this._dbConnector.DeleteAsync(this._dbConnection, collectionName, k, cancellationToken))).ConfigureAwait(false);
116+
await this._dbConnector.DeleteBatchAsync(this._dbConnection, collectionName, keys.ToArray(), cancellationToken).ConfigureAwait(false);
117117
}
118118

119119
/// <inheritdoc/>
@@ -218,8 +218,7 @@ private SqliteMemoryStore(string filename)
218218

219219
private static DateTimeOffset? ParseTimestamp(string? str)
220220
{
221-
if (!string.IsNullOrEmpty(str)
222-
&& DateTimeOffset.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTimeOffset timestamp))
221+
if (DateTimeOffset.TryParse(str, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out DateTimeOffset timestamp))
223222
{
224223
return timestamp;
225224
}

dotnet/src/IntegrationTests/IntegrationTests.csproj

-3
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,6 @@
9292
<None Update="testsettings.json">
9393
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
9494
</None>
95-
<None Update="testsettings.development.json" Condition="Exists('testsettings.development.json')">
96-
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
97-
</None>
9895
<Content Include="CrossLanguage\Data\LightBulbApi.json">
9996
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
10097
</Content>

python/poetry.lock

+37-36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)