Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ChromaDB.Client.Tests/ChromaTestsBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public async Task OneTimeSetUp()
{
_container = ConfigureContainer(new ChromaDBBuilder()).Build();
await _container.StartAsync();
_baseConfigurationOptions = new ChromaConfigurationOptions(uri: $"http://{_container.IpAddress}:{_container.GetMappedPublicPort(ChromaDBBuilder.ChromaDBPort)}/api/v1/");
_baseConfigurationOptions = new ChromaConfigurationOptions(uri: $"http://{_container.IpAddress}:{_container.GetMappedPublicPort(ChromaDBBuilder.ChromaDBPort)}/api/v2/");
}

[OneTimeTearDown]
Expand Down
18 changes: 9 additions & 9 deletions ChromaDB.Client/ChromaClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,23 @@ public async Task<List<ChromaCollection>> ListCollections(string? tenant = null,
var requestParams = new RequestQueryParams()
.Insert("{tenant}", tenant)
.Insert("{database}", database);
return await _httpClient.Get<List<ChromaCollection>>("collections?tenant={tenant}&database={database}", requestParams);
return await _httpClient.Get<List<ChromaCollection>>("tenants/{tenant}/databases/{database}/collections", requestParams);
}

public async Task<ChromaCollection> GetCollection(string name, string? tenant = null, string? database = null)
{
tenant = tenant is not null and not [] ? tenant : _currentTenant.Name;
database = database is not null and not [] ? database : _currentDatabase.Name;
var requestParams = new RequestQueryParams()
.Insert("{collectionName}", name)
.Insert("{collection_id}", name) // it seems to be a chroma bug: https://github.com/chroma-core/chroma/issues/4456
.Insert("{tenant}", tenant)
.Insert("{database}", database);
return await _httpClient.Get<ChromaCollection>("collections/{collectionName}?tenant={tenant}&database={database}", requestParams);
return await _httpClient.Get<ChromaCollection>("tenants/{tenant}/databases/{database}/collections/{collection_id}", requestParams);
}

public async Task<ChromaHeartbeat> Heartbeat()
{
return await _httpClient.Get<ChromaHeartbeat>("", new RequestQueryParams());
return await _httpClient.Get<ChromaHeartbeat>("heartbeat", new RequestQueryParams());
}

public async Task<ChromaCollection> CreateCollection(string name, Dictionary<string, object>? metadata = null, string? tenant = null, string? database = null)
Expand All @@ -69,7 +69,7 @@ public async Task<ChromaCollection> CreateCollection(string name, Dictionary<str
Name = name,
Metadata = metadata
};
return await _httpClient.Post<CreateCollectionRequest, ChromaCollection>("collections?tenant={tenant}&database={database}", request, requestParams);
return await _httpClient.Post<CreateCollectionRequest, ChromaCollection>("tenants/{tenant}/databases/{database}/collections", request, requestParams);
}

public async Task<ChromaCollection> GetOrCreateCollection(string name, Dictionary<string, object>? metadata = null, string? tenant = null, string? database = null)
Expand All @@ -84,18 +84,18 @@ public async Task<ChromaCollection> GetOrCreateCollection(string name, Dictionar
Name = name,
Metadata = metadata
};
return await _httpClient.Post<GetOrCreateCollectionRequest, ChromaCollection>("collections?tenant={tenant}&database={database}", request, requestParams);
return await _httpClient.Post<GetOrCreateCollectionRequest, ChromaCollection>("tenants/{tenant}/databases/{database}/collections", request, requestParams);
}

public async Task DeleteCollection(string name, string? tenant = null, string? database = null)
{
tenant = tenant is not null and not [] ? tenant : _currentTenant.Name;
database = database is not null and not [] ? database : _currentDatabase.Name;
var requestParams = new RequestQueryParams()
.Insert("{collectionName}", name)
.Insert("{collection_id}", name)
.Insert("{tenant}", tenant)
.Insert("{database}", database);
await _httpClient.Delete("collections/{collectionName}?tenant={tenant}&database={database}", requestParams);
await _httpClient.Delete("tenants/{tenant}/databases/{database}/collections/{collection_id}", requestParams);
}

