Skip to content

Commit d427040

Browse files
.Net: Add missing directory Plugin in concepts + Warning fixes (#11858)
### Motivation and Context I noted that we don't actually have any Concept in `Plugins` folder showcasing a good and also long available feature from Semantic Kernel for importing File/Directory based Template Plugins. - Added some minor "message level" fixes to this change. --------- Co-authored-by: Mark Wallace <127216156+markwallace-microsoft@users.noreply.github.com>
1 parent 854330c commit d427040

File tree

11 files changed

+129
-13
lines changed

11 files changed

+129
-13
lines changed

dotnet/Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<LangVersion>12</LangVersion>
1010
<Nullable>enable</Nullable>
1111
<ImplicitUsings>disable</ImplicitUsings>
12+
<NoWarn>$(NoWarn);IDE0290;IDE0079</NoWarn>
1213
</PropertyGroup>
1314

1415
<PropertyGroup>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) Microsoft. All rights reserved.
2+
3+
using Microsoft.SemanticKernel;
4+
5+
namespace Plugins;
6+
7+
/// <summary>
8+
/// This sample shows how to create templated plugins from file directories.
9+
/// </summary>
10+
public class CreatePromptPluginFromDirectory(ITestOutputHelper output) : BaseTest(output)
11+
{
12+
[Fact]
13+
public async Task ImportAndUsePromptPluginFromDirectoryWithOpenAI()
14+
{
15+
// Get the current directory of the application
16+
var pluginDirectory = Path.Combine(AppContext.BaseDirectory, "Plugins", "FunPlugin");
17+
18+
var kernel = Kernel.CreateBuilder()
19+
.AddOpenAIChatCompletion(
20+
modelId: TestConfiguration.OpenAI.ChatModelId,
21+
apiKey: TestConfiguration.OpenAI.ApiKey)
22+
.Build();
23+
24+
CreateFileBasedPluginTemplate(pluginDirectory);
25+
26+
var funPlugin = kernel.ImportPluginFromPromptDirectoryYaml(pluginDirectory, "FunPlugin");
27+
28+
// Invoke the plugin with a prompt
29+
var result = await kernel.InvokeAsync(funPlugin["Joke"], new()
30+
{
31+
["input"] = "Why did the chicken cross the road?",
32+
["style"] = "dad joke"
33+
});
34+
35+
Console.WriteLine(result);
36+
}
37+
38+
/// <summary>
39+
/// After running this method, a new importable plugin directory structure will be created at the application root.
40+
/// <code>
41+
/// ./Plugins/FunPlugin/
42+
/// joke.yml
43+
/// </code>
44+
/// Within the <c>FunPlugin</c> directory, any yml file will be imported as a distinct prompt function for the <see cref="KernelPlugin"/>.
45+
/// </summary>
46+
private static void CreateFileBasedPluginTemplate(string pluginRootDirectory)
47+
{
48+
// Create the sub-directory for the plugin function "Joke"
49+
var pluginRelativeDirectory = Path.Combine(pluginRootDirectory, "Joke");
50+
51+
const string PluginYmlFileContent =
52+
"""
53+
name: Joke
54+
template: |
55+
WRITE EXACTLY ONE JOKE or HUMOROUS STORY ABOUT THE TOPIC BELOW
56+
57+
JOKE MUST BE:
58+
- G RATED
59+
- WORKPLACE/FAMILY SAFE
60+
NO SEXISM, RACISM OR OTHER BIAS/BIGOTRY
61+
62+
BE CREATIVE AND FUNNY. I WANT TO LAUGH.
63+
Incorporate the style suggestion, if provided: {{$style}}
64+
+++++
65+
66+
{{$input}}
67+
+++++
68+
template_format: semantic-kernel
69+
description: A function that generates a story about a topic.
70+
input_variables:
71+
- name: input
72+
description: Joke subject.
73+
is_required: true
74+
- name: style
75+
description: Give a hint about the desired joke style.
76+
is_required: true
77+
output_variable:
78+
description: The generated funny joke.
79+
execution_settings:
80+
default:
81+
temperature: 0.9
82+
max_tokens: 1000
83+
top_p: 0.0
84+
presence_penalty: 0.0
85+
frequency_penalty: 0.0
86+
""";
87+
88+
// Create the directory structure
89+
if (!Directory.Exists(pluginRootDirectory))
90+
{
91+
Directory.CreateDirectory(pluginRootDirectory);
92+
}
93+
94+
// Create the config.json file if not exists
95+
var ymlFilePath = Path.Combine(pluginRootDirectory, "joke.yml");
96+
File.WriteAllText(ymlFilePath, PluginYmlFileContent);
97+
}
98+
}

dotnet/samples/Concepts/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ dotnet test -l "console;verbosity=detailed" --filter "FullyQualifiedName=ChatCom
170170
- [CreatePluginFromOpenApiSpec_Jira](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CreatePluginFromOpenApiSpec_Jira.cs)
171171
- [CreatePluginFromOpenApiSpec_Klarna](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CreatePluginFromOpenApiSpec_Klarna.cs)
172172
- [CreatePluginFromOpenApiSpec_RepairService](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CreatePluginFromOpenApiSpec_RepairService.cs)
173+
- [CreatePromptPluginFromDirectory](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CreatePromptPluginFromDirectory.cs)
173174
- [CrewAI_Plugin](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/CrewAI_Plugin.cs)
174175
- [OpenApiPlugin_PayloadHandling](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/OpenApiPlugin_PayloadHandling.cs)
175176
- [OpenApiPlugin_CustomHttpContentReader](https://github.com/microsoft/semantic-kernel/blob/main/dotnet/samples/Concepts/Plugins/OpenApiPlugin_CustomHttpContentReader.cs)

dotnet/src/Connectors/Connectors.Memory.AzureAISearch/AzureAISearchVectorStoreRecordCollection.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,10 @@ public Task CreateCollectionAsync(CancellationToken cancellationToken = default)
168168
}
169169

