Skip to content

Commit 97a2911

Browse files
Added basic support for MaaS (Azure#49115)
* Added support for MaaS though OpenAI * updated APIs * changed AI services * fixed MaaS scopes * fixed a test
1 parent d95bf01 commit 97a2911

22 files changed

+722
-91
lines changed

sdk/cloudmachine/Azure.Projects.OpenAI/api/Azure.Projects.OpenAI.net8.0.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1+
namespace Azure.AI.Models
2+
{
3+
public partial class ModelsClient
4+
{
5+
protected ModelsClient() { }
6+
public ModelsClient(System.Uri endpoint, Azure.Core.TokenCredential credential) { }
7+
public ModelsClient(System.Uri endpoint, Azure.Core.TokenCredential credential, OpenAI.OpenAIClientOptions options) { }
8+
public ModelsClient(System.Uri endpoint, System.ClientModel.ApiKeyCredential credential) { }
9+
public ModelsClient(System.Uri endpoint, System.ClientModel.ApiKeyCredential credential, OpenAI.OpenAIClientOptions options) { }
10+
public OpenAI.Chat.ChatClient GetChatClient(string model) { throw null; }
11+
public OpenAI.Embeddings.EmbeddingClient GetEmbeddingClient(string model) { throw null; }
12+
}
13+
}
114
namespace Azure.AI.OpenAI
215
{
16+
public static partial class AIServicesExtensions
17+
{
18+
public static Azure.AI.Models.ModelsClient GetModelsClient(this System.ClientModel.Primitives.ConnectionProvider provider, string? deploymentName = null) { throw null; }
19+
}
320
public static partial class AzureOpenAIExtensions
421
{
522
public static void Add(this System.Collections.Generic.List<OpenAI.Chat.ChatMessage> messages, OpenAI.Chat.ChatCompletion completion) { }
@@ -20,6 +37,11 @@ public enum AIModelKind
2037
Chat = 0,
2138
Embedding = 1,
2239
}
40+
public partial class AIServicesFeature : Azure.Projects.Core.AzureProjectFeature
41+
{
42+
public AIServicesFeature(string model, string modelVersion) { }
43+
protected override void EmitConstructs(Azure.Projects.ProjectInfrastructure infrastructure) { }
44+
}
2345
public partial class ChatProcessor
2446
{
2547
public ChatProcessor(OpenAI.Chat.ChatClient chat) { }

sdk/cloudmachine/Azure.Projects.OpenAI/api/Azure.Projects.OpenAI.netstandard2.0.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1+
namespace Azure.AI.Models
2+
{
3+
public partial class ModelsClient
4+
{
5+
protected ModelsClient() { }
6+
public ModelsClient(System.Uri endpoint, Azure.Core.TokenCredential credential) { }
7+
public ModelsClient(System.Uri endpoint, Azure.Core.TokenCredential credential, OpenAI.OpenAIClientOptions options) { }
8+
public ModelsClient(System.Uri endpoint, System.ClientModel.ApiKeyCredential credential) { }
9+
public ModelsClient(System.Uri endpoint, System.ClientModel.ApiKeyCredential credential, OpenAI.OpenAIClientOptions options) { }
10+
public OpenAI.Chat.ChatClient GetChatClient(string model) { throw null; }
11+
public OpenAI.Embeddings.EmbeddingClient GetEmbeddingClient(string model) { throw null; }
12+
}
13+
}
114
namespace Azure.AI.OpenAI
215
{
16+
public static partial class AIServicesExtensions
17+
{
18+
public static Azure.AI.Models.ModelsClient GetModelsClient(this System.ClientModel.Primitives.ConnectionProvider provider, string? deploymentName = null) { throw null; }
19+
}
320
public static partial class AzureOpenAIExtensions
421
{
522
public static void Add(this System.Collections.Generic.List<OpenAI.Chat.ChatMessage> messages, OpenAI.Chat.ChatCompletion completion) { }
@@ -20,6 +37,11 @@ public enum AIModelKind
2037
Chat = 0,
2138
Embedding = 1,
2239
}
40+
public partial class AIServicesFeature : Azure.Projects.Core.AzureProjectFeature
41+
{
42+
public AIServicesFeature(string model, string modelVersion) { }
43+
protected override void EmitConstructs(Azure.Projects.ProjectInfrastructure infrastructure) { }
44+
}
2345
public partial class ChatProcessor
2446
{
2547
public ChatProcessor(OpenAI.Chat.ChatClient chat) { }
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Projects.Core;
5+
using Azure.Provisioning.CognitiveServices;
6+
7+
namespace Azure.Projects.OpenAI;
8+
9+
/// <summary>
10+
/// AIServices feature.
11+
/// </summary>
12+
public class AIServicesFeature : AzureProjectFeature
13+
{
14+
private string _model;
15+
private string _modelVersion;
16+
17+
/// <summary>
18+
/// Creates a new instance of the AIServices feature.
19+
/// </summary>
20+
/// <param name="model"></param>
21+
/// <param name="modelVersion"></param>
22+
public AIServicesFeature(string model, string modelVersion)
23+
{
24+
_model = model;
25+
_modelVersion = modelVersion;
26+
}
27+
28+
/// <summary>
29+
/// Adds the feature to the project infrastructure.
30+
/// </summary>
31+
/// <param name="infrastructure"></param>
32+
protected override void EmitConstructs(ProjectInfrastructure infrastructure)
33+
{
34+
CognitiveServicesAccount cognitiveServices = new("aiservices")
35+
{
36+
Name = infrastructure.ProjectId,
37+
Kind = "AIServices",
38+
Sku = new CognitiveServicesSku { Name = "S0" },
39+
Properties = new CognitiveServicesAccountProperties()
40+
{
41+
PublicNetworkAccess = ServiceAccountPublicNetworkAccess.Enabled,
42+
CustomSubDomainName = infrastructure.ProjectId,
43+
DisableLocalAuth = true,
44+
NetworkAcls = new CognitiveServicesNetworkRuleSet()
45+
{
46+
DefaultAction = CognitiveServicesNetworkRuleAction.Allow
47+
},
48+
},
49+
};
50+
51+
CognitiveServicesAccountDeployment deployment = new($"aimodel", "2024-06-01-preview")
52+
{
53+
Parent = cognitiveServices,
54+
Name = $"{infrastructure.ProjectId}_chat",
55+
Properties = new CognitiveServicesAccountDeploymentProperties()
56+
{
57+
Model = new CognitiveServicesAccountDeploymentModel()
58+
{
59+
Name = _model,
60+
Format = "DeepSeek",
61+
Version = _modelVersion
62+
},
63+
VersionUpgradeOption = DeploymentModelVersionUpgradeOption.OnceNewDefaultVersionAvailable,
64+
RaiPolicyName = "Microsoft.DefaultV2",
65+
},
66+
Sku = new CognitiveServicesSku
67+
{
68+
Capacity = 1,
69+
Name = "GlobalStandard"
70+
},
71+
};
72+
73+
infrastructure.AddConstruct(Id, cognitiveServices);
74+
infrastructure.AddConstruct(Id + "_deployment", deployment);
75+
76+
infrastructure.AddSystemRole(
77+
cognitiveServices,
78+
CognitiveServicesBuiltInRole.GetBuiltInRoleName(CognitiveServicesBuiltInRole.CognitiveServicesContributor),
79+
CognitiveServicesBuiltInRole.CognitiveServicesContributor.ToString()
80+
);
81+
82+
EmitConnection(infrastructure, "Azure.AI.Models.ModelsClient", $"https://{infrastructure.ProjectId}.services.ai.azure.com/models");
83+
}
84+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#nullable enable
5+
6+
using System;
7+
using System.ClientModel;
8+
using System.ClientModel.Primitives;
9+
using Azure.AI.Models;
10+
using Azure.Core;
11+
12+
namespace Azure.AI.OpenAI;
13+
14+
/// <summary>
15+
/// The Azure OpenAI extensions.
16+
/// </summary>
17+
public static partial class AIServicesExtensions
18+
{
19+
/// <summary>
20+
/// Gets the OpenAI embedding client.
21+
/// </summary>
22+
/// <param name="provider"></param>
23+
/// <param name="deploymentName"></param>
24+
/// <returns></returns>
25+
public static ModelsClient GetModelsClient(this ConnectionProvider provider, string? deploymentName = null)
26+
{
27+
ModelsClient client = provider.Subclients.GetClient(() => CreateModelsClient(provider), null!);
28+
return client;
29+
}
30+
31+
private static ModelsClient CreateModelsClient(this ConnectionProvider provider)
32+
{
33+
ClientConnection connection = provider.GetConnection(typeof(ModelsClient).FullName!);
34+
35+
if (!connection.TryGetLocatorAsUri(out Uri? uri) || uri is null)
36+
{
37+
throw new InvalidOperationException("Invalid URI.");
38+
}
39+
40+
return connection.Authentication == ClientAuthenticationMethod.Credential
41+
? new ModelsClient(uri, (connection.Credential as TokenCredential)!)
42+
: new ModelsClient(uri, new ApiKeyCredential(connection.ApiKeyCredential!));
43+
}
44+
}

sdk/cloudmachine/Azure.Projects.OpenAI/src/Azure.Projects.OpenAI.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" />
1818
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
1919
<PackageReference Include="Microsoft.Bcl.Numerics" />
20-
<PackageReference Include="System.Memory.Data" VersionOverride="8.0.1"/>
20+
<PackageReference Include="System.Memory.Data" VersionOverride="8.0.1" />
2121
</ItemGroup>
2222

2323
<ItemGroup>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
6+
[assembly: SuppressMessage("Usage", "AZC0007:DO provide a minimal constructor that takes only the parameters required to connect to the service.", Justification = "<Pending>", Scope = "member", Target = "~M:Azure.AI.Models.ModelsClient.#ctor(System.Uri,Azure.Core.TokenCredential)")]
7+
[assembly: SuppressMessage("Usage", "AZC0007:DO provide a minimal constructor that takes only the parameters required to connect to the service.", Justification = "<Pending>", Scope = "member", Target = "~M:Azure.AI.Models.ModelsClient.#ctor(System.Uri,Azure.Core.TokenCredential,OpenAI.OpenAIClientOptions)")]
8+
[assembly: SuppressMessage("Usage", "AZC0007:DO provide a minimal constructor that takes only the parameters required to connect to the service.", Justification = "<Pending>", Scope = "member", Target = "~M:Azure.AI.Models.ModelsClient.#ctor(System.Uri,System.ClientModel.ApiKeyCredential)")]
9+
[assembly: SuppressMessage("Usage", "AZC0007:DO provide a minimal constructor that takes only the parameters required to connect to the service.", Justification = "<Pending>", Scope = "member", Target = "~M:Azure.AI.Models.ModelsClient.#ctor(System.Uri,System.ClientModel.ApiKeyCredential,OpenAI.OpenAIClientOptions)")]
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Core;
5+
using Azure.Core.Pipeline;
6+
using OpenAI;
7+
using System;
8+
using System.ClientModel.Primitives;
9+
10+
namespace Azure.AI.Models
11+
{
12+
internal static class MaaSClientHelpers
13+
{
14+
private static readonly string[] _scopes = ["https://cognitiveservices.azure.com/.default"];
15+
16+
internal static OpenAIClientOptions CreateOptions(Uri endpoint)
17+
{
18+
OpenAIClientOptions options = new OpenAIClientOptions();
19+
options.Endpoint = endpoint;
20+
return options;
21+
}
22+
23+
internal static ClientPipeline CreatePipeline(TokenCredential credential, OpenAIClientOptions? options = default)
24+
{
25+
if (options == null)
26+
{
27+
options = new OpenAIClientOptions();
28+
}
29+
30+
TokenCredentialAuthenticationPolicy auth = new(credential, _scopes);
31+
32+
return ClientPipeline.Create(
33+
options,
34+
perCallPolicies: [],
35+
perTryPolicies: [auth],
36+
beforeTransportPolicies: []
37+
);
38+
}
39+
}
40+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Core;
5+
using OpenAI.Embeddings;
6+
using System;
7+
using System.ClientModel;
8+
9+
namespace Azure.AI.Models
10+
{
11+
internal class ModelEmbeddingsClient : EmbeddingClient
12+
{
13+
public ModelEmbeddingsClient(string model, Uri endpoint, ApiKeyCredential key)
14+
: base(model, key, MaaSClientHelpers.CreateOptions(endpoint))
15+
{
16+
}
17+
18+
public ModelEmbeddingsClient(string model, Uri endpoint, TokenCredential credential)
19+
: base(MaaSClientHelpers.CreatePipeline(credential), model, MaaSClientHelpers.CreateOptions(endpoint))
20+
{
21+
}
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using Azure.Core;
5+
using OpenAI.Chat;
6+
using System;
7+
using System.ClientModel;
8+
9+
namespace Azure.AI.Models
10+
{
11+
internal class ModelsChatClient : ChatClient
12+
{
13+
public ModelsChatClient(string model, Uri endpoint, ApiKeyCredential credential)
14+
: base(model, credential, MaaSClientHelpers.CreateOptions(endpoint))
15+
{
16+
}
17+
18+
public ModelsChatClient(string model, Uri endpoint, TokenCredential credential)
19+
: base(MaaSClientHelpers.CreatePipeline(credential), model, MaaSClientHelpers.CreateOptions(endpoint))
20+
{
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)