Skip to content
Merged
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 .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ jobs:
strategy:
fail-fast: false
matrix:
version: ["1.32.27", "1.33.18", "1.34.20", "1.35.23", "1.36.23", "1.37.16", "1.38.9", "1.39.0"]
version: ["1.32.27", "1.33.18", "1.34.20", "1.35.23", "1.36.23", "1.37.16", "1.38.9", "1.39.3"]
uses: ./.github/workflows/test-on-weaviate-version.yml
secrets: inherit
with:
Expand Down
2 changes: 1 addition & 1 deletion ci/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ services:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true'
PERSISTENCE_DATA_PATH: '/var/lib/weaviate'
ENABLE_MODULES: text2vec-transformers,text2vec-cohere,backup-filesystem,generative-dummy,generative-anyscale,reranker-dummy,reranker-cohere,text2vec-ollama,generative-ollama,multi2vec-google,generative-deepseek,generative-digitalocean
ENABLE_MODULES: text2vec-transformers,text2vec-cohere,backup-filesystem,generative-dummy,generative-anyscale,reranker-dummy,reranker-cohere,text2vec-ollama,generative-ollama,multi2vec-google,generative-deepseek,generative-digitalocean,generative-meta
BACKUP_FILESYSTEM_PATH: "/tmp/backups"
EXPORT_ENABLED: 'true'
EXPORT_DEFAULT_PATH: "/tmp/exports"
Expand Down
44 changes: 44 additions & 0 deletions src/Weaviate.Client.Tests/Integration/TestCollections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,50 @@ public async Task Collection_Creates_And_Retrieves_GenerativeDigitalOcean_Config
Assert.Equal(["STOP"], digitalOcean.Stop);
}

/// <summary>
/// Tests that a generative-meta collection round-trips through a real server.
/// </summary>
/// <remarks>
/// Fractional floats are dropped by the server's config parser — integral values only.
/// </remarks>
[Fact]
public async Task Collection_Creates_And_Retrieves_GenerativeMeta_Config()
{
RequireModule("generative-meta");

// Arrange
var collectionClient = await CollectionFactory(
properties: [Property.Text("Name")],
generativeConfig: Configure.Generative.Meta(
model: "muse-spark-1.2",
temperature: 1,
maxTokens: 100,
frequencyPenalty: 0,
presencePenalty: 0,
topP: 1,
baseURL: "https://api.meta.ai",
reasoningEffort: "xhigh"
)
);

// Act
var collection = await _weaviate
.Collections.Use(collectionClient.Name)
.Config.Get(TestContext.Current.CancellationToken);

// Assert
Assert.NotNull(collection);
var meta = Assert.IsType<GenerativeConfig.Meta>(collection.GenerativeConfig);
Assert.Equal("muse-spark-1.2", meta.Model);
Assert.Equal(1, meta.Temperature);
Assert.Equal(100, meta.MaxTokens);
Assert.Equal(0, meta.FrequencyPenalty);
Assert.Equal(0, meta.PresencePenalty);
Assert.Equal(1, meta.TopP);
Assert.Equal("https://api.meta.ai", meta.BaseURL);
Assert.Equal("xhigh", meta.ReasoningEffort);
}

/// <summary>
/// Tests that test collections export
/// </summary>
Expand Down
64 changes: 64 additions & 0 deletions src/Weaviate.Client.Tests/Unit/TestCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,70 @@ public void Collection_GenerativeDigitalOcean_Serializes_And_RoundTrips()
Assert.Equal(["STOP"], typed.Stop);
}

