Skip to content

Commit

Permalink
Merge pull request #2087 from solliancenet/cj-code-execution
Browse files Browse the repository at this point in the history
Code execution session identifiers using ACA Dynamic Sessions
  • Loading branch information
joelhulen authored Dec 16, 2024
2 parents 3c26346 + a7a909b commit 2f44e1e
Show file tree
Hide file tree
Showing 19 changed files with 333 additions and 21 deletions.
14 changes: 14 additions & 0 deletions docs/release-notes/breaking-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@
## Starting with 0.9.1

### Configuration changes

The following new App Configuration settings are required:

|Name | Default value | Description |
|--- | --- | --- |
|`FoundationaLLM:Code:CodeExecution:AzureContainerAppsDynamicSessions` | `{"DynamicSessionsEndpoints": []}` | Provides the configuration for the Azure Container Apps Dynamic Sessions code execution service. `DynamicSessionsEnpoints` is a list of Dynamic Sessions endpoints that are used to run code execution sessions. Must contain at least one value. |

### Agent tool configuration changes

Each agent tool should have an entry in the `properties` dictionary named `foundationallm_aca_code_execution_enabled` (`true` or `false`) to indicate whether the tool requires code execution sessions based on the the Azure Container Apps Dynamic Sessions service.

### Prompt definition changes

