diff --git a/README.md b/README.md index 05326e61..6fcb4ae7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > “Start with the customer experience and work backwards for the technology” - Steve Jobs > -> "Change is the only constant" - Heraclitus +> "Change is the only constant" - Ancient wisdom

diff --git a/sandbox/usecases/auto-invest-agency-planning.ipynb b/sandbox/usecases/auto-invest-agency-planning.ipynb index 67244652..45de2d0c 100644 --- a/sandbox/usecases/auto-invest-agency-planning.ipynb +++ b/sandbox/usecases/auto-invest-agency-planning.ipynb @@ -21,7 +21,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -81,7 +81,7 @@ "source": [ "var builder = new KernelBuilder();\n", "\n", - "var (_, model, azureEndpoint, apiKey, org) = Settings.LoadFromFile();\n", + "var (_, model, azureEndpoint, apiKey, org, bingApiKey) = Settings.LoadFromFile();\n", "builder.WithAzureChatCompletionService(model, azureEndpoint, apiKey);\n", "\n", "IKernel kernel = builder.Build();" diff --git a/sandbox/usecases/config/Settings.cs b/sandbox/usecases/config/Settings.cs index 4f8e4fca..5298d6b0 100644 --- a/sandbox/usecases/config/Settings.cs +++ b/sandbox/usecases/config/Settings.cs @@ -19,11 +19,13 @@ public static class Settings private const string SecretKey = "apikey"; private const string OrgKey = "org"; private const bool StoreConfigOnFile = true; + private const string BingApiKey = "bingApiKey"; + // Prompt user for Azure Endpoint URL public static async Task AskAzureEndpoint(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) { - var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); + var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey) = ReadSettings(_useAzureOpenAI, configFile); // If needed prompt user for Azure endpoint if (useAzureOpenAI && string.IsNullOrWhiteSpace(azureEndpoint)) @@ -31,7 +33,7 @@ public static async Task AskAzureEndpoint(bool _useAzureOpenAI = true, s azureEndpoint = await InteractiveKernel.GetInputAsync("Please enter your Azure OpenAI endpoint"); } - WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); // Print report if (useAzureOpenAI) @@ -47,7 +49,7 @@ public static async Task AskAzureEndpoint(bool _useAzureOpenAI = true, s // Prompt user for OpenAI model name / Azure OpenAI deployment name public static async Task AskModel(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) { - var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); + var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey) = ReadSettings(_useAzureOpenAI, configFile); // If needed prompt user for model name / deployment name if (string.IsNullOrWhiteSpace(model)) @@ -63,7 +65,7 @@ public static async Task AskModel(bool _useAzureOpenAI = true, string co } } - WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); // Print report if (useAzureOpenAI) @@ -85,7 +87,7 @@ public static async Task AskModel(bool _useAzureOpenAI = true, string co // Prompt user for API Key public static async Task AskApiKey(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) { - var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); + var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey) = ReadSettings(_useAzureOpenAI, configFile); // If needed prompt user for API key if (string.IsNullOrWhiteSpace(apiKey)) @@ -101,7 +103,7 @@ public static async Task AskApiKey(bool _useAzureOpenAI = true, string c } } - WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); // Print report Console.WriteLine("Settings: " + (string.IsNullOrWhiteSpace(apiKey) @@ -114,7 +116,7 @@ public static async Task AskApiKey(bool _useAzureOpenAI = true, string c // Prompt user for OpenAI Organization Id public static async Task AskOrg(bool _useAzureOpenAI = true, string configFile = DefaultConfigFile) { - var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = ReadSettings(_useAzureOpenAI, configFile); + var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey) = ReadSettings(_useAzureOpenAI, configFile); // If needed prompt user for OpenAI Org Id if (!useAzureOpenAI && string.IsNullOrWhiteSpace(orgId)) @@ -122,13 +124,13 @@ public static async Task AskOrg(bool _useAzureOpenAI = true, string conf orgId = await InteractiveKernel.GetInputAsync("Please enter your OpenAI Organization Id (enter 'NONE' to skip)"); } - WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + WriteSettings(configFile, useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); return orgId; } // Load settings from file - public static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) + public static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId, string bingApiKey) LoadFromFile(string configFile = DefaultConfigFile) { if (!File.Exists(DefaultConfigFile)) @@ -146,17 +148,19 @@ public static (bool useAzureOpenAI, string model, string azureEndpoint, string a string azureEndpoint = config[EndpointKey]; string apiKey = config[SecretKey]; string orgId = config[OrgKey]; + string bingApiKey = config[BingApiKey]; if (orgId == "none") { orgId = ""; } - return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); } catch (Exception e) { Console.WriteLine("Something went wrong: " + e.Message); - return (true, "", "", "", ""); + return (true, "", "", "", "", ""); } } + // Delete settings file public static void Reset(string configFile = DefaultConfigFile) { @@ -173,8 +177,8 @@ public static void Reset(string configFile = DefaultConfigFile) } } - // Read and return settings from file - private static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) + // Read and return settings from file + private static (bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId, string bingApiKey) ReadSettings(bool _useAzureOpenAI, string configFile) { // Save the preference set in the notebook @@ -183,12 +187,13 @@ private static (bool useAzureOpenAI, string model, string azureEndpoint, string string azureEndpoint = ""; string apiKey = ""; string orgId = ""; + string bingApiKey = ""; try { if (File.Exists(configFile)) { - (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = LoadFromFile(configFile); + (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey) = LoadFromFile(configFile); } } catch (Exception e) @@ -205,14 +210,16 @@ private static (bool useAzureOpenAI, string model, string azureEndpoint, string azureEndpoint = ""; apiKey = ""; orgId = ""; + bingApiKey = ""; } - return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId); + return (useAzureOpenAI, model, azureEndpoint, apiKey, orgId, bingApiKey); } + // Write settings to file private static void WriteSettings( - string configFile, bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId) + string configFile, bool useAzureOpenAI, string model, string azureEndpoint, string apiKey, string orgId, string bingApiKey) { try { @@ -225,6 +232,7 @@ private static void WriteSettings( { EndpointKey, azureEndpoint }, { SecretKey, apiKey }, { OrgKey, orgId }, + { BingApiKey, bingApiKey } }; var options = new JsonSerializerOptions { WriteIndented = true }; diff --git a/sandbox/usecases/config/settings.json.azure-example b/sandbox/usecases/config/settings.json.azure-example index dc1c4250..86c10851 100644 --- a/sandbox/usecases/config/settings.json.azure-example +++ b/sandbox/usecases/config/settings.json.azure-example @@ -3,5 +3,6 @@ "model": "... your Azure OpenAI deployment name ...", "endpoint": "https:// ... your endpoint ... .openai.azure.com/", "apikey": "... your Azure OpenAI key ...", - "org": "" // it's not used for azure, but the parser requires it so do not delete + "org": "" // it's not used for azure, but the parser requires it so do not delete, + "bingApiKey": "... your Bing API key ..." } \ No newline at end of file diff --git a/sandbox/usecases/config/settings.json.openai-example b/sandbox/usecases/config/settings.json.openai-example index 7b22ea43..5935a892 100644 --- a/sandbox/usecases/config/settings.json.openai-example +++ b/sandbox/usecases/config/settings.json.openai-example @@ -3,5 +3,6 @@ "endpoint": "NOT-USED-BUT-REQUIRED-FOR-PARSER", "model": "text-davinci-003", "apikey": "... your OpenAI key ...", - "org": "" + "org": "", + "bingApiKey": "... your Bing API key ..." } \ No newline at end of file diff --git a/sandbox/usecases/sentiment-analysis.ipynb b/sandbox/usecases/sentiment-analysis.ipynb new file mode 100644 index 00000000..44d223a7 --- /dev/null +++ b/sandbox/usecases/sentiment-analysis.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Discriminative use case: Sentiment Analysis\n", + "\n", + "In this notebook, we will explore how we can perform classical ML task such as sentiment analysis using LLM.\n", + "\n", + "### Use case description\n", + "\n", + "Sentiment analysis is a common NLP task that involves classifying text into a pre-defined sentiment. For example, with Miyagi, we can classify a user's stock portfolio into a predefined categories based on current market sentiment, which can be determined using a Bing search.\n", + "\n", + "> Note - To improve reliability of the model output, set the temperature to 0 and use top_k sampling. This will ensure that the model always generates the same output for the same input." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 1. Import Semantic Kernel dependencies" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "notebookRunGroups": { + "groupValue": "1" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.SemanticKernel, 0.17.230711.7-preview
  • Microsoft.SemanticKernel.Planning.StepwisePlanner, 0.17.230711.7-preview
  • Microsoft.SemanticKernel.Skills.Web, 0.17.230711.7-preview
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230711.7-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel.Planning.StepwisePlanner, 0.17.230711.7-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel.Skills.Web, 0.17.230711.7-preview\"\n", + "\n", + "#!import config/Settings.cs\n", + "\n", + "using Microsoft.SemanticKernel;\n", + "using Microsoft.SemanticKernel.SemanticFunctions;\n", + "using Microsoft.SemanticKernel.Planning;\n", + "using Microsoft.SemanticKernel.Orchestration;\n", + "using Microsoft.SemanticKernel.Skills.Web;\n", + "using Microsoft.SemanticKernel.Skills.Web.Bing;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 2. Initialize kernel" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "var builder = new KernelBuilder();\n", + "\n", + "var (_, model, azureEndpoint, apiKey, org, bingApiKey) = Settings.LoadFromFile();\n", + "builder.WithAzureChatCompletionService(model, azureEndpoint, apiKey);\n", + "\n", + "IKernel kernel = builder.Build();" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3. Create a Semantic Function (Prompt Template)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "ename": "Error", + "evalue": "(34,17): error CS0103: The name 'kernel' does not exist in the current context", + "output_type": "error", + "traceback": [ + "(34,17): error CS0103: The name 'kernel' does not exist in the current context" + ] + } + ], + "source": [ + "string skPrompt = @\"\n", + "This is a chat between a classification system and human looking to rate their stock portfolio. Given a portfolio in valid JSON, respond back a sentiment in JSON for the attribute: sentiment. To determine this attribute, consider Web results from Bing and propietary data below.\n", + "\n", + "Example:\n", + "\"\"stocks\"\": [\n", + " {\n", + " \"\"symbol\"\": \"\"MSFT\"\",\n", + " \"\"allocation\"\": 0.3,\n", + " \"\"sentiment\"\": \"\"positive\"\"\n", + " },\n", + " {\n", + " \"\"symbol\"\": \"\"ACN\"\",\n", + " \"\"allocation\"\": 0.1,\n", + " \"\"sentiment\"\": \"\"negative\"\"\n", + " },\n", + " {\n", + " \"\"symbol\"\": \"\"JPM\"\",\n", + " \"\"allocation\"\": 0.3,\n", + " \"\"sentiment\"\": \"\"neutral\"\"\n", + " },\n", + " {\n", + " \"\"symbol\"\": \"\"PEP\"\",\n", + " \"\"allocation\"\": 0.3,\n", + " \"\"sentiment\"\": \"\"neutral\"\"\n", + " }\n", + " ]\n", + "\n", + "Rate my portfolio:\n", + "\n", + "{{$portfolio}}\n", + "\n", + "\n", + "Question: {{$input}}\n", + "\n", + "Context: \n", + "Web Results: {{$web}}\n", + "Propietary data: {{$propietary}}\n", + "\";\n", + "\n", + "// create semantic function\n", + "var textToSQL = kernel.CreateSemanticFunction(skPrompt, maxTokens: 1000, temperature: 0, topP: 0.5);\n", + "Console.WriteLine(textToSQL.ToString());" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 3. Create Context variables" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "var tableInfo = @\"\n", + " Users table has columns: user_id, first_name, last_name, and email.\n", + " Transactions table has columns: transaction_id, user_id, transaction_amount, transaction_date, and transaction_type.\n", + "\";\n", + "\n", + "// context variables\n", + "var context = kernel.CreateNewContext();\n", + "context[\"dialect\"] = \"PostgreSQL\";\n", + "context[\"tableInfo\"] = tableInfo;" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### 4. Generate SQL from natural language" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Question: What was the most expensive purchase made in the last year?\n", + "\n", + "SQLQuery: SELECT \n", + " t.transaction_id,\n", + " t.transaction_date,\n", + " t.transaction_amount,\n", + " t.transaction_type,\n", + " u.first_name,\n", + " u.last_name\n", + " FROM \n", + " transactions t\n", + " JOIN \n", + " users u ON t.user_id = u.user_id\n", + " WHERE \n", + " t.transaction_date >= DATE_TRUNC('year', CURRENT_DATE - INTERVAL '1 year')\n", + " AND t.transaction_date < DATE_TRUNC('year', CURRENT_DATE)\n", + " ORDER BY \n", + " t.transaction_amount DESC\n", + " LIMIT 1;\n", + "\n", + "Answer: The most expensive purchase made in the last year was {transaction_type} for {transaction_amount} by {first_name} {last_name} on {transaction_date}.\r\n" + ] + } + ], + "source": [ + "context[\"input\"] = \"Most expensive purchase in the last year\";\n", + "var sql = await textToSQL.InvokeAsync(context);\n", + "Console.WriteLine(sql);\n", + "\n", + "\n", + "using var bingConnector = new BingConnector(Env.Var(\"BING_API_KEY\"));\n", + " var webSearchEngineSkill = new WebSearchEngineSkill(bingConnector);\n", + "\n", + " kernel.ImportSkill(webSearchEngineSkill, \"WebSearch\");\n", + " kernel.ImportSkill(new LanguageCalculatorSkill(kernel), \"advancedCalculator\");\n", + " // kernel.ImportSkill(new SimpleCalculatorSkill(kernel), \"basicCalculator\");\n", + " kernel.ImportSkill(new TimeSkill(), \"time\");\n", + "\n", + " Console.WriteLine(\"*****************************************************\");\n", + " Stopwatch sw = new();\n", + " Console.WriteLine(\"Question: \" + question);\n", + "\n", + " var config = new Microsoft.SemanticKernel.Planning.Stepwise.StepwisePlannerConfig();\n", + " config.ExcludedFunctions.Add(\"TranslateMathProblem\");\n", + " config.MinIterationTimeMs = 1500;\n", + " config.MaxTokens = 4000;\n", + "\n", + " StepwisePlanner planner = new(kernel, config);\n", + " sw.Start();\n", + " var plan = planner.CreatePlan(question);\n", + "\n", + " var result = await plan.InvokeAsync(kernel.CreateNewContext());\n", + " Console.WriteLine(\"Result: \" + result);\n", + " if (result.Variables.TryGetValue(\"stepCount\", out string? stepCount))\n", + " {\n", + " Console.WriteLine(\"Steps Taken: \" + stepCount);\n", + " }\n", + "\n", + " if (result.Variables.TryGetValue(\"skillCount\", out string? skillCount))\n", + " {\n", + " Console.WriteLine(\"Skills Used: \" + skillCount);\n", + " }\n", + "\n", + " Console.WriteLine(\"Time Taken: \" + sw.Elapsed);\n", + " Console.WriteLine(\"*****************************************************\");\n", + " }" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "polyglot-notebook" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/sandbox/usecases/sql-code-gen.ipynb b/sandbox/usecases/sql-code-gen.ipynb index f9cdb030..5eb3357a 100644 --- a/sandbox/usecases/sql-code-gen.ipynb +++ b/sandbox/usecases/sql-code-gen.ipynb @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -42,7 +42,7 @@ { "data": { "text/html": [ - "
Installed Packages
  • Microsoft.SemanticKernel, 0.17.230704.3-preview
" + "
Installed Packages
  • Microsoft.SemanticKernel, 0.17.230711.7-preview
" ] }, "metadata": {}, @@ -50,7 +50,7 @@ } ], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.17.230704.3-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230711.7-preview\"\n", "\n", "#!import config/Settings.cs\n", "\n", @@ -68,7 +68,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -81,7 +81,7 @@ "source": [ "var builder = new KernelBuilder();\n", "\n", - "var (_, model, azureEndpoint, apiKey, org) = Settings.LoadFromFile();\n", + "var (_, model, azureEndpoint, apiKey, org, bingApiKey) = Settings.LoadFromFile();\n", "builder.WithAzureChatCompletionService(model, azureEndpoint, apiKey);\n", "\n", "IKernel kernel = builder.Build();" @@ -110,7 +110,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{\"Name\":\"func382f61d9a12e4fd8abb5d5b12daf684e\",\"SkillName\":\"_GLOBAL_FUNCTIONS_\",\"Description\":\"Generic function, unknown purpose\",\"IsSemantic\":true,\"IsSensitive\":false,\"TrustServiceInstance\":{},\"RequestSettings\":{\"Temperature\":0,\"TopP\":0.5,\"PresencePenalty\":0,\"FrequencyPenalty\":0,\"MaxTokens\":200,\"StopSequences\":[],\"ResultsPerPrompt\":1,\"ChatSystemPrompt\":\"Assistant is a large language model.\",\"TokenSelectionBiases\":{}},\"Parameters\":[{\"Name\":\"input\",\"Description\":\"\",\"DefaultValue\":\"\"}]}\r\n" + "{\"Name\":\"func4e7e959b9d6f4c1fbedbc17472c3798f\",\"SkillName\":\"_GLOBAL_FUNCTIONS_\",\"Description\":\"Generic function, unknown purpose\",\"IsSemantic\":true,\"RequestSettings\":{\"Temperature\":0,\"TopP\":0.5,\"PresencePenalty\":0,\"FrequencyPenalty\":0,\"MaxTokens\":200,\"StopSequences\":[],\"ResultsPerPrompt\":1,\"ChatSystemPrompt\":\"Assistant is a large language model.\",\"TokenSelectionBiases\":{}},\"Parameters\":[{\"Name\":\"input\",\"Description\":\"\",\"DefaultValue\":\"\"},{\"Name\":\"tableInfo\",\"Description\":\"\",\"DefaultValue\":\"\"}]}\r\n" ] } ], @@ -140,9 +140,9 @@ "Only use the following tables:\n", "\n", "Table info:\n", - "{tableInfo}\n", + "{{$tableInfo}}\n", "\n", - "Question: {input}.\n", + "Question: {{$input}}.\n", "\";\n", "\n", "// create semantic function\n", @@ -204,19 +204,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "Question: What was the most expensive purchase made in the last year?\n", - "\n", "SQLQuery: SELECT \n", - " t.transaction_id,\n", - " t.transaction_date,\n", - " t.transaction_amount,\n", - " t.transaction_type,\n", " u.first_name,\n", - " u.last_name\n", + " u.last_name,\n", + " t.transaction_amount,\n", + " t.transaction_date\n", " FROM \n", - " transactions t\n", + " users u\n", " JOIN \n", - " users u ON t.user_id = u.user_id\n", + " transactions t ON u.user_id = t.user_id\n", " WHERE \n", " t.transaction_date >= DATE_TRUNC('year', CURRENT_DATE - INTERVAL '1 year')\n", " AND t.transaction_date < DATE_TRUNC('year', CURRENT_DATE)\n", @@ -224,7 +220,7 @@ " t.transaction_amount DESC\n", " LIMIT 1;\n", "\n", - "Answer: The most expensive purchase made in the last year was {transaction_type} for {transaction_amount} by {first_name} {last_name} on {transaction_date}.\r\n" + "This query will return the first name, last name, transaction amount, and transaction date of the user who made the most expensive purchase in the last year. The results will be ordered by transaction amount in descending order, and only the top result will be returned using the LIMIT keyword.\r\n" ] } ], diff --git a/services/README.md b/services/README.md index 543fff12..c3809d50 100644 --- a/services/README.md +++ b/services/README.md @@ -14,7 +14,7 @@ This folder contains the microservices that implement the [use cases](https://ia | Chat (Q&A) | [sk-copilot-chat-api](../services/sk-copilot-chat-api/) | | Synthetic data | [user-service](./user-service/java/) | -### Discriminative +### Discriminative (Traditional ML) | Use Case | Subfolder | |----------|-----------|