/// <summary>
/// Pins the exact wire keys — a wrong key or casing is silently ignored by the server.
/// </summary>
[Fact]
public void Collection_GenerativeMeta_Serializes_And_RoundTrips()
{
// Arrange
var full = Assert.IsType<GenerativeConfig.Meta>(
Configure.Generative.Meta(
model: "muse-spark-1.2",
temperature: 0.5,
maxTokens: 100,
frequencyPenalty: 0.1,
presencePenalty: 0.2,
topP: 0.9,
baseURL: "https://api.meta.ai",
reasoningEffort: "xhigh"
)
);
var empty = Assert.IsType<GenerativeConfig.Meta>(Configure.Generative.Meta());

// Act
var jsonFull = JsonSerializer.Serialize(
full,
Rest.WeaviateRestClient.RestJsonSerializerOptions
);
var jsonEmpty = JsonSerializer.Serialize(
empty,
Rest.WeaviateRestClient.RestJsonSerializerOptions
);

// Assert
Assert.Equal("generative-meta", full.Type);
Assert.Contains("\"model\":\"muse-spark-1.2\"", jsonFull);
Assert.Contains("\"temperature\":0.5", jsonFull);
Assert.Contains("\"maxTokens\":100", jsonFull);
Assert.Contains("\"frequencyPenalty\":0.1", jsonFull);
Assert.Contains("\"presencePenalty\":0.2", jsonFull);
Assert.Contains("\"topP\":0.9", jsonFull);
Assert.Contains("\"baseURL\":\"https://api.meta.ai\"", jsonFull);
Assert.Contains("\"reasoningEffort\":\"xhigh\"", jsonFull);
Assert.Contains("\"type\":\"generative-meta\"", jsonFull);

// Nothing set means nothing else sent, so the server keeps its own defaults.
Assert.Equal("{\"type\":\"generative-meta\"}", jsonEmpty);

var roundTripped = GenerativeConfigSerialization.Factory(
GenerativeConfig.Meta.TypeValue,
JsonSerializer.Deserialize<object>(
jsonFull,
Rest.WeaviateRestClient.RestJsonSerializerOptions
)
);
var typed = Assert.IsType<GenerativeConfig.Meta>(roundTripped);
Assert.Equal("muse-spark-1.2", typed.Model);
Assert.Equal(0.5, typed.Temperature);
Assert.Equal(100, typed.MaxTokens);
Assert.Equal(0.1, typed.FrequencyPenalty);
Assert.Equal(0.2, typed.PresencePenalty);
Assert.Equal(0.9, typed.TopP);
Assert.Equal("https://api.meta.ai", typed.BaseURL);
Assert.Equal("xhigh", typed.ReasoningEffort);
}

/// <summary>
/// Tests that collection rerank deserializes into i reranker config
/// </summary>
Expand Down
47 changes: 47 additions & 0 deletions src/Weaviate.Client.Tests/Unit/TestGenerativeShortcuts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,53 @@ await client
Assert.False(providerQuery.Digitalocean.HasPresencePenalty);
}

/// <summary>
/// Tests that the Meta provider maps onto the gRPC message; unset optionals stay unset.
/// </summary>
[Fact]
public async Task GenerateClient_FetchObjects_WithMetaProvider_MapsSetFieldsAndOmitsUnset()
{
// Arrange
var provider = new Providers.Meta
{
BaseUrl = "https://api.meta.ai",
Model = "muse-spark-1.2",
Temperature = 0.5,
MaxTokens = 100,
FrequencyPenalty = 0.1,
TopP = 0.9,
ReasoningEffort = Providers.Meta.ReasoningEffortLevel.XHigh,
};
var (client, getCapturedRequest) = CreateClientWithRequestCapture();

// Act
await client
.Collections.Use("TestCollection")
.Generate.FetchObjects(
limit: 10,
singlePrompt: "Summarize this",
provider: provider,
cancellationToken: TestContext.Current.CancellationToken
);

// Assert
var capturedRequest = getCapturedRequest();
Assert.NotNull(capturedRequest);
var providerQuery = capturedRequest!.Generative!.Single!.Queries[0];
Assert.NotNull(providerQuery.Meta);
Assert.Equal("https://api.meta.ai", providerQuery.Meta.BaseUrl);
Assert.Equal("muse-spark-1.2", providerQuery.Meta.Model);
Assert.Equal(0.5, providerQuery.Meta.Temperature);
Assert.Equal(100, providerQuery.Meta.MaxTokens);
Assert.Equal(0.1, providerQuery.Meta.FrequencyPenalty);
Assert.Equal(0.9, providerQuery.Meta.TopP);
Assert.Equal(
GenerativeMeta.Types.ReasoningEffort.Xhigh,
providerQuery.Meta.ReasoningEffort
);
Assert.False(providerQuery.Meta.HasPresencePenalty);
}

#endregion

#region Helper Methods
Expand Down
34 changes: 34 additions & 0 deletions src/Weaviate.Client/Configure/GenerativeConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,40 @@ public IGenerativeConfig FriendliAI(
Temperature = temperature,
};