Prompt prefixes and suffixes support FoundationaLLM variables for dynamic replacement at runtime. The variable format is `{{foundationallm:variable_name[:format]}}` where
- `variable_name` is the name of the well-known variable.
- `format` is the optional formatting applied to the value of the variable.
Expand Down
23 changes: 23 additions & 0 deletions src/dotnet/Common/Constants/Agents/AgentToolPropertyNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace FoundationaLLM.Common.Constants.Agents
{
/// <summary>
/// Provides well-known parameter names for agent tools.
/// </summary>
public static class AgentToolPropertyNames
{
/// <summary>
/// Indicates whether code execution is enabled or not.
/// </summary>
public const string FoundationaLLM_AzureContainerApps_CodeExecution_Enabled = "foundationallm_aca_code_execution_enabled";

/// <summary>
/// The session identifier required to execute code in Azure Container Apps Dynamic Sessions.
/// </summary>
public const string FoundationaLLM_AzureContainerApps_CodeExecution_SessionId = "foundationallm_aca_code_execution_session_id";

/// <summary>
/// The endpoint required to execute code in Azure Container Apps Dynamic Sessions.
/// </summary>
public const string FoundationaLLM_AzureContainerApps_CodeExecution_Endpoint = "foundationallm_aca_code_execution_endpoint";
}
}
17 changes: 17 additions & 0 deletions src/dotnet/Common/Constants/Data/AppConfiguration.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,23 @@
}
]
},
{
"namespace": "Code:CodeExecution",
"dependency_injection_key": null,
"configuration_section": {
"description": "Configuration section used to identify settings for code execution services."
},
"configuration_keys": [
{
"name": "AzureContainerAppsDynamicSessions",
"description": "The settings for the Azure Container Apps Dynamic Sessions code execution service.",
"secret": "",
"value": "{\"DynamicSessionsEndpoints\": []}",
"content_type": "application/json",
"first_version": "0.9.1"
}
]
},
{
"namespace": "ResourceProviders:AIModel",
"dependency_injection_key": {
Expand Down
25 changes: 25 additions & 0 deletions src/dotnet/Common/Interfaces/ICodeExecutionService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using FoundationaLLM.Common.Models.Authentication;
using FoundationaLLM.Common.Models.CodeExecution;

namespace FoundationaLLM.Common.Interfaces
{
/// <summary>
/// Defines the capabilities for code execution services.
/// </summary>
public interface ICodeExecutionService
{
/// <summary>
/// Creates a new code execution session.
/// </summary>
/// <param name="instanceId">The unique identifier of the FoundationaLLM instance.</param>
/// <param name="context">The context in which the code execution session is created. This is usually the name of the agent tool, but it is not limited to that.</param>
/// <param name="conversationId">The unique identifier of the conversation.</param>
/// <param name="userIdentity">The <see cref="UnifiedUserIdentity"/> providing the user identity information.</param>
/// <returns>A <see cref="CodeExecutionSession"/> object with the properties of the code execution session.</returns>
Task<CodeExecutionSession> CreateCodeExecutionSession(
string instanceId,
string context,
string conversationId,
UnifiedUserIdentity userIdentity);
}
}
18 changes: 18 additions & 0 deletions src/dotnet/Common/Models/CodeExecution/CodeExecutionSession.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
namespace FoundationaLLM.Common.Models.CodeExecution
{
/// <summary>
/// Provides details about a code execution session.
/// </summary>
public class CodeExecutionSession
{
/// <summary>
/// The unique identifier for the code execution session.
/// </summary>
public required string SessionId { get; set; }

/// <summary>
/// The endpoint used to execute the code.
/// </summary>
public required string Endpoint { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace FoundationaLLM.Common.Models.Configuration.CodeExecution
{
/// <summary>
/// Provides settings for the Azure Container Apps code execution service.
/// </summary>
public class AzureContainerAppsCodeExecutionServiceSettings
{
/// <summary>
/// Get or sets the list of Azure Container Apps Dynamic Sessions endpoints.
/// </summary>
public List<string> DynamicSessionsEndpoints { get; set; } = [];
}
}
23 changes: 22 additions & 1 deletion src/dotnet/Common/Models/ResourceProviders/Agent/AgentTool.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace FoundationaLLM.Common.Models.ResourceProviders.Agent
{
Expand Down Expand Up @@ -38,5 +39,25 @@ public class AgentTool
/// </summary>
[JsonPropertyName("properties")]
public Dictionary<string, object> Properties { get; set; } = [];

/// <summary>
/// Tries to get the value of a property.
/// </summary>
/// <typeparam name="T">The type of the property being retrieved.</typeparam>
/// <param name="propertyName">The name of the property being retrieved.</param>
/// <param name="propertyValue">The resultig property value.</param>
/// <returns><see langword="true"/> if the property value was successfull retrieved, <see langword="false"/> otherwise.</returns>
public bool TryGetPropertyValue<T>(string propertyName, out T? propertyValue)
{
propertyValue = default;

if (Properties.TryGetValue(propertyName, out var value))
{
propertyValue = ((JsonElement)value).Deserialize<T>();
return true;
}

return false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using FoundationaLLM.Common.Interfaces;
using FoundationaLLM.Common.Models.Authentication;
using FoundationaLLM.Common.Models.CodeExecution;
using FoundationaLLM.Common.Models.Configuration.CodeExecution;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace FoundationaLLM.Common.Services.CodeExecution
{
/// <summary>
/// Provides a code execution service that uses Azure Container Apps Dynamic Sessions to execute code.
/// </summary>
/// <param name="options">The options for the Azure Container Apps code execution service.</param>
/// <param name="logger">The logger used for logging.</param>
public class AzureContainerAppsCodeExecutionService(
IOptions<AzureContainerAppsCodeExecutionServiceSettings> options,
ILogger<AzureContainerAppsCodeExecutionService> logger) : ICodeExecutionService
{
private readonly AzureContainerAppsCodeExecutionServiceSettings _settings = options.Value;
private readonly ILogger<AzureContainerAppsCodeExecutionService> _logger = logger;

/// <inheritdoc />
public Task<CodeExecutionSession> CreateCodeExecutionSession(
string instanceId,
string context,
string conversationId,
UnifiedUserIdentity userIdentity)
{
string newSessionId;

if (string.IsNullOrWhiteSpace(context))
{
// Since the context is invalid, the session identifier will be a random GUID.

_logger.LogWarning("An empty context was provided for creating a code execution session identifier.");
newSessionId = Guid.NewGuid().ToString().ToLower();
}
else if (string.IsNullOrWhiteSpace(conversationId))
{
// Since the conversation identifier is invalid, the session identifier will use a random GUID instead.
_logger.LogWarning("An empty conversation identifier was provided for creating a code execution session identifier.");
newSessionId = $"{context}-{Guid.NewGuid().ToString().ToLower()}";
}
else
{
// The session identifier will be a combination of the context and conversation identifier.
newSessionId = $"{context}-{conversationId}";
}

// Ensure the session identifier is no longer than 128 characters.
if (newSessionId.Length > 128)
{
_logger.LogWarning("The generated code execution session identifier is longer than 128 characters. It will be truncated.");
newSessionId = newSessionId[..128];
}

return Task.FromResult(new CodeExecutionSession
{
SessionId = newSessionId,
Endpoint = _settings.DynamicSessionsEndpoints.First()
});
}
}
}
36 changes: 36 additions & 0 deletions src/dotnet/Common/Services/CodeExecution/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using FoundationaLLM.Common.Constants.Configuration;
using FoundationaLLM.Common.Interfaces;
using FoundationaLLM.Common.Models.Configuration.CodeExecution;
using FoundationaLLM.Common.Services.CodeExecution;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FoundationaLLM
{
/// <summary>
/// General purpose dependency injection extensions.
/// </summary>
public static partial class DependencyInjection
{
/// <summary>
/// Registers the <see cref="ICodeExecutionService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder"/> application builder managing the dependency injection container.</param>
public static void AddAzureContainerAppsCodeExecutionService(this IHostApplicationBuilder builder) =>
builder.Services.AddAzureContainerAppsCodeExecutionService(builder.Configuration);

/// <summary>
/// Registers the <see cref="ICodeExecutionService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> dependency injection container service collection.</param>
/// <param name="configuration">The <see cref="IConfigurationManager"/> application configuration manager.</param>
public static void AddAzureContainerAppsCodeExecutionService(this IServiceCollection services, IConfigurationManager configuration)
{
services.AddOptions<AzureContainerAppsCodeExecutionServiceSettings>()
.Bind(configuration.GetSection(AppConfigurationKeys.FoundationaLLM_Code_CodeExecution_AzureContainerAppsDynamicSessions));

services.AddSingleton<ICodeExecutionService, AzureContainerAppsCodeExecutionService>();
}
}
}
18 changes: 1 addition & 17 deletions src/dotnet/Common/Services/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Azure.Monitor.OpenTelemetry.AspNetCore;
using Azure.Monitor.OpenTelemetry.Exporter;
using Azure.Monitor.OpenTelemetry.Exporter;
using FoundationaLLM.Common.Authentication;
using FoundationaLLM.Common.Constants;
using FoundationaLLM.Common.Constants.Authorization;
Expand All @@ -10,7 +9,6 @@
using FoundationaLLM.Common.Services.API;
using FoundationaLLM.Common.Services.Azure;
using FoundationaLLM.Common.Services.Security;
using FoundationaLLM.Common.Services.Templates;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Fluent;
Expand Down Expand Up @@ -298,19 +296,5 @@ public static void AddAzureCosmosDBService(this IServiceCollection services, ICo

services.AddSingleton<IAzureCosmosDBService, AzureCosmosDBService>();
}

/// <summary>
/// Registers the <see cref="ITemplatingService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder"/> application builder managing the dependency injection container.</param>
public static void AddRegexTemplatingEngine(this IHostApplicationBuilder builder) =>
builder.Services.AddSingleton<ITemplatingService, RegexTemplatingService>();

/// <summary>
/// Registers the <see cref="ITemplatingService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> dependency injection container service collection.</param>
public static void AddRegexTemplatingEngine(this IServiceCollection services) =>
services.AddSingleton<ITemplatingService, RegexTemplatingService>();
}
}
27 changes: 27 additions & 0 deletions src/dotnet/Common/Services/Templates/DependencyInjection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using FoundationaLLM.Common.Interfaces;
using FoundationaLLM.Common.Services.Templates;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace FoundationaLLM
{
/// <summary>
/// General purpose dependency injection extensions.
/// </summary>
public static partial class DependencyInjection
{
/// <summary>
/// Registers the <see cref="ITemplatingService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="builder">The <see cref="IHostApplicationBuilder"/> application builder managing the dependency injection container.</param>
public static void AddRegexTemplatingService(this IHostApplicationBuilder builder) =>
builder.Services.AddSingleton<ITemplatingService, RegexTemplatingService>();

/// <summary>
/// Registers the <see cref="ITemplatingService"/> implementation with the dependency injection container.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/> dependency injection container service collection.</param>
public static void AddRegexTemplatingService(this IServiceCollection services) =>
services.AddSingleton<ITemplatingService, RegexTemplatingService>();
}
}
6 changes: 6 additions & 0 deletions src/dotnet/Common/Templates/AppConfigurationKeyFilters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public static partial class AppConfigurationKeyFilters
public const string FoundationaLLM_PythonSDK =
"FoundationaLLM:PythonSDK:*";

/// <summary>
/// Filter for the configuration section used to identify settings for code execution services.
/// </summary>
public const string FoundationaLLM_Code_CodeExecution =
"FoundationaLLM:Code:CodeExecution:*";

/// <summary>
/// Filter for the configuration section used to identify the storage settings for the FoundationaLLM.AIModel resource provider.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions src/dotnet/Common/Templates/AppConfigurationKeySections.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public static partial class AppConfigurationKeySections
public const string FoundationaLLM_PythonSDK =
"FoundationaLLM:PythonSDK";

/// <summary>
/// Configuration section used to identify settings for code execution services.
/// </summary>
public const string FoundationaLLM_Code_CodeExecution =
"FoundationaLLM:Code:CodeExecution";

/// <summary>
/// Configuration section used to identify the storage settings for the FoundationaLLM.AIModel resource provider.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/dotnet/Common/Templates/AppConfigurationKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ public static class AppConfigurationKeys

#endregion

#region FoundationaLLM:Code:CodeExecution

/// <summary>
/// The app configuration key for the FoundationaLLM:Code:CodeExecution:AzureContainerAppsDynamicSessions setting.
/// <para>Value description:<br/>The settings for the Azure Container Apps Dynamic Sessions code execution service.</para>
/// </summary>
public const string FoundationaLLM_Code_CodeExecution_AzureContainerAppsDynamicSessions =
"FoundationaLLM:Code:CodeExecution:AzureContainerAppsDynamicSessions";

#endregion

#region FoundationaLLM:ResourceProviders:AIModel

#endregion
Expand Down
7 changes: 7 additions & 0 deletions src/dotnet/Common/Templates/appconfig.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@
"content_type": "",
"tags": {}
},
{
"key": "FoundationaLLM:Code:CodeExecution:AzureContainerAppsDynamicSessions",
"value": "{"DynamicSessionsEndpoints": []}",
"label": null,
"content_type": "application/json",
"tags": {}
},
{
"key": "FoundationaLLM:ResourceProviders:AIModel:Storage:AuthenticationType",
"value": "AzureIdentity",
Expand Down
Loading

0 comments on commit 2f44e1e

Please sign in to comment.