├── notebooks
└── images
│ └── summaries-entities-relations.jpg
├── samples
└── demos
│ ├── BostonAzure-June2024
│ ├── demo-script.md
│ ├── MvpWebApp
│ │ ├── Prompts
│ │ │ └── RAG
│ │ │ │ ├── skprompt.txt
│ │ │ │ └── config.json
│ │ ├── appsettings.json
│ │ ├── Properties
│ │ │ └── launchSettings.json
│ │ ├── Program.cs
│ │ ├── MvpWebApp.csproj
│ │ └── HttpClientHandlers.cs
│ ├── MvpWebAppClient
│ │ ├── MvpWebAppClient.csproj
│ │ └── Program.cs
│ └── README.md
│ ├── PropertyGraphRAG
│ ├── PropertyGraph.Common
│ │ ├── Models
│ │ │ └── Records.cs
│ │ ├── Prompts
│ │ │ ├── ExtractKeywords
│ │ │ │ ├── skprompt.txt
│ │ │ │ └── config.json
│ │ │ ├── RewriteQuery
│ │ │ │ ├── config.json
│ │ │ │ └── skprompt.txt
│ │ │ ├── RequestWithContext
│ │ │ │ ├── config.json
│ │ │ │ └── skprompt.txt
│ │ │ └── ExtractEntities
│ │ │ │ ├── config.json
│ │ │ │ └── skprompt.txt
│ │ ├── Configuration
│ │ │ ├── Neo4jOptions.cs
│ │ │ ├── OpenAIOptions.cs
│ │ │ ├── Configuration.cs
│ │ │ ├── PropertyGraphOptions.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── IAppOptions.cs
│ │ ├── KeywordExtractor.cs
│ │ ├── DataObjects.cs
│ │ ├── Extensions.cs
│ │ ├── PropertyGraph.Common.csproj
│ │ └── Utilities.cs
│ ├── PropertyGraphIngestor
│ │ ├── Data
│ │ │ └── summaries.txt
│ │ ├── Properties
│ │ │ └── launchSettings.json
│ │ ├── PropertyGraphIngestor.csproj
│ │ ├── appsettings.json
│ │ ├── CommandOptions.cs
│ │ └── Program.cs
│ └── PropertyGraphRAG
│ │ ├── PropertyGraphRAG.csproj
│ │ ├── appsettings.json
│ │ └── Program.cs
│ ├── Text-to-Sql
│ ├── TextToSql.Console
│ │ ├── Prompts
│ │ │ ├── DescribeResults
│ │ │ │ ├── skprompt.txt
│ │ │ │ └── config.json
│ │ │ ├── EvaluateResult
│ │ │ │ ├── skprompt.txt
│ │ │ │ └── config.json
│ │ │ ├── EvaluateIntent
│ │ │ │ ├── config.json
│ │ │ │ └── skprompt.txt
│ │ │ └── SqlGenerate
│ │ │ │ ├── config.json
│ │ │ │ └── skprompt.txt
│ │ ├── Configuration
│ │ │ ├── PluginConfig.cs
│ │ │ ├── TextToSqlOptions.cs
│ │ │ ├── SqlSchemaOptions.cs
│ │ │ ├── OpenAIOptions.cs
│ │ │ └── Configuration.cs
│ │ ├── appsettings.json
│ │ ├── Nl2Sql
│ │ │ ├── SqlConnectionProvider.cs
│ │ │ ├── SqlCommandExecutor.cs
│ │ │ └── SqlScemaLoader.cs
│ │ └── TextToSql.Console.csproj
│ └── nl2sql.library
│ │ ├── SqlQueryResult.cs
│ │ ├── Schema
│ │ ├── ISchemaFormatter.cs
│ │ ├── ISchemaFormatterExtensions.cs
│ │ ├── SchemaDefinition.cs
│ │ ├── SchemaTable.cs
│ │ ├── SchemaProvider.cs
│ │ ├── SchemaSerializer.cs
│ │ ├── SchemaColumn.cs
│ │ └── YamlSchemaFormatter.cs
│ │ ├── Nl2Sql.Library.csproj
│ │ ├── Internal
│ │ └── FunctionResultExtensions.cs
│ │ └── SqlQueryGenerator.cs
│ └── QueryRewrite
│ ├── Configuration
│ ├── OpenAIOptions.cs
│ └── Configuration.cs
│ ├── appsettings.json
│ ├── QueryRewrite.csproj
│ ├── Plugins
│ └── BlogInfoPlugin.cs
│ └── Program.cs
├── src
├── .editorconfig
├── HelloWorld.Plugin1.Console
│ ├── Prompts
│ │ └── DailyFact
│ │ │ ├── skprompt.txt
│ │ │ └── config.json
│ ├── Configuration
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── HelloWorld.Plugin1.Console.csproj
│ └── Program.cs
├── HelloWorld.Agent1.Console
│ ├── Configuration
│ │ ├── PluginConfig.cs
│ │ ├── OpenAIOptions.cs
│ │ └── Configuration.cs
│ ├── appsettings.json
│ ├── HelloWorld.Agent1.Console.csproj
│ └── BingConnector2.cs
├── HelloWorld.WebSearchEnginePlugin.Console
│ ├── Configuration
│ │ ├── PluginConfig.cs
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── HelloWorld.WebSearchEnginePlugin.Console.csproj
│ └── Program.cs
├── HelloWorld.Console
│ ├── Configuration
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── HelloWorld.Console.csproj
│ └── Program.cs
├── HelloWorld.Planner1.Console
│ ├── Configuration
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── Extensions
│ │ └── HandlebarsPlannerExtensions.cs
│ ├── HelloWorld.Planner1.Console.csproj
│ ├── Plugins
│ │ └── DailyFactPlugin.cs
│ └── Program.cs
├── HelloWorld.Planner2.Console
│ ├── Configuration
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── HelloWorld.Planner2.Console.csproj
│ ├── Plugins
│ │ └── DailyFactPlugin.cs
│ └── Program.cs
├── HelloWorld.Plugin2.Console
│ ├── Configuration
│ │ ├── OpenAIOptions.cs
│ │ ├── Configuration.cs
│ │ └── ServiceCollectionExtensions.cs
│ ├── appsettings.json
│ ├── Plugins
│ │ └── DailyFactPlugin.cs
│ ├── HelloWorld.Plugin2.Console.csproj
│ └── Program.cs
└── HelloWorld.Plugin3.Console
│ ├── Configuration
│ ├── OpenAIOptions.cs
│ └── Configuration.cs
│ ├── appsettings.json
│ ├── HelloWorld.Plugin3.Console.csproj
│ ├── Plugins
│ └── DailyFactPlugin.cs
│ └── Program.cs
├── LICENSE
└── README.md
/notebooks/images/summaries-entities-relations.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonHaley/semantic-kernel-getting-started/HEAD/notebooks/images/summaries-entities-relations.jpg
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/demo-script.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonHaley/semantic-kernel-getting-started/HEAD/samples/demos/BostonAzure-June2024/demo-script.md
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Models/Records.cs:
--------------------------------------------------------------------------------
1 | namespace PropertyGraph.Common.Models;
2 |
3 | public record TripletWithChunk(string triplet, string chunk, double score);
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/Data/summaries.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JasonHaley/semantic-kernel-getting-started/HEAD/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/Data/summaries.txt
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/DescribeResults/skprompt.txt:
--------------------------------------------------------------------------------
1 |
2 | Given the following data set, please describe the contents.
3 |
4 | SQL RESULT: {{$data_result}}
5 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # SKEXP0055: Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
4 | dotnet_diagnostic.SKEXP0055.severity = none
5 |
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/Prompts/RAG/skprompt.txt:
--------------------------------------------------------------------------------
1 | Please answer the question with only the context provided.
2 | ## Question:
3 | {{$question}}
4 | ## Context:
5 | {{$context}}
6 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Prompts/DailyFact/skprompt.txt:
--------------------------------------------------------------------------------
1 | Tell me an interesting fact from world
2 | about an event that took place on {{$today}}.
3 | Be sure to mention the date in history for context.
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "PropertyGraphIngestor": {
4 | "commandName": "Project",
5 | "commandLineArgs": ".\\data\\summaries.txt -v"
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Trace"
5 | }
6 | },
7 | "AllowedHosts": "*",
8 | "AI": {
9 | "OpenAI": {
10 | "APIKey": ""
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/SqlQueryResult.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | namespace SemanticKernel.Data.Nl2Sql.Library;
4 |
5 | public record SqlQueryResult(string Schema, string Query)
6 | {
7 | // No specialization
8 | }
9 |
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/Configuration/PluginConfig.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Configuration;
2 |
3 | public class PluginOptions
4 | {
5 | public const string PluginConfig = "PluginConfig";
6 |
7 | public string BingApiKey { get; set; } = string.Empty;
8 | }
9 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Configuration/PluginConfig.cs:
--------------------------------------------------------------------------------
1 | namespace TextToSql.Console.Configuration;
2 | public class PluginOptions
3 | {
4 | public const string PluginConfig = "PluginConfig";
5 |
6 | public string BingApiKey { get; set; } = string.Empty;
7 | }
8 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/Configuration/PluginConfig.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Configuration;
2 |
3 | public class PluginOptions
4 | {
5 | public const string PluginConfig = "PluginConfig";
6 |
7 | public string BraveApiKey { get; set; } = string.Empty;
8 | }
9 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/ExtractKeywords/skprompt.txt:
--------------------------------------------------------------------------------
1 | Given a user question, pick or use 1 to 3 words to create a keyword to capture what the user is asking for'.
2 |
3 | QUERY: {{$questionText}}
4 | ######################
5 | KEYWORDS:
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebAppClient/MvpWebAppClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/EvaluateResult/skprompt.txt:
--------------------------------------------------------------------------------
1 |
2 | Given the following objective, corresponding SQL query, and SQL result, answer the user question.
3 |
4 | OBJECTIVE: {{$data_objective}}
5 | SQL QUERY: {{$data_query}}
6 | SQL RESULT: {{$data_result}}
7 | ANSWER:
8 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Configuration/TextToSqlOptions.cs:
--------------------------------------------------------------------------------
1 | namespace TextToSql.Console.Configuration;
2 | public class TextToSqlOptions
3 | {
4 | public const string TextToSqlConfig = "TextToSql";
5 |
6 | public string SchemaNames { get; set; } = string.Empty;
7 | public double MinSchemaRelevance { get; set; } = 0.7;
8 | }
9 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/ISchemaFormatter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.IO;
4 | using System.Threading.Tasks;
5 |
6 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
7 |
8 | internal interface ISchemaFormatter
9 | {
10 | Task WriteAsync(TextWriter writer, SchemaDefinition schema);
11 | }
12 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Configuration/Neo4jOptions.cs:
--------------------------------------------------------------------------------
1 | namespace PropertyGraph.Common;
2 |
3 | public class Neo4jOptions
4 | {
5 | public const string Neo4j = "Neo4j";
6 |
7 | public string User { get; set; } = string.Empty;
8 | public string Password { get; set; } = string.Empty;
9 | public string URI { get; set; } = string.Empty;
10 | }
11 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Configuration/SqlSchemaOptions.cs:
--------------------------------------------------------------------------------
1 | namespace TextToSql.Console.Configuration;
2 | public class SqlSchemaOptions
3 | {
4 | public const string SqlSchemaConfig = "SqlSchemaConfig ";
5 |
6 | public string ConnectionName { get; set; } = string.Empty;
7 | public string Description { get; set; } = string.Empty;
8 | public string? Tables { get; set; }
9 | }
10 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/DescribeResults/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Describes the data results",
4 | "execution_settings": {
5 | "default": {
6 | "temperature": 0.0
7 | }
8 | },
9 | "input_variables": [
10 | {
11 | "name": "data_result",
12 | "description": "Results from the query",
13 | "required": true
14 | }
15 | ]
16 | }
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebAppClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Http.Json;
2 |
3 | using HttpClient hc = new() { BaseAddress = new("http://localhost:5171") };
4 | while (true)
5 | {
6 | Console.WriteLine("");
7 | Console.Write("Question: ");
8 |
9 | await foreach (var msg in hc.GetFromJsonAsAsyncEnumerable($"/copilot?question={Console.ReadLine()}"))
10 | Console.Write(msg);
11 |
12 | Console.WriteLine();
13 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Prompts/DailyFact/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Provides interesting historic facts for the current date.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 250,
7 | "temperature": 0.7
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "today",
13 | "description": "Current date",
14 | "required": true
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/RewriteQuery/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Has the LLM rewrite the original query.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 2500,
7 | "temperature": 0.0
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "questionText",
13 | "description": "User's question to answer.",
14 | "required": true
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/ExtractKeywords/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Extracts keywords and synonyms from text.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 2500,
7 | "temperature": 0.1
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "questionText",
13 | "description": "Text to extract keywords and synonyms from.",
14 | "required": true
15 | }
16 | ]
17 | }
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "http": {
4 | "commandName": "Project",
5 | "launchUrl": "copilot",
6 | "environmentVariables": {
7 | "ASPNETCORE_ENVIRONMENT": "Development"
8 | },
9 | "dotnetRunMessages": true,
10 | "applicationUrl": "http://localhost:5171",
11 | "hotReloadEnabled": true
12 | }
13 | },
14 | "$schema": "http://json.schemastore.org/launchsettings.json"
15 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/Program.cs:
--------------------------------------------------------------------------------
1 | var builder = WebApplication.CreateBuilder(args);
2 | var app = builder.Build();
3 |
4 | app.MapGet("/copilot", (string question) =>
5 | {
6 | return GetResponseAsync(question);
7 | });
8 |
9 | app.Run();
10 |
11 | static async IAsyncEnumerable GetResponseAsync(string question)
12 | {
13 |
14 | foreach (string word in question.Split(' '))
15 |
16 | {
17 |
18 | await Task.Delay(250);
19 |
20 | yield return word + " ";
21 |
22 | }
23 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin2.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin2.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin2.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin1.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin2.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace HelloWorld.Plugin2.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string ApiKey { get; set; } = string.Empty;
9 | public string ChatDeploymentName { get; set; } = string.Empty;
10 | public string Endpoint { get; set; } = string.Empty;
11 | }
12 |
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "ConnectionStrings": {
14 | //"OpenAI": "Source=AzureOpenAI;Key=your-key;ChatDeploymentName=your-chat-deployment-name;Endpoint=your-endpoint"
15 | "OpenAI": "Source=OpenAI;ChatModelId=gpt-4o-2024-08-06;ApiKey=Your-OpenAI-API-Key"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "ConnectionStrings": {
14 | //"OpenAI": "Source=AzureOpenAI;Key=your-key;ChatDeploymentName=your-chat-deployment-name;Endpoint=your-endpoint"
15 | "OpenAI": "Source=OpenAI;ChatModelId=gpt-4o-2024-08-06;ApiKey=Your-OpenAI-API-Key"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/EvaluateIntent/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Determines if the user request is related to the described schema",
4 | "execution_settings": {
5 | "default": {
6 | "temperature": 0.0
7 | }
8 | },
9 | "input_variables": [
10 | {
11 | "name": "data_schema",
12 | "description": "Schema of the database tables",
13 | "required": true
14 | },
15 | {
16 | "name": "data_objective",
17 | "description": "Request from the user",
18 | "required": true
19 | }
20 | ]
21 | }
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/Prompts/RAG/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Provides prompt with a question and context variables for RAG.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 2000,
7 | "temperature": 0.3
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "question",
13 | "description": "User's question'",
14 | "required": true
15 | },
16 | {
17 | "name": "context",
18 | "description": "Context to user for answering the question",
19 | "required": true
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/IAppOptions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Microsoft.SemanticKernel;
3 |
4 | namespace PropertyGraph.Common;
5 |
6 | public interface IAppOptions
7 | {
8 | Kernel Kernel { get; }
9 | OpenAIOptions OpenAI { get; }
10 | Neo4jOptions Neo4j { get; }
11 | PropertyGraphOptions PropertyGraph { get; }
12 | ILoggerFactory LoggerFactory { get; }
13 | }
14 |
15 | public record class DefaultOptions(
16 | Kernel Kernel,
17 | OpenAIOptions OpenAI,
18 | Neo4jOptions Neo4j,
19 | PropertyGraphOptions PropertyGraph,
20 | ILoggerFactory LoggerFactory) : IAppOptions;
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/RequestWithContext/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Makes a request providing context for the LLM to use in answering the request.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 2500,
7 | "temperature": 0.0
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "context",
13 | "description": "The context to use to answer the question.",
14 | "required": true
15 | },
16 | {
17 | "name": "questionText",
18 | "description": "User's question to answer.",
19 | "required": true
20 | }
21 | ]
22 | }
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace TextToSql.Console.Configuration;
2 | internal class OpenAIOptions
3 | {
4 | public const string OpenAI = "OpenAI";
5 |
6 | public string Source { get; set; } = string.Empty;
7 | public string ChatModelId { get; set; } = string.Empty;
8 | public string TextEmbeddingsModelId { get; set; } = string.Empty;
9 | public string ApiKey { get; set; } = string.Empty;
10 | public string ChatDeploymentName { get; set; } = string.Empty;
11 | public string TextEmbeddingsDeploymentName { get; set; } = string.Empty;
12 | public string Endpoint { get; set; } = string.Empty;
13 | }
14 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/EvaluateResult/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Answers the user question for the given sql query and results",
4 | "execution_settings": {
5 | "default": {
6 | "temperature": 0.0
7 | }
8 | },
9 | "input_variables": [
10 | {
11 | "name": "data_objective",
12 | "description": "Request from the user",
13 | "required": true
14 | },
15 | {
16 | "name": "data_query",
17 | "description": "SQL query",
18 | "required": true
19 | },
20 | {
21 | "name": "data_result",
22 | "description": "Results from the query",
23 | "required": true
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/SqlGenerate/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Creates valid SQL for a given user request.",
4 | "execution_settings": {
5 | "default": {
6 | "temperature": 0.0
7 | }
8 | },
9 | "input_variables": [
10 | {
11 | "name": "data_platform",
12 | "description": "SQL data platform type",
13 | "required": true
14 | },
15 | {
16 | "name": "data_schema",
17 | "description": "Schema of the database tables",
18 | "required": true
19 | },
20 | {
21 | "name": "data_objective",
22 | "description": "Request from the user",
23 | "required": true
24 | }
25 | ]
26 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "AzureOpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-35-gpt",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | },
22 | "PluginConfig": {
23 | "BingApiKey": "" // Add your Bing API key here
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "AzureOpenAI", // or "OpenAI"
15 | "ChatModelId": "gpt-4o",
16 | "ApiKey": "Your-OpenAI-API-Key"
17 |
18 | // Add these settings if you are using AzureOpenAI
19 | // "ChatDeploymentName": "your-chat-deployment-name",
20 | // "Endpoint": "your-endpoint"
21 | },
22 | "PluginConfig": {
23 | "BraveApiKey": "" // Add your Brave API key here
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/ISchemaFormatterExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System;
4 | using System.IO;
5 | using System.Threading.Tasks;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
8 |
9 | internal static class SchemaDefinitionExtensions
10 | {
11 | public static async Task FormatAsync(this SchemaDefinition schema, ISchemaFormatter formatter)
12 | {
13 | formatter = formatter ?? throw new ArgumentNullException(nameof(formatter));
14 |
15 | using var writer = new StringWriter();
16 |
17 | await formatter.WriteAsync(writer, schema).ConfigureAwait(false);
18 |
19 | return writer.ToString();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Configuration/OpenAIOptions.cs:
--------------------------------------------------------------------------------
1 | namespace PropertyGraph.Common;
2 |
3 | public class OpenAIOptions
4 | {
5 | public const string OpenAI = "OpenAI";
6 |
7 | public string Source { get; set; } = string.Empty;
8 | public string ChatModelId { get; set; } = string.Empty;
9 | public string TextEmbeddingsModelId { get; set; } = string.Empty;
10 | public string ApiKey { get; set; } = string.Empty;
11 | public string ChatDeploymentName { get; set; } = string.Empty;
12 | public string TextEmbeddingsDeploymentName { get; set; } = string.Empty;
13 | public string Endpoint { get; set; } = string.Empty;
14 | public string Resource { get; set; } = string.Empty; // Used by Neo4j
15 | }
16 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/SchemaDefinition.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 |
6 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
7 |
8 | public sealed class SchemaDefinition
9 | {
10 | public SchemaDefinition(
11 | string name,
12 | string platform,
13 | string? description,
14 | IEnumerable tables)
15 | {
16 | this.Name = name;
17 | this.Platform = platform;
18 | this.Description = description;
19 | this.Tables = tables ?? Array.Empty();
20 | }
21 |
22 | public string Name { get; }
23 |
24 | public string? Description { get; }
25 |
26 | public string Platform { get; }
27 |
28 | public IEnumerable Tables { get; }
29 | }
30 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/RewriteQuery/skprompt.txt:
--------------------------------------------------------------------------------
1 | Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching a retriever system.
2 | Generate a search query based on the conversation and the new question.
3 | If you cannot generate a search query, return the original user question.
4 | DO NOT return anything besides the query.
5 |
6 | What does Jason blog about?"What does Jason blog about?"What is the name of his blog?What is the name of Jason's blog?Does he blog often?Does Jason blog often{{$questionText}}
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Nl2Sql.Library.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | SemanticKernel.Data.Nl2Sql.Library
5 | nl2sql.library
6 | net9.0
7 | LatestMajor
8 | disable
9 | enable
10 | false
11 | $(NoWarn);CA1869,SKEXP0001
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/ExtractEntities/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": 1,
3 | "description": "Extracts entities and relationships from text.",
4 | "execution_settings": {
5 | "default": {
6 | "max_tokens": 2500,
7 | "temperature": 0.1
8 | }
9 | },
10 | "input_variables": [
11 | {
12 | "name": "maxTripletsPerChunk",
13 | "description": "Maximum number of triplets to extract.",
14 | "required": true
15 | },
16 | {
17 | "name": "entityTypes",
18 | "description": "Types of entities to start with.",
19 | "required": true
20 | },
21 | {
22 | "name": "relationTypes",
23 | "description": "Types of relations to start with.",
24 | "required": true
25 | },
26 | {
27 | "name": "text",
28 | "description": "Text to extract the entities and relationships from.",
29 | "required": true
30 | }
31 | ]
32 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/KeywordExtractor.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Microsoft.SemanticKernel;
3 |
4 | namespace PropertyGraph.Common;
5 |
6 | public class KeywordExtractor
7 | {
8 | private readonly IAppOptions _options;
9 | private readonly ILogger _logger;
10 |
11 | public KeywordExtractor(IAppOptions options)
12 | {
13 | _options = options;
14 | _logger = _options.LoggerFactory.CreateLogger(nameof(KeywordExtractor));
15 | }
16 |
17 | public async Task> ExtractAsync(string text)
18 | {
19 | var prompts = _options.Kernel.CreatePluginFromPromptDirectory("Prompts");
20 |
21 | var result = await _options.Kernel.InvokeAsync(
22 | prompts["ExtractKeywords"],
23 | new() {
24 | { "questionText", text },
25 | });
26 |
27 | _logger.LogTrace(result.ToString());
28 |
29 | return result.ToString().Split("~");
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/SchemaTable.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Text.Json.Serialization;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
8 |
9 | public sealed class SchemaTable
10 | {
11 | public SchemaTable(
12 | string name,
13 | string? description = null,
14 | bool isView = false,
15 | IEnumerable? columns = null)
16 | {
17 | this.Name = name;
18 | this.Description = description;
19 | this.Columns = columns ?? Array.Empty();
20 | this.IsView = isView;
21 | }
22 |
23 | public string Name { get; }
24 |
25 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
26 | public string? Description { get; }
27 |
28 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
29 | public bool IsView { get; }
30 |
31 | public IEnumerable Columns { get; }
32 | }
33 |
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace PropertyGraph.Common;
4 |
5 | public class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin2.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace TextToSql.Console.Configuration;
4 | internal class Configuration
5 | {
6 | public static IConfigurationRoot ConfigureAppSettings()
7 | {
8 | var config = new ConfigurationBuilder()
9 | .SetBasePath(Directory.GetCurrentDirectory())
10 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
11 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
13 | #if DEBUG
14 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
15 | #endif
16 | .Build();
17 | return config;
18 | }
19 |
20 | static string GetUserJsonFilename()
21 | {
22 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin1.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin2.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin2.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin2.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/Configuration/Configuration.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 |
3 | namespace HelloWorld.Plugin2.Console.Configuration;
4 |
5 | internal class Configuration
6 | {
7 | public static IConfigurationRoot ConfigureAppSettings()
8 | {
9 | var config = new ConfigurationBuilder()
10 | .SetBasePath(Directory.GetCurrentDirectory())
11 | .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
12 | .AddJsonFile("appsettings.Development.json", optional: true, reloadOnChange: true)
13 | .AddJsonFile("appsettings.Production.json", optional: true, reloadOnChange: true)
14 | #if DEBUG
15 | .AddJsonFile(GetUserJsonFilename(), optional: true, reloadOnChange: true)
16 | #endif
17 | .Build();
18 | return config;
19 | }
20 |
21 | static string GetUserJsonFilename()
22 | {
23 | return $"appsettings.user_{Environment.UserName.ToLower()}.json";
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/SchemaProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using Microsoft.SemanticKernel.Memory;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
8 |
9 | ///
10 | /// Responsible for loading the defined schemas into kernel memory.
11 | ///
12 | public static class SchemaProvider
13 | {
14 | public const string MemoryCollectionName = "data-schemas";
15 |
16 | public static async Task InitializeAsync(ISemanticTextMemory memory, IEnumerable schemaPaths)
17 | {
18 | foreach (var schemaPath in schemaPaths)
19 | {
20 | var schema = await SchemaSerializer.ReadAsync(schemaPath).ConfigureAwait(false);
21 |
22 | var schemaText = await schema.FormatAsync(YamlSchemaFormatter.Instance).ConfigureAwait(false);
23 |
24 | await memory.SaveInformationAsync(MemoryCollectionName, schemaText, schema.Name, additionalMetadata: schema.Platform).ConfigureAwait(false);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Jason Haley
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/HelloWorld.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 |
4 | namespace HelloWorld.Console.Configuration;
5 |
6 | internal static class ServiceCollectionExtensions
7 | {
8 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
9 | {
10 | switch (openAIOptions.Source)
11 | {
12 | case "AzureOpenAI":
13 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
14 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
15 | break;
16 |
17 | case "OpenAI":
18 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
19 | break;
20 |
21 | default:
22 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
23 | }
24 |
25 | return serviceCollection;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/SchemaSerializer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.IO;
4 | using System.Text.Json;
5 | using System.Threading.Tasks;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
8 |
9 | public static class SchemaSerializer
10 | {
11 | public static async Task ReadAsync(string path)
12 | {
13 | using var stream = File.OpenRead(path);
14 |
15 | return await ReadAsync(stream).ConfigureAwait(false);
16 | }
17 |
18 | public static async Task ReadAsync(Stream stream)
19 | {
20 | return
21 | await JsonSerializer.DeserializeAsync(
22 | stream,
23 | new JsonSerializerOptions
24 | {
25 | PropertyNameCaseInsensitive = true
26 | }).ConfigureAwait(false) ??
27 | throw new JsonException("Unable to read schema.");
28 | }
29 |
30 | public static string ToJson(this SchemaDefinition schema)
31 | {
32 | return JsonSerializer.Serialize(schema, new JsonSerializerOptions { WriteIndented = true });
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 |
4 | namespace HelloWorld.Plugin1.Console.Configuration;
5 |
6 | internal static class ServiceCollectionExtensions
7 | {
8 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
9 | {
10 | switch (openAIOptions.Source)
11 | {
12 | case "AzureOpenAI":
13 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
14 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
15 | break;
16 |
17 | case "OpenAI":
18 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
19 | break;
20 |
21 | default:
22 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
23 | }
24 |
25 | return serviceCollection;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Configuration/PropertyGraphOptions.cs:
--------------------------------------------------------------------------------
1 | namespace PropertyGraph.Common;
2 |
3 | public class PropertyGraphOptions
4 | {
5 | public const string PropertyGraph = "PropertyGraph";
6 |
7 | public bool UseTokenSplitter { get; set; } = true;
8 | public int? ChunkSize { get; set; }
9 | public int? Overlap { get; set; }
10 |
11 | public string? EntityTypes { get; set; }
12 | public string? RelationshipTypes { get; set; }
13 | public string? EntityExtractonTemplatePreamble { get; set; }
14 | public string? DocumentChunkTypeLabel { get; set; }
15 | public int? MaxTripletsPerChunk { get; set; }
16 |
17 | public bool IncludeEntityTextSearch { get; set; } = true;
18 | public bool UseKeywords { get; set; } = true;
19 | public string TypeEntityTextOfSearch { get; set; } = "FULL_TEXT"; // "VECTOR"
20 | public bool IncludeTriplets { get; set; } = true;
21 | public int MaxTriplets { get; set; } = 30;
22 | public bool IncludeRelatedChunks { get; set; } = true;
23 | public int MaxRelatedChunks { get; set; } = 3;
24 |
25 | public bool IncludeChunkVectorSearch { get; set; } = true;
26 | public int MaxChunks { get; set; } = 5;
27 | }
28 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-4",
16 | "TextEmbeddingsModelId": "text-embedding-ada-002",
17 | "ApiKey": "your-api-key",
18 | "ChatDeploymentName": "gpt4",
19 | "TextEmbeddingsDeploymentName": "text-embedding-ada-002",
20 | "Endpoint": "your-azure-endpoint"
21 | },
22 | "PluginConfig": {
23 | "BingApiKey": "" // Add your Bing API key here
24 | },
25 | "TextToSql": {
26 | "SchemaNames": "AdventureWorks", // comma delimited list
27 | "MinSchemaRelevance": 0.7
28 | },
29 | "AdventureWorks": {
30 | "ConnectionName": "AdventureWorksDb",
31 | "Description": "Product, sales, and customer data for the AdentureWorks company."
32 | //"Tables": "SalesLT.Customer,SalesLT.Address" // commented out or otherwise comma delimited list of tables including schema (ie. dbo.Users)
33 | },
34 | "ConnectionStrings": {
35 | "AdventureWorks": "your-database-connection-string"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/MvpWebApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | $(NoWarn);SKEXP0001;SKEXP0010;SKEXP0050;SKEXP0130;
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | PreserveNewest
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/DataObjects.cs:
--------------------------------------------------------------------------------
1 | namespace PropertyGraph.Common;
2 | public record DocumentMetadata(string id, string source);
3 | public record ChunkMetadata(string id, string name, int sequence, string documentId, string text);
4 | public record TripletRow(string head, string head_type, string relation, string tail, string tail_type);
5 | public class EntityMetadata
6 | {
7 | public string name { get; set; } = string.Empty;
8 | public string type { get; set; } = string.Empty;
9 | public string id { get; set; } = string.Empty;
10 | public string text { get; set; } = string.Empty;
11 | public Dictionary mentionedInChunks { get; set; } = new Dictionary();
12 | }
13 |
14 | public static class Defaults
15 | {
16 | public const int CHUNK_SIZE = 500;
17 | public const int OVERLAP = 100;
18 | public const string ENTITY_TYPES = "BLOG_POST,BOOK,MOVIE,PRESENTATION,EVENT,ORGANIZATION,PERSON,PLACE,PRODUCT,REVIEW,ACTION";
19 | public const string RELATION_TYPES = "INTRODUCED,USED_FOR,WRITTEN_IN,PART_OF,LOCATED_IN,GIVEN,LIVES_IN,TRAVELED_TO";
20 | public const string DOCUMENT_CHUNK_TYPE = "DOCUMENT_CHUNK";
21 | public const int MAX_TRIPLETS_PER_CHUNK = 10;
22 | public const int MAX_KEYWORDS = 10;
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/SchemaColumn.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.Text.Json.Serialization;
4 |
5 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
6 |
7 | public sealed class SchemaColumn
8 | {
9 | public SchemaColumn(
10 | string name,
11 | string? description,
12 | string type,
13 | bool isPrimary,
14 | string? referencedTable = null,
15 | string? referencedColumn = null)
16 | {
17 | this.Name = name;
18 | this.Description = description;
19 | this.Type = type;
20 | this.IsPrimary = isPrimary;
21 | this.ReferencedTable = referencedTable;
22 | this.ReferencedColumn = referencedColumn;
23 | }
24 |
25 | public string Name { get; }
26 |
27 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
28 | public string? Description { get; }
29 |
30 | public string Type { get; }
31 |
32 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
33 | public bool IsPrimary { get; }
34 |
35 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
36 | public string? ReferencedTable { get; }
37 |
38 | [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
39 | public string? ReferencedColumn { get; }
40 | }
41 |
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/README.md:
--------------------------------------------------------------------------------
1 | # .NET AI Demo with Semantic Kernel
2 |
3 | This demo was started from a repo written by [James Montemagno](https://github.com/jamesmontemagno/AIDemo/blob/master/readme.md)
4 |
5 | My updated [demo-script](demo-script.md) walks through the stepts I took for my demo to discuss how to use Semantic Kernel to:
6 |
7 | * Connect to OpenAI
8 | * Chunk a text file into smaller pieces
9 | * Setup an in memory vector store and configure the embedding service
10 | * Add addition logging to see the network traffic
11 | * Search the vector store
12 | * Build a prompt to perform RAG and call Open AI
13 |
14 |
15 | For additional references
16 | * [Build your first AI Chat Bot with OPenAI and .NET in Minute](https://www.youtube.com/watch?v=NNPI4QQ8LhE)
17 | * [AI for .NET Developers documentation](https://learn.microsoft.com/dotnet/ai/)
18 | * [.NET AI Samples](https://github.com/dotnet/ai-samples)
19 | * [RAG with Azure and OpenAI Sample](https://github.com/Azure-Samples/azure-search-openai-demo-csharp)
20 | * [Semantic Kernel](https://learn.microsoft.com/semantic-kernel/overview/)
21 |
22 |
23 | ## Configuration
24 |
25 | 1. Create a developer account on [OpenAI](https://platform.openai.com/) and enable GPT-4 access (you may need to deposit $5)
26 | 2. Create a developer key and update **MvpWebApp/appsettings.json**
27 | 3. Open in Visual Studio or Visual Studio Code and enable multi project deployment to run both apps at the same time
28 | 4. The backend will run and a console window will be where we do our entry to call the API
29 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/EvaluateIntent/skprompt.txt:
--------------------------------------------------------------------------------
1 |
2 | Determine if the requested OBJECTIVE is related to the tables described in the YAML SCHEMA
3 | If so, ANSWER YES
4 | Otherwise, ANSWER NO
5 |
6 |
7 | [SCHEMA]
8 | description: historical record of concerts, stadiums and singers
9 | tables:
10 | - stadium:
11 | columns:
12 | Stadium_ID:
13 | Location:
14 | Name:
15 | Capacity:
16 | Highest:
17 | Lowest:
18 | Average:
19 | - singer:
20 | columns:
21 | Singer_ID:
22 | Name:
23 | Country:
24 | Song_Name:
25 | Song_release_year:
26 | Age:
27 | Is_male:
28 | - concert:
29 | columns:
30 | concert_ID:
31 | concert_Name:
32 | Theme:
33 | Stadium_ID:
34 | Year:
35 | - singer_in_concert:
36 | columns:
37 | concert_ID:
38 | Singer_ID:
39 | references:
40 | concert.Stadium_ID: stadium.Stadium_ID
41 | references:
42 | singer_in_concert.concert_ID: concert.concert_ID
43 | singer_in_concert.Singer_ID: singer.Singer_ID
44 |
45 | [OBJECTIVE]
46 | How many heads of the departments are older than 56 ?
47 |
48 |
49 | select count(*) department_head_count from head where age > 56
50 |
51 |
52 | SCHEMA: (same as previous)
53 |
54 | OBJECTIVE: List all tables?
55 |
56 |
57 | NO
58 |
59 |
60 | [SCHEMA]
61 | {{$data_schema}}
62 |
63 | [OBJECTIVE]
64 | {{$data_objective}}
65 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphRAG/PropertyGraphRAG.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0010
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/HelloWorld.Console/HelloWorld.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Always
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/Plugins/DailyFactPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using System.ComponentModel;
3 |
4 | namespace HelloWorld.Plugin.Console.Plugins;
5 |
6 | public class DailyFactPlugin
7 | {
8 | private const string DESCRIPTION = "Provides interesting historic facts for the current date.";
9 | private const string TEMPLATE = @"Tell me an interesting fact from world
10 | about an event that took place on {{$today}}.
11 | Be sure to mention the date in history for context.";
12 | private const string GET_DAILY_FACT_FUNC = "GetDailyFactFunc";
13 | internal const string PLUGIN_NAME = "DailyFactPlugin";
14 | internal const string GET_DAILY_FACT = "GetDailyFact";
15 |
16 | private readonly KernelFunction _dailyFact;
17 |
18 | public DailyFactPlugin()
19 | {
20 | PromptExecutionSettings settings = new()
21 | {
22 | ExtensionData = new Dictionary()
23 | {
24 | { "Temperature", 0.7 },
25 | { "MaxTokens", 250 }
26 | }
27 |
28 | };
29 |
30 | _dailyFact = KernelFunctionFactory.CreateFromPrompt(TEMPLATE,
31 | functionName: GET_DAILY_FACT_FUNC,
32 | description: DESCRIPTION,
33 | executionSettings: settings);
34 | }
35 |
36 | [KernelFunction]
37 | public async Task GetDailyFact([Description("Current date")] string today, Kernel kernel)
38 | {
39 | var result = await _dailyFact.InvokeAsync(kernel, new() { ["today"] = today }).ConfigureAwait(false);
40 |
41 | return result.ToString();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Internal/FunctionResultExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using Microsoft.SemanticKernel;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Internal;
8 |
9 | internal static class FunctionResultExtensions
10 | {
11 | private static readonly HashSet s_delimitersResult = new() { '\'', '"', '`' };
12 |
13 | public static string ParseValue(this FunctionResult result, string? label = null)
14 | {
15 | if (result == null)
16 | {
17 | return string.Empty;
18 | }
19 |
20 | var resultText = TrimDelimiters(result.GetValue() ?? string.Empty);
21 |
22 | if (!string.IsNullOrWhiteSpace(label))
23 | {
24 | // Trim out label, if present.
25 | int index = resultText.IndexOf($"{label}", StringComparison.OrdinalIgnoreCase);
26 | if (index == 0)
27 | {
28 | resultText = resultText.Substring(index + label.Length + 1).Trim();
29 | }
30 | }
31 |
32 | return resultText;
33 | }
34 |
35 | private static string TrimDelimiters(string expression)
36 | {
37 | for (var index = 0; index < expression.Length; ++index)
38 | {
39 | if (s_delimitersResult.Contains(expression[index]) &&
40 | s_delimitersResult.Contains(expression[expression.Length - index - 1]))
41 | {
42 | continue;
43 | }
44 |
45 | return expression.Substring(index, expression.Length - (index * 2)).Trim();
46 | }
47 |
48 | return expression;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/HelloWorld.Plugin2.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Always
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/HelloWorld.Plugin3.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Always
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/QueryRewrite.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0010
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/HelloWorld.WebSearchEnginePlugin.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0050
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Extensions/HandlebarsPlannerExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using Microsoft.SemanticKernel.Planning.Handlebars;
3 |
4 | namespace HelloWorld.Planner1.Console;
5 |
6 | public static class HandlebarsPlannerExtensions
7 | {
8 | // Load from an existing file or create a new plan and save it
9 | public async static Task GetOrCreatePlanAsync(this HandlebarsPlanner planner, string filename,
10 | Kernel kernel, string goal, KernelArguments? arguments = null)
11 | {
12 | if (Exists(filename))
13 | {
14 | return planner.Load(filename);
15 | }
16 | else
17 | {
18 | return await planner.CreateAndSavePlanAsync(filename, kernel, goal, arguments);
19 | }
20 | }
21 | // Create a new plan then save it
22 | public async static Task CreateAndSavePlanAsync(this HandlebarsPlanner planner, string filename,
23 | Kernel kernel, string goal, KernelArguments? arguments = null)
24 | {
25 | var plan = await planner.CreatePlanAsync(kernel, goal, arguments);
26 |
27 | plan.Save(filename);
28 |
29 | return plan;
30 | }
31 |
32 | public static bool Exists(string filename)
33 | {
34 | return File.Exists(filename);
35 | }
36 |
37 | public static HandlebarsPlan Load(this HandlebarsPlanner planner, string filename)
38 | {
39 | // Load the saved plan
40 | var savedPlan = File.ReadAllText(filename);
41 |
42 | // Populate intance
43 | return new HandlebarsPlan(savedPlan);
44 | }
45 |
46 | public static void Save(this HandlebarsPlan plan, string filename)
47 | {
48 | File.WriteAllText(filename, plan.ToString());
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Prompts/SqlGenerate/skprompt.txt:
--------------------------------------------------------------------------------
1 |
2 | Generate a SQL SELECT query that is compatible with {{$data_platform}}, use aliases for all tables and reference those aliases when used and achieves the OBJECTIVE exclusively using only the tables and views described in "SCHEMA:".
3 |
4 | Only generate SQL if the OBJECTIVE can be answered by querying a database with tables described in SCHEMA.
5 |
6 |
7 | Respond with only with valid SQL
8 |
9 |
10 | SCHEMA:
11 | description: historical record of concerts, stadiums and singers
12 | tables:
13 | - stadium:
14 | columns:
15 | Stadium_ID:
16 | Location:
17 | Name:
18 | Capacity:
19 | Highest:
20 | Lowest:
21 | Average:
22 | - singer:
23 | columns:
24 | Singer_ID:
25 | Name:
26 | Country:
27 | Song_Name:
28 | Song_release_year:
29 | Age:
30 | Is_male:
31 | - concert:
32 | columns:
33 | concert_ID:
34 | concert_Name:
35 | Theme:
36 | Stadium_ID:
37 | Year:
38 | - singer_in_concert:
39 | columns:
40 | concert_ID:
41 | Singer_ID:
42 | references:
43 | concert.Stadium_ID: stadium.Stadium_ID
44 | references:
45 | singer_in_concert.concert_ID: concert.concert_ID
46 | singer_in_concert.Singer_ID: singer.Singer_ID
47 |
48 | OBJECTIVE: How many heads of the departments are older than 56 ?
49 |
50 |
51 | select count(*) department_head_count from head where age > 56
52 |
53 |
54 | SCHEMA:
55 | {{$data_schema}}
56 |
57 | OBJECTIVE: {{$data_objective}}
58 |
59 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/HelloWorld.Planner1.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0060
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/HelloWorld.Planner2.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0060
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/Schema/YamlSchemaFormatter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql.Library.Schema;
8 |
9 | ///
10 | /// Format a object in YAML format.
11 | ///
12 | ///
13 | /// Turns out YAML is extremely efficient with token usage.
14 | ///
15 | internal sealed class YamlSchemaFormatter : ISchemaFormatter
16 | {
17 | public static YamlSchemaFormatter Instance { get; } = new YamlSchemaFormatter();
18 |
19 | private YamlSchemaFormatter() { }
20 |
21 | async Task ISchemaFormatter.WriteAsync(TextWriter writer, SchemaDefinition schema)
22 | {
23 | if (!string.IsNullOrWhiteSpace(schema.Description))
24 | {
25 | await writer.WriteLineAsync($"description: {schema.Description}").ConfigureAwait(false);
26 | }
27 |
28 | await writer.WriteLineAsync("tables:").ConfigureAwait(false);
29 |
30 | foreach (var table in schema.Tables)
31 | {
32 | await writer.WriteLineAsync($" - {table.Name}: {table.Description}").ConfigureAwait(false);
33 | await writer.WriteLineAsync(" columns:").ConfigureAwait(false);
34 |
35 | foreach (var column in table.Columns)
36 | {
37 | await writer.WriteLineAsync($" {column.Name}: {column.Description}").ConfigureAwait(false);
38 | }
39 | }
40 |
41 | await writer.WriteLineAsync("references:").ConfigureAwait(false);
42 | foreach (var (table, column) in schema.Tables.SelectMany(t => t.Columns.Where(c => !string.IsNullOrEmpty(c.ReferencedTable)).Select(c => (t.Name, c))))
43 | {
44 | await writer.WriteLineAsync($" {table}.{column.Name}: {column.ReferencedTable}.{column.ReferencedColumn}").ConfigureAwait(false);
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/ExtractEntities/skprompt.txt:
--------------------------------------------------------------------------------
1 | Please extract up to {{$maxTripletsPerChunk}} knowledge triplets from the provied text.
2 | {{$preamble}}
3 | Each triplet should be in the form of (head, relation, tail) with their respective types.
4 | ######################
5 | ONTOLOGY:
6 | Entity Types: {{$entityTypes}}
7 | Relation Types: {{$relationTypes}}
8 |
9 | Use these entity types and relation types as a starting point, introduce new types if necessary based on the context.
10 |
11 | GUIDELINES:
12 | - Output in JSON format: [{""head"": """", ""head_type"": """", ""relation"": """", ""tail"": """", ""tail_type"": """"}]
13 | - Use the full form for entities (ie., 'Artificial Intelligence' instead of 'AI')
14 | - Keep entities and relation names concise (3-5 words max)
15 | - Break down complex phrases into multiple triplets
16 | - Ensure the knowledge graph is coherent and easily understandable
17 | ######################
18 | EXAMPLE:
19 | Text: Jason Haley, chief engineer of Jason Haley Consulting, wrote a new blog post titled 'Study Notes: GraphRAG - Property Grids' about creating a property grid RAG system using Semantic Kernel.
20 | Output:
21 | [{""head"": ""Jason Haley"", ""head_type"": ""PERSON"", ""relation"": ""WORKS_FOR"", ""tail"": ""Jason Haley Consulting"", ""tail_type"": ""COMPANY""},
22 | {""head"": ""Study Notes: GraphRAG - Property Grids"", ""head_type"": ""BLOG_POST"", ""relation"": ""WRITTEN_BY"", ""tail"": ""Jason Haley"", ""tail_type"": ""PERSON""},
23 | {""head"": ""Study Notes: GraphRAG - Property Grids"", ""head_type"": ""BLOG_POST"", ""relation"": ""TOPIC"", ""tail"": ""Semantic Kernel"", ""tail_type"": ""TECHNOLOGY""},
24 | {""head"": ""property grid RAG system"", ""head_type"": ""SOFTWARE_SYSTEM"", ""relation"": ""USES"", ""tail"": ""Semantic Kernel"", ""tail_type"": ""TECHNOLOGY""}]
25 | ######################
26 | Text: {{$text}}
27 | ######################
28 | Output:
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphRAG/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "OpenAI": {
3 | "Source": "OpenAI", // or "AzureOpenAI"
4 | "ChatModelId": "gpt-4",
5 | "TextEmbeddingsModelId": "text-embedding-ada-002",
6 | "ApiKey": "your-api-key",
7 | "ChatDeploymentName": "gpt4",
8 | "TextEmbeddingsDeploymentName": "text-embedding-ada-002",
9 | "Endpoint": "your-azure-endpoint",
10 | "Resource": "your-openai-resource-name"
11 | },
12 | "PluginConfig": {
13 | "BingApiKey": "" // Add your Bing API key here
14 | },
15 | "TextToSql": {
16 | "SchemaNames": "AdventureWorks", // comma delimited list
17 | "MinSchemaRelevance": 0.7
18 | },
19 | "AdventureWorks": {
20 | "ConnectionName": "AdventureWorksDb",
21 | "Description": "Product, sales, and customer data for the AdentureWorks company."
22 | //"Tables": "SalesLT.Customer,SalesLT.Address" // commented out or otherwise comma delimited list of tables including schema (ie. dbo.Users)
23 | },
24 | "ConnectionStrings": {
25 | "AdventureWorks": "your-database-connection-string"
26 | },
27 | "PropertyGraph": {
28 | "UseTokenSplitter": false,
29 | "ChunkSize": 200, // tokens
30 | "Overlap": 0,
31 | "EntityTypes": "BLOG_POST,BOOK,MOVIE,PRESENTATION,EVENT,ORGANIZATION,PERSON,PLACE,PRODUCT,REVIEW,ACTION",
32 | "RelationTypes": "WRITTEN_BY,PRESENTED,USED_FOR,PART_OF,LOCATED_IN,GIVEN,LIVES_IN,TRAVELED_TO",
33 | "EntityExtractonTemplatePreamble": "The given text document contains blog entry summaries with a Title, Author, Posted On date, Topics and Summary. Make sure to add the WRITTEN_BY relationship for the author.",
34 | "DocumentChunkTypeLabel": "",
35 | "MaxTripletsPerChunk": 20,
36 |
37 | "IncludeEntityTextSearch": true,
38 | "TypeEntityTextOfSearch": "VECTOR", // FULL_TEXT
39 | "UseKeywords": true,
40 | "IncludeTriplets": true,
41 | "MaxTriplets": 30,
42 | "IncludeRelatedChunks": false,
43 | "MaxRelatedChunks": 5,
44 |
45 | "IncludeChunkVectorSearch": false,
46 | "MaxChunks": 5
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/HelloWorld.Agent1.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0001,SKEXP0010,SKEXP0110,SKEXP0050
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Always
19 |
20 |
21 | Always
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/HelloWorld.Plugin1.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Always
20 |
21 |
22 | Always
23 |
24 |
25 | Always
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/Plugins/BlogInfoPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using System.ComponentModel;
3 | using System.ComponentModel.DataAnnotations;
4 |
5 | namespace HelloWorld.Plugin.Console.Plugins;
6 |
7 | public class BlogInfoPlugin
8 | {
9 | private const string DESCRIPTION = "Provides answers to blog queries.";
10 | //private const string TEMPLATE = @"Tell me an interesting fact from world
11 | // about an event that took place on {{$today}}.
12 | // Be sure to mention the date in history for context.";
13 | private const string GET_DAILY_FACT_FUNC = "GetBlogInformation";
14 | internal const string PLUGIN_NAME = "DailyFactPlugin";
15 | internal const string GET_DAILY_FACT = "GetDailyFact";
16 |
17 | //private readonly KernelFunction _dailyFact;
18 | private readonly KernelFunction _currentDay;
19 |
20 | public BlogInfoPlugin()
21 | {
22 | PromptExecutionSettings settings = new()
23 | {
24 | ExtensionData = new Dictionary()
25 | {
26 | { "Temperature", 0.0 },
27 | { "MaxTokens", 250 }
28 | }
29 |
30 | };
31 |
32 | //_dailyFact = KernelFunctionFactory.CreateFromPrompt(TEMPLATE,
33 | // functionName: GET_DAILY_FACT_FUNC,
34 | // executionSettings: settings);
35 |
36 | _currentDay = KernelFunctionFactory.CreateFromMethod(() => DateTime.Now.ToString("MMMM dd"), "GetCurrentDay");
37 | }
38 |
39 | [KernelFunction, Description(DESCRIPTION)]
40 | public async Task GetBlogInformation([Description("Blog query"), Required] string query, Kernel kernel)
41 | {
42 | //var result = await _dailyFact.InvokeAsync(kernel, new() { ["today"] = today }).ConfigureAwait(false);
43 |
44 | return "Hello World";
45 | }
46 |
47 | [KernelFunction, Description("Retrieves the current day.")]
48 | public async Task GetCurrentDay(Kernel kernel)
49 | {
50 | var today = await _currentDay.InvokeAsync(kernel);
51 |
52 | return today.ToString();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/PropertyGraphIngestor.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0050
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Always
20 |
21 |
22 | Always
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Plugins/DailyFactPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using System.ComponentModel;
3 | using System.ComponentModel.DataAnnotations;
4 |
5 | namespace HelloWorld.Plugin.Console.Plugins;
6 |
7 | public class DailyFactPlugin
8 | {
9 | private const string DESCRIPTION = "Provides interesting historic facts for the current date.";
10 | private const string TEMPLATE = @"Tell me an interesting fact from world
11 | about an event that took place on {{$today}}.
12 | Be sure to mention the date in history for context.";
13 | private const string GET_DAILY_FACT_FUNC = "GetDailyFactFunc";
14 | internal const string PLUGIN_NAME = "DailyFactPlugin";
15 | internal const string GET_DAILY_FACT = "GetDailyFact";
16 |
17 | private readonly KernelFunction _dailyFact;
18 | private readonly KernelFunction _currentDay;
19 |
20 | public DailyFactPlugin()
21 | {
22 | PromptExecutionSettings settings = new()
23 | {
24 | ExtensionData = new Dictionary()
25 | {
26 | { "Temperature", 0.7 },
27 | { "MaxTokens", 250 }
28 | }
29 |
30 | };
31 |
32 | _dailyFact = KernelFunctionFactory.CreateFromPrompt(TEMPLATE,
33 | functionName: GET_DAILY_FACT_FUNC,
34 | executionSettings: settings);
35 |
36 | _currentDay = KernelFunctionFactory.CreateFromMethod(() => DateTime.Now.ToString("MMMM dd"), "GetCurrentDay");
37 | }
38 |
39 | [KernelFunction, Description(DESCRIPTION)]
40 | public async Task GetDailyFact([Description("Current day"), Required] string today, Kernel kernel)
41 | {
42 | var result = await _dailyFact.InvokeAsync(kernel, new() { ["today"] = today }).ConfigureAwait(false);
43 |
44 | return result.ToString();
45 | }
46 |
47 | [KernelFunction, Description("Retrieves the current day.")]
48 | public async Task GetCurrentDay(Kernel kernel)
49 | {
50 | var today = await _currentDay.InvokeAsync(kernel);
51 |
52 | return today.ToString();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/Plugins/DailyFactPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using System.ComponentModel;
3 | using System.ComponentModel.DataAnnotations;
4 |
5 | namespace HelloWorld.Plugin.Console.Plugins;
6 |
7 | public class DailyFactPlugin
8 | {
9 | private const string DESCRIPTION = "Provides interesting historic facts for the current date.";
10 | private const string TEMPLATE = @"Tell me an interesting fact from world
11 | about an event that took place on {{$today}}.
12 | Be sure to mention the date in history for context.";
13 | private const string GET_DAILY_FACT_FUNC = "GetDailyFactFunc";
14 | internal const string PLUGIN_NAME = "DailyFactPlugin";
15 | internal const string GET_DAILY_FACT = "GetDailyFact";
16 |
17 | private readonly KernelFunction _dailyFact;
18 | private readonly KernelFunction _currentDay;
19 |
20 | public DailyFactPlugin()
21 | {
22 | PromptExecutionSettings settings = new()
23 | {
24 | ExtensionData = new Dictionary()
25 | {
26 | { "Temperature", 0.7 },
27 | { "MaxTokens", 250 }
28 | }
29 |
30 | };
31 |
32 | _dailyFact = KernelFunctionFactory.CreateFromPrompt(TEMPLATE,
33 | functionName: GET_DAILY_FACT_FUNC,
34 | executionSettings: settings);
35 |
36 | _currentDay = KernelFunctionFactory.CreateFromMethod(() => DateTime.Now.ToString("MMMM dd"), "GetCurrentDay");
37 | }
38 |
39 | [KernelFunction, Description(DESCRIPTION)]
40 | public async Task GetDailyFact([Description("Current day"), Required] string today, Kernel kernel)
41 | {
42 | var result = await _dailyFact.InvokeAsync(kernel, new() { ["today"] = today }).ConfigureAwait(false);
43 |
44 | return result.ToString();
45 | }
46 |
47 | [KernelFunction, Description("Retrieves the current day.")]
48 | public async Task GetCurrentDay(Kernel kernel)
49 | {
50 | var today = await _currentDay.InvokeAsync(kernel);
51 |
52 | return today.ToString();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/Plugins/DailyFactPlugin.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using System.ComponentModel;
3 | using System.ComponentModel.DataAnnotations;
4 |
5 | namespace HelloWorld.Plugin.Console.Plugins;
6 |
7 | public class DailyFactPlugin
8 | {
9 | private const string DESCRIPTION = "Provides interesting historic facts for the current date.";
10 | private const string TEMPLATE = @"Tell me an interesting fact from world
11 | about an event that took place on {{$today}}.
12 | Be sure to mention the date in history for context.";
13 | private const string GET_DAILY_FACT_FUNC = "GetDailyFactFunc";
14 | internal const string PLUGIN_NAME = "DailyFactPlugin";
15 | internal const string GET_DAILY_FACT = "GetDailyFact";
16 |
17 | private readonly KernelFunction _dailyFact;
18 | private readonly KernelFunction _currentDay;
19 |
20 | public DailyFactPlugin()
21 | {
22 | PromptExecutionSettings settings = new()
23 | {
24 | ExtensionData = new Dictionary()
25 | {
26 | { "Temperature", 0.7 },
27 | { "MaxTokens", 250 }
28 | }
29 |
30 | };
31 |
32 | _dailyFact = KernelFunctionFactory.CreateFromPrompt(TEMPLATE,
33 | functionName: GET_DAILY_FACT_FUNC,
34 | executionSettings: settings);
35 |
36 | _currentDay = KernelFunctionFactory.CreateFromMethod(() => DateTime.Now.ToString("MMMM dd"), "GetCurrentDay");
37 | }
38 |
39 | [KernelFunction, Description(DESCRIPTION)]
40 | public async Task GetDailyFact([Description("Current day"), Required] string today, Kernel kernel)
41 | {
42 | var result = await _dailyFact.InvokeAsync(kernel, new() { ["today"] = today }).ConfigureAwait(false);
43 |
44 | return result.ToString();
45 | }
46 |
47 | [KernelFunction, Description("Retrieves the current day.")]
48 | public async Task GetCurrentDay(Kernel kernel)
49 | {
50 | var today = await _currentDay.InvokeAsync(kernel);
51 |
52 | return today.ToString();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Prompts/RequestWithContext/skprompt.txt:
--------------------------------------------------------------------------------
1 | Answer ONLY with the facts listed in the list of sources below. If there isn't enough information below, say you don't know. Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question.
2 | For tabular information return it as an html table. Do not return markdown format. If the question is not in English, answer in the language used in the question.
3 |
4 | To plan the response, begin by examining the Neo4j entity relations and their structured data to determine if the answer is present within. Follow these steps:
5 |
6 | 1. Analyze the provided Neo4j entity relations and their structured data:
7 | 2. Look at the nodes, relationships, and properties in the graph.
8 | 3. Identify the entities and their connections relevant to the question.
9 | 4. Identify relevant information:
10 | 5. Extract data points and relationships that are pertinent to the question.
11 | 6. Consider how these relationships influence the answer.
12 | 7. Explain how you got the answer in a section that starts with ""Explaination:"
13 | 8. Synthesize the identified information:
14 |
15 | Combine the extracted information logically.
16 | Formulate a coherent and comprehensive response.
17 | Here are some examples to guide the process:
18 |
19 | ######################
20 | Example:
21 | (Semantic Kernel)-[:TOPIC]->(Blog Post Title 1)
22 | (Semantic Kernel)-[:HAS_TOPIC]->(Blog Post Title 2)
23 | (Semantic Kernel)-[:INCLUDES_TOPIC]->(Blog Post Title 3)
24 | (Jason)-[:PRESENTED]->(Presentation about Semantic Kernel)
25 |
26 | Question:
27 | What blog posts are about Semantic Kernel?
28 |
29 | Explaination:
30 | I used the notes that indicated they had a topic of Semantic Kernel to determine when blog posts were pertinent.
31 |
32 | Answer:
33 | Blog Post Title 1, Blog Post Title 2 and Blog Post Title 3 are about Semantic Kernel.
34 |
35 | ######################
36 | Answer the question based solely on the following context:
37 | {{$context}}
38 |
39 | ######################
40 | Question: {{$questionText}}
41 | ######################
42 | Answer:
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Nl2Sql/SqlConnectionProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using Microsoft.Data.SqlClient;
4 | using Microsoft.Extensions.Configuration;
5 | using Microsoft.Extensions.DependencyInjection;
6 |
7 | namespace SemanticKernel.Data.Nl2Sql;
8 |
9 | ///
10 | /// Responsible for producing a connection string for the requested schema.
11 | ///
12 | internal sealed class SqlConnectionProvider
13 | {
14 | private readonly IConfiguration _configuration;
15 |
16 | ///
17 | /// Factory method for
18 | ///
19 | public static Func Create(IConfiguration configuration)
20 | {
21 | return CreateProvider;
22 |
23 | SqlConnectionProvider CreateProvider(IServiceProvider provider)
24 | {
25 | return new SqlConnectionProvider(configuration);
26 | }
27 | }
28 |
29 | private SqlConnectionProvider(IConfiguration configuration)
30 | {
31 | this._configuration = configuration;
32 | }
33 |
34 | ///
35 | /// Factory method for producing a live SQL connection instance.
36 | ///
37 | /// The schema name (which should match a corresponding connectionstring setting).
38 | /// A instance in the "Open" state.
39 | ///
40 | /// Connection pooling enabled by default makes re-establishing connections
41 | /// relatively efficient.
42 | ///
43 | public async Task ConnectAsync(string schemaName)
44 | {
45 | var connectionString =
46 | this._configuration.GetConnectionString(schemaName) ??
47 | throw new InvalidDataException($"Missing configuration for connection-string: {schemaName}");
48 |
49 | var connection = new SqlConnection(connectionString);
50 |
51 | try
52 | {
53 | await connection.OpenAsync().ConfigureAwait(false);
54 | }
55 | catch
56 | {
57 | connection.Dispose();
58 | throw;
59 | }
60 |
61 | return connection;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.SemanticKernel": "Information"
6 | },
7 | "Console": {
8 | "LogLevel": {
9 | "Default": "Information"
10 | }
11 | }
12 | },
13 | "OpenAI": {
14 | "Source": "OpenAI", // or "AzureOpenAI"
15 | "ChatModelId": "gpt-4",
16 | "TextEmbeddingsModelId": "text-embedding-ada-002",
17 | "ApiKey": "your-api-key",
18 | "ChatDeploymentName": "gpt4",
19 | "TextEmbeddingsDeploymentName": "text-embedding-ada-002",
20 | "Endpoint": "your-azure-endpoint",
21 | "Resource": "your-openai-resource-name"
22 | },
23 | "PluginConfig": {
24 | "BingApiKey": "" // Add your Bing API key here
25 | },
26 | "TextToSql": {
27 | "SchemaNames": "AdventureWorks", // comma delimited list
28 | "MinSchemaRelevance": 0.7
29 | },
30 | "AdventureWorks": {
31 | "ConnectionName": "AdventureWorksDb",
32 | "Description": "Product, sales, and customer data for the AdentureWorks company."
33 | //"Tables": "SalesLT.Customer,SalesLT.Address" // commented out or otherwise comma delimited list of tables including schema (ie. dbo.Users)
34 | },
35 | "ConnectionStrings": {
36 | "AdventureWorks": "your-database-connection-string"
37 | },
38 | "PropertyGraph": {
39 | "UseTokenSplitter": false,
40 | "ChunkSize": 200, // tokens
41 | "Overlap": 0,
42 | "EntityTypes": "BLOG_POST,PRESENTATION,EVENT,ORGANIZATION,PERSON,PLACE,TECHNOLOGY,SOFTWARE_SYSTEM,REVIEW,ACTION",
43 | "RelationTypes": "WRITTEN_BY,PRESENTED_BY,PART_OF,LOCATED_IN,LIVES_IN,TRAVELED_TO",
44 | "EntityExtractonTemplatePreamble": "The given text document contains blog entry summaries with a Title, Author, Posted On date, Topics and Summary. Make sure to add the WRITTEN_BY relationship for the author.",
45 | "DocumentChunkTypeLabel": "DOCUMENT_CHUNK",
46 | "MaxTripletsPerChunk": 20,
47 |
48 | "IncludeEntityTextSearch": true,
49 | "UseKeywords": true,
50 | "TypeEntityTextOfSearch": "VECTOR", // "FULL_TEXT"
51 | "IncludeTriplets": true,
52 | "MaxTriplets": 50,
53 | "IncludeRelatedChunks": true,
54 | "MaxRelatedChunks": 5,
55 |
56 | "IncludeChunkVectorSearch": false,
57 | "MaxChunks": 5
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Extensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.SemanticKernel;
2 | using Microsoft.SemanticKernel.ChatCompletion;
3 | using System.Text;
4 | using System.Text.Json;
5 |
6 | namespace PropertyGraph.Common;
7 |
8 | public static class StringExtensions
9 | {
10 | public static string CleanJsonText(this string jsonText)
11 | {
12 | return jsonText.Replace("```json", "").Replace("```", "").Replace("'", "").Trim();
13 | }
14 | }
15 |
16 | public static class FunctionResultExtentions
17 | {
18 | public static string ToCleanString(this FunctionResult? result)
19 | {
20 | if (result == null)
21 | {
22 | return "";
23 | }
24 |
25 | string jsonText = result.ToString();
26 | return jsonText.CleanJsonText();
27 | }
28 |
29 | public static T? As(this FunctionResult? result)
30 | {
31 | if (result == null)
32 | {
33 | return default;
34 | }
35 |
36 | return JsonSerializer.Deserialize(result.ToCleanString());
37 | }
38 | }
39 |
40 | public static class KernelExtensions
41 | {
42 | public static async Task InvokePromptAsync(this Kernel kernel, KernelFunction plugin, KernelArguments kernelArguments)
43 | {
44 | var result = await kernel.InvokeAsync(plugin, kernelArguments);
45 |
46 | return result.As();
47 | }
48 | }
49 |
50 | public static class ChatHistoryExtensions
51 | {
52 |
53 | public static async IAsyncEnumerable AddStreamingMessageAsync(this ChatHistory chatHistory, IAsyncEnumerable streamingMessageContents)
54 | {
55 | List messageContents = [];
56 |
57 | StringBuilder? contentBuilder = null;
58 |
59 | await foreach (var chatMessage in streamingMessageContents.ConfigureAwait(false))
60 | {
61 | if (chatMessage.ToString() is { Length: > 0 } contentUpdate)
62 | {
63 | (contentBuilder ??= new()).Append(contentUpdate);
64 | }
65 |
66 | messageContents.Add(chatMessage);
67 | yield return chatMessage;
68 | }
69 |
70 | if (messageContents.Count != 0)
71 | {
72 | chatHistory.AddAssistantMessage(contentBuilder?.ToString() ?? string.Empty);
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/CommandOptions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using Microsoft.SemanticKernel;
3 | using PropertyGraph.Common;
4 | using System.CommandLine;
5 | using System.CommandLine.Invocation;
6 |
7 | internal static class CommandOptions
8 | {
9 | internal static readonly Argument Files = new(name: "-f", description: "Files or directory to be processed");
10 |
11 | internal static readonly Option Verbose = new(name: "-v", description: "Writes out verbose logging to console.");
12 |
13 | internal static readonly Option Remove = new(name: "-r", description: "Remove all nodes and relations for a specified file.");
14 |
15 | internal static readonly Option RemoveAll = new(name: "-ra", description: "Removes all nodes and relations in the database.");
16 |
17 | internal static readonly RootCommand RootCommand = new(description: """
18 | Prepare documents by extracting knowledge graph triplets ( -> -> ) using OpenAI and
19 | inserting the entities and relations into Neo4j.
20 | """)
21 | {
22 | Files,
23 | Verbose,
24 | Remove,
25 | RemoveAll,
26 | };
27 | internal static AppOptions GetParsedAppOptions(InvocationContext context, Kernel kernel, OpenAIOptions openAIOptions, Neo4jOptions neo4JOptions, PropertyGraphOptions propertyGraph, ILoggerFactory loggerFactory) => new(
28 | Files: context.ParseResult.GetValueForArgument(Files),
29 | Remove: context.ParseResult.GetValueForOption(Remove),
30 | RemoveAll: context.ParseResult.GetValueForOption(RemoveAll),
31 | Verbose: context.ParseResult.GetValueForOption(Verbose),
32 | Console: context.Console,
33 | Kernel: kernel,
34 | OpenAI: openAIOptions,
35 | Neo4j: neo4JOptions,
36 | PropertyGraph : propertyGraph,
37 | LoggerFactory: loggerFactory );
38 |
39 | internal record class AppOptions(
40 | string Files,
41 | bool Verbose,
42 | bool Remove,
43 | bool RemoveAll,
44 | IConsole Console,
45 | Kernel Kernel,
46 | OpenAIOptions OpenAI,
47 | Neo4jOptions Neo4j,
48 | PropertyGraphOptions PropertyGraph,
49 | ILoggerFactory LoggerFactory) : AppConsole(Console), IAppOptions;
50 |
51 | internal record class AppConsole(IConsole Console);
52 | }
53 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Nl2Sql/SqlCommandExecutor.cs:
--------------------------------------------------------------------------------
1 |
2 | using Microsoft.Data.SqlClient;
3 | using System.Data;
4 |
5 | namespace TextToSql.Console.Nl2Sql;
6 | public class SqlCommandExecutor
7 | {
8 | private readonly string _connectionString;
9 |
10 | public SqlCommandExecutor(string connectionString)
11 | {
12 | _connectionString = connectionString;
13 | }
14 |
15 | public async Task>> ExecuteAsync(string sql)
16 | {
17 | if (sql.IndexOf("SELECT") == -1)
18 | {
19 | return new List>();
20 | }
21 |
22 | var rows = new List>();
23 | try
24 | {
25 | using (var connection = new SqlConnection(_connectionString))
26 | {
27 | await connection.OpenAsync();
28 | using var command = connection.CreateCommand();
29 |
30 | #pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
31 | command.CommandText = sql;
32 | #pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
33 |
34 | using var reader = await command.ExecuteReaderAsync();
35 |
36 | bool headersAdded = false;
37 | while (reader.Read())
38 | {
39 | var cols = new List();
40 | var headerCols = new List();
41 | if (!headersAdded)
42 | {
43 | for (int i = 0; i < reader.FieldCount; i++)
44 | {
45 | headerCols.Add(reader.GetName(i).ToString());
46 | }
47 | headersAdded = true;
48 | rows.Add(headerCols);
49 | }
50 |
51 | for (int i = 0; i <= reader.FieldCount - 1; i++)
52 | {
53 | try
54 | {
55 | cols.Add(reader.GetValue(i).ToString());
56 | }
57 | catch
58 | {
59 | cols.Add("DataTypeConversionError");
60 | }
61 | }
62 | rows.Add(cols);
63 | }
64 | }
65 | }
66 | catch
67 | {
68 | throw;
69 | }
70 | return rows;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/samples/demos/BostonAzure-June2024/MvpWebApp/HttpClientHandlers.cs:
--------------------------------------------------------------------------------
1 |
2 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
3 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
4 | {
5 | protected override async Task SendAsync(
6 | HttpRequestMessage request, CancellationToken cancellationToken)
7 | {
8 | string requestContent;
9 | if (request.Content is not null)
10 | {
11 | requestContent = await request.Content.ReadAsStringAsync(cancellationToken);
12 | System.Console.WriteLine("***********************************************");
13 | System.Console.WriteLine("Request:");
14 | System.Console.WriteLine(requestContent);
15 | System.Console.WriteLine("***********************************************");
16 | }
17 |
18 | HttpResponseMessage result = null;
19 | string content = null;
20 | try
21 | {
22 | result = await base.SendAsync(request, cancellationToken);
23 |
24 | // Comment out since it is streaming and shows tokens as they come back - needs to rollback the stream or clone it
25 | // if (result.Content is not null)
26 | // {
27 | // content = await result.Content.ReadAsStringAsync(cancellationToken);
28 | // System.Console.WriteLine("***********************************************");
29 | // System.Console.WriteLine("Response:");
30 | // System.Console.WriteLine(content);
31 | // System.Console.WriteLine("***********************************************");
32 | //}
33 | }
34 | catch (Exception ex)
35 | {
36 | System.Console.WriteLine($"Exception: {ex.Message}");
37 | }
38 |
39 | return result;
40 | }
41 | }
42 | public class RequestLoggingHttpClientHandler : HttpClientHandler
43 | {
44 | protected override async Task SendAsync(
45 | HttpRequestMessage request, CancellationToken cancellationToken)
46 | {
47 | if (request.Content is not null)
48 | {
49 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
50 | System.Console.WriteLine("***********************************************");
51 | System.Console.WriteLine("Request:");
52 | System.Console.WriteLine(content);
53 | System.Console.WriteLine("***********************************************");
54 | }
55 |
56 | return await base.SendAsync(request, cancellationToken);
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Plugin.Console.Plugins;
8 | using HelloWorld.Plugin2.Console.Configuration;
9 |
10 | internal class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 | MainAsync(args).Wait();
15 | }
16 |
17 | static async Task MainAsync(string[] args)
18 | {
19 | var config = Configuration.ConfigureAppSettings();
20 |
21 | // Get Settings (all this is just so I don't have hard coded config settings here)
22 | var openAiSettings = new OpenAIOptions();
23 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
24 |
25 | using var loggerFactory = LoggerFactory.Create(builder =>
26 | {
27 | builder.SetMinimumLevel(LogLevel.Information);
28 | builder.AddConfiguration(config);
29 | builder.AddConsole();
30 | });
31 |
32 | // Configure Semantic Kernel
33 | var builder = Kernel.CreateBuilder();
34 |
35 | builder.Services.AddSingleton(loggerFactory);
36 | builder.Services.AddChatCompletionService(openAiSettings);
37 |
38 | // --------------------------------------------------------------------------------------
39 | // Exercise from Virtual Boston Azure for creating a prompt
40 | // --------------------------------------------------------------------------------------
41 |
42 | builder.Plugins.AddFromType();
43 |
44 | Kernel kernel = builder.Build();
45 |
46 | // output today's date just for fun
47 | var today = DateTime.Now.ToString("MMMM dd");
48 | WriteLine($"Today is {today}");
49 |
50 | // Using a function with a parameter -----------------------------
51 | var funcargs = new KernelArguments { ["today"] = today };
52 |
53 | var funcresult = await kernel.InvokeAsync(
54 | DailyFactPlugin.PLUGIN_NAME,
55 | DailyFactPlugin.GET_DAILY_FACT,
56 | funcargs
57 | );
58 |
59 | WriteLine($"\nRESPONSE: \n\n{funcresult}");
60 | }
61 |
62 | static void WriteLine(string message)
63 | {
64 | Console.WriteLine("----------------------------------------------");
65 |
66 | Console.WriteLine(message);
67 |
68 | Console.WriteLine("----------------------------------------------");
69 | }
70 | }
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Configuration;
8 | using Microsoft.SemanticKernel.Connectors.OpenAI;
9 | using Microsoft.SemanticKernel.Plugins.Web;
10 |
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | MainAsync(args).Wait();
16 | }
17 |
18 | static async Task MainAsync(string[] args)
19 | {
20 | var config = Configuration.ConfigureAppSettings();
21 |
22 | // Get Settings (all this is just so I don't have hard coded config settings here)
23 | var openAiSettings = new OpenAIOptions();
24 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
25 |
26 | var pluginSettings = new PluginOptions();
27 | config.GetSection(PluginOptions.PluginConfig).Bind(pluginSettings);
28 |
29 | using var loggerFactory = LoggerFactory.Create(builder =>
30 | {
31 | builder.SetMinimumLevel(LogLevel.Information);
32 |
33 | builder.AddConfiguration(config);
34 | builder.AddConsole();
35 | });
36 |
37 | // Configure Semantic Kernel
38 | var builder = Kernel.CreateBuilder();
39 |
40 | builder.Services.AddSingleton(loggerFactory);
41 | builder.AddChatCompletionService(openAiSettings);
42 | //builder.AddChatCompletionService(openAiSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
43 |
44 | //builder.AddBraveConnector(pluginSettings);
45 | builder.AddBraveConnector(pluginSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
46 |
47 | builder.Plugins.AddFromType();
48 |
49 | Kernel kernel = builder.Build();
50 |
51 | var prompt = "Who are the organizers for the Boston Azure meetup?";
52 |
53 | WriteLine($"\nQUESTION: \n\n{prompt}");
54 |
55 | OpenAIPromptExecutionSettings settings = new()
56 | {
57 | ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
58 | Temperature = 0.7f,
59 | MaxTokens = 2500
60 | };
61 |
62 | var funcresult = await kernel.InvokePromptAsync(prompt, new KernelArguments(settings));
63 |
64 | WriteLine($"\nANSWER: \n\n{funcresult}");
65 | }
66 |
67 | static void WriteLine(string message)
68 | {
69 | Console.WriteLine("----------------------------------------------");
70 |
71 | Console.WriteLine(message);
72 |
73 | Console.WriteLine("----------------------------------------------");
74 | }
75 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Plugin.Console.Plugins;
8 | using HelloWorld.Plugin2.Console.Configuration;
9 | using Microsoft.SemanticKernel.Planning.Handlebars;
10 | using HelloWorld.Planner1.Console;
11 |
12 | internal class Program
13 | {
14 | static void Main(string[] args)
15 | {
16 | MainAsync(args).Wait();
17 | }
18 |
19 | static async Task MainAsync(string[] args)
20 | {
21 | var config = Configuration.ConfigureAppSettings();
22 |
23 | // Get Settings (all this is just so I don't have hard coded config settings here)
24 | var openAiSettings = new OpenAIOptions();
25 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
26 |
27 | using var loggerFactory = LoggerFactory.Create(builder =>
28 | {
29 | builder.SetMinimumLevel(LogLevel.Information);
30 |
31 | builder.AddConfiguration(config);
32 | builder.AddConsole();
33 | });
34 |
35 | // Configure Semantic Kernel
36 | var builder = Kernel.CreateBuilder();
37 |
38 | builder.Services.AddSingleton(loggerFactory);
39 | builder.AddChatCompletionService(openAiSettings);
40 | //builder.AddChatCompletionService(openAiSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
41 |
42 | // --------------------------------------------------------------------------------------
43 | // Exercise from Virtual Boston Azure for creating a prompt
44 | // --------------------------------------------------------------------------------------
45 |
46 | builder.Plugins.AddFromType();
47 |
48 | Kernel kernel = builder.Build();
49 |
50 | // TODO: CHALLENGE 1: does the AI respond accurately to this prompt? How to fix?
51 | var prompt = $"Tell me an interesting fact from world about an event " +
52 | $"that took place on today's date. " +
53 | $"Be sure to mention the date in history for context.";
54 |
55 | var planner = new HandlebarsPlanner(new HandlebarsPlannerOptions() { AllowLoops = true });
56 |
57 | var plan = await planner.GetOrCreatePlanAsync("SavedPlan.hbs", kernel, prompt);
58 |
59 | WriteLine($"\nPLAN: \n\n{plan}");
60 |
61 | var result = await plan.InvokeAsync(kernel);
62 |
63 | WriteLine($"\nRESPONSE: \n\n{result}");
64 | }
65 |
66 | static void WriteLine(string message)
67 | {
68 | Console.WriteLine("----------------------------------------------");
69 |
70 | Console.WriteLine(message);
71 |
72 | Console.WriteLine("----------------------------------------------");
73 | }
74 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin3.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Plugin.Console.Plugins;
8 | using HelloWorld.Plugin2.Console.Configuration;
9 | using Microsoft.SemanticKernel.Connectors.OpenAI;
10 |
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | MainAsync(args).Wait();
16 | }
17 |
18 | static async Task MainAsync(string[] args)
19 | {
20 | var config = Configuration.ConfigureAppSettings();
21 |
22 | // Get Settings (all this is just so I don't have hard coded config settings here)
23 | var openAiSettings = new OpenAIOptions();
24 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
25 |
26 | using var loggerFactory = LoggerFactory.Create(builder =>
27 | {
28 | builder.SetMinimumLevel(LogLevel.Warning);
29 |
30 | builder.AddConfiguration(config);
31 | builder.AddConsole();
32 | });
33 |
34 | // Configure Semantic Kernel
35 | var builder = Kernel.CreateBuilder();
36 |
37 | builder.Services.AddSingleton(loggerFactory);
38 | builder.AddChatCompletionService(config.GetConnectionString("OpenAI"));
39 | //builder.AddChatCompletionService(openAiSettings);
40 | //builder.AddChatCompletionService(openAiSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
41 |
42 | // --------------------------------------------------------------------------------------
43 | // Exercise from Virtual Boston Azure for creating a prompt
44 | // --------------------------------------------------------------------------------------
45 |
46 | builder.Plugins.AddFromType();
47 |
48 | Kernel kernel = builder.Build();
49 |
50 | // TODO: CHALLENGE 1: does the AI respond accurately to this prompt? How to fix?
51 | var prompt = $"Tell me an interesting fact from world about an event " +
52 | $"that took place on today's date. " +
53 | $"Be sure to mention the date in history for context.";
54 |
55 | OpenAIPromptExecutionSettings settings = new()
56 | {
57 | ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
58 | Temperature = 0.7f,
59 | MaxTokens = 250
60 | };
61 |
62 | var funcresult = await kernel.InvokePromptAsync(prompt, new KernelArguments(settings));
63 |
64 | WriteLine($"\nRESPONSE: \n\n{funcresult}");
65 | }
66 |
67 | static void WriteLine(string message)
68 | {
69 | Console.WriteLine("----------------------------------------------");
70 |
71 | Console.WriteLine(message);
72 |
73 | Console.WriteLine("----------------------------------------------");
74 | }
75 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/PropertyGraph.Common.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | SKEXP0050
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Always
24 |
25 |
26 | Always
27 |
28 |
29 | Always
30 |
31 |
32 | Always
33 |
34 |
35 | Always
36 |
37 |
38 | Always
39 |
40 |
41 | Always
42 |
43 |
44 | Always
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Plugin.Console.Plugins;
8 | using HelloWorld.Plugin2.Console.Configuration;
9 | using Microsoft.SemanticKernel.Planning;
10 | using System.Text.Json;
11 |
12 | internal class Program
13 | {
14 | static void Main(string[] args)
15 | {
16 | MainAsync(args).Wait();
17 | }
18 |
19 | static async Task MainAsync(string[] args)
20 | {
21 |
22 | var config = Configuration.ConfigureAppSettings();
23 |
24 | // Get Settings (all this is just so I don't have hard coded config settings here)
25 | var openAiSettings = new OpenAIOptions();
26 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
27 |
28 | using var loggerFactory = LoggerFactory.Create(builder =>
29 | {
30 | builder.SetMinimumLevel(LogLevel.Information);
31 |
32 | builder.AddConfiguration(config);
33 | builder.AddConsole();
34 | });
35 |
36 | // Configure Semantic Kernel
37 | var builder = Kernel.CreateBuilder();
38 |
39 | builder.Services.AddSingleton(loggerFactory);
40 | builder.AddChatCompletionService(openAiSettings);
41 | //builder.AddChatCompletionService(openAiSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
42 |
43 | // --------------------------------------------------------------------------------------
44 | // Exercise from Virtual Boston Azure for creating a prompt
45 | // --------------------------------------------------------------------------------------
46 |
47 | builder.Plugins.AddFromType();
48 |
49 | Kernel kernel = builder.Build();
50 |
51 | // TODO: CHALLENGE 1: does the AI respond accurately to this prompt? How to fix?
52 | var prompt = $"Tell me an interesting fact from world about an event " +
53 | $"that took place on today's date. " +
54 | $"Be sure to mention the date in history for context.";
55 |
56 | var planner = new FunctionCallingStepwisePlanner(new FunctionCallingStepwisePlannerOptions
57 | {
58 | MaxIterations = 15,
59 | MaxTokens = 2500
60 | });
61 |
62 | var result = await planner.ExecuteAsync(kernel, prompt);
63 |
64 | // Uncomment to see the chat history
65 | //WriteLine($"HISTORY:\n{JsonSerializer.Serialize(result.ChatHistory, new JsonSerializerOptions()
66 | //{
67 | // WriteIndented = true
68 | //})}");
69 |
70 | WriteLine($"\nRESPONSE: \n\n{result.FinalAnswer}");
71 |
72 | }
73 |
74 | static void WriteLine(string message)
75 | {
76 | Console.WriteLine("----------------------------------------------");
77 |
78 | Console.WriteLine(message);
79 |
80 | Console.WriteLine("----------------------------------------------");
81 | }
82 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin1.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Azure.AI.OpenAI;
6 | using OpenTelemetry;
7 | using OpenTelemetry.Metrics;
8 | using OpenTelemetry.Logs;
9 | using HelloWorld.Plugin1.Console.Configuration;
10 |
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | MainAsync(args).Wait();
16 | }
17 |
18 | static async Task MainAsync(string[] args)
19 | {
20 | var config = Configuration.ConfigureAppSettings();
21 |
22 | // Get Settings (all this is just so I don't have hard coded config settings here)
23 | var openAiSettings = new OpenAIOptions();
24 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
25 |
26 | #region OpenTelemetry Logging Provider
27 |
28 | // Uncomment to add OpenTelemetry as a logging provider
29 | //using var meterProvider = Sdk.CreateMeterProviderBuilder()
30 | // .AddMeter("Microsoft.SemanticKernel*")
31 | // .AddConsoleExporter()
32 | // .Build();
33 |
34 | #endregion
35 |
36 | using var loggerFactory = LoggerFactory.Create(builder =>
37 | {
38 | builder.SetMinimumLevel(LogLevel.Trace);
39 |
40 | #region OpenTelemetry Logging Provider
41 |
42 | // Uncomment to add OpenTelemetry as a logging provider
43 | //builder.AddOpenTelemetry(options =>
44 | //{
45 | // options.AddConsoleExporter();
46 | // options.IncludeFormattedMessage = true;
47 | //});
48 |
49 | #endregion
50 |
51 | builder.AddConfiguration(config);
52 | builder.AddConsole();
53 | });
54 |
55 | // Configure Semantic Kernel
56 | var builder = Kernel.CreateBuilder();
57 |
58 | builder.Services.AddSingleton(loggerFactory);
59 | builder.Services.AddChatCompletionService(openAiSettings);
60 |
61 | // --------------------------------------------------------------------------------------
62 | // Exercise from Virtual Boston Azure for creating a prompt
63 | // --------------------------------------------------------------------------------------
64 |
65 | Kernel kernel = builder.Build();
66 |
67 | // output today's date just for fun
68 | var today = DateTime.Now.ToString("MMMM dd");
69 | WriteLine($"Today is {today}");
70 |
71 | // Using a Prompt -----------------------------------------
72 | var prompts = kernel.CreatePluginFromPromptDirectory("Prompts");
73 |
74 | var result = await kernel.InvokeAsync(
75 | prompts["DailyFact"],
76 | new() {
77 | { "today", today },
78 | }
79 | );
80 |
81 | WriteLine($"\nRESPONSE: \n\n{result}");
82 | }
83 |
84 | static void WriteLine(string message)
85 | {
86 | Console.WriteLine("----------------------------------------------");
87 |
88 | Console.WriteLine(message);
89 |
90 | Console.WriteLine("----------------------------------------------");
91 | }
92 | }
--------------------------------------------------------------------------------
/src/HelloWorld.Plugin2.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 | using System.Text.Json;
4 |
5 |
6 | namespace HelloWorld.Plugin2.Console.Configuration;
7 |
8 | internal static class ServiceCollectionExtensions
9 | {
10 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
11 | {
12 | switch (openAIOptions.Source)
13 | {
14 | case "AzureOpenAI":
15 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
16 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
17 | break;
18 |
19 | case "OpenAI":
20 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
21 | break;
22 |
23 | default:
24 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
25 | }
26 |
27 | return serviceCollection;
28 | }
29 | }
30 |
31 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
32 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
33 | {
34 | protected override async Task SendAsync(
35 | HttpRequestMessage request, CancellationToken cancellationToken)
36 | {
37 | if (request.Content is not null)
38 | {
39 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
40 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
41 | new JsonSerializerOptions { WriteIndented = true });
42 | System.Console.WriteLine("Request:");
43 | System.Console.WriteLine(json);
44 | }
45 |
46 | var result = await base.SendAsync(request, cancellationToken);
47 |
48 | if (result.Content is not null)
49 | {
50 | var content = await result.Content.ReadAsStringAsync(cancellationToken);
51 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
52 | new JsonSerializerOptions { WriteIndented = true });
53 | System.Console.WriteLine("Response:");
54 | System.Console.WriteLine(json);
55 | }
56 |
57 | return result;
58 | }
59 | }
60 | public class RequestLoggingHttpClientHandler : HttpClientHandler
61 | {
62 | protected override async Task SendAsync(
63 | HttpRequestMessage request, CancellationToken cancellationToken)
64 | {
65 | if (request.Content is not null)
66 | {
67 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
68 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
69 | new JsonSerializerOptions { WriteIndented = true });
70 | System.Console.WriteLine("Request:");
71 | System.Console.WriteLine(json);
72 | }
73 |
74 | return await base.SendAsync(request, cancellationToken);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Utilities.cs:
--------------------------------------------------------------------------------
1 | using System.Security.Cryptography;
2 | using System.Text;
3 | using System.Text.RegularExpressions;
4 |
5 | namespace PropertyGraph.Common;
6 |
7 | public class Utilities
8 | {
9 | public static string CreateId(string text)
10 | {
11 | using (SHA1 sha1 = SHA1.Create())
12 | {
13 | byte[] inputBytes = Encoding.UTF8.GetBytes(text);
14 | byte[] hashBytes = sha1.ComputeHash(inputBytes);
15 | StringBuilder sb = new StringBuilder();
16 | for (int i = 0; i < hashBytes.Length; i++)
17 | {
18 | sb.Append(hashBytes[i].ToString("X2").ToLower());
19 | }
20 | return sb.ToString();
21 | }
22 | }
23 | public static EntityMetadata PopulateEntityMetadata(ChunkMetadata chunkMetadata, TripletRow triplet, EntityMetadata entityMetadata, bool isHead = true)
24 | {
25 | if (isHead)
26 | {
27 | entityMetadata.name = CreateName(triplet.head);
28 | entityMetadata.type = triplet.head_type;
29 | entityMetadata.text = triplet.head;
30 | }
31 | else
32 | {
33 | entityMetadata.name = CreateName(triplet.tail);
34 | entityMetadata.type = triplet.tail_type;
35 | entityMetadata.text = triplet.tail;
36 | }
37 |
38 | entityMetadata.id = CreateId(entityMetadata.name);
39 | entityMetadata.mentionedInChunks.Add(chunkMetadata.id, chunkMetadata);
40 |
41 | return entityMetadata;
42 | }
43 |
44 | public static string CreateName(string text)
45 | {
46 | if (string.IsNullOrEmpty(text))
47 | return text;
48 |
49 | // Split the text into words
50 | string[] words = text.Split(new[] { ' ', '-', '_' }, StringSplitOptions.RemoveEmptyEntries);
51 |
52 | StringBuilder nameText = new StringBuilder();
53 |
54 | foreach (string word in words)
55 | {
56 | // Capitalize the first letter and make the rest lowercase
57 | var lword = word;
58 | if (char.IsDigit(word[0]))
59 | {
60 | lword = "_" + word;
61 | }
62 |
63 | nameText.Append(lword.ToLower());
64 | }
65 | var textOnly = Regex.Replace(nameText.ToString(), "[^a-zA-Z0-9_]", "");
66 | if (char.IsDigit(textOnly[0]))
67 | {
68 | textOnly = "_" + textOnly;
69 | }
70 | return textOnly;
71 | }
72 |
73 | public static List SplitPlainTextOnEmptyLine(string[] lines)
74 | {
75 | List allLines = new List(lines);
76 | List result = new List();
77 |
78 | // Make sure there is an empty string as last line to split into paragraph
79 | var last = allLines.Last();
80 | if (last.Length > 0)
81 | {
82 | allLines.Add("");
83 | }
84 |
85 | StringBuilder paragraphBuilder = new StringBuilder();
86 | foreach (string input in allLines)
87 | {
88 | if (input.Length == 0)
89 | {
90 | result.Add(paragraphBuilder.ToString());
91 | paragraphBuilder.Clear();
92 | }
93 | paragraphBuilder.Append($"{input} ");
94 | }
95 |
96 | return result;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/TextToSql.Console.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | SKEXP0001,SKEXP0010,SKEXP0110,SKEXP0050
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Always
27 |
28 |
29 | Always
30 |
31 |
32 | Always
33 |
34 |
35 | Always
36 |
37 |
38 | Always
39 |
40 |
41 | Always
42 |
43 |
44 | Always
45 |
46 |
47 | Always
48 |
49 |
50 | Always
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Semantic Kernel
2 |
3 | This repository contains the source code for serveral blog posts and presentations I have given in 2024. Most are available in the [semantic-kernel listing on my blog](https://jasonhaley.com/tags/semantic-kernel/)
4 |
5 | ## Blog Entries
6 | I have a couple of blog series that include Semantic Kernel.
7 |
8 | ### Semantic Kernel Hello World (Blog Series)
9 | This series is about individual features of Semantic Kernel. The source code is supposed to be reusable source code for future projects.
10 |
11 | #### [Semantic Kernel Hello World](https://jasonhaley.com/2024/03/30/semantic-kernel-hello-world/)
12 | (*March 30, 2024*) This is a very simple walk through of using Semantic Kernel to call an OpenAI chat completion endpoint.
13 |
14 | #### [Semantic Kernel Hello World Plugins Part 1](https://jasonhaley.com/2024/04/11/semantic-kernel-hello-world-plugin-part1/)
15 | (*April 11, 2024*) This walks through creating prompts in text files and using them with Semantic Kernel.
16 |
17 | #### [Semantic Kernel Hello World Plugins Part 2](https://jasonhaley.com/2024/04/26/semantic-kernel-hello-world-plugin-part2/)
18 | (*April 26, 2024*) This is about Native Functions in Semantic Kernel and converts the previous prompt into a native function.
19 |
20 | #### [Semantic Kernel Hello World Plugins Part 3](https://jasonhaley.com/2024/04/30/semantic-kernel-hello-world-plugin-part3/)
21 | (*April 30, 2024*) This builds on the native function entry and extends it to use Open AI function calling.
22 |
23 | #### [Semantic Kernel Hello World Planners Part 1](https://jasonhaley.com/2024/05/19/semantic-kernel-hello-world-planners-part1/)
24 | (*May 19, 2024*) This moves the same sample to using the Handlebars planner and analyzes what it does.
25 |
26 | #### [Semantic Kernel Hello World Planners Part 2](https://jasonhaley.com/2024/05/27/semantic-kernel-hello-world-planners-part2/)
27 | (*May 27, 2024*) This takes the same approach as the previous blog entry but uses the Function Calling Stepwise Planner.
28 |
29 | #### [Semantic Kernel Hello World WebSearchEnginePlugin](https://jasonhaley.com/2024/06/10/semantic-kernel-hello-world-websearchengineplugin/)
30 | (*June 10, 2024*) This takes a look at the usefulness of incorporating the ability to have the LLM call Bing search.
31 |
32 | ### Study Notes (Blog Series)
33 | This series is where I am putting resource created from specific topics like text-to-sql and graph RAG.
34 |
35 | #### [Study Notes: Text-to-SQL](https://jasonhaley.com/2024/07/05/study-notes-text-to-sql/)
36 | (*July 5, 2024*) This is the post describing what I learned focusing on Text-to-Sql for a week.
37 |
38 | #### [Study Notes: Text-to-SQL Code Sample](https://jasonhaley.com/2024/07/06/study-notes-text-to-sql-code-sample/)
39 | (*July 6, 2024*) This is the post about code that I put together to demonstrate how Text-to-Sql works.
40 |
41 | #### [Study Notes: Graph RAG - Property Graph RAG](https://jasonhaley.com/2024/08/05/study-notes-graph-rag1/)
42 | (*August 5, 2024*) This is the post describing what I learned focusing on graph RAG (specifically property graph RAG).
43 |
44 | #### [Study Notes: Graph RAG - Property Graph RAG (The Notebook)](https://jasonhaley.com/2024/08/06/study-notes-graph-rag1-code-sample-notebook/)
45 | (*August 6, 2024*) This is about the C# notebook I put together to highlight the steps and demonstrate property graph RAG.
46 |
47 | #### [Study Notes: Graph RAG - Property Graph RAG (The Projects)](https://jasonhaley.com/2024/08/16/study-notes-graph-rag1-code-sample-projects/)
48 | (*August 16, 2024*) This is about the C# projects I created for the ingestion and retrieval functionality of a property graph RAG system.
49 |
50 | ## Presentations
51 |
52 | #### [Boston Azure June 2024](https://jasonhaley.com/2024/06/25/boston-azure-june-2024/)
53 | (*June 25, 2024*) This highlights the demo code I used in the in person (no recording) Boston Azure meeting in June.
54 |
--------------------------------------------------------------------------------
/src/HelloWorld.Console/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using Microsoft.SemanticKernel.Connectors.OpenAI;
6 | using Microsoft.SemanticKernel.ChatCompletion;
7 | using OpenTelemetry.Metrics;
8 | using OpenTelemetry.Logs;
9 | using HelloWorld.Console.Configuration;
10 |
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | MainAsync(args).Wait();
16 | }
17 |
18 | static async Task MainAsync(string[] args)
19 | {
20 | var config = Configuration.ConfigureAppSettings();
21 |
22 | // Get Settings (all this is just so I don't have hard coded config settings here)
23 | var openAiSettings = new OpenAIOptions();
24 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
25 |
26 | #region OpenTelemetry Logging Provider
27 |
28 | //// Uncomment to add OpenTelemetry as a logging provider
29 | //using var meterProvider = Sdk.CreateMeterProviderBuilder()
30 | // .AddMeter("Microsoft.SemanticKernel*")
31 | // .AddConsoleExporter()
32 | // .Build();
33 |
34 | #endregion
35 |
36 | using var loggerFactory = LoggerFactory.Create(builder =>
37 | {
38 | builder.SetMinimumLevel(LogLevel.Information);
39 |
40 | #region OpenTelemetry Logging Provider
41 |
42 | // Uncomment to add OpenTelemetry as a logging provider
43 | //builder.AddOpenTelemetry(options =>
44 | //{
45 | // options.AddConsoleExporter();
46 | // options.IncludeFormattedMessage = true;
47 | //});
48 |
49 | #endregion
50 |
51 | builder.AddConfiguration(config);
52 | builder.AddConsole();
53 | });
54 |
55 | // Configure Semantic Kernel
56 | var builder = Kernel.CreateBuilder();
57 |
58 | builder.Services.AddSingleton(loggerFactory);
59 | builder.Services.AddChatCompletionService(openAiSettings);
60 |
61 | Kernel kernel = builder.Build();
62 |
63 | // --------------------------------------------------------------------------------------
64 | // Exercise from Virtual Boston Azure for creating a prompt
65 | // --------------------------------------------------------------------------------------
66 |
67 | // output today's date just for fun
68 | WriteLine($"\n----------------- DEBUG INFO -----------------");
69 | var today = DateTime.Now.ToString("MMMM dd");
70 | WriteLine($"Today is {today}");
71 | WriteLine("----------------------------------------------");
72 |
73 | IChatCompletionService chatCompletionService = kernel.GetRequiredService();
74 |
75 | // TODO: CHALLENGE 1: does the AI respond accurately to this prompt? How to fix?
76 | var prompt = $"Tell me an interesting fact from world about an event " +
77 | $"that took place on {today}. " +
78 | $"Be sure to mention the date in history for context.";
79 |
80 | OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
81 | {
82 | Temperature = 0.7f,
83 | MaxTokens = 250
84 | };
85 |
86 | var result = await chatCompletionService.GetChatMessageContentsAsync(prompt, openAIPromptExecutionSettings, kernel);
87 |
88 | WriteLine($"\nPROMPT: \n\n{prompt}");
89 |
90 | // Write out the result
91 | foreach (var content in result)
92 | {
93 | WriteLine($"\nRESPONSE:\n{content}");
94 | }
95 | }
96 |
97 | static void WriteLine(string message)
98 | {
99 | var currentColor = Console.ForegroundColor;
100 | Console.ForegroundColor = ConsoleColor.Green;
101 |
102 | Console.WriteLine(message);
103 |
104 | Console.ForegroundColor = currentColor;
105 | }
106 | }
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/TextToSql.Console/Nl2Sql/SqlScemaLoader.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Data.SqlClient;
2 | using Microsoft.Extensions.Configuration;
3 | using SemanticKernel.Data.Nl2Sql.Harness;
4 | using TextToSql.Console.Configuration;
5 | using SemanticKernel.Data.Nl2Sql.Library.Schema;
6 | using Microsoft.SemanticKernel.Memory;
7 |
8 | namespace TextToSql.Console.Nl2Sql;
9 | internal class SqlScemaLoader
10 | {
11 | private readonly IConfiguration _configuration;
12 | private TextToSqlOptions _textToSqlOptions = new TextToSqlOptions();
13 | private readonly Dictionary _sqlSchemaOptionsMap = new Dictionary();
14 | public SqlScemaLoader(IConfiguration confuration)
15 | {
16 | _configuration = confuration;
17 | Initialize();
18 | }
19 |
20 | public IList SchemaNames { get { return _textToSqlOptions.SchemaNames.Split(','); } }
21 | public double MinSchemaRelevance { get { return _textToSqlOptions.MinSchemaRelevance; } }
22 |
23 | private void Initialize()
24 | {
25 | _configuration.GetSection(TextToSqlOptions.TextToSqlConfig).Bind(_textToSqlOptions);
26 | if (!string.IsNullOrEmpty(_textToSqlOptions.SchemaNames))
27 | {
28 | foreach (var name in SchemaNames)
29 | {
30 | var schema = new SqlSchemaOptions();
31 | _configuration.GetSection(name).Bind(schema);
32 | _sqlSchemaOptionsMap.Add(name, schema);
33 | }
34 | }
35 | }
36 |
37 | private bool HasSchemas()
38 | {
39 | return _sqlSchemaOptionsMap.Count > 0;
40 | }
41 |
42 | private bool SchemeFileExists(string schemaName)
43 | {
44 | // If the database schema doesn't exist, the create one
45 | var schemaFile = $"{schemaName}.json";
46 | return File.Exists(schemaFile);
47 | }
48 |
49 | private async Task CreateSchemaFileAsync(string schemaName, SqlSchemaOptions options)
50 | {
51 | // If there is no ConnectionString, messages and exit
52 | var connectionString = GetConnectionString(schemaName);
53 | if (string.IsNullOrEmpty(connectionString))
54 | {
55 | System.Console.WriteLine($"Please add a connection string for {schemaName} in the appsettings.json file before running");
56 | return false;
57 | }
58 |
59 | // Connect to database and create schema
60 | using (var connection = new SqlConnection(connectionString))
61 | {
62 | await connection.OpenAsync().ConfigureAwait(false);
63 | var provider = new SqlSchemaProvider(connection);
64 |
65 | SchemaDefinition schemaDef;
66 | string[] tableNames;
67 | if (options.Tables != null)
68 | {
69 | tableNames = options.Tables.Split(',');
70 | schemaDef = await provider.GetSchemaAsync(schemaName, options.Description, tableNames).ConfigureAwait(false);
71 | }
72 | else
73 | {
74 | schemaDef = await provider.GetSchemaAsync(schemaName, options.Description).ConfigureAwait(false);
75 | }
76 |
77 | await connection.CloseAsync().ConfigureAwait(false);
78 |
79 | using var streamCompact = new StreamWriter(
80 | $"{schemaName}.json",
81 | new FileStreamOptions
82 | {
83 | Access = FileAccess.Write,
84 | Mode = FileMode.Create,
85 | });
86 |
87 | await streamCompact.WriteAsync(schemaDef.ToJson()).ConfigureAwait(false);
88 | }
89 | return true;
90 | }
91 |
92 | public string GetConnectionString(string schemaName)
93 | {
94 | return _configuration.GetConnectionString(schemaName) ?? "";
95 | }
96 | public async Task TryLoadAsync(ISemanticTextMemory memory)
97 | {
98 | if (!HasSchemas())
99 | {
100 | System.Console.WriteLine("No schemas configured in appsettings.json");
101 | return false;
102 | }
103 |
104 | foreach (var schema in _sqlSchemaOptionsMap.Keys)
105 | {
106 | if (!SchemeFileExists(schema))
107 | {
108 | await CreateSchemaFileAsync(schema, _sqlSchemaOptionsMap[schema]);
109 | }
110 | }
111 |
112 | await SchemaProvider.InitializeAsync(memory, _sqlSchemaOptionsMap.Keys.Select(s => $"{s}.json")).ConfigureAwait(false);
113 |
114 | return true;
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/src/HelloWorld.Agent1.Console/BingConnector2.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System.Text.Json;
4 | using Microsoft.Extensions.Logging;
5 | using Microsoft.Extensions.Logging.Abstractions;
6 |
7 | namespace Microsoft.SemanticKernel.Plugins.Web.Bing;
8 |
9 | ///
10 | /// Bing API connector2.
11 | ///
12 | public sealed class BingConnector2: IWebSearchEngineConnector
13 | {
14 | private readonly ILogger _logger;
15 | private readonly HttpClient _httpClient;
16 | private readonly string? _apiKey;
17 | private readonly Uri? _uri = null;
18 | private const string DefaultUri = "https://api.bing.microsoft.com/v7.0/search?q";
19 |
20 | ///
21 | /// Initializes a new instance of the class.
22 | ///
23 | /// The API key to authenticate the connector.
24 | /// The HTTP client to use for making requests.
25 | /// The URI of the Bing Search instance. Defaults to "https://api.bing.microsoft.com/v7.0/search?q".
26 | /// The to use for logging. If null, no logging will be performed.
27 | public BingConnector2(string apiKey, HttpClient httpClient, Uri? uri = null, ILoggerFactory? loggerFactory = null)
28 | {
29 |
30 | this._apiKey = apiKey;
31 | this._logger = loggerFactory?.CreateLogger(typeof(BingConnector)) ?? NullLogger.Instance;
32 | this._httpClient = httpClient;
33 | this._uri = uri ?? new Uri(DefaultUri);
34 | }
35 |
36 | ///
37 | public async Task> SearchAsync(string query, int count = 1, int offset = 0, CancellationToken cancellationToken = default)
38 | {
39 | if (count is <= 0 or >= 50)
40 | {
41 | throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} value must be greater than 0 and less than 50.");
42 | }
43 |
44 | Uri uri = new($"{this._uri}={Uri.EscapeDataString(query.Trim())}&count={count}&offset={offset}");
45 |
46 | this._logger.LogDebug("Sending request: {Uri}", uri);
47 |
48 | using HttpResponseMessage response = await this.SendGetRequestAsync(uri, cancellationToken).ConfigureAwait(false);
49 |
50 | this._logger.LogDebug("Response received: {StatusCode}", response.StatusCode);
51 |
52 | string json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
53 |
54 | // Sensitive data, logging as trace, disabled by default
55 | this._logger.LogTrace("Response content received: {Data}", json);
56 |
57 | WebSearchResponse? data = JsonSerializer.Deserialize(json);
58 |
59 | List? returnValues = null;
60 | if (data?.WebPages?.Value is not null)
61 | {
62 | if (typeof(T) == typeof(string))
63 | {
64 | WebPage[]? results = data?.WebPages?.Value;
65 | var item = results?.GetRandomItem();
66 | returnValues = new string[] { @$"Source URL: {item?.Url}
67 | {item?.Snippet}" }.ToList() as List;
68 | }
69 | else if (typeof(T) == typeof(WebPage))
70 | {
71 | List? webPages = [.. data.WebPages.Value];
72 | returnValues = webPages.Take(count).ToList() as List;
73 | }
74 | else
75 | {
76 | throw new NotSupportedException($"Type {typeof(T)} is not supported.");
77 | }
78 | }
79 |
80 | return
81 | returnValues is null ? [] :
82 | returnValues.Count <= count ? returnValues :
83 | returnValues.Take(count);
84 | }
85 |
86 | ///
87 | /// Sends a GET request to the specified URI.
88 | ///
89 | /// The URI to send the request to.
90 | /// A cancellation token to cancel the request.
91 | /// A representing the response from the request.
92 | private async Task SendGetRequestAsync(Uri uri, CancellationToken cancellationToken = default)
93 | {
94 | using var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
95 |
96 | if (!string.IsNullOrEmpty(this._apiKey))
97 | {
98 | httpRequestMessage.Headers.Add("Ocp-Apim-Subscription-Key", this._apiKey);
99 | }
100 |
101 | return await this._httpClient.SendAsync(httpRequestMessage, cancellationToken).ConfigureAwait(false);
102 | }
103 | }
104 | public static class EnumerableExtensions
105 | {
106 | private static readonly Random _random = new Random();
107 |
108 | public static T GetRandomItem(this IEnumerable source)
109 | {
110 | if (source == null)
111 | {
112 | throw new ArgumentNullException(nameof(source));
113 | }
114 |
115 | var list = source.ToList();
116 | if (!list.Any())
117 | {
118 | throw new InvalidOperationException("Sequence contains no elements");
119 | }
120 |
121 | int randomIndex = _random.Next(list.Count);
122 | return list[randomIndex];
123 | }
124 | }
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphRAG/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.Extensions.Logging;
3 | using Microsoft.SemanticKernel;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using PropertyGraph.Common;
6 | using Microsoft.SemanticKernel.ChatCompletion;
7 |
8 | internal class Program
9 | {
10 | private static string[] TEST_MESSAGES = new string[]
11 | {
12 | "What does Jason blog about?",
13 | "How many blogs has he written?",
14 | "How many blogs has Jason written?",
15 | "What blogs has Jason written?",
16 | "What has he written about Java?",
17 | "How about Python?",
18 | "What presentations has he given?",
19 | "Are all his blogs about AI in some way?",
20 | "What do you know about Code Camp?",
21 | "What has Jason mentioned about Boston Azure?",
22 | "Which blogs are about Semantic Kernel?",
23 | "What blogs are about LangChain?",
24 | };
25 |
26 | static void Main(string[] args)
27 | {
28 | MainAsync(args).Wait();
29 | }
30 |
31 | static async Task MainAsync(string[] args)
32 | {
33 | var config = Configuration.ConfigureAppSettings();
34 |
35 | // Get Settings (all this is just so I don't have hard coded config settings here)
36 | var openAiSettings = new OpenAIOptions();
37 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
38 |
39 | var neo4jSettings = new Neo4jOptions();
40 | config.GetSection(Neo4jOptions.Neo4j).Bind(neo4jSettings);
41 |
42 | var propertyGraphSettings = new PropertyGraphOptions();
43 | config.GetSection(PropertyGraphOptions.PropertyGraph).Bind(propertyGraphSettings);
44 |
45 | using var loggerFactory = LoggerFactory.Create(builder =>
46 | {
47 | builder.SetMinimumLevel(LogLevel.Warning);
48 |
49 | builder.AddConfiguration(config);
50 | builder.AddConsole();
51 | });
52 |
53 | // Configure Semantic Kernel
54 | var builder = Kernel.CreateBuilder();
55 |
56 | builder.Services.AddSingleton(loggerFactory);
57 | builder.AddChatCompletionService(openAiSettings);
58 | //builder.AddChatCompletionService(openAiSettings, ApiLoggingLevel.ResponseAndRequest); // use this line to see the JSON between SK and OpenAI
59 |
60 | Kernel kernel = builder.Build();
61 |
62 | var appOptions = new DefaultOptions(kernel, openAiSettings, neo4jSettings, propertyGraphSettings, loggerFactory);
63 |
64 | ChatHistory chatHistory = new ChatHistory();
65 | PropertyGraphRetriever graphRAGRetriever = new PropertyGraphRetriever(appOptions);
66 | while (true)
67 | {
68 | Console.WriteLine("Enter User Message:");
69 | Console.WriteLine("");
70 |
71 | string? userMessage = Console.ReadLine();
72 | if (string.IsNullOrEmpty(userMessage) || userMessage.ToLower() == "exit")
73 | {
74 | return;
75 | }
76 |
77 | if (userMessage.ToLower() == "run tests")
78 | {
79 | await RunTestMessagesInLoop(chatHistory, graphRAGRetriever);
80 | return;
81 | }
82 |
83 | if (userMessage.ToLower() == "clear")
84 | {
85 | chatHistory.Clear();
86 | continue;
87 | }
88 |
89 | if (userMessage.ToLower().StartsWith("raw:"))
90 | {
91 | userMessage = userMessage.Substring(4);
92 |
93 | Console.WriteLine(userMessage);
94 | chatHistory.AddUserMessage(userMessage);
95 | await foreach (var update in kernel.InvokePromptStreamingAsync(userMessage))
96 | {
97 | Console.Write(update);
98 | }
99 | }
100 | else
101 | {
102 | chatHistory.AddUserMessage(userMessage);
103 | await foreach (StreamingKernelContent update in chatHistory.AddStreamingMessageAsync(await graphRAGRetriever.RetrieveAsync(userMessage)))
104 | {
105 | Console.Write(update);
106 | }
107 | }
108 |
109 | Console.WriteLine("");
110 | Console.WriteLine("");
111 | }
112 | }
113 |
114 | private static async Task RunTestMessagesInLoop(ChatHistory chatHistory, PropertyGraphRetriever graphRAGRetriever)
115 | {
116 |
117 | foreach (var userMessage in TEST_MESSAGES)
118 | {
119 | Console.WriteLine(userMessage);
120 | chatHistory.AddUserMessage(userMessage);
121 | await foreach (StreamingKernelContent update in chatHistory.AddStreamingMessageAsync(await graphRAGRetriever.RetrieveAsync(userMessage)))
122 | {
123 | Console.Write(update);
124 | }
125 |
126 | Console.WriteLine("");
127 | Console.WriteLine("");
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraphIngestor/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
3 | using Microsoft.Extensions.FileSystemGlobbing;
4 | using Microsoft.Extensions.Logging;
5 | using System.CommandLine;
6 | using Microsoft.SemanticKernel;
7 | using Microsoft.Extensions.DependencyInjection;
8 | using PropertyGraph.Common;
9 | using static CommandOptions;
10 |
11 | internal class Program
12 | {
13 | static void Main(string[] args)
14 | {
15 | MainAsync(args).Wait();
16 | }
17 |
18 | static async Task MainAsync(string[] args)
19 | {
20 | var config = Configuration.ConfigureAppSettings();
21 |
22 | // Get Settings (all this is just so I don't have hard coded config settings here)
23 | var openAiSettings = new OpenAIOptions();
24 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
25 |
26 | var neo4jSettings = new Neo4jOptions();
27 | config.GetSection(Neo4jOptions.Neo4j).Bind(neo4jSettings);
28 |
29 | var propertyGraphSettings = new PropertyGraphOptions();
30 | config.GetSection(PropertyGraphOptions.PropertyGraph).Bind(propertyGraphSettings);
31 |
32 | using var loggerFactory = LoggerFactory.Create(builder =>
33 | {
34 | builder.SetMinimumLevel(LogLevel.Trace);
35 |
36 | builder.AddConfiguration(config);
37 | builder.AddConsole();
38 | });
39 |
40 | // Configure Semantic Kernel
41 | var builder = Kernel.CreateBuilder();
42 |
43 | builder.Services.AddSingleton(loggerFactory);
44 | builder.Services.AddChatCompletionService(openAiSettings);
45 |
46 | Kernel kernel = builder.Build();
47 |
48 | var rootCommand = CommandOptions.RootCommand;
49 |
50 | rootCommand.SetHandler(
51 | async (context) =>
52 | {
53 | AppOptions options = CommandOptions.GetParsedAppOptions(context, kernel, openAiSettings, neo4jSettings, propertyGraphSettings, loggerFactory);
54 | if (options.RemoveAll)
55 | {
56 | await RemoveAllNodes(options);
57 | }
58 | else
59 | {
60 | Matcher matcher = new();
61 | matcher.AddInclude(options.Files);
62 |
63 | var results = matcher.Execute(
64 | new DirectoryInfoWrapper(
65 | new DirectoryInfo(Directory.GetCurrentDirectory())));
66 |
67 | var files = results.HasMatches
68 | ? results.Files.Select(f => f.Path).ToArray()
69 | : Array.Empty();
70 |
71 | context.Console.WriteLine($"Processing {files.Length} files...");
72 |
73 | var tasks = Enumerable.Range(0, files.Length)
74 | .Select(i =>
75 | {
76 | var fileName = files[i];
77 | return ProcessSingleFileAsync(options, fileName);
78 | });
79 |
80 | await Task.WhenAll(tasks);
81 | }
82 |
83 | Console.WriteLine("Done.");
84 | });
85 | return await rootCommand.InvokeAsync(args);
86 | }
87 |
88 | static async Task ProcessSingleFileAsync(AppOptions options, string fileName)
89 | {
90 | if (options.Verbose)
91 | {
92 | options.Console.WriteLine($"Processing '{fileName}'");
93 | }
94 |
95 | var service = new Neo4jService(options);
96 |
97 | if (options.Remove)
98 | {
99 | Console.WriteLine($"Are you sure you want to remove all nodes connected to '{fileName}'? Y/N");
100 | Console.WriteLine("");
101 |
102 | var response = Console.ReadLine();
103 | if (response != null && response.ToLower() == "y")
104 | {
105 | await service.RemoveNodesWithSource(fileName);
106 |
107 | options.Console.WriteLine($"Nodes connected to '{fileName}' removed");
108 | }
109 | return;
110 | }
111 |
112 | await service.PopulateGraphFromDocumentAsync(fileName);
113 |
114 | if (options.Verbose)
115 | {
116 | // TODO: Add stopwatch timings
117 | options.Console.WriteLine($"'{fileName}' processing complete");
118 | }
119 | }
120 |
121 | static async Task RemoveAllNodes(AppOptions options)
122 | {
123 | var service = new Neo4jService(options);
124 | var counts = await service.GetAllNodesAndRelationshipsCountsAsync();
125 |
126 | Console.WriteLine($"There are {counts.Item1} nodes and {counts.Item2} relationships in the database.");
127 | Console.WriteLine("");
128 | Console.WriteLine("Are you sure you want to remove all nodes? Y/N");
129 | Console.WriteLine("");
130 | var response = Console.ReadLine();
131 | if (response != null && response.ToLower() == "y")
132 | {
133 | await service.RemoveAllNodesAsync();
134 | }
135 | }
136 |
137 | }
--------------------------------------------------------------------------------
/samples/demos/QueryRewrite/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Configuration;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.Extensions.Logging;
4 | using Microsoft.Extensions.DependencyInjection;
5 | using OpenTelemetry.Metrics;
6 | using OpenTelemetry.Logs;
7 | using HelloWorld.Plugin.Console.Plugins;
8 | using HelloWorld.Plugin2.Console.Configuration;
9 | using Microsoft.SemanticKernel.Connectors.OpenAI;
10 | using Microsoft.SemanticKernel.ChatCompletion;
11 | using HandlebarsDotNet;
12 | using Microsoft.SemanticKernel.Embeddings;
13 | using Microsoft.SemanticKernel.Text;
14 | using System.ComponentModel;
15 | using System.Text.Json;
16 |
17 | internal class Program
18 | {
19 | private static string[] TEST_MESSAGES = new string[]
20 | {
21 | "What does Jason blog about?",
22 | "How many blogs has he written?",
23 | "How many blogs has Jason written?",
24 | "What blogs has Jason written?",
25 | "What has he written about Java?",
26 | "How about Python?",
27 | "What presentations has he given?",
28 | "Are all his blogs about AI in some way?",
29 | "What do you know about Code Camp?",
30 | "What has Jason mentioned about Boston Azure?",
31 | "Which blogs are about Semantic Kernel?",
32 | "What blogs are about LangChain?",
33 | };
34 | static void Main(string[] args)
35 | {
36 | MainAsync(args).Wait();
37 | }
38 |
39 | static async Task MainAsync(string[] args)
40 | {
41 | var config = Configuration.ConfigureAppSettings();
42 |
43 | // Get Settings (all this is just so I don't have hard coded config settings here)
44 | var openAiSettings = new OpenAIOptions();
45 | config.GetSection(OpenAIOptions.OpenAI).Bind(openAiSettings);
46 |
47 | using var loggerFactory = LoggerFactory.Create(builder =>
48 | {
49 | builder.SetMinimumLevel(LogLevel.Warning);
50 |
51 | builder.AddConfiguration(config);
52 | builder.AddConsole();
53 | });
54 |
55 | // Configure Semantic Kernel
56 | var builder = Kernel.CreateBuilder();
57 |
58 | builder.Services.AddSingleton(loggerFactory);
59 | builder.AddChatCompletionService(config.GetConnectionString("OpenAI"));
60 | //builder.AddChatCompletionService(config.GetConnectionString("OpenAI"), ApiLoggingLevel.RequestOnly); // use this line to see the JSON between SK and OpenAI);
61 |
62 | builder.Plugins.AddFromType();
63 |
64 | OpenAIPromptExecutionSettings settings = new()
65 | {
66 | ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions,
67 | Temperature = 0.0f
68 | };
69 |
70 | //var tools = new AssistantTools();
71 |
72 | Kernel kernel = builder.Build();
73 | //kernel.Plugins.AddFromObject(tools);
74 |
75 | IChatCompletionService chat = kernel.GetRequiredService();
76 |
77 | var sysMessage = @"Below is a history of the conversation so far, and a new question asked by the user that needs to be answered by searching a retriever system.
78 | Generate a search query based on the conversation and the new question.
79 | If you cannot generate a search query, return the original user question.
80 | DO NOT return anything besides the query.";
81 |
82 | ChatHistory chatHistory = new ChatHistory(sysMessage);
83 | chatHistory.AddUserMessage("What does Jason blog about?");
84 | chatHistory.AddAssistantMessage("Jason blogs about xyz.");
85 | chatHistory.AddUserMessage("What is the name of his blog?");
86 | chatHistory.AddAssistantMessage("Jason's blog is named blog.");
87 | chatHistory.AddUserMessage("Does he blog often?");
88 | chatHistory.AddAssistantMessage("Yes Jason blogs 2 or 3 times a month.");
89 | //while (true)
90 | //{
91 | //Console.WriteLine("Enter User Message:");
92 | //Console.WriteLine("");
93 |
94 | //string? userMessage = Console.ReadLine();
95 | //if (string.IsNullOrEmpty(userMessage) || userMessage.ToLower() == "exit")
96 | //{
97 | // return;
98 | //}
99 |
100 | //if (userMessage.ToLower() == "clear")
101 | //{
102 | // chatHistory.Clear();
103 | // continue;
104 | //}
105 |
106 | //chatHistory.AddUserMessage(userMessage);
107 | foreach (var userMessage in TEST_MESSAGES)
108 | {
109 | Console.WriteLine(userMessage);
110 | chatHistory.AddUserMessage(userMessage);
111 | await foreach (StreamingKernelContent update in chat.GetStreamingChatMessageContentsAsync(chatHistory, settings, kernel))
112 | {
113 | Console.Write(update);
114 |
115 | var json = JsonSerializer.Serialize(chatHistory, new JsonSerializerOptions { WriteIndented = true });
116 | Console.WriteLine(json);
117 | }
118 |
119 | Console.WriteLine("");
120 | Console.WriteLine("");
121 | }
122 | //await foreach (StreamingKernelContent update in chat.GetStreamingChatMessageContentsAsync(chatHistory, settings, kernel))
123 | //{
124 | // Console.Write(update);
125 | //}
126 |
127 | Console.WriteLine("");
128 | Console.WriteLine("");
129 | //}
130 |
131 | }
132 |
133 | public class AssistantTools
134 | {
135 | [KernelFunction, Description("Provides answers to questions about blogs.")]
136 | public async Task SearchAsync([Description("User query")] string query)
137 | {
138 | return await Task.FromResult(query);
139 | }
140 | }
141 | }
--------------------------------------------------------------------------------
/samples/demos/Text-to-Sql/nl2sql.library/SqlQueryGenerator.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved.
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Security.AccessControl;
8 | using System.Text.Json;
9 | using System.Threading.Tasks;
10 | using Microsoft.SemanticKernel;
11 | using Microsoft.SemanticKernel.Memory;
12 | using SemanticKernel.Data.Nl2Sql.Library.Internal;
13 | using SemanticKernel.Data.Nl2Sql.Library.Schema;
14 |
15 | namespace SemanticKernel.Data.Nl2Sql.Library;
16 |
17 | ///
18 | /// Generate SQL query targeting Microsoft SQL Server.
19 | ///
20 | public sealed class SqlQueryGenerator
21 | {
22 | public const double DefaultMinRelevance = 0.7D;
23 |
24 | public const string ContextParamObjective = "data_objective";
25 | public const string ContextParamSchema = "data_schema";
26 | public const string ContextParamSchemaId = "data_schema_id";
27 | public const string ContextParamQuery = "data_query";
28 | public const string ContextParamPlatform = "data_platform";
29 | public const string ContextParamResult = "data_result";
30 | public const string ContextParamError = "data_error";
31 |
32 | private const string ContentLabelQuery = "sql";
33 | private const string ContentLabelAnswer = "answer";
34 | private const string ContentAffirmative = "yes";
35 |
36 | private readonly double _minRelevanceScore;
37 | private readonly KernelFunction _promptEval;
38 | private readonly KernelFunction _promptGenerator;
39 | private readonly KernelFunction _promptResultEval;
40 | private readonly KernelFunction _promptDescribeResults;
41 | private readonly Kernel _kernel;
42 | private readonly ISemanticTextMemory _memory;
43 |
44 | public SqlQueryGenerator(
45 | Kernel kernel,
46 | ISemanticTextMemory memory,
47 | double minRelevanceScore = DefaultMinRelevance)
48 | {
49 | var prompts = kernel.CreatePluginFromPromptDirectory("Prompts");
50 |
51 | this._promptEval = prompts["EvaluateIntent"];
52 | this._promptGenerator = prompts["SqlGenerate"];
53 | this._promptResultEval = prompts["EvaluateResult"];
54 | this._promptDescribeResults = prompts["DescribeResults"];
55 | this._kernel = kernel;
56 | this._memory = memory;
57 | this._minRelevanceScore = minRelevanceScore;
58 | }
59 |
60 | ///
61 | /// Attempt to produce a query for the given objective based on the registered schemas.
62 | ///
63 | /// A natural language objective
64 | /// A object
65 | /// A SQL query (or null if not able)
66 | public async Task SolveObjectiveAsync(string objective)
67 | {
68 | // Search for schema with best similarity match to the objective
69 | var recall =
70 | await this._memory.SearchAsync(
71 | SchemaProvider.MemoryCollectionName,
72 | objective,
73 | limit: 1, // Take top result with maximum relevance (> minRelevanceScore)
74 | minRelevanceScore: this._minRelevanceScore,
75 | withEmbeddings: true).ToArrayAsync().ConfigureAwait(false);
76 |
77 | var best = recall.FirstOrDefault();
78 | if (best == null)
79 | {
80 | return null; // No schema / no query
81 | }
82 |
83 | var schemaName = best.Metadata.Id;
84 | var schemaText = best.Metadata.Text;
85 |
86 | var arguments = new KernelArguments();
87 | arguments[ContextParamSchema] = schemaText;
88 | arguments[ContextParamObjective] = objective;
89 |
90 | // Screen objective to determine if it can be solved with the selected schema.
91 | if (!await this.ScreenObjectiveAsync(arguments).ConfigureAwait(false))
92 | {
93 | return null; // Objective doesn't pass screen
94 | }
95 |
96 | var sqlPlatform = best.Metadata.AdditionalMetadata;
97 | arguments[ContextParamPlatform] = sqlPlatform;
98 |
99 | // Generate query
100 | var result = await this._promptGenerator.InvokeAsync(this._kernel, arguments).ConfigureAwait(false);
101 |
102 | // Parse result to handle
103 | string query = result.ParseValue(ContentLabelQuery);
104 |
105 | return new SqlQueryResult(schemaName, query);
106 | }
107 |
108 | public async Task ProcessResultAsync(string objective, string query, List> dataResult)
109 | {
110 | var arguments = new KernelArguments();
111 | arguments[ContextParamObjective] = objective;
112 | arguments[ContextParamQuery] = query;
113 | arguments[ContextParamResult] = JsonSerializer.Serialize(dataResult);
114 |
115 |
116 | // Generate query
117 | var result = await this._promptResultEval.InvokeAsync(this._kernel, arguments).ConfigureAwait(false);
118 | var answer = result.ToString();
119 |
120 | return answer;
121 | }
122 |
123 | public async Task DescribeResultsAsync(List> dataResult)
124 | {
125 | var arguments = new KernelArguments();
126 | arguments[ContextParamResult] = JsonSerializer.Serialize(dataResult.Take(10));
127 |
128 |
129 | // Generate query
130 | var result = await this._promptDescribeResults.InvokeAsync(this._kernel, arguments).ConfigureAwait(false);
131 | var answer = result.ToString();
132 |
133 | return answer;
134 | }
135 |
136 | private async Task ScreenObjectiveAsync(KernelArguments context)
137 | {
138 | var result = await this._promptEval.InvokeAsync(this._kernel, context).ConfigureAwait(false);
139 |
140 | var answer = result.ParseValue(ContentLabelAnswer);
141 | return answer.Equals(ContentAffirmative, StringComparison.OrdinalIgnoreCase);
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner1.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 | using System.Text.Json;
4 |
5 | namespace HelloWorld.Plugin2.Console.Configuration;
6 |
7 | internal static class ServiceCollectionExtensions
8 | {
9 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
10 | {
11 | switch (openAIOptions.Source)
12 | {
13 | case "AzureOpenAI":
14 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
15 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
16 | break;
17 |
18 | case "OpenAI":
19 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
20 | break;
21 |
22 | default:
23 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
24 | }
25 |
26 | return serviceCollection;
27 | }
28 | }
29 | public enum ApiLoggingLevel
30 | {
31 | None = 0,
32 | RequestOnly = 1,
33 | ResponseAndRequest = 2,
34 | }
35 |
36 | internal static class IKernelBuilderExtensions
37 | {
38 | internal static IKernelBuilder AddChatCompletionService(this IKernelBuilder kernelBuilder, OpenAIOptions openAIOptions, ApiLoggingLevel apiLoggingLevel = ApiLoggingLevel.None)
39 | {
40 | switch (openAIOptions.Source)
41 | {
42 | case "AzureOpenAI":
43 | {
44 | if (apiLoggingLevel == ApiLoggingLevel.None)
45 | {
46 | kernelBuilder = kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
47 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
48 | }
49 | else
50 | {
51 | var client = CreateHttpClient(apiLoggingLevel);
52 | kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, openAIOptions.Endpoint, openAIOptions.ApiKey, null, null, client);
53 | }
54 | break;
55 | }
56 | case "OpenAI":
57 | {
58 | if (apiLoggingLevel == ApiLoggingLevel.None)
59 | {
60 | kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
61 | break;
62 | }
63 | else
64 | {
65 | var client = CreateHttpClient(apiLoggingLevel);
66 | kernelBuilder.AddOpenAIChatCompletion(openAIOptions.ChatModelId, openAIOptions.ApiKey, null, null, client);
67 | }
68 | break;
69 | }
70 | default:
71 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
72 | }
73 |
74 | return kernelBuilder;
75 | }
76 |
77 | private static HttpClient CreateHttpClient(ApiLoggingLevel apiLoggingLevel)
78 | {
79 | HttpClientHandler httpClientHandler;
80 | if (apiLoggingLevel == ApiLoggingLevel.RequestOnly)
81 | {
82 | httpClientHandler = new RequestLoggingHttpClientHandler();
83 | }
84 | else
85 | {
86 | httpClientHandler = new RequestAndResponseLoggingHttpClientHandler();
87 | }
88 | var client = new HttpClient(httpClientHandler);
89 | return client;
90 | }
91 | }
92 |
93 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
94 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
95 | {
96 | protected override async Task SendAsync(
97 | HttpRequestMessage request, CancellationToken cancellationToken)
98 | {
99 | if (request.Content is not null)
100 | {
101 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
102 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
103 | new JsonSerializerOptions { WriteIndented = true });
104 | System.Console.WriteLine("***********************************************");
105 | System.Console.WriteLine("Request:");
106 | System.Console.WriteLine(json);
107 | }
108 |
109 | var result = await base.SendAsync(request, cancellationToken);
110 |
111 | if (result.Content is not null)
112 | {
113 | var content = await result.Content.ReadAsStringAsync(cancellationToken);
114 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
115 | new JsonSerializerOptions { WriteIndented = true });
116 | System.Console.WriteLine("***********************************************");
117 | System.Console.WriteLine("Response:");
118 | System.Console.WriteLine(json);
119 | }
120 |
121 | return result;
122 | }
123 | }
124 | public class RequestLoggingHttpClientHandler : HttpClientHandler
125 | {
126 | protected override async Task SendAsync(
127 | HttpRequestMessage request, CancellationToken cancellationToken)
128 | {
129 | if (request.Content is not null)
130 | {
131 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
132 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
133 | new JsonSerializerOptions { WriteIndented = true });
134 | System.Console.WriteLine("***********************************************");
135 | System.Console.WriteLine("Request:");
136 | System.Console.WriteLine(json);
137 | }
138 |
139 | return await base.SendAsync(request, cancellationToken);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/HelloWorld.Planner2.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 | using System.Text.Json;
4 |
5 | namespace HelloWorld.Plugin2.Console.Configuration;
6 |
7 | internal static class ServiceCollectionExtensions
8 | {
9 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
10 | {
11 | switch (openAIOptions.Source)
12 | {
13 | case "AzureOpenAI":
14 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
15 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
16 | break;
17 |
18 | case "OpenAI":
19 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
20 | break;
21 |
22 | default:
23 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
24 | }
25 |
26 | return serviceCollection;
27 | }
28 | }
29 | public enum ApiLoggingLevel
30 | {
31 | None = 0,
32 | RequestOnly = 1,
33 | ResponseAndRequest = 2,
34 | }
35 |
36 | internal static class IKernelBuilderExtensions
37 | {
38 | internal static IKernelBuilder AddChatCompletionService(this IKernelBuilder kernelBuilder, OpenAIOptions openAIOptions, ApiLoggingLevel apiLoggingLevel = ApiLoggingLevel.None)
39 | {
40 | switch (openAIOptions.Source)
41 | {
42 | case "AzureOpenAI":
43 | {
44 | if (apiLoggingLevel == ApiLoggingLevel.None)
45 | {
46 | kernelBuilder = kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
47 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
48 | }
49 | else
50 | {
51 | var client = CreateHttpClient(apiLoggingLevel);
52 | kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, openAIOptions.Endpoint, openAIOptions.ApiKey, null, null, client);
53 | }
54 | break;
55 | }
56 | case "OpenAI":
57 | {
58 | if (apiLoggingLevel == ApiLoggingLevel.None)
59 | {
60 | kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
61 | break;
62 | }
63 | else
64 | {
65 | var client = CreateHttpClient(apiLoggingLevel);
66 | kernelBuilder.AddOpenAIChatCompletion(openAIOptions.ChatModelId, openAIOptions.ApiKey, null, null, client);
67 | }
68 | break;
69 | }
70 | default:
71 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
72 | }
73 |
74 | return kernelBuilder;
75 | }
76 |
77 | private static HttpClient CreateHttpClient(ApiLoggingLevel apiLoggingLevel)
78 | {
79 | HttpClientHandler httpClientHandler;
80 | if (apiLoggingLevel == ApiLoggingLevel.RequestOnly)
81 | {
82 | httpClientHandler = new RequestLoggingHttpClientHandler();
83 | }
84 | else
85 | {
86 | httpClientHandler = new RequestAndResponseLoggingHttpClientHandler();
87 | }
88 | var client = new HttpClient(httpClientHandler);
89 | return client;
90 | }
91 | }
92 |
93 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
94 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
95 | {
96 | protected override async Task SendAsync(
97 | HttpRequestMessage request, CancellationToken cancellationToken)
98 | {
99 | if (request.Content is not null)
100 | {
101 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
102 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
103 | new JsonSerializerOptions { WriteIndented = true });
104 | System.Console.WriteLine("***********************************************");
105 | System.Console.WriteLine("Request:");
106 | System.Console.WriteLine(json);
107 | }
108 |
109 | var result = await base.SendAsync(request, cancellationToken);
110 |
111 | if (result.Content is not null)
112 | {
113 | var content = await result.Content.ReadAsStringAsync(cancellationToken);
114 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
115 | new JsonSerializerOptions { WriteIndented = true });
116 | System.Console.WriteLine("***********************************************");
117 | System.Console.WriteLine("Response:");
118 | System.Console.WriteLine(json);
119 | }
120 |
121 | return result;
122 | }
123 | }
124 | public class RequestLoggingHttpClientHandler : HttpClientHandler
125 | {
126 | protected override async Task SendAsync(
127 | HttpRequestMessage request, CancellationToken cancellationToken)
128 | {
129 | if (request.Content is not null)
130 | {
131 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
132 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
133 | new JsonSerializerOptions { WriteIndented = true });
134 | System.Console.WriteLine("***********************************************");
135 | System.Console.WriteLine("Request:");
136 | System.Console.WriteLine(json);
137 | }
138 |
139 | return await base.SendAsync(request, cancellationToken);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/samples/demos/PropertyGraphRAG/PropertyGraph.Common/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 | using System.Text.Json;
4 |
5 | namespace PropertyGraph.Common;
6 |
7 | public static class ServiceCollectionExtensions
8 | {
9 | public static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
10 | {
11 | switch (openAIOptions.Source)
12 | {
13 | case "AzureOpenAI":
14 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
15 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
16 | break;
17 |
18 | case "OpenAI":
19 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
20 | break;
21 |
22 | default:
23 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
24 | }
25 |
26 | return serviceCollection;
27 | }
28 | }
29 | public enum ApiLoggingLevel
30 | {
31 | None = 0,
32 | RequestOnly = 1,
33 | ResponseAndRequest = 2,
34 | }
35 |
36 | public static class IKernelBuilderExtensions
37 | {
38 | public static IKernelBuilder AddChatCompletionService(this IKernelBuilder kernelBuilder, OpenAIOptions openAIOptions, ApiLoggingLevel apiLoggingLevel = ApiLoggingLevel.None)
39 | {
40 | switch (openAIOptions.Source)
41 | {
42 | case "AzureOpenAI":
43 | {
44 | if (apiLoggingLevel == ApiLoggingLevel.None)
45 | {
46 | kernelBuilder = kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
47 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
48 | }
49 | else
50 | {
51 | var client = CreateHttpClient(apiLoggingLevel);
52 | kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, openAIOptions.Endpoint, openAIOptions.ApiKey, null, null, client);
53 | }
54 | break;
55 | }
56 | case "OpenAI":
57 | {
58 | if (apiLoggingLevel == ApiLoggingLevel.None)
59 | {
60 | kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
61 | break;
62 | }
63 | else
64 | {
65 | var client = CreateHttpClient(apiLoggingLevel);
66 | kernelBuilder.AddOpenAIChatCompletion(openAIOptions.ChatModelId, openAIOptions.ApiKey, null, null, client);
67 | }
68 | break;
69 | }
70 | default:
71 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
72 | }
73 |
74 | return kernelBuilder;
75 | }
76 |
77 | public static HttpClient CreateHttpClient(ApiLoggingLevel apiLoggingLevel)
78 | {
79 | HttpClientHandler httpClientHandler;
80 | if (apiLoggingLevel == ApiLoggingLevel.RequestOnly)
81 | {
82 | httpClientHandler = new RequestLoggingHttpClientHandler();
83 | }
84 | else
85 | {
86 | httpClientHandler = new RequestAndResponseLoggingHttpClientHandler();
87 | }
88 | var client = new HttpClient(httpClientHandler);
89 | return client;
90 | }
91 | }
92 |
93 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
94 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
95 | {
96 | protected override async Task SendAsync(
97 | HttpRequestMessage request, CancellationToken cancellationToken)
98 | {
99 | Console.WriteLine("***********************************************");
100 | Console.WriteLine($"Request: {request.Method} {request.RequestUri}");
101 | if (request.Content is not null)
102 | {
103 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
104 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
105 | new JsonSerializerOptions { WriteIndented = true });
106 | Console.WriteLine(json);
107 | }
108 |
109 | var result = await base.SendAsync(request, cancellationToken);
110 |
111 | if (result.Content is not null)
112 | {
113 | var content = await result.Content.ReadAsStringAsync(cancellationToken);
114 | //var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
115 | // new JsonSerializerOptions { WriteIndented = true });
116 | Console.WriteLine("***********************************************");
117 | Console.WriteLine("Response:");
118 | //Console.WriteLine(json);
119 | Console.WriteLine(content);
120 | }
121 |
122 | return result;
123 | }
124 | }
125 | public class RequestLoggingHttpClientHandler : HttpClientHandler
126 | {
127 | protected override async Task SendAsync(
128 | HttpRequestMessage request, CancellationToken cancellationToken)
129 | {
130 | Console.WriteLine("***********************************************");
131 | Console.WriteLine($"Request: {request.Method} {request.RequestUri}");
132 | if (request.Content is not null)
133 | {
134 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
135 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
136 | new JsonSerializerOptions { WriteIndented = true });
137 | Console.WriteLine(json);
138 | }
139 |
140 | return await base.SendAsync(request, cancellationToken);
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/HelloWorld.WebSearchEnginePlugin.Console/Configuration/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.DependencyInjection;
2 | using Microsoft.SemanticKernel;
3 | using Microsoft.SemanticKernel.Plugins.Web;
4 | using Microsoft.SemanticKernel.Plugins.Web.Brave;
5 | using System.Text.Json;
6 |
7 | namespace HelloWorld.Configuration;
8 |
9 | internal static class ServiceCollectionExtensions
10 | {
11 | internal static IServiceCollection AddChatCompletionService(this IServiceCollection serviceCollection, OpenAIOptions openAIOptions)
12 | {
13 | switch (openAIOptions.Source)
14 | {
15 | case "AzureOpenAI":
16 | serviceCollection = serviceCollection.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
17 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
18 | break;
19 |
20 | case "OpenAI":
21 | serviceCollection = serviceCollection.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
22 | break;
23 |
24 | default:
25 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
26 | }
27 |
28 | return serviceCollection;
29 | }
30 | }
31 | public enum ApiLoggingLevel
32 | {
33 | None = 0,
34 | RequestOnly = 1,
35 | ResponseAndRequest = 2,
36 | }
37 |
38 | internal static class IKernelBuilderExtensions
39 | {
40 | internal static IKernelBuilder AddBraveConnector(this IKernelBuilder kernelBuilder, PluginOptions pluginOptions, ApiLoggingLevel apiLoggingLevel = ApiLoggingLevel.None)
41 | {
42 | if (apiLoggingLevel == ApiLoggingLevel.None)
43 | {
44 | kernelBuilder.Services.AddSingleton(new BraveConnector(pluginOptions.BraveApiKey));
45 | }
46 | else
47 | {
48 | var client = CreateHttpClient(apiLoggingLevel);
49 | kernelBuilder.Services.AddSingleton(new BraveConnector(pluginOptions.BraveApiKey, client));
50 | }
51 |
52 | return kernelBuilder;
53 | }
54 |
55 | internal static IKernelBuilder AddChatCompletionService(this IKernelBuilder kernelBuilder, OpenAIOptions openAIOptions, ApiLoggingLevel apiLoggingLevel = ApiLoggingLevel.None)
56 | {
57 | switch (openAIOptions.Source)
58 | {
59 | case "AzureOpenAI":
60 | {
61 | if (apiLoggingLevel == ApiLoggingLevel.None)
62 | {
63 | kernelBuilder = kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, endpoint: openAIOptions.Endpoint,
64 | apiKey: openAIOptions.ApiKey, serviceId: openAIOptions.ChatModelId);
65 | }
66 | else
67 | {
68 | var client = CreateHttpClient(apiLoggingLevel);
69 | kernelBuilder.AddAzureOpenAIChatCompletion(openAIOptions.ChatDeploymentName, openAIOptions.Endpoint, openAIOptions.ApiKey, null, null, client);
70 | }
71 | break;
72 | }
73 | case "OpenAI":
74 | {
75 | if (apiLoggingLevel == ApiLoggingLevel.None)
76 | {
77 | kernelBuilder = kernelBuilder.AddOpenAIChatCompletion(modelId: openAIOptions.ChatModelId, apiKey: openAIOptions.ApiKey);
78 | break;
79 | }
80 | else
81 | {
82 | var client = CreateHttpClient(apiLoggingLevel);
83 | kernelBuilder.AddOpenAIChatCompletion(openAIOptions.ChatModelId, openAIOptions.ApiKey, null, null, client);
84 | }
85 | break;
86 | }
87 | default:
88 | throw new ArgumentException($"Invalid source: {openAIOptions.Source}");
89 | }
90 |
91 | return kernelBuilder;
92 | }
93 |
94 | public static HttpClient CreateHttpClient(ApiLoggingLevel apiLoggingLevel)
95 | {
96 | HttpClientHandler httpClientHandler;
97 | if (apiLoggingLevel == ApiLoggingLevel.RequestOnly)
98 | {
99 | httpClientHandler = new RequestLoggingHttpClientHandler();
100 | }
101 | else
102 | {
103 | httpClientHandler = new RequestAndResponseLoggingHttpClientHandler();
104 | }
105 | var client = new HttpClient(httpClientHandler);
106 | return client;
107 | }
108 | }
109 |
110 | // Found most of this implementation via: https://github.com/microsoft/semantic-kernel/issues/5107
111 | public class RequestAndResponseLoggingHttpClientHandler : HttpClientHandler
112 | {
113 | protected override async Task SendAsync(
114 | HttpRequestMessage request, CancellationToken cancellationToken)
115 | {
116 | if (request.Content is not null)
117 | {
118 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
119 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
120 | new JsonSerializerOptions { WriteIndented = true });
121 | System.Console.WriteLine("***********************************************");
122 | System.Console.WriteLine("Request:");
123 | System.Console.WriteLine(json);
124 | }
125 | else
126 | {
127 | System.Console.WriteLine("***********************************************");
128 | System.Console.WriteLine($"Request: {request.Method} {request.RequestUri}");
129 | }
130 |
131 | var result = await base.SendAsync(request, cancellationToken);
132 |
133 | if (result.Content is not null)
134 | {
135 | var content = await result.Content.ReadAsStringAsync(cancellationToken);
136 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
137 | new JsonSerializerOptions { WriteIndented = true });
138 | System.Console.WriteLine("***********************************************");
139 | System.Console.WriteLine("Response:");
140 | System.Console.WriteLine(json);
141 | }
142 |
143 | return result;
144 | }
145 | }
146 | public class RequestLoggingHttpClientHandler : HttpClientHandler
147 | {
148 | protected override async Task SendAsync(
149 | HttpRequestMessage request, CancellationToken cancellationToken)
150 | {
151 | if (request.Content is not null)
152 | {
153 | var content = await request.Content.ReadAsStringAsync(cancellationToken);
154 | var json = JsonSerializer.Serialize(JsonSerializer.Deserialize(content),
155 | new JsonSerializerOptions { WriteIndented = true });
156 | System.Console.WriteLine("***********************************************");
157 | System.Console.WriteLine("Request:");
158 | System.Console.WriteLine(json);
159 | }
160 | else
161 | {
162 | System.Console.WriteLine("***********************************************");
163 | System.Console.WriteLine($"Request: {request.Method} {request.RequestUri}");
164 | }
165 | return await base.SendAsync(request, cancellationToken);
166 | }
167 | }
168 |
--------------------------------------------------------------------------------