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 global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "6.0.113",
"version": "7.0.202",
"rollForward": "latestFeature",
"allowPrerelease": false
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -18,5 +18,6 @@ namespace SearchPioneer.Weaviate.Client;
public static class Vectorizer
{
public static string Text2VecContextionary = "text2vec-contextionary";
public static string Img2VecNeural = "img2vec-neural";
public static string None = "none";
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ namespace SearchPioneer.Weaviate.Client;
public enum Tokenization
{
Word,
Field
Field,
WhiteSpace
}
5 changes: 4 additions & 1 deletion src/SearchPioneer.Weaviate.Client/Api/Schema/SchemaApi.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -45,6 +45,9 @@ public async Task<ApiResponse<Shard[]>> GetShardsAsync(GetShardsRequest request,
public ApiResponse<WeaviateClass> CreateSchemaClass(CreateClassRequest request)
=> _transport.PostAsync<WeaviateClass, WeaviateClass>("/schema", request).GetAwaiter().GetResult();

public ApiResponse<WeaviateClass> CreateSchemaClassString(string request)
=> _transport.PostStringAsync<string, WeaviateClass>("/schema", request).GetAwaiter().GetResult();

public async Task<ApiResponse<WeaviateClass>> CreateSchemaClassAsync(CreateClassRequest request, CancellationToken cancellationToken = default)
=> await _transport.PostAsync<WeaviateClass, WeaviateClass>("/schema", request, cancellationToken).ConfigureAwait(false);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ internal class TokenizationJsonConverter : JsonConverter<Tokenization>
{
private const string Word = "word";
private const string Field = "field";
private const string WhiteSpace = "whitespace";

private static Tokenization FromString(string status) =>
status switch
{
Word => Tokenization.Word,
Field => Tokenization.Field,
WhiteSpace => Tokenization.WhiteSpace,
_ => throw new ArgumentOutOfRangeException(nameof(status))
};

Expand All @@ -36,6 +38,7 @@ private static string ToString(Tokenization status) =>
{
Tokenization.Word => Word,
Tokenization.Field => Field,
Tokenization.WhiteSpace => WhiteSpace,
_ => throw new ArgumentOutOfRangeException(nameof(status))
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
<Title>Weaviate .NET client</Title>
<Description>.NET client for Weaviate</Description>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
10 changes: 9 additions & 1 deletion src/SearchPioneer.Weaviate.Client/Transport.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -137,6 +137,14 @@ public async Task<ApiResponse<TResult>> PostAsync<TRequest, TResult>(string endp
return result;
}

public async Task<ApiResponse<TResult>> PostStringAsync<TRequest, TResult>(string endpoint, TRequest stringPayload, CancellationToken cancellationToken = default)
{
var result = GetResult<TRequest, TResult>(endpoint, stringPayload, "POST");
var response = await _flurlClient.Request(result.Uri).PostStringAsync(stringPayload as string, cancellationToken).ConfigureAwait(false);
await EnrichResult(result, response).ConfigureAwait(false);
return result;
}

public async Task<ApiResponse> PostAsync<TRequest>(string endpoint, TRequest payload, CancellationToken cancellationToken = default)
{
var result = GetResult(endpoint, payload, "POST");
Expand Down
4 changes: 2 additions & 2 deletions src/SearchPioneer.Weaviate.Client/WeaviateClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -24,7 +24,7 @@ namespace SearchPioneer.Weaviate.Client;
/// </summary>
public class WeaviateClient
{
private const string ClientVersion = "1.18.0";
private const string ClientVersion = "1.19.6";
private static readonly Config DefaultConfig = new("http", "localhost:8080");

private readonly DbVersionSupport _dbVersionSupport;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -14,12 +14,114 @@


using Xunit;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace SearchPioneer.Weaviate.Client.IntegrationTests.Api.Schema;

[Collection("Sequential")]
public class SchemaTests : TestBase
{
[Fact]
// [How to build an Image Search Application with Weaviate](https://weaviate.io/blog/how-to-build-an-image-search-application-with-weaviate) in .NET
public void BuildAnImageSearchApplication()
{
Client.Schema.DeleteAllClasses();

ApiResponse<WeaviateClass>? createStatus = Client.Schema.CreateSchemaClassString(DogSchema);
Assert.True(createStatus.HttpStatusCode == 200);

ApiResponse<WeaviateSchema>? schema = Client.Schema.GetSchema();
Assert.True(schema.HttpStatusCode == 200);
Assert.Single(schema.Result.Classes);

// Convert sample images to base64
const string path =
@"C:\UnitySrc\private repos\weaviate-examples\nearest-neighbor-dog-search\flask-app\static\img";

// Iterate over all files in path
string[] files = Directory.GetFiles(path);
var requests = new List<WeaviateObject>();
foreach (string filePath in files)
{
var imageArray = File.ReadAllBytes(filePath);
var base64ImageRepresentation = Convert.ToBase64String(imageArray);

var breed = Path.GetFileNameWithoutExtension(filePath).Replace("-", " ");
requests.Add(new WeaviateObject
{
Class = "Dog",
Properties = new Dictionary<string, object>
{
{ "breed", breed },
{ "image", base64ImageRepresentation },
{ "filepath", filePath }
}
});
}
ApiResponse<ObjectResponse[]>? batch = Client.Batch.CreateObjects(new CreateObjectsBatchRequest(requests.ToArray())
{
ConsistencyLevel = ConsistencyLevel.One
});
Assert.True(batch.HttpStatusCode == 200);

const string searchImagePath = @"C:\UnitySrc\private repos\weaviate-examples\nearest-neighbor-dog-search\flask-app\static\golden-doodle-puppy.jpg";
string searchImage = Convert.ToBase64String(File.ReadAllBytes(searchImagePath));
GraphGetRequest request = new ()
{
Class = "Dog", Limit = 2,
Fields = new Field[] {"breed".AsField(), "image".AsField(), "filepath".AsField()},
NearImage = new NearImage {Image = searchImage}
};
ApiResponse<GraphResponse>? results = Client.Graph.Get(request);
string json = results.Result.Data["Get"]!["Dog"].ToString();
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
Dog[] dogs = JsonSerializer.Deserialize<Dog[]>(json, options);
Assert.True(dogs.Length == 2);
Assert.Multiple(
() => Assert.Contains(dogs, dog => dog.Breed == "Goldendoodle"),
() => Assert.Contains(dogs, dog => dog.Breed == "Golden Retriever"));
}

public class Dog
{
public string Breed { get; set; } = null!;
public string Image { get; set; } = null!;
public string Filepath { get; set; } = null!;
}
private const string DogSchema = @"
{
""class"": ""Dog"",
""description"": ""Images of different dogs"",
""moduleConfig"": {
""img2vec-neural"": {
""imageFields"": [
""image""
]
}
},
""vectorIndexType"": ""hnsw"",
""vectorizer"": ""img2vec-neural"",
""properties"": [
{
""name"": ""breed"",
""dataType"": [""string""],
""description"": ""name of dog breed""
},
{
""name"": ""image"",
""dataType"": [""blob""],
""description"": ""image""
},
{
""name"": ""filepath"",
""dataType"":[""string""],
""description"": ""filepath of the images""
}
]
}
";

[Fact]
public void CreateBandClass()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
// Copyright (C) 2023 Search Pioneer - https://www.searchpioneer.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -32,7 +32,7 @@ public abstract class TestBase
protected static readonly string PIZZA_DOENER_ID = "d2b393ff-4b26-48c7-b554-218d970a9e17";
protected static readonly string SOUP_CHICKENSOUP_ID = "8c156d37-81aa-4ce9-a811-621e2702b825";
protected static readonly string SOUP_BEAUTIFUL_ID = "27351361-2898-4d1a-aad7-1ca48253eb0b";
protected readonly WeaviateClient Client = new(new("http", "localhost:8080", "my-secret-key"), new FlurlClient());
protected readonly WeaviateClient Client = new(new("http", "localhost:8080"), new FlurlClient());

// Uncomment to try alternate seperators
// protected TestBase() =>
Expand Down