public async Task<string> GetVersion()
Expand All @@ -115,6 +115,6 @@ public async Task<int> CountCollections(string? tenant = null, string? database
var requestParams = new RequestQueryParams()
.Insert("{tenant}", tenant)
.Insert("{database}", database);
return await _httpClient.Get<int>("count_collections?tenant={tenant}&database={database}", requestParams);
return await _httpClient.Get<int>("tenants/{tenant}/databases/{database}/collections_count", requestParams);
}
}
90 changes: 81 additions & 9 deletions ChromaDB.Client/ChromaCollectionClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@ public class ChromaCollectionClient
{
private readonly ChromaCollection _collection;
private readonly HttpClient _httpClient;
private readonly ChromaTenant _currentTenant;
private readonly ChromaDatabase _currentDatabase;

public ChromaCollectionClient(ChromaCollection collection, ChromaConfigurationOptions options, HttpClient httpClient)
{
_collection = collection;
_httpClient = httpClient;
_currentTenant = options.Tenant is not null and not []
? new ChromaTenant(options.Tenant)
: ClientConstants.DefaultTenant;
_currentDatabase = options.Database is not null and not []
? new ChromaDatabase(options.Database)
: ClientConstants.DefaultDatabase;

if (_httpClient.BaseAddress != options.Uri)
{
Expand All @@ -29,7 +37,10 @@ public ChromaCollectionClient(ChromaCollection collection, ChromaConfigurationOp
public async Task<List<ChromaCollectionEntry>> Get(List<string>? ids = null, ChromaWhereOperator? where = null, ChromaWhereDocumentOperator? whereDocument = null, int? limit = null, int? offset = null, ChromaGetInclude? include = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionGetRequest()
{
Ids = ids,
Expand All @@ -39,7 +50,12 @@ public async Task<List<ChromaCollectionEntry>> Get(List<string>? ids = null, Chr
Offset = offset,
Include = (include ?? ChromaGetInclude.Metadatas | ChromaGetInclude.Documents).ToInclude(),
};
var response = await _httpClient.Post<CollectionGetRequest, CollectionEntriesGetResponse>("collections/{collection_id}/get", request, requestParams);

var response = await _httpClient.Post<CollectionGetRequest, CollectionEntriesGetResponse>(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/get",
request,
requestParams);

return response.Map() ?? [];
}

Expand All @@ -49,7 +65,10 @@ public async Task<List<ChromaCollectionQueryEntry>> Query(ReadOnlyMemory<float>
public async Task<List<List<ChromaCollectionQueryEntry>>> Query(List<ReadOnlyMemory<float>> queryEmbeddings, int nResults = 10, ChromaWhereOperator? where = null, ChromaWhereDocumentOperator? whereDocument = null, ChromaQueryInclude? include = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionQueryRequest()
{
QueryEmbeddings = queryEmbeddings,
Expand All @@ -58,93 +77,146 @@ public async Task<List<List<ChromaCollectionQueryEntry>>> Query(List<ReadOnlyMem
WhereDocument = whereDocument?.ToWhereDocument(),
Include = (include ?? ChromaQueryInclude.Metadatas | ChromaQueryInclude.Documents | ChromaQueryInclude.Distances).ToInclude(),
};
var response = await _httpClient.Post<CollectionQueryRequest, CollectionEntriesQueryResponse>("collections/{collection_id}/query", request, requestParams);

var response = await _httpClient.Post<CollectionQueryRequest, CollectionEntriesQueryResponse>(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/query",
request,
requestParams);

return response.Map() ?? [];
}

public async Task Add(List<string> ids, List<ReadOnlyMemory<float>>? embeddings = null, List<Dictionary<string, object>>? metadatas = null, List<string>? documents = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionAddRequest()
{
Ids = ids,
Embeddings = embeddings,
Metadatas = metadatas,
Documents = documents,
};
await _httpClient.Post("collections/{collection_id}/add", request, requestParams);

await _httpClient.Post(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/add",
request,
requestParams);
}

public async Task Update(List<string> ids, List<ReadOnlyMemory<float>>? embeddings = null, List<Dictionary<string, object>>? metadatas = null, List<string>? documents = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionUpdateRequest()
{
Ids = ids,
Embeddings = embeddings,
Metadatas = metadatas,
Documents = documents,
};
await _httpClient.Post("collections/{collection_id}/update", request, requestParams);

await _httpClient.Post(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/update",
request,
requestParams);
}

public async Task Upsert(List<string> ids, List<ReadOnlyMemory<float>>? embeddings = null, List<Dictionary<string, object>>? metadatas = null, List<string>? documents = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionUpsertRequest()
{
Ids = ids,
Embeddings = embeddings,
Metadatas = metadatas,
Documents = documents,
};
await _httpClient.Post("collections/{collection_id}/upsert", request, requestParams);

await _httpClient.Post(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/upsert",
request,
requestParams);
}

public async Task Delete(List<string> ids, ChromaWhereOperator? where = null, ChromaWhereDocumentOperator? whereDocument = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionDeleteRequest()
{
Ids = ids,
Where = where?.ToWhere(),
WhereDocument = whereDocument?.ToWhereDocument(),
};
await _httpClient.Post("collections/{collection_id}/delete", request, requestParams);

await _httpClient.Post(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/delete",
request,
requestParams);
}

public async Task<int> Count()
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);
return await _httpClient.Get<int>("collections/{collection_id}/count", requestParams);

return await _httpClient.Get<int>(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/count",
requestParams);
}

public async Task<List<ChromaCollectionEntry>> Peek(int limit = 10)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionPeekRequest()
{
Limit = limit,
};
var response = await _httpClient.Post<CollectionPeekRequest, CollectionEntriesGetResponse>("collections/{collection_id}/get", request, requestParams);

var response = await _httpClient.Post<CollectionPeekRequest, CollectionEntriesGetResponse>(
"tenants/{tenant}/databases/{database}/collections/{collection_id}/get",
request,
requestParams);

return response.Map() ?? [];
}

public async Task Modify(string? name = null, Dictionary<string, object>? metadata = null)
{
var requestParams = new RequestQueryParams()
.Insert("{tenant}", _currentTenant.Name)
.Insert("{database}", _currentDatabase.Name)
.Insert("{collection_id}", _collection.Id);

var request = new CollectionModifyRequest()
{
Name = name,
Metadata = metadata,
};
await _httpClient.Put("collections/{collection_id}", request, requestParams);

await _httpClient.Put(
"tenants/{tenant}/databases/{database}/collections/{collection_id}",
request,
requestParams);
}
}
1 change: 0 additions & 1 deletion ChromaDB.Client/ChromaCollectionEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ public class ChromaCollectionEntry
public Dictionary<string, object>? Metadata { get; init; }
public string? Document { get; init; }
public List<string?>? Uris { get; init; }
public dynamic? Data { get; init; }

public ChromaCollectionEntry(string id)
{
Expand Down
1 change: 0 additions & 1 deletion ChromaDB.Client/ChromaCollectionQueryEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public class ChromaCollectionQueryEntry
public ReadOnlyMemory<float>? Embeddings { get; init; }
public string? Document { get; init; }
public List<string?>? Uris { get; init; }
public dynamic? Data { get; init; }

public ChromaCollectionQueryEntry(string id)
{
Expand Down
2 changes: 1 addition & 1 deletion ChromaDB.Client/Common/ClientConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ internal static class ClientConstants
{
public const string DefaultTenantName = "default_tenant";
public const string DefaultDatabaseName = "default_database";
public const string DefaultUri = "http://localhost:8000/api/v1/";
public const string DefaultUri = "http://localhost:8000/api/v2/";
public const string ChromaTokenHeader = "X-Chroma-Token";

public static ChromaTenant DefaultTenant { get; } = new(DefaultTenantName);
Expand Down
1 change: 0 additions & 1 deletion ChromaDB.Client/Common/CollectionEntryMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ public static List<ChromaCollectionEntry> Map(this CollectionEntriesGetResponse
Metadata = response.Metadatas?[i],
Document = response.Documents?[i],
Uris = response.Uris?[i],
Data = response.Data,
})
.ToList();
}
Expand Down
1 change: 0 additions & 1 deletion ChromaDB.Client/Common/CollectionQueryEntryMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public static List<List<ChromaCollectionQueryEntry>> Map(this CollectionEntriesQ
Embeddings = response.Embeddings?[i][j],
Document = response.Documents?[i][j],
Uris = response.Uris?[i][j],
Data = response.Data,
})
.ToList())
.ToList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,4 @@ internal class CollectionEntriesGetResponse

[JsonPropertyName("uris")]
public required List<List<string?>?> Uris { get; init; }

[JsonPropertyName("data")]
public required dynamic? Data { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,4 @@ internal class CollectionEntriesQueryResponse

[JsonPropertyName("uris")]
public required List<List<List<string?>>>? Uris { get; init; }

[JsonPropertyName("data")]
public required dynamic? Data { get; init; }
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ _ChromaDB.Client_ is a .NET SDK that offers a seamless connection to the Chroma
```csharp
using ChromaDB.Client;

var configOptions = new ChromaConfigurationOptions(uri: "http://localhost:8000/api/v1/");
var configOptions = new ChromaConfigurationOptions(uri: "http://localhost:8000/api/v2/");
using var httpClient = new HttpClient();
var client = new ChromaClient(configOptions, httpClient);

Expand Down
2 changes: 1 addition & 1 deletion Samples/ChromaDB.Client.Sample/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using ChromaDB.Client;

var configOptions = new ChromaConfigurationOptions(uri: "http://localhost:8000/api/v1/");
var configOptions = new ChromaConfigurationOptions(uri: "http://localhost:8000/api/v2/");
using var httpClient = new HttpClient();
var client = new ChromaClient(configOptions, httpClient);

Expand Down
Loading