/// <summary>
/// Create a generative configuration for Meta.
/// </summary>
/// <param name="model">The model to use.</param>
/// <param name="temperature">The temperature.</param>
/// <param name="maxTokens">The maximum number of tokens to generate.</param>
/// <param name="frequencyPenalty">The frequency penalty.</param>
/// <param name="presencePenalty">The presence penalty.</param>
/// <param name="topP">The top P.</param>
/// <param name="baseURL">The base URL.</param>
/// <param name="reasoningEffort">The reasoning effort.</param>
/// <returns>A <see cref="IGenerativeConfig"/> instance.</returns>
public IGenerativeConfig Meta(
string? model = null,
double? temperature = null,
int? maxTokens = null,
double? frequencyPenalty = null,
double? presencePenalty = null,
double? topP = null,
string? baseURL = null,
string? reasoningEffort = null
) =>
new GenerativeConfig.Meta
{
Model = model,
Temperature = temperature,
MaxTokens = maxTokens,
FrequencyPenalty = frequencyPenalty,
PresencePenalty = presencePenalty,
TopP = topP,
BaseURL = baseURL,
ReasoningEffort = reasoningEffort,
};

/// <summary>
/// Create a generative configuration for Mistral.
/// </summary>
Expand Down
34 changes: 34 additions & 0 deletions src/Weaviate.Client/Configure/GenerativeProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,40 @@ public Providers.GoogleVertex GoogleVertex(
ImageProperties = imageProperties,
};

/// <summary>
/// Creates a Meta runtime provider configuration.
/// </summary>
/// <param name="baseUrl">The base url</param>
/// <param name="model">The model</param>
/// <param name="temperature">The temperature</param>
/// <param name="maxTokens">The max tokens</param>
/// <param name="frequencyPenalty">The frequency penalty</param>
/// <param name="presencePenalty">The presence penalty</param>
/// <param name="topP">The top</param>
/// <param name="reasoningEffort">The reasoning effort</param>
/// <returns>The providers meta</returns>
public Providers.Meta Meta(
string? baseUrl = null,
string? model = null,
double? temperature = null,
long? maxTokens = null,
double? frequencyPenalty = null,
double? presencePenalty = null,
double? topP = null,
Providers.Meta.ReasoningEffortLevel? reasoningEffort = null
) =>
new()
{
BaseUrl = baseUrl,
Model = model,
Temperature = temperature,
MaxTokens = maxTokens,
FrequencyPenalty = frequencyPenalty,
PresencePenalty = presencePenalty,
TopP = topP,
ReasoningEffort = reasoningEffort,
};

/// <summary>
/// Mistrals the base url
/// </summary>
Expand Down
87 changes: 87 additions & 0 deletions src/Weaviate.Client/Models/Generative/Providers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,93 @@ public record DigitalOcean() : GenerativeProvider("digitalocean")
public List<string>? Stop { get; set; }
}

/// <summary>
/// Configuration for Meta generative AI provider.
/// </summary>
public record Meta() : GenerativeProvider("meta")
{
/// <summary>
/// Specifies the reasoning effort level for reasoning models.
/// </summary>
public enum ReasoningEffortLevel
{
/// <summary>
/// Unspecified reasoning effort level.
/// </summary>
Unspecified = 0,

/// <summary>
/// No reasoning effort.
/// </summary>
None = 1,

/// <summary>
/// Minimal reasoning effort.
/// </summary>
Minimal = 2,

/// <summary>
/// Low reasoning effort.
/// </summary>
Low = 3,

/// <summary>
/// Medium reasoning effort.
/// </summary>
Medium = 4,

/// <summary>
/// High reasoning effort.
/// </summary>
High = 5,

/// <summary>
/// Extra-high reasoning effort.
/// </summary>
XHigh = 6,
}

/// <summary>
/// Gets or sets the base URL for the Meta API endpoint.
/// </summary>
public string? BaseUrl { get; set; }

/// <summary>
/// Gets or sets the model identifier to use.
/// </summary>
public string? Model { get; set; }

/// <summary>
/// Gets or sets the temperature for controlling randomness in generation.
/// </summary>
public double? Temperature { get; set; }

/// <summary>
/// Gets or sets the maximum number of tokens to generate.
/// </summary>
public long? MaxTokens { get; set; }

/// <summary>
/// Gets or sets the frequency penalty to reduce repetition.
/// </summary>
public double? FrequencyPenalty { get; set; }

/// <summary>
/// Gets or sets the presence penalty to encourage topic diversity.
/// </summary>
public double? PresencePenalty { get; set; }

/// <summary>
/// Gets or sets the top-p (nucleus) sampling parameter.
/// </summary>
public double? TopP { get; set; }

/// <summary>
/// Gets or sets the reasoning effort level for reasoning models.
/// </summary>
public ReasoningEffortLevel? ReasoningEffort { get; set; }
}

/// <summary>
/// Configuration for FriendliAI generative AI provider.
/// </summary>
Expand Down
Loading
Loading