170170
// Create the index.
171-
var searchIndex = new SearchIndex(this._collectionName, searchFields);
172-
searchIndex.VectorSearch = vectorSearchConfig;
171+
var searchIndex = new SearchIndex(this._collectionName, searchFields)
172+
{
173+
VectorSearch = vectorSearchConfig
174+
};
173175

174176
return this.RunOperationAsync(
175177
"CreateIndex",

dotnet/src/Connectors/Connectors.Memory.Postgres/PostgresSqlBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ internal static PostgresSqlCommandInfo BuildUpsertBatchCommand(string schema, st
174174
var valuesRows = string.Join(", ",
175175
rows.Select((row, rowIndex) =>
176176
$"({string.Join(", ",
177-
columns.Select((c, colIndex) => $"${rowIndex * columns.Count + colIndex + 1}"))})"));
177+
columns.Select((c, colIndex) => $"${(rowIndex * columns.Count) + colIndex + 1}"))})"));
178178

179179
// Generate the update set clause
180180
var updateSetClause = string.Join(", ", columns.Where(c => c != keyColumn).Select(c => $"\"{c}\" = EXCLUDED.\"{c}\""));

dotnet/src/Connectors/Connectors.Memory.Qdrant/QdrantVectorStoreRecordCollection.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -585,8 +585,10 @@ private async IAsyncEnumerable<VectorSearchResult<TRecord>> SearchCoreAsync<TVec
585585
#pragma warning restore CS0618 // Type or member is obsolete
586586

587587
// Specify whether to include vectors in the search results.
588-
var vectorsSelector = new WithVectorsSelector();
589-
vectorsSelector.Enable = options.IncludeVectors;
588+
var vectorsSelector = new WithVectorsSelector
589+
{
590+
Enable = options.IncludeVectors
591+
};
590592

591593
var query = new Query
592594
{

dotnet/src/Connectors/Connectors.Ollama.UnitTests/Settings/OllamaPromptExecutionSettingsTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ public void FromExecutionSettingsShouldRestoreFunctionChoiceBehavior()
7171
// Arrange
7272
var functionChoiceBehavior = FunctionChoiceBehavior.Auto();
7373

74-
var originalExecutionSettings = new PromptExecutionSettings();
75-
originalExecutionSettings.FunctionChoiceBehavior = functionChoiceBehavior;
74+
var originalExecutionSettings = new PromptExecutionSettings
75+
{
76+
FunctionChoiceBehavior = functionChoiceBehavior
77+
};
7678

7779
// Act
7880
var result = OllamaPromptExecutionSettings.FromExecutionSettings(originalExecutionSettings);

dotnet/src/IntegrationTests/Connectors/Memory/AzureAISearch/AzureAISearchVectorStoreFixture.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,10 @@ public static async Task CreateIndexAsync(string indexName, SearchIndexClient ad
172172
searchFields.Add(new VectorSearchField("DescriptionEmbedding", 1536, "my-vector-profile"));
173173

174174
// Create an index definition with a vectorizer to use when doing vector searches using text.
175-
var definition = new SearchIndex(indexName, searchFields);
176-
definition.VectorSearch = new VectorSearch();
175+
var definition = new SearchIndex(indexName, searchFields)
176+
{
177+
VectorSearch = new VectorSearch()
178+
};
177179
definition.VectorSearch.Vectorizers.Add(new AzureOpenAIVectorizer("text-embedding-vectorizer")
178180
{
179181
Parameters = new AzureOpenAIVectorizerParameters

dotnet/src/IntegrationTests/CrossLanguage/KernelRequestTracer.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,12 @@ private void ResetHttpComponents()
143143
{
144144
this.DisposeHttpResources();
145145
this._memoryDummyResponse = new MemoryStream(Encoding.UTF8.GetBytes(DummyResponse));
146-
this._httpMessageHandlerStub = new HttpMessageHandlerStub();
147-
this._httpMessageHandlerStub.ResponseToReturn = new HttpResponseMessage(HttpStatusCode.OK)
146+
this._httpMessageHandlerStub = new HttpMessageHandlerStub
148147
{
149-
Content = new StreamContent(this._memoryDummyResponse)
148+
ResponseToReturn = new HttpResponseMessage(HttpStatusCode.OK)
149+
{
150+
Content = new StreamContent(this._memoryDummyResponse)
151+
}
150152
};
151153
this._httpClient = new HttpClient(this._httpMessageHandlerStub);
152154
}

dotnet/src/InternalUtilities/src/System/IndexRange.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99

1010
#pragma warning disable RCS1168
1111
#pragma warning disable RCS1211
12+
#pragma warning disable RCS1220
1213
#pragma warning disable IDE0009
1314
#pragma warning disable IDE0011
15+
#pragma warning disable IDE0038
16+
#pragma warning disable IDE0046
17+
#pragma warning disable IDE0048
1418
#pragma warning disable IDE0090
19+
#pragma warning disable IDE0301
20+
#pragma warning disable CS8604
1521

1622
using System.Runtime.CompilerServices;
1723

0 commit comments

Comments
 (0)