Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[.Net][AutoGen.DotnetInteractive] add DotnetInteractiveStdioConnector #3337

Merged
merged 6 commits into from
Aug 10, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public async Task CodeSnippet1()

#region code_snippet_1_1
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder() // add C# and F# kernels
.CreateDefaultInProcessKernelBuilder() // add C# and F# kernels
.Build();
#endregion code_snippet_1_1

Expand Down Expand Up @@ -67,7 +67,7 @@ public async Task CodeSnippet1()

#region code_snippet_1_4
var pythonKernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder()
.CreateDefaultInProcessKernelBuilder()
.AddPythonKernel(venv: "python3")
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static async Task RunAsync()
var instance = new Example04_Dynamic_GroupChat_Coding_Task();

var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultBuilder()
.CreateDefaultInProcessKernelBuilder()
.AddPythonKernel("python3")
.Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,9 @@ public static async Task<IAgent> CreateReviewerAgentAsync(OpenAIClient openAICli
public static async Task RunWorkflowAsync()
{
long the39thFibonacciNumber = 63245986;
var kernel = DotnetInteractiveKernelBuilder.CreateDefaultBuilder().Build();
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
.Build();

var config = LLMConfiguration.GetAzureOpenAIGPT3_5_Turbo();
var openaiClient = new OpenAIClient(new Uri(config.Endpoint), new Azure.AzureKeyCredential(config.ApiKey));
Expand Down Expand Up @@ -344,7 +346,9 @@ public static async Task RunAsync()
var config = LLMConfiguration.GetAzureOpenAIGPT3_5_Turbo();
var openaiClient = new OpenAIClient(new Uri(config.Endpoint), new Azure.AzureKeyCredential(config.ApiKey));

var kernel = DotnetInteractiveKernelBuilder.CreateDefaultBuilder().Build();
var kernel = DotnetInteractiveKernelBuilder
.CreateDefaultInProcessKernelBuilder()
.Build();
#region create_group_chat
var reviewer = await CreateReviewerAgentAsync(openaiClient, config.DeploymentName);
var coder = await CreateCoderAgentAsync(openaiClient, config.DeploymentName);
Expand Down
117 changes: 9 additions & 108 deletions dotnet/src/AutoGen.DotnetInteractive/DotnetInteractiveKernelBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,127 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DotnetInteractiveKernelBuilder.cs

#if NET8_0_OR_GREATER
using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.FSharp;
using Microsoft.DotNet.Interactive.Jupyter;
using Microsoft.DotNet.Interactive.PackageManagement;
using Microsoft.DotNet.Interactive.PowerShell;

namespace AutoGen.DotnetInteractive;

public class DotnetInteractiveKernelBuilder
public static class DotnetInteractiveKernelBuilder
{
private readonly CompositeKernel compositeKernel;

private DotnetInteractiveKernelBuilder()
#if NET8_0_OR_GREATER
public static InProccessDotnetInteractiveKernelBuilder CreateEmptyInProcessKernelBuilder()
{
this.compositeKernel = new CompositeKernel();

// add jupyter connector
this.compositeKernel.AddKernelConnector(
new ConnectJupyterKernelCommand()
.AddConnectionOptions(new JupyterHttpKernelConnectionOptions())
.AddConnectionOptions(new JupyterLocalKernelConnectionOptions()));
return new InProccessDotnetInteractiveKernelBuilder();
}

/// <summary>
/// Create an empty builder.
/// </summary>
/// <returns></returns>
public static DotnetInteractiveKernelBuilder CreateEmptyBuilder()
{
return new DotnetInteractiveKernelBuilder();
}

/// <summary>
/// Create a default builder with C# and F# kernels.
/// </summary>
public static DotnetInteractiveKernelBuilder CreateDefaultBuilder()
public static InProccessDotnetInteractiveKernelBuilder CreateDefaultInProcessKernelBuilder()
{
return new DotnetInteractiveKernelBuilder()
return new InProccessDotnetInteractiveKernelBuilder()
.AddCSharpKernel()
.AddFSharpKernel();
}
#endif

public DotnetInteractiveKernelBuilder AddCSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["c#", "C#"];
// create csharp kernel
var csharpKernel = new CSharpKernel()
.UseNugetDirective((k, resolvedPackageReference) =>
{

k.AddAssemblyReferences(resolvedPackageReference
.SelectMany(r => r.AssemblyPaths));
return Task.CompletedTask;
})
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(csharpKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddFSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["f#", "F#"];
// create fsharp kernel
var fsharpKernel = new FSharpKernel()
.UseDefaultFormatting()
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(fsharpKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddPowershellKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["pwsh", "powershell"];
// create powershell kernel
var powershellKernel = new PowerShellKernel()
.UseProfiles()
.UseValueSharing();

this.AddKernel(powershellKernel, aliases);

return this;
}

public DotnetInteractiveKernelBuilder AddPythonKernel(string venv, string kernelName = "python", IEnumerable<string>? aliases = null)
{
aliases ??= [kernelName];
// create python kernel
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);
var result = this.compositeKernel.SendAsync(connectCommand).Result;

result.ThrowOnCommandFailed();

return this;
}

public CompositeKernel Build()
{
return this.compositeKernel
.UseDefaultMagicCommands()
.UseImportMagicCommand();
}

private DotnetInteractiveKernelBuilder AddKernel(Kernel kernel, IEnumerable<string>? aliases = null)
public static DotnetInteractiveStdioKernelConnector CreateKernelBuilder(string workingDirectory, string kernelName = "root-proxy")
{
this.compositeKernel.Add(kernel, aliases);
return this;
return new DotnetInteractiveStdioKernelConnector(workingDirectory, kernelName);
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// DotnetInteractiveStdioKernelConnector.cs

using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.Connection;

namespace AutoGen.DotnetInteractive;

public class DotnetInteractiveStdioKernelConnector
{
private string workingDirectory;
private InteractiveService interactiveService;
private string kernelName;
private List<SubmitCode> setupCommands = new List<SubmitCode>();

internal DotnetInteractiveStdioKernelConnector(string workingDirectory, string kernelName = "root-proxy")
{
this.workingDirectory = workingDirectory;
this.interactiveService = new InteractiveService(workingDirectory);
this.kernelName = kernelName;
}

public DotnetInteractiveStdioKernelConnector RestoreDotnetInteractive()
{
if (this.interactiveService.RestoreDotnetInteractive())
{
return this;
}
else
{
throw new Exception("Failed to restore dotnet interactive tool.");
}
}

public DotnetInteractiveStdioKernelConnector AddPythonKernel(
string venv,
string kernelName = "python")
{
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);

this.setupCommands.Add(connectCommand);

return this;
}

public async Task<Kernel> BuildAsync(CancellationToken ct = default)
{
var compositeKernel = new CompositeKernel();
var url = KernelHost.CreateHostUri(this.kernelName);
var cmd = new string[]
{
"dotnet",
"tool",
"run",
"dotnet-interactive",
$"[cb-{this.kernelName}]",
"stdio",
//"--default-kernel",
//"csharp",
"--working-dir",
$@"""{workingDirectory}""",
};

var connector = new StdIoKernelConnector(
cmd,
this.kernelName,
url,
new DirectoryInfo(this.workingDirectory));

var rootProxyKernel = await connector.CreateRootProxyKernelAsync();

rootProxyKernel.KernelInfo.SupportedKernelCommands.Add(new(nameof(SubmitCode)));

var dotnetKernel = await connector.CreateProxyKernelAsync(".NET");
foreach (var setupCommand in this.setupCommands)
{
var setupCommandResult = await rootProxyKernel.SendAsync(setupCommand, ct);
setupCommandResult.ThrowOnCommandFailed();
}

return rootProxyKernel;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// InProccessDotnetInteractiveKernelBuilder.cs

#if NET8_0_OR_GREATER
using AutoGen.DotnetInteractive.Extension;
using Microsoft.DotNet.Interactive;
using Microsoft.DotNet.Interactive.Commands;
using Microsoft.DotNet.Interactive.CSharp;
using Microsoft.DotNet.Interactive.FSharp;
using Microsoft.DotNet.Interactive.Jupyter;
using Microsoft.DotNet.Interactive.PackageManagement;
using Microsoft.DotNet.Interactive.PowerShell;

namespace AutoGen.DotnetInteractive;

/// <summary>
/// Build an in-proc dotnet interactive kernel.
/// </summary>
public class InProccessDotnetInteractiveKernelBuilder
{
private readonly CompositeKernel compositeKernel;

internal InProccessDotnetInteractiveKernelBuilder()
{
this.compositeKernel = new CompositeKernel();

// add jupyter connector
this.compositeKernel.AddKernelConnector(
new ConnectJupyterKernelCommand()
.AddConnectionOptions(new JupyterHttpKernelConnectionOptions())
.AddConnectionOptions(new JupyterLocalKernelConnectionOptions()));
}

public InProccessDotnetInteractiveKernelBuilder AddCSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["c#", "C#", "csharp"];
// create csharp kernel
var csharpKernel = new CSharpKernel()
.UseNugetDirective((k, resolvedPackageReference) =>
{

k.AddAssemblyReferences(resolvedPackageReference
.SelectMany(r => r.AssemblyPaths));
return Task.CompletedTask;
})
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(csharpKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddFSharpKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["f#", "F#", "fsharp"];
// create fsharp kernel
var fsharpKernel = new FSharpKernel()
.UseDefaultFormatting()
.UseKernelHelpers()
.UseWho()
.UseMathAndLaTeX()
.UseValueSharing();

this.AddKernel(fsharpKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddPowershellKernel(IEnumerable<string>? aliases = null)
{
aliases ??= ["pwsh", "powershell"];
// create powershell kernel
var powershellKernel = new PowerShellKernel()
.UseProfiles()
.UseValueSharing();

this.AddKernel(powershellKernel, aliases);

return this;
}

public InProccessDotnetInteractiveKernelBuilder AddPythonKernel(string venv, string kernelName = "python")
{
// create python kernel
var magicCommand = $"#!connect jupyter --kernel-name {kernelName} --kernel-spec {venv}";
var connectCommand = new SubmitCode(magicCommand);
var result = this.compositeKernel.SendAsync(connectCommand).Result;

result.ThrowOnCommandFailed();

return this;
}

public CompositeKernel Build()
{
return this.compositeKernel
.UseDefaultMagicCommands()
.UseImportMagicCommand();
}

private InProccessDotnetInteractiveKernelBuilder AddKernel(Kernel kernel, IEnumerable<string>? aliases = null)
{
this.compositeKernel.Add(kernel, aliases);
return this;
}
}
#endif
Loading
Loading