Skip to content

.Net: Add support for relative file references in Prompty #11435

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

Merged
merged 5 commits into from
Apr 15, 2025
Merged
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
@@ -39,4 +39,9 @@
</None>
<EmbeddedResource Include="TestData\**\*.prompty" />
</ItemGroup>
<ItemGroup>
<None Update="TestData\**\*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
41 changes: 41 additions & 0 deletions dotnet/src/Functions/Functions.Prompty.UnitTests/PromptyTest.cs
Original file line number Diff line number Diff line change
@@ -357,6 +357,47 @@ public void ItCreatesInputVariablesOnlyWhenNoneAreExplicitlySet()
Assert.Equal(expectedVariables, kernelFunction.Metadata.Parameters.Select(p => p.Name));
}

[Fact]
public void ItShouldCreateFunctionFromPromptYamlContainingRelativeFileReferences()
{
// Arrange
Kernel kernel = new();
var promptyPath = Path.Combine("TestData", "relativeFileReference.prompty");

// Act
var kernelFunction = kernel.CreateFunctionFromPromptyFile(promptyPath);

// Assert
Assert.NotNull(kernelFunction);
var executionSettings = kernelFunction.ExecutionSettings;
Assert.Single(executionSettings!);
Assert.True(executionSettings!.ContainsKey("default"));
var defaultExecutionSetting = executionSettings["default"];
Assert.Equal("gpt-35-turbo", defaultExecutionSetting.ModelId);
}

[Fact]
public void ItShouldCreateFunctionFromPromptYamlContainingRelativeFileReferencesWithFileProvider()
{
// Arrange
Kernel kernel = new();
var currentDirectory = Directory.GetCurrentDirectory();
var promptyPath = Path.Combine("TestData", "relativeFileReference.prompty");
using PhysicalFileProvider fileProvider = new(currentDirectory);

// Act
var kernelFunction = kernel.CreateFunctionFromPromptyFile(promptyPath,
fileProvider);

// Assert
Assert.NotNull(kernelFunction);
var executionSettings = kernelFunction.ExecutionSettings;
Assert.Single(executionSettings!);
Assert.True(executionSettings!.ContainsKey("default"));
var defaultExecutionSetting = executionSettings["default"];
Assert.Equal("gpt-35-turbo", defaultExecutionSetting.ModelId);
}

private sealed class EchoTextGenerationService : ITextGenerationService
{
public IReadOnlyDictionary<string, object?> Attributes { get; } = new Dictionary<string, object?>();
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"api": "chat",
"configuration": {
"type": "azure_openai",
"api_version": "2023-07-01-preview"
},
"parameters": {
"model_id": "gpt-35-turbo"
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
name: TestRelativeFileReference
description: A test prompt for relative file references
authors:
- Test Author
model: ${file:model.json}

---

# This is a test prompt for relative file references
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ public static KernelFunction CreateFunctionFromPromptyFile(
Verify.NotNullOrWhiteSpace(promptyFilePath);

var promptyTemplate = File.ReadAllText(promptyFilePath);
return kernel.CreateFunctionFromPrompty(promptyTemplate, promptTemplateFactory);
return kernel.CreateFunctionFromPrompty(promptyTemplate, promptTemplateFactory, promptyFilePath);
}

/// <summary>
@@ -46,19 +46,21 @@ public static KernelFunction CreateFunctionFromPromptyFile(
/// The <see cref="IPromptTemplateFactory"/> to use when interpreting the prompt template configuration into a <see cref="IPromptTemplate"/>.
/// If null, a <see cref="AggregatorPromptTemplateFactory"/> will be used with support for Liquid and Handlebars prompt templates.
/// </param>
/// <param name="promptyFilePath">Optional: File path to the prompty file.</param>
/// <returns>The created <see cref="KernelFunction"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="kernel"/> is null.</exception>
/// <exception cref="ArgumentNullException"><paramref name="promptyTemplate"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="promptyTemplate"/> is empty or composed entirely of whitespace.</exception>
public static KernelFunction CreateFunctionFromPrompty(
this Kernel kernel,
string promptyTemplate,
IPromptTemplateFactory? promptTemplateFactory = null)
IPromptTemplateFactory? promptTemplateFactory = null,
string? promptyFilePath = null)
{
Verify.NotNull(kernel);
Verify.NotNullOrWhiteSpace(promptyTemplate);

var promptTemplateConfig = KernelFunctionPrompty.ToPromptTemplateConfig(promptyTemplate);
var promptTemplateConfig = KernelFunctionPrompty.ToPromptTemplateConfig(promptyTemplate, promptyFilePath);

return KernelFunctionFactory.CreateFromPrompt(
promptTemplateConfig,
@@ -118,6 +120,6 @@ public static KernelFunction CreateFunctionFromPromptyFile(

using StreamReader reader = new(fileInfo.CreateReadStream());
var promptyTemplate = reader.ReadToEnd();
return kernel.CreateFunctionFromPrompty(promptyTemplate, promptTemplateFactory);
return kernel.CreateFunctionFromPrompty(promptyTemplate, promptTemplateFactory, fileInfo.PhysicalPath);
}
}
Original file line number Diff line number Diff line change
@@ -45,15 +45,16 @@ public static KernelFunction FromPrompty(
/// Create a <see cref="PromptTemplateConfig"/> from a prompty template.
/// </summary>
/// <param name="promptyTemplate">Prompty representation of a prompt-based <see cref="KernelFunction"/>.</param>
/// <param name="promptyFilePath">Optional: File path to the prompty file.</param>
/// <returns>The created <see cref="PromptTemplateConfig"/>.</returns>
/// <exception cref="ArgumentNullException"><paramref name="promptyTemplate"/> is null.</exception>
/// <exception cref="ArgumentException"><paramref name="promptyTemplate"/> is empty or composed entirely of whitespace.</exception>
public static PromptTemplateConfig ToPromptTemplateConfig(string promptyTemplate)
public static PromptTemplateConfig ToPromptTemplateConfig(string promptyTemplate, string? promptyFilePath = null)
{
Verify.NotNullOrWhiteSpace(promptyTemplate);

Dictionary<string, object> globalConfig = [];
PromptyCore.Prompty prompty = PromptyCore.Prompty.Load(promptyTemplate, globalConfig);
PromptyCore.Prompty prompty = PromptyCore.Prompty.Load(promptyTemplate, globalConfig, promptyFilePath);

var promptTemplateConfig = new PromptTemplateConfig
{