diff --git a/.gitignore b/.gitignore index 34fc91e88..5eebed827 100644 --- a/.gitignore +++ b/.gitignore @@ -429,8 +429,6 @@ FodyWeavers.xsd certs/ # to make sure we don't commit local settings which might contain credentials -launchSettings.json -*launchSettings.json* config.development.yaml *.development.config *.development.json diff --git a/KernelMemory.sln b/KernelMemory.sln index 16bbd4aee..b073a777d 100644 --- a/KernelMemory.sln +++ b/KernelMemory.sln @@ -108,7 +108,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "extensions", "extensions", EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{CA49F1A1-C3FA-4E99-ACB3-D7FF33D47976}" ProjectSection(SolutionItems) = preProject - tools\ask.sh = tools\ask.sh tools\README.md = tools\README.md tools\run-elasticsearch.sh = tools\run-elasticsearch.sh tools\run-mongodb-atlas.sh = tools\run-mongodb-atlas.sh @@ -117,10 +116,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{CA49F1A1 tools\run-rabbitmq.sh = tools\run-rabbitmq.sh tools\run-redis.sh = tools\run-redis.sh tools\run-s3ninja.sh = tools\run-s3ninja.sh - tools\search.sh = tools\search.sh - tools\upload-file.sh = tools\upload-file.sh - tools\dockerize-amd64.sh = tools\dockerize-amd64.sh - tools\dockerize-arm64.sh = tools\dockerize-arm64.sh EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Abstractions", "service\Abstractions\Abstractions.csproj", "{8A9FA587-7EBA-4D43-BE47-38D798B1C74C}" @@ -339,6 +334,32 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tiktoken", "extensions\Tikt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "303-dotnet-aspire", "examples\303-dotnet-aspire\303-dotnet-aspire.csproj", "{DD643765-8D45-4574-92C3-CBEF0C330242}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "aspire", "aspire", "{07A91D09-CA4D-425F-83AD-F955336AACD7}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "all-azure", "tools\aspire\all-azure\all-azure.csproj", "{6E5EB6F3-17E2-4C71-B35A-5F8F0B7E407F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "volatile-openai", "tools\aspire\volatile-openai\volatile-openai.csproj", "{D81B99FF-E13D-4127-AC01-4BF0C8B02C71}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Extensions", "tools\aspire\Aspire.Extensions\Aspire.Extensions.csproj", "{4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dev", "dev", "{3C1C483D-2C09-4B0D-9394-82B2AF1D61F1}" + ProjectSection(SolutionItems) = preProject + tools\dev\build.sh = tools\dev\build.sh + tools\dev\changes-since-last-release.sh = tools\dev\changes-since-last-release.sh + tools\dev\create-azure-webapp-publish-artifacts.sh = tools\dev\create-azure-webapp-publish-artifacts.sh + tools\dev\dockerize-amd64.sh = tools\dev\dockerize-amd64.sh + tools\dev\dockerize-arm64.sh = tools\dev\dockerize-arm64.sh + tools\dev\get-azure-token.py = tools\dev\get-azure-token.py + tools\dev\run-unit-tests.sh = tools\dev\run-unit-tests.sh + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "km-cli", "km-cli", "{239F5FE9-EAEE-4FA7-A3D5-09608FBA6EED}" + ProjectSection(SolutionItems) = preProject + tools\km-cli\ask.sh = tools\km-cli\ask.sh + tools\km-cli\search.sh = tools\km-cli\search.sh + tools\km-cli\upload-file.sh = tools\km-cli\upload-file.sh + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -634,6 +655,16 @@ Global {DD643765-8D45-4574-92C3-CBEF0C330242}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DD643765-8D45-4574-92C3-CBEF0C330242}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD643765-8D45-4574-92C3-CBEF0C330242}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6E5EB6F3-17E2-4C71-B35A-5F8F0B7E407F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6E5EB6F3-17E2-4C71-B35A-5F8F0B7E407F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6E5EB6F3-17E2-4C71-B35A-5F8F0B7E407F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D81B99FF-E13D-4127-AC01-4BF0C8B02C71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D81B99FF-E13D-4127-AC01-4BF0C8B02C71}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D81B99FF-E13D-4127-AC01-4BF0C8B02C71}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -736,6 +767,14 @@ Global {AF1E12A9-D8A1-4815-995E-C6F7B2022016} = {0A43C65C-6007-4BB4-B3FE-8D439FC91841} {830C91B5-6F8D-4DAD-B1BD-3C2F9DEEC8F6} = {155DA079-E267-49AF-973A-D1D44681970F} {DD643765-8D45-4574-92C3-CBEF0C330242} = {0A43C65C-6007-4BB4-B3FE-8D439FC91841} + {07A91D09-CA4D-425F-83AD-F955336AACD7} = {CA49F1A1-C3FA-4E99-ACB3-D7FF33D47976} + {6E5EB6F3-17E2-4C71-B35A-5F8F0B7E407F} = {07A91D09-CA4D-425F-83AD-F955336AACD7} + {D81B99FF-E13D-4127-AC01-4BF0C8B02C71} = {07A91D09-CA4D-425F-83AD-F955336AACD7} + {4E5BAA7B-7DB6-4F24-8D91-E9C3AC9773E7} = {07A91D09-CA4D-425F-83AD-F955336AACD7} + {3C1C483D-2C09-4B0D-9394-82B2AF1D61F1} = {CA49F1A1-C3FA-4E99-ACB3-D7FF33D47976} + {239F5FE9-EAEE-4FA7-A3D5-09608FBA6EED} = {CA49F1A1-C3FA-4E99-ACB3-D7FF33D47976} + {CA49F1A1-C3FA-4E99-ACB3-D7FF33D47976} = {6EF76FD8-4C35-4370-8539-5DDF45357A50} + {7BA7F1B2-19E2-46EB-B000-513EE2F65769} = {6EF76FD8-4C35-4370-8539-5DDF45357A50} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {CC136C62-115C-41D1-B414-F9473EFF6EA8} diff --git a/KernelMemory.sln.DotSettings b/KernelMemory.sln.DotSettings index 56b15a2c0..afe4c4bcd 100644 --- a/KernelMemory.sln.DotSettings +++ b/KernelMemory.sln.DotSettings @@ -107,6 +107,7 @@ IOS JSON JWT + KM MQ MQTT MS diff --git a/README.md b/README.md index cf6eb197b..ca9bce30a 100644 --- a/README.md +++ b/README.md @@ -235,7 +235,7 @@ which documents ground the response. > ``` The OpenAPI schema ("swagger") is available at http://127.0.0.1:9001/swagger/index.html when -running the service locally with OpenAPI enabled. +running the service locally with OpenAPI enabled. [Here's a copy](https://editor.swagger.io/?url=https://raw.githubusercontent.com/microsoft/kernel-memory/refs/heads/main/swagger.json). @@ -471,9 +471,9 @@ Examples and Tools ## Tools 1. [.NET appsettings.json generator](tools/InteractiveSetup) -2. [Curl script to upload files](tools/upload-file.sh) -3. [Curl script to ask questions](tools/ask.sh) -4. [Curl script to search documents](tools/search.sh) +2. [Curl script to upload files](tools/km-cli/upload-file.sh) +3. [Curl script to ask questions](tools/km-cli/ask.sh) +4. [Curl script to search documents](tools/km-cli/search.sh) 5. [Script to start Qdrant for development tasks](tools/run-qdrant.sh) 6. [Script to start Elasticsearch for development tasks](tools/run-elasticsearch.sh) 7. [Script to start MS SQL Server for development tasks](tools/run-mssql.sh) @@ -539,30 +539,30 @@ githubcontrib --repo kernel-memory --owner microsoft --showlogin true --sortBy l :---: |:---: |:---: |:---: |:---: |:---: | [aaronpowell](https://github.com/aaronpowell) |[afederici75](https://github.com/afederici75) |[akordowski](https://github.com/akordowski) |[alexibraimov](https://github.com/alexibraimov) |[alexmg](https://github.com/alexmg) |[alkampfergit](https://github.com/alkampfergit) | -[amomra](https://github.com/amomra) |[anthonypuppo](https://github.com/anthonypuppo) |[chaelli](https://github.com/chaelli) |[cherchyk](https://github.com/cherchyk) |[coryisakson](https://github.com/coryisakson) |[crickman](https://github.com/crickman) | +[amomra](https://github.com/amomra) |[anthonypuppo](https://github.com/anthonypuppo) |[carlodek](https://github.com/carlodek) |[chaelli](https://github.com/chaelli) |[cherchyk](https://github.com/cherchyk) |[coryisakson](https://github.com/coryisakson) | :---: |:---: |:---: |:---: |:---: |:---: | -[amomra](https://github.com/amomra) |[anthonypuppo](https://github.com/anthonypuppo) |[chaelli](https://github.com/chaelli) |[cherchyk](https://github.com/cherchyk) |[coryisakson](https://github.com/coryisakson) |[crickman](https://github.com/crickman) | +[amomra](https://github.com/amomra) |[anthonypuppo](https://github.com/anthonypuppo) |[carlodek](https://github.com/carlodek) |[chaelli](https://github.com/chaelli) |[cherchyk](https://github.com/cherchyk) |[coryisakson](https://github.com/coryisakson) | -[dependabot[bot]](https://github.com/apps/dependabot) |[dluc](https://github.com/dluc) |[DM-98](https://github.com/DM-98) |[EelcoKoster](https://github.com/EelcoKoster) |[Foorcee](https://github.com/Foorcee) |[GraemeJones104](https://github.com/GraemeJones104) | +[crickman](https://github.com/crickman) |[dependabot[bot]](https://github.com/apps/dependabot) |[dluc](https://github.com/dluc) |[DM-98](https://github.com/DM-98) |[EelcoKoster](https://github.com/EelcoKoster) |[Foorcee](https://github.com/Foorcee) | :---: |:---: |:---: |:---: |:---: |:---: | -[dependabot[bot]](https://github.com/apps/dependabot) |[dluc](https://github.com/dluc) |[DM-98](https://github.com/DM-98) |[EelcoKoster](https://github.com/EelcoKoster) |[Foorcee](https://github.com/Foorcee) |[GraemeJones104](https://github.com/GraemeJones104) | +[crickman](https://github.com/crickman) |[dependabot[bot]](https://github.com/apps/dependabot) |[dluc](https://github.com/dluc) |[DM-98](https://github.com/DM-98) |[EelcoKoster](https://github.com/EelcoKoster) |[Foorcee](https://github.com/Foorcee) | -[imranshams](https://github.com/imranshams) |[jurepurgar](https://github.com/jurepurgar) |[JustinRidings](https://github.com/JustinRidings) |[kbeaugrand](https://github.com/kbeaugrand) |[koteus](https://github.com/koteus) |[KSemenenko](https://github.com/KSemenenko) | +[GraemeJones104](https://github.com/GraemeJones104) |[imranshams](https://github.com/imranshams) |[jurepurgar](https://github.com/jurepurgar) |[JustinRidings](https://github.com/JustinRidings) |[kbeaugrand](https://github.com/kbeaugrand) |[koteus](https://github.com/koteus) | :---: |:---: |:---: |:---: |:---: |:---: | -[imranshams](https://github.com/imranshams) |[jurepurgar](https://github.com/jurepurgar) |[JustinRidings](https://github.com/JustinRidings) |[kbeaugrand](https://github.com/kbeaugrand) |[koteus](https://github.com/koteus) |[KSemenenko](https://github.com/KSemenenko) | +[GraemeJones104](https://github.com/GraemeJones104) |[imranshams](https://github.com/imranshams) |[jurepurgar](https://github.com/jurepurgar) |[JustinRidings](https://github.com/JustinRidings) |[kbeaugrand](https://github.com/kbeaugrand) |[koteus](https://github.com/koteus) | -[lecramr](https://github.com/lecramr) |[luismanez](https://github.com/luismanez) |[marcominerva](https://github.com/marcominerva) |[neel015](https://github.com/neel015) |[pascalberger](https://github.com/pascalberger) |[pawarsum12](https://github.com/pawarsum12) | +[KSemenenko](https://github.com/KSemenenko) |[lecramr](https://github.com/lecramr) |[luismanez](https://github.com/luismanez) |[marcominerva](https://github.com/marcominerva) |[neel015](https://github.com/neel015) |[pascalberger](https://github.com/pascalberger) | :---: |:---: |:---: |:---: |:---: |:---: | -[lecramr](https://github.com/lecramr) |[luismanez](https://github.com/luismanez) |[marcominerva](https://github.com/marcominerva) |[neel015](https://github.com/neel015) |[pascalberger](https://github.com/pascalberger) |[pawarsum12](https://github.com/pawarsum12) | +[KSemenenko](https://github.com/KSemenenko) |[lecramr](https://github.com/lecramr) |[luismanez](https://github.com/luismanez) |[marcominerva](https://github.com/marcominerva) |[neel015](https://github.com/neel015) |[pascalberger](https://github.com/pascalberger) | -[pradeepr-roboticist](https://github.com/pradeepr-roboticist) |[qihangnet](https://github.com/qihangnet) |[roldengarm](https://github.com/roldengarm) |[setuc](https://github.com/setuc) |[slapointe](https://github.com/slapointe) |[slorello89](https://github.com/slorello89) | +[pawarsum12](https://github.com/pawarsum12) |[pradeepr-roboticist](https://github.com/pradeepr-roboticist) |[qihangnet](https://github.com/qihangnet) |[roldengarm](https://github.com/roldengarm) |[setuc](https://github.com/setuc) |[slapointe](https://github.com/slapointe) | :---: |:---: |:---: |:---: |:---: |:---: | -[pradeepr-roboticist](https://github.com/pradeepr-roboticist) |[qihangnet](https://github.com/qihangnet) |[roldengarm](https://github.com/roldengarm) |[setuc](https://github.com/setuc) |[slapointe](https://github.com/slapointe) |[slorello89](https://github.com/slorello89) | +[pawarsum12](https://github.com/pawarsum12) |[pradeepr-roboticist](https://github.com/pradeepr-roboticist) |[qihangnet](https://github.com/qihangnet) |[roldengarm](https://github.com/roldengarm) |[setuc](https://github.com/setuc) |[slapointe](https://github.com/slapointe) | -[snakex64](https://github.com/snakex64) |[spenavajr](https://github.com/spenavajr) |[TaoChenOSU](https://github.com/TaoChenOSU) |[teresaqhoang](https://github.com/teresaqhoang) |[tomasz-skarzynski](https://github.com/tomasz-skarzynski) |[v-msamovendyuk](https://github.com/v-msamovendyuk) | +[slorello89](https://github.com/slorello89) |[snakex64](https://github.com/snakex64) |[spenavajr](https://github.com/spenavajr) |[TaoChenOSU](https://github.com/TaoChenOSU) |[teresaqhoang](https://github.com/teresaqhoang) |[tomasz-skarzynski](https://github.com/tomasz-skarzynski) | :---: |:---: |:---: |:---: |:---: |:---: | -[snakex64](https://github.com/snakex64) |[spenavajr](https://github.com/spenavajr) |[TaoChenOSU](https://github.com/TaoChenOSU) |[teresaqhoang](https://github.com/teresaqhoang) |[tomasz-skarzynski](https://github.com/tomasz-skarzynski) |[v-msamovendyuk](https://github.com/v-msamovendyuk) | +[slorello89](https://github.com/slorello89) |[snakex64](https://github.com/snakex64) |[spenavajr](https://github.com/spenavajr) |[TaoChenOSU](https://github.com/TaoChenOSU) |[teresaqhoang](https://github.com/teresaqhoang) |[tomasz-skarzynski](https://github.com/tomasz-skarzynski) | -[Valkozaur](https://github.com/Valkozaur) |[vicperdana](https://github.com/vicperdana) |[walexee](https://github.com/walexee) |[westdavidr](https://github.com/westdavidr) |[xbotter](https://github.com/xbotter) | -:---: |:---: |:---: |:---: |:---: | -[Valkozaur](https://github.com/Valkozaur) |[vicperdana](https://github.com/vicperdana) |[walexee](https://github.com/walexee) |[westdavidr](https://github.com/westdavidr) |[xbotter](https://github.com/xbotter) | +[v-msamovendyuk](https://github.com/v-msamovendyuk) |[Valkozaur](https://github.com/Valkozaur) |[vicperdana](https://github.com/vicperdana) |[walexee](https://github.com/walexee) |[westdavidr](https://github.com/westdavidr) |[xbotter](https://github.com/xbotter) | +:---: |:---: |:---: |:---: |:---: |:---: | +[v-msamovendyuk](https://github.com/v-msamovendyuk) |[Valkozaur](https://github.com/Valkozaur) |[vicperdana](https://github.com/vicperdana) |[walexee](https://github.com/walexee) |[westdavidr](https://github.com/westdavidr) |[xbotter](https://github.com/xbotter) | diff --git a/examples/302-dotnet-sk-km-chat/Properties/launchSettings.json.example b/examples/003-dotnet-SemanticKernel-plugin/Properties/launchSettings.json similarity index 57% rename from examples/302-dotnet-sk-km-chat/Properties/launchSettings.json.example rename to examples/003-dotnet-SemanticKernel-plugin/Properties/launchSettings.json index 423ee0064..dea57200c 100644 --- a/examples/302-dotnet-sk-km-chat/Properties/launchSettings.json.example +++ b/examples/003-dotnet-SemanticKernel-plugin/Properties/launchSettings.json @@ -1,11 +1,10 @@ { "profiles": { - "example302": { + "console": { "commandName": "Project", "launchBrowser": false, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "OPENAI_APIKEY": "" + "ASPNETCORE_ENVIRONMENT": "Development" } } } diff --git a/examples/004-dotnet-serverless-custom-pipeline/Properties/launchSettings.json b/examples/004-dotnet-serverless-custom-pipeline/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/004-dotnet-serverless-custom-pipeline/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/005-dotnet-async-memory-custom-pipeline/Properties/launchSettings.json b/examples/005-dotnet-async-memory-custom-pipeline/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/005-dotnet-async-memory-custom-pipeline/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/106-dotnet-retrieve-synthetics/Properties/launchSettings.json b/examples/106-dotnet-retrieve-synthetics/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/106-dotnet-retrieve-synthetics/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/107-dotnet-SemanticKernel-TextCompletion/Properties/launchSettings.json b/examples/107-dotnet-SemanticKernel-TextCompletion/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/107-dotnet-SemanticKernel-TextCompletion/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/109-dotnet-custom-webscraper/Properties/launchSettings.json b/examples/109-dotnet-custom-webscraper/Properties/launchSettings.json new file mode 100644 index 000000000..8ea3fceb9 --- /dev/null +++ b/examples/109-dotnet-custom-webscraper/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/110-dotnet-anthropic/Properties/launchSettings.json b/examples/110-dotnet-anthropic/Properties/launchSettings.json new file mode 100644 index 000000000..8ea3fceb9 --- /dev/null +++ b/examples/110-dotnet-anthropic/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/examples/201-dotnet-serverless-custom-handler/Properties/launchSettings.json b/examples/201-dotnet-serverless-custom-handler/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/201-dotnet-serverless-custom-handler/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/202-dotnet-custom-handler-as-a-service/Properties/launchSettings.json b/examples/202-dotnet-custom-handler-as-a-service/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/202-dotnet-custom-handler-as-a-service/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/203-dotnet-using-KM-nuget/Properties/launchSettings.json b/examples/203-dotnet-using-KM-nuget/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/203-dotnet-using-KM-nuget/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/204-dotnet-ASP.NET-MVC-integration/Properties/launchSettings.json b/examples/204-dotnet-ASP.NET-MVC-integration/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/204-dotnet-ASP.NET-MVC-integration/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/208-dotnet-lmstudio/Properties/launchSettings.json b/examples/208-dotnet-lmstudio/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/208-dotnet-lmstudio/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/212-dotnet-ollama/Properties/launchSettings.json b/examples/212-dotnet-ollama/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/212-dotnet-ollama/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/302-dotnet-sk-km-chat/Properties/.gitignore b/examples/302-dotnet-sk-km-chat/Properties/.gitignore deleted file mode 100644 index 417feb72a..000000000 --- a/examples/302-dotnet-sk-km-chat/Properties/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -launchSettings.json -!launchSettings.json.example diff --git a/examples/302-dotnet-sk-km-chat/Properties/launchSettings.json b/examples/302-dotnet-sk-km-chat/Properties/launchSettings.json new file mode 100644 index 000000000..dea57200c --- /dev/null +++ b/examples/302-dotnet-sk-km-chat/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "console": { + "commandName": "Project", + "launchBrowser": false, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/examples/303-dotnet-aspire/Properties/launchSettings.json b/examples/303-dotnet-aspire/Properties/launchSettings.json new file mode 100644 index 000000000..78acf10fd --- /dev/null +++ b/examples/303-dotnet-aspire/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:30000;http://localhost:30001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:30002", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:30003" + } + }, + "http": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "http://localhost:30001", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:30002", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:30003" + } + } + } +} diff --git a/service/Abstractions/HTTP/SSE.cs b/service/Abstractions/HTTP/SSE.cs index e6d9254fd..f9786d96b 100644 --- a/service/Abstractions/HTTP/SSE.cs +++ b/service/Abstractions/HTTP/SSE.cs @@ -34,8 +34,8 @@ public async static IAsyncEnumerable ParseStreamAsync( buffer.Clear(); if (message.Trim() == DoneMessage) { yield break; } - var memoryAnswer = ParseMessage(message); - if (memoryAnswer != null) { yield return memoryAnswer; } + var value = ParseMessage(message); + if (value != null) { yield return value; } } else { @@ -49,8 +49,8 @@ public async static IAsyncEnumerable ParseStreamAsync( string message = buffer.ToString(); if (message.Trim() == DoneMessage) { yield break; } - var memoryAnswer = ParseMessage(message); - if (memoryAnswer != null) { yield return memoryAnswer; } + var value = ParseMessage(message); + if (value != null) { yield return value; } } } diff --git a/service/Core/Configuration/ConfigEnvVars.cs b/service/Core/Configuration/ConfigEnvVars.cs new file mode 100644 index 000000000..eb4a6d2c2 --- /dev/null +++ b/service/Core/Configuration/ConfigEnvVars.cs @@ -0,0 +1,107 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +namespace Microsoft.KernelMemory.Configuration; + +public static class ConfigEnvVars +{ + /// + /// Generate env vars to override settings in appsettings.json + /// + /// Configuration settings + /// Namespace within the appsettings.json file + /// Environment variables + public static Dictionary GenerateEnvVarsFromObject( + object? source, params string[] parents) + { + if (source == null) { return new Dictionary(StringComparer.OrdinalIgnoreCase); } + + var prefix = GetPrefix(parents); + return GenerateEnvVars(source, prefix); + } + + /// + /// Generate env vars to override settings in appsettings.json, + /// ignoring defaults found in the type. + /// Note: defaults in appsettings.json might differ. + /// + /// Configuration settings + /// Namespace within the appsettings.json file + /// Environment variables + public static Dictionary GenerateEnvVarsFromObjectNoDefaults( + object? source, params string[] parents) + { + if (source == null) { return new Dictionary(StringComparer.OrdinalIgnoreCase); } + + var variables = GenerateEnvVarsFromObject(source, parents); + var prefix = GetPrefix(parents); + + var defaults = GenerateEnvVars(CreateInstanceOfSameType(source), prefix); + foreach (var pair in defaults) + { + if (variables.TryGetValue(pair.Key, out string? value) && value == pair.Value) + { + variables.Remove(pair.Key); + } + } + + return variables; + } + + private static string GetPrefix(params string[] parents) + { + return parents.Length > 0 ? string.Join("__", parents) + "__" : string.Empty; + } + + private static Dictionary GenerateEnvVars(object source, string prefix) + { + var result = new Dictionary(StringComparer.OrdinalIgnoreCase); + var objProperties = source.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); + + foreach (var property in objProperties) + { + var fullKey = $"{prefix}{property.Name}"; + var value = property.GetValue(source); + + if (value is IDictionary dictionary) + { + foreach (var key in dictionary.Keys) + { + if (dictionary[key] != null) + { + var dictKey = $"{fullKey}_{key}"; + result[dictKey] = dictionary[key]?.ToString() ?? string.Empty; + } + } + } + else if (value is IEnumerable enumerable and not string) + { + int index = 0; + foreach (var item in enumerable) + { + var arrayKey = $"{fullKey}__{index}"; + result[arrayKey] = item?.ToString() ?? string.Empty; + index++; + } + } + else if (value != null) + { + result[fullKey] = value.ToString() ?? string.Empty; + } + } + + return result; + } + + private static object CreateInstanceOfSameType(object source) + { + var type = source.GetType(); + var result = Activator.CreateInstance(type); + + return result ?? throw new InvalidOperationException($"Unable to create instance of type {type.FullName}"); + } +} diff --git a/service/Service/.gitignore b/service/Service/.gitignore new file mode 100644 index 000000000..5730a1951 --- /dev/null +++ b/service/Service/.gitignore @@ -0,0 +1,2 @@ +launchSettings.json +*launchSettings.json* diff --git a/service/Service/appsettings.json b/service/Service/appsettings.json index db88ad35c..0a661d6c9 100644 --- a/service/Service/appsettings.json +++ b/service/Service/appsettings.json @@ -1,15 +1,5 @@ { "AllowedHosts": "*", - "Kestrel": { - "Endpoints": { - "Http": { - "Url": "http://*:9001" - } - // "Https": { - // "Url": "https://*:9002" - // } - } - }, "Logging": { "LogLevel": { "Default": "Information", @@ -276,6 +266,15 @@ "GlobalSafetyThreshold": 0.0, "IgnoredWords": [] }, + "AzureAIDocIntel": { + // "APIKey" or "AzureIdentity". + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + // Required when Auth == APIKey + "APIKey": "", + "Endpoint": "" + }, "AzureAISearch": { // "ApiKey" or "AzureIdentity". For other options see . // AzureIdentity: use automatic AAD authentication mechanism. You can test locally @@ -298,15 +297,6 @@ // See https://learn.microsoft.com/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-07-01&tabs=HTTP#request-body "UseStickySessions": false }, - "AzureAIDocIntel": { - // "APIKey" or "AzureIdentity". - // AzureIdentity: use automatic AAD authentication mechanism. You can test locally - // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. - "Auth": "AzureIdentity", - // Required when Auth == APIKey - "APIKey": "", - "Endpoint": "" - }, "AzureBlobs": { // "ConnectionString" or "AzureIdentity". For other options see . // AzureIdentity: use automatic AAD authentication mechanism. You can test locally diff --git a/service/tests/Core.UnitTests/Configuration/ConfigEnvVarsTest.cs b/service/tests/Core.UnitTests/Configuration/ConfigEnvVarsTest.cs new file mode 100644 index 000000000..cb6b84c60 --- /dev/null +++ b/service/tests/Core.UnitTests/Configuration/ConfigEnvVarsTest.cs @@ -0,0 +1,336 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.KernelMemory; +using Microsoft.KernelMemory.Configuration; +using Microsoft.KernelMemory.DocumentStorage.DevTools; +using Microsoft.KernelMemory.FileSystem.DevTools; +using Microsoft.KernelMemory.MemoryStorage.DevTools; +using Microsoft.KernelMemory.Pipeline.Queue.DevTools; +using Microsoft.KernelMemory.Safety.AzureAIContentSafety; +using Microsoft.KM.TestHelpers; +using Xunit.Abstractions; + +namespace Microsoft.KM.Core.UnitTests.Configuration; + +public class ConfigEnvVarsTest : BaseUnitTestCase +{ + public ConfigEnvVarsTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void ItIgnoresDefaultValues() + { + // Arrange + var target = new AzureAIContentSafetyConfig(); + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObjectNoDefaults( + target, "KernelMemory", "Services", "AzureAIContentSafety"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Empty(result); + } + + [Fact] + public void ItWorksForAzureAIContentSafetyConfig() + { + // Arrange + var target = new AzureAIContentSafetyConfig + { + Auth = AzureAIContentSafetyConfig.AuthTypes.APIKey, + Endpoint = "http://endpoint", + APIKey = "xyz", + GlobalSafetyThreshold = 0.35, + IgnoredWords = ["foo", "bar"] + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureAIContentSafety"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(6, result.Count); + Assert.Equal("APIKey", result["KernelMemory__Services__AzureAIContentSafety__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureAIContentSafety__Endpoint"]); + Assert.Equal("xyz", result["KernelMemory__Services__AzureAIContentSafety__APIKey"]); + Assert.Equal("0.35", result["KernelMemory__Services__AzureAIContentSafety__GlobalSafetyThreshold"]); + Assert.Equal("foo", result["KernelMemory__Services__AzureAIContentSafety__IgnoredWords__0"]); + Assert.Equal("bar", result["KernelMemory__Services__AzureAIContentSafety__IgnoredWords__1"]); + } + + [Fact] + public void ItWorksForAzureAIDocIntelConfig() + { + // Arrange + var target = new AzureAIDocIntelConfig + { + Auth = AzureAIDocIntelConfig.AuthTypes.APIKey, + Endpoint = "http://endpoint", + APIKey = "xyz", + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureAIDocIntel"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(3, result.Count); + Assert.Equal("APIKey", result["KernelMemory__Services__AzureAIDocIntel__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureAIDocIntel__Endpoint"]); + Assert.Equal("xyz", result["KernelMemory__Services__AzureAIDocIntel__APIKey"]); + } + + [Fact] + public void ItWorksForAzureAISearchConfig() + { + // Arrange + var target = new AzureAISearchConfig + { + Auth = AzureAISearchConfig.AuthTypes.APIKey, + Endpoint = "http://endpoint", + APIKey = "xyz", + UseHybridSearch = true, + UseStickySessions = true, + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureAISearch"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(5, result.Count); + Assert.Equal("APIKey", result["KernelMemory__Services__AzureAISearch__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureAISearch__Endpoint"]); + Assert.Equal("xyz", result["KernelMemory__Services__AzureAISearch__APIKey"]); + Assert.Equal("True", result["KernelMemory__Services__AzureAISearch__UseHybridSearch"]); + Assert.Equal("True", result["KernelMemory__Services__AzureAISearch__UseStickySessions"]); + } + + [Fact] + public void ItWorksForAzureBlobsConfig() + { + // Arrange + var target = new AzureBlobsConfig + { + Auth = AzureBlobsConfig.AuthTypes.ConnectionString, + ConnectionString = "http://endpoint", + Account = "acct", + AccountKey = "acctKey", + Container = "container name", + EndpointSuffix = "sfx", + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureBlobs"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(6, result.Count); + Assert.Equal("ConnectionString", result["KernelMemory__Services__AzureBlobs__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureBlobs__ConnectionString"]); + Assert.Equal("acct", result["KernelMemory__Services__AzureBlobs__Account"]); + Assert.Equal("acctKey", result["KernelMemory__Services__AzureBlobs__AccountKey"]); + Assert.Equal("container name", result["KernelMemory__Services__AzureBlobs__Container"]); + Assert.Equal("sfx", result["KernelMemory__Services__AzureBlobs__EndpointSuffix"]); + } + + [Fact] + public void ItWorksForAzureOpenAIConfig() + { + // Arrange + var target = new AzureOpenAIConfig + { + APIType = AzureOpenAIConfig.APITypes.ChatCompletion, + Auth = AzureOpenAIConfig.AuthTypes.APIKey, + APIKey = "x y z", + Endpoint = "http://endpoint", + Deployment = "gpt", + MaxTokenTotal = 9000, + Tokenizer = "o200k", + EmbeddingDimensions = 1000, + MaxEmbeddingBatchSize = 10, + MaxRetries = 5, + TrustedCertificateThumbprints = ["abc", "bb"], + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureOpenAIxyz"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(12, result.Count); + Assert.Equal("ChatCompletion", result["KernelMemory__Services__AzureOpenAIxyz__APIType"]); + Assert.Equal("APIKey", result["KernelMemory__Services__AzureOpenAIxyz__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureOpenAIxyz__Endpoint"]); + Assert.Equal("gpt", result["KernelMemory__Services__AzureOpenAIxyz__Deployment"]); + Assert.Equal("9000", result["KernelMemory__Services__AzureOpenAIxyz__MaxTokenTotal"]); + Assert.Equal("o200k", result["KernelMemory__Services__AzureOpenAIxyz__Tokenizer"]); + Assert.Equal("1000", result["KernelMemory__Services__AzureOpenAIxyz__EmbeddingDimensions"]); + Assert.Equal("10", result["KernelMemory__Services__AzureOpenAIxyz__MaxEmbeddingBatchSize"]); + Assert.Equal("5", result["KernelMemory__Services__AzureOpenAIxyz__MaxRetries"]); + Assert.Equal("abc", result["KernelMemory__Services__AzureOpenAIxyz__TrustedCertificateThumbprints__0"]); + Assert.Equal("bb", result["KernelMemory__Services__AzureOpenAIxyz__TrustedCertificateThumbprints__1"]); + } + + [Fact] + public void ItWorksForAzureQueuesConfig() + { + // Arrange + var target = new AzureQueuesConfig + { + Auth = AzureQueuesConfig.AuthTypes.ConnectionString, + ConnectionString = "http://endpoint", + Account = "acct", + AccountKey = "acctKey", + EndpointSuffix = "sfx", + PollDelayMsecs = 5, + FetchBatchSize = 6, + FetchLockSeconds = 7, + MaxRetriesBeforePoisonQueue = 8, + PoisonQueueSuffix = "dl", + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "AzureQueues"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(10, result.Count); + Assert.Equal("ConnectionString", result["KernelMemory__Services__AzureQueues__Auth"]); + Assert.Equal("http://endpoint", result["KernelMemory__Services__AzureQueues__ConnectionString"]); + Assert.Equal("acct", result["KernelMemory__Services__AzureQueues__Account"]); + Assert.Equal("acctKey", result["KernelMemory__Services__AzureQueues__AccountKey"]); + Assert.Equal("sfx", result["KernelMemory__Services__AzureQueues__EndpointSuffix"]); + Assert.Equal("5", result["KernelMemory__Services__AzureQueues__PollDelayMsecs"]); + Assert.Equal("6", result["KernelMemory__Services__AzureQueues__FetchBatchSize"]); + Assert.Equal("7", result["KernelMemory__Services__AzureQueues__FetchLockSeconds"]); + Assert.Equal("8", result["KernelMemory__Services__AzureQueues__MaxRetriesBeforePoisonQueue"]); + Assert.Equal("dl", result["KernelMemory__Services__AzureQueues__PoisonQueueSuffix"]); + } + + [Fact] + public void ItWorksForOpenAIConfig() + { + // Arrange + var target = new OpenAIConfig + { + TextGenerationType = OpenAIConfig.TextGenerationTypes.Chat, + APIKey = "key", + OrgId = "org", + Endpoint = "openai.com", + TextModel = "dv", + TextModelMaxTokenTotal = 100, + TextModelTokenizer = "o200k", + EmbeddingModel = "ada", + EmbeddingModelMaxTokenTotal = 200, + EmbeddingModelTokenizer = "cl100k", + EmbeddingDimensions = 444, + MaxEmbeddingBatchSize = 20, + MaxRetries = 8 + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "OpenAI"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(13, result.Count); + Assert.Equal("Chat", result["KernelMemory__Services__OpenAI__TextGenerationType"]); + Assert.Equal("key", result["KernelMemory__Services__OpenAI__APIKey"]); + Assert.Equal("org", result["KernelMemory__Services__OpenAI__OrgId"]); + Assert.Equal("openai.com", result["KernelMemory__Services__OpenAI__Endpoint"]); + Assert.Equal("dv", result["KernelMemory__Services__OpenAI__TextModel"]); + Assert.Equal("100", result["KernelMemory__Services__OpenAI__TextModelMaxTokenTotal"]); + Assert.Equal("o200k", result["KernelMemory__Services__OpenAI__TextModelTokenizer"]); + Assert.Equal("ada", result["KernelMemory__Services__OpenAI__EmbeddingModel"]); + Assert.Equal("200", result["KernelMemory__Services__OpenAI__EmbeddingModelMaxTokenTotal"]); + Assert.Equal("cl100k", result["KernelMemory__Services__OpenAI__EmbeddingModelTokenizer"]); + Assert.Equal("444", result["KernelMemory__Services__OpenAI__EmbeddingDimensions"]); + Assert.Equal("20", result["KernelMemory__Services__OpenAI__MaxEmbeddingBatchSize"]); + Assert.Equal("8", result["KernelMemory__Services__OpenAI__MaxRetries"]); + } + + [Fact] + public void ItWorksForSimpleFileStorageConfig() + { + // Arrange + var target = new SimpleFileStorageConfig + { + StorageType = FileSystemTypes.Disk, + Directory = "c:/" + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "SimpleFileStorage"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(2, result.Count); + Assert.Equal("Disk", result["KernelMemory__Services__SimpleFileStorage__StorageType"]); + Assert.Equal("c:/", result["KernelMemory__Services__SimpleFileStorage__Directory"]); + } + + [Fact] + public void ItWorksForSimpleVectorDbConfig() + { + // Arrange + var target = new SimpleVectorDbConfig + { + StorageType = FileSystemTypes.Disk, + Directory = "c:/" + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "SimpleVectorDb"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(2, result.Count); + Assert.Equal("Disk", result["KernelMemory__Services__SimpleVectorDb__StorageType"]); + Assert.Equal("c:/", result["KernelMemory__Services__SimpleVectorDb__Directory"]); + } + + [Fact] + public void ItWorksForSimpleQueuesConfig() + { + // Arrange + var target = new SimpleQueuesConfig + { + StorageType = FileSystemTypes.Disk, + Directory = "c:/", + PollDelayMsecs = 1, + DispatchFrequencyMsecs = 2, + FetchBatchSize = 3, + FetchLockSeconds = 4, + MaxRetriesBeforePoisonQueue = 5, + PoisonQueueSuffix = "dl" + }; + + // Act + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject( + target, "KernelMemory", "Services", "SimpleQueues"); + foreach (var v in result) { Console.WriteLine($"{v.Key}: {v.Value}"); } + + // Assert + Assert.Equal(8, result.Count); + Assert.Equal("Disk", result["KernelMemory__Services__SimpleQueues__StorageType"]); + Assert.Equal("c:/", result["KernelMemory__Services__SimpleQueues__Directory"]); + Assert.Equal("1", result["KernelMemory__Services__SimpleQueues__PollDelayMsecs"]); + Assert.Equal("2", result["KernelMemory__Services__SimpleQueues__DispatchFrequencyMsecs"]); + Assert.Equal("3", result["KernelMemory__Services__SimpleQueues__FetchBatchSize"]); + Assert.Equal("4", result["KernelMemory__Services__SimpleQueues__FetchLockSeconds"]); + Assert.Equal("5", result["KernelMemory__Services__SimpleQueues__MaxRetriesBeforePoisonQueue"]); + Assert.Equal("dl", result["KernelMemory__Services__SimpleQueues__PoisonQueueSuffix"]); + } +} diff --git a/tools/AzureBlobUpload/Properties/launchSettings.json.example b/tools/AzureBlobUpload/Properties/launchSettings.json.example new file mode 100644 index 000000000..836b15a7b --- /dev/null +++ b/tools/AzureBlobUpload/Properties/launchSettings.json.example @@ -0,0 +1,15 @@ +{ + "profiles": { + "run": { + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "BLOB_CONN_STRING": "DefaultEndpointsProtocol=https;AccountName=...FOO...;AccountKey=...KEY...;EndpointSuffix=core.windows.net", + "BLOB_CONTAINER": "...NAME...", + "BLOB_PATH": "/", + "DOCUMENT_ID": "...NAME..." + }, + "commandName": "Project", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/tools/README.md b/tools/README.md index a3865e77d..6b772dbaa 100644 --- a/tools/README.md +++ b/tools/README.md @@ -1,33 +1,41 @@ -# Kernel memory web service scripts +# Tools -### upload-file.sh +This folder contains a list of various tools used during development. + +- `aspire` folder: some .NET Aspire configurations +- `dev` folder: build, test, release scripts +- `InteractiveSetup` folder: project used to generate/update `appsettings.development.json` files + +# Kernel Memory from CLI + +### km-cli/upload-file.sh Simple client for command line uploads to Kernel Memory. Instructions: ```bash -./upload-file.sh -h +./km-cli/upload-file.sh -h ``` -### ask.sh +### km-cli/ask.sh Simple client for asking questions about your documents from the command line. Instructions: ```bash -./ask.sh -h +./km-cli/ask.sh -h ``` -### search.sh +### km-cli/search.sh Simple client for searching your indexed documents from the command line. Instructions: ```bash -./search.sh -h +./km-cli/search.sh -h ``` # Vector DB scripts diff --git a/tools/aspire/Aspire.Extensions/Aspire.Extensions.csproj b/tools/aspire/Aspire.Extensions/Aspire.Extensions.csproj new file mode 100644 index 000000000..060b77dbb --- /dev/null +++ b/tools/aspire/Aspire.Extensions/Aspire.Extensions.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + Microsoft.KernelMemory.Aspire + Microsoft.KernelMemory.Aspire + false + $(NoWarn);IDE0058;IDE0160;IDE0008; + + + + + + + + + + + + diff --git a/tools/aspire/Aspire.Extensions/AspireExtensions.cs b/tools/aspire/Aspire.Extensions/AspireExtensions.cs new file mode 100644 index 000000000..d09341b50 --- /dev/null +++ b/tools/aspire/Aspire.Extensions/AspireExtensions.cs @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.KernelMemory.Configuration; + +namespace Microsoft.KernelMemory.Aspire; + +public static class AspireExtensions +{ + public static IResourceBuilder WithKmServiceConfig( + this IResourceBuilder builder, string serviceName, object config) + where T : IResourceWithEnvironment + { + return builder.WithKmConfig(config, "KernelMemory", "Services", serviceName); + } + + public static IResourceBuilder WithKmConfig( + this IResourceBuilder builder, object config, params string[] parents) + where T : IResourceWithEnvironment + { + Dictionary result = ConfigEnvVars.GenerateEnvVarsFromObject(config, parents); + foreach (var v in result) + { + builder.WithEnvironment(v.Key, v.Value); + } + + return builder; + } + + public static IResourceBuilder WithKmTextEmbeddingGenerationEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder + .WithEnvironment("KernelMemory__DataIngestion__EmbeddingGeneratorTypes__0", serviceName ?? "") + .WithEnvironment("KernelMemory__Retrieval__EmbeddingGeneratorType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmTextGenerationEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder.WithEnvironment("KernelMemory__TextGeneratorType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmDocumentStorageEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder.WithEnvironment("KernelMemory__DocumentStorageType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmMemoryDbEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder + .WithEnvironment("KernelMemory__DataIngestion__MemoryDbTypes__0", serviceName ?? "") + .WithEnvironment("KernelMemory__Retrieval__MemoryDbType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmOrchestrationEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder.WithEnvironment("KernelMemory__DataIngestion__DistributedOrchestration__QueueType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmContentSafetyModerationEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder.WithEnvironment("KernelMemory__ContentModerationType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } + + public static IResourceBuilder WithKmOcrEnvironment( + this IResourceBuilder builder, string? serviceName, object? config = null) + where T : IResourceWithEnvironment + { + builder.WithEnvironment("KernelMemory__DataIngestion__ImageOcrType", serviceName ?? ""); + if (serviceName != null && config != null) + { + builder.WithKmServiceConfig(serviceName, config); + } + + return builder; + } +} diff --git a/tools/aspire/all-azure/Program.cs b/tools/aspire/all-azure/Program.cs new file mode 100644 index 000000000..708163472 --- /dev/null +++ b/tools/aspire/all-azure/Program.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.KernelMemory.Safety.AzureAIContentSafety; +using Projects; + +namespace Microsoft.KernelMemory.Aspire.AppHost; + +internal static class Program +{ + private static readonly AzureAIContentSafetyConfig s_azureAIContentSafetyConfig = new(); + private static readonly AzureAIDocIntelConfig s_azureAIDocIntelConfig = new(); + private static readonly AzureAISearchConfig s_azureAISearchConfig = new(); + private static readonly AzureBlobsConfig s_azureBlobsConfig = new(); + private static readonly AzureOpenAIConfig s_azureOpenAIEmbeddingConfig = new(); + private static readonly AzureOpenAIConfig s_azureOpenAITextConfig = new(); + private static readonly AzureQueuesConfig s_azureQueuesConfig = new(); + + internal static void Main() + { + new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddJsonFile("appsettings.development.json", optional: true) + .AddJsonFile("appsettings.Development.json", optional: true) + .Build() + .BindSection("KernelMemory:Services:AzureAIContentSafety", s_azureAIContentSafetyConfig) + .BindSection("KernelMemory:Services:AzureAIDocIntel", s_azureAIDocIntelConfig) + .BindSection("KernelMemory:Services:AzureAISearch", s_azureAISearchConfig) + .BindSection("KernelMemory:Services:AzureBlobs", s_azureBlobsConfig) + .BindSection("KernelMemory:Services:AzureOpenAIEmbedding", s_azureOpenAIEmbeddingConfig) + .BindSection("KernelMemory:Services:AzureOpenAIText", s_azureOpenAITextConfig) + .BindSection("KernelMemory:Services:AzureQueues", s_azureQueuesConfig); + + RunFromCode(); + } + + private static void RunFromCode() + { + var builder = DistributedApplication.CreateBuilder(); + + builder.AddProject("kernel-memory") + .WithHttpEndpoint(targetPort: 20001) + .WithEnvironment("ASPNETCORE_URLS", "http://+:20001") + .WithEnvironment("ASPNETCORE_ENVIRONMENT", "Development") + .WithEnvironment("KernelMemory__Service__OpenApiEnabled", "True") + .WithKmTextEmbeddingGenerationEnvironment("AzureOpenAIEmbedding", s_azureOpenAIEmbeddingConfig) + .WithKmTextGenerationEnvironment("AzureOpenAIText", s_azureOpenAITextConfig) + .WithKmMemoryDbEnvironment("AzureAISearch", s_azureAISearchConfig) + .WithKmOrchestrationEnvironment("AzureQueues", s_azureQueuesConfig) + .WithKmDocumentStorageEnvironment("AzureBlobs", s_azureBlobsConfig) + .WithKmContentSafetyModerationEnvironment("AzureAIContentSafety", s_azureAIContentSafetyConfig) + .WithKmOcrEnvironment("AzureAIDocIntel", s_azureAIDocIntelConfig); + + builder.Build().Run(); + } +} diff --git a/tools/aspire/all-azure/Properties/launchSettings.json b/tools/aspire/all-azure/Properties/launchSettings.json new file mode 100644 index 000000000..72bdeb8df --- /dev/null +++ b/tools/aspire/all-azure/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:20100;http://localhost:20101", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:20102", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:20103" + } + }, + "http": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "http://localhost:20101", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:20102", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20103" + } + } + } +} diff --git a/tools/aspire/all-azure/all-azure.csproj b/tools/aspire/all-azure/all-azure.csproj new file mode 100644 index 000000000..3e837fe47 --- /dev/null +++ b/tools/aspire/all-azure/all-azure.csproj @@ -0,0 +1,26 @@ + + + + + + Exe + net8.0 + enable + enable + true + Microsoft.KernelMemory.Aspire.AppHost + $(NoWarn);IDE0058;IDE0160; + + + + + + + + + + + + + + diff --git a/tools/aspire/all-azure/appsettings.json b/tools/aspire/all-azure/appsettings.json new file mode 100644 index 000000000..ae8033834 --- /dev/null +++ b/tools/aspire/all-azure/appsettings.json @@ -0,0 +1,151 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + }, + "KernelMemory": { + "Services": { + "AzureAIContentSafety": { + // "ApiKey" or "AzureIdentity". For other options see . + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + "Endpoint": "https://<...>", + "APIKey": "", + "GlobalSafetyThreshold": 0.0, + "IgnoredWords": [] + }, + "AzureAISearch": { + // "ApiKey" or "AzureIdentity". For other options see . + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + "Endpoint": "https://<...>", + "APIKey": "", + // Hybrid search is not enabled by default. Note that when using hybrid search + // relevance scores are different, usually lower, than when using just vector search + "UseHybridSearch": false, + // Helps improve relevance score consistency for search services with multiple replicas by + // attempting to route a given request to the same replica for that session. Use this when + // favoring consistent scoring over lower latency. Can adversely affect performance. + // + // Whether to use sticky sessions, which can help getting more consistent results. + // When using sticky sessions, a best-effort attempt will be made to target the same replica set. + // Be wary that reusing the same replica repeatedly can interfere with the load balancing of + // the requests across replicas and adversely affect the performance of the search service. + // + // See https://learn.microsoft.com/rest/api/searchservice/documents/search-post?view=rest-searchservice-2024-07-01&tabs=HTTP#request-body + "UseStickySessions": false + }, + "AzureAIDocIntel": { + // "APIKey" or "AzureIdentity". + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + // Required when Auth == APIKey + "APIKey": "", + "Endpoint": "" + }, + "AzureBlobs": { + // "ConnectionString" or "AzureIdentity". For other options see . + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + // Azure Storage account name, required when using AzureIdentity auth + // Note: you can use an env var 'KernelMemory__Services__AzureBlobs__Account' to set this + "Account": "", + // Container where to create directories and upload files + "Container": "smemory", + // Required when Auth == ConnectionString + // Note: you can use an env var 'KernelMemory__Services__AzureBlobs__ConnectionString' to set this + "ConnectionString": "", + // Setting used only for country clouds + "EndpointSuffix": "core.windows.net" + }, + "AzureOpenAIEmbedding": { + // "ApiKey" or "AzureIdentity" + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + "Endpoint": "https://<...>.openai.azure.com/", + "APIKey": "", + // Your Azure Deployment name + "Deployment": "", + // The max number of tokens supported by model deployed + // See https://learn.microsoft.com/azure/ai-services/openai/concepts/models + "MaxTokenTotal": 8191, + // Which tokenizer to use to correctly measure the size of chunks. + // Supported values: "p50k", "cl100k", "o200k". Leave it empty if unsure. + // - Use p50k for the old text-davinci-003 models + // - Use cl100k for the old gpt-3.4 and gpt-4 family, and for text embedding models + // - Use o200k for the most recent gpt-4o family + "Tokenizer": "cl100k", + // The number of dimensions output embeddings should have. + // Only supported in "text-embedding-3" and later models developed with + // MRL, see https://arxiv.org/abs/2205.13147 + "EmbeddingDimensions": null, + // How many embeddings to calculate in parallel. The max value depends on + // the model and deployment in use. + // See https://learn.microsoft.com/azure/ai-services/openai/reference#embeddings + "MaxEmbeddingBatchSize": 1, + // How many times to retry in case of throttling. + "MaxRetries": 10, + // Thumbprints of certificates that should be trusted for HTTPS requests when SSL policy errors are detected. + // This should only be used for local development when using a proxy to call the OpenAI endpoints. + "TrustedCertificateThumbprints": [] + }, + "AzureOpenAIText": { + // "ApiKey" or "AzureIdentity" + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + "Endpoint": "https://<...>.openai.azure.com/", + "APIKey": "", + "Deployment": "", + // The max number of tokens supported by model deployed + // See https://learn.microsoft.com/azure/ai-services/openai/concepts/models + "MaxTokenTotal": 16384, + // Which tokenizer to use to correctly measure the size of chunks. + // Supported values: "p50k", "cl100k", "o200k". Leave it empty if unsure. + // - Use p50k for the old text-davinci-003 models + // - Use cl100k for the old gpt-3.4 and gpt-4 family, and for text embedding models + // - Use o200k for the most recent gpt-4o family + "Tokenizer": "o200k", + // "ChatCompletion" or "TextCompletion" + "APIType": "ChatCompletion", + // How many times to retry in case of throttling. + "MaxRetries": 10, + // Thumbprints of certificates that should be trusted for HTTPS requests when SSL policy errors are detected. + // This should only be used for local development when using a proxy to call the OpenAI endpoints. + "TrustedCertificateThumbprints": [] + }, + "AzureQueues": { + // "ConnectionString" or "AzureIdentity". For other options see . + // AzureIdentity: use automatic AAD authentication mechanism. You can test locally + // using the env vars AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET. + "Auth": "AzureIdentity", + // Azure Storage account name, required when using AzureIdentity auth + // Note: you can use an env var 'KernelMemory__Services__AzureQueue__Account' to set this + "Account": "", + // Required when Auth == ConnectionString + // Note: you can use an env var 'KernelMemory__Services__AzureQueue__ConnectionString' to set this + "ConnectionString": "", + // Setting used only for country clouds + "EndpointSuffix": "core.windows.net", + // How often to check if there are new messages + "PollDelayMsecs": 100, + // How many messages to fetch at a time + "FetchBatchSize": 3, + // How long to lock messages once fetched. Azure Queue default is 30 secs + "FetchLockSeconds": 300, + // How many times to dequeue a messages and process before moving it to a poison queue + "MaxRetriesBeforePoisonQueue": 20, + // Suffix used for the poison queues. + "PoisonQueueSuffix": "-poison" + } + } + } +} diff --git a/tools/aspire/all-azure/run.sh b/tools/aspire/all-azure/run.sh new file mode 100755 index 000000000..fb33b2f3e --- /dev/null +++ b/tools/aspire/all-azure/run.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "${BASH_SOURCE[0]:-$0}")" + +ASPNETCORE_ENVIRONMENT=Development dotnet run diff --git a/tools/aspire/volatile-openai/Program.cs b/tools/aspire/volatile-openai/Program.cs new file mode 100644 index 000000000..5891970d6 --- /dev/null +++ b/tools/aspire/volatile-openai/Program.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.KernelMemory.DocumentStorage.DevTools; +using Microsoft.KernelMemory.MemoryStorage.DevTools; +using Microsoft.KernelMemory.Pipeline.Queue.DevTools; +using Projects; + +namespace Microsoft.KernelMemory.Aspire.AppHost; + +// Run KM in volatile mode, with OpenAI models +internal static class Program +{ + private static readonly SimpleFileStorageConfig s_simpleFileStorageConfig = new(); + private static readonly SimpleQueuesConfig s_simpleQueuesConfig = new(); + private static readonly SimpleVectorDbConfig s_simpleVectorDbConfig = new(); + private static readonly OpenAIConfig s_openAIConfig = new(); + + internal static void Main() + { + new ConfigurationBuilder() + .AddJsonFile("appsettings.json") + .AddJsonFile("appsettings.development.json", optional: true) + .AddJsonFile("appsettings.Development.json", optional: true) + .Build() + .BindSection("KernelMemory:Services:SimpleFileStorage", s_simpleFileStorageConfig) + .BindSection("KernelMemory:Services:SimpleQueues", s_simpleQueuesConfig) + .BindSection("KernelMemory:Services:SimpleVectorDb", s_simpleVectorDbConfig) + .BindSection("KernelMemory:Services:OpenAI", s_openAIConfig); + + RunFromCode(); + } + + private static void RunFromCode() + { + var builder = DistributedApplication.CreateBuilder(); + builder.AddProject("kernel-memory") + .WithHttpEndpoint(targetPort: 21001) + .WithEnvironment("ASPNETCORE_URLS", "http://+:21001") + .WithEnvironment("ASPNETCORE_ENVIRONMENT", "Development") + .WithEnvironment("KernelMemory__Service__OpenApiEnabled", "True") + .WithKmTextEmbeddingGenerationEnvironment("OpenAI", s_openAIConfig) + .WithKmTextGenerationEnvironment("OpenAI", s_openAIConfig) + .WithKmMemoryDbEnvironment("SimpleVectorDb", s_simpleVectorDbConfig) + .WithKmOrchestrationEnvironment("SimpleQueues", s_simpleQueuesConfig) + .WithKmDocumentStorageEnvironment("SimpleFileStorage", s_simpleFileStorageConfig) + .WithKmContentSafetyModerationEnvironment(null) // ensure moderation is disabled + .WithKmOcrEnvironment(null); // ensure OCR is disabled; + + builder.Build().Run(); + } +} diff --git a/tools/aspire/volatile-openai/Properties/launchSettings.json b/tools/aspire/volatile-openai/Properties/launchSettings.json new file mode 100644 index 000000000..67ee32301 --- /dev/null +++ b/tools/aspire/volatile-openai/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "profiles": { + "https": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "https://localhost:21100;http://localhost:21101", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21102", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:21103" + } + }, + "http": { + "commandName": "Project", + "launchBrowser": true, + "applicationUrl": "http://localhost:21101", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "DOTNET_ENVIRONMENT": "Development", + "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:21102", + "DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:21103" + } + } + } +} diff --git a/tools/aspire/volatile-openai/appsettings.json b/tools/aspire/volatile-openai/appsettings.json new file mode 100644 index 000000000..eda793a16 --- /dev/null +++ b/tools/aspire/volatile-openai/appsettings.json @@ -0,0 +1,46 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning", + "Aspire.Hosting.Dcp": "Warning" + } + }, + "KernelMemory": { + "Services": { + "OpenAI": { + "APIKey": "sk-..." + }, + "SimpleFileStorage": { + // Options: "Disk" or "Volatile". Volatile data is lost after each execution. + "StorageType": "Volatile", + // Directory where files are stored. + "Directory": "_files" + }, + "SimpleQueues": { + // Options: "Disk" or "Volatile". Volatile data is lost after each execution. + "StorageType": "Volatile", + // Directory where files are stored. + "Directory": "_queues", + // How often to check if there are new messages. + "PollDelayMsecs": 100, + // How often to dispatch messages in the queue. + "DispatchFrequencyMsecs": 100, + // How many messages to fetch at a time. + "FetchBatchSize": 3, + // How long to lock messages once fetched. + "FetchLockSeconds": 300, + // How many times to retry processing a failing message. + "MaxRetriesBeforePoisonQueue": 1, + // Suffix used for the poison queue directories + "PoisonQueueSuffix": ".poison" + }, + "SimpleVectorDb": { + // Options: "Disk" or "Volatile". Volatile data is lost after each execution. + "StorageType": "Volatile", + // Directory where files are stored. + "Directory": "_vectors" + }, + } + } +} diff --git a/tools/aspire/volatile-openai/run.sh b/tools/aspire/volatile-openai/run.sh new file mode 100755 index 000000000..fb33b2f3e --- /dev/null +++ b/tools/aspire/volatile-openai/run.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e + +cd "$(dirname "${BASH_SOURCE[0]:-$0}")" + +ASPNETCORE_ENVIRONMENT=Development dotnet run diff --git a/tools/aspire/volatile-openai/volatile-openai.csproj b/tools/aspire/volatile-openai/volatile-openai.csproj new file mode 100644 index 000000000..3e837fe47 --- /dev/null +++ b/tools/aspire/volatile-openai/volatile-openai.csproj @@ -0,0 +1,26 @@ + + + + + + Exe + net8.0 + enable + enable + true + Microsoft.KernelMemory.Aspire.AppHost + $(NoWarn);IDE0058;IDE0160; + + + + + + + + + + + + + + diff --git a/tools/dockerize-amd64.sh b/tools/dev/dockerize-amd64.sh similarity index 88% rename from tools/dockerize-amd64.sh rename to tools/dev/dockerize-amd64.sh index a41a43e8e..7b1d205f4 100755 --- a/tools/dockerize-amd64.sh +++ b/tools/dev/dockerize-amd64.sh @@ -28,8 +28,10 @@ docker buildx build --no-cache --load \ --build-arg RUN_IMAGE_TAG=8.0-alpine-amd64 \ -t ${IMG}${TAG} . -echo "Signing in as ${USR}..." -docker login -u ${USR} +# echo "Signing in as ${USR}..." +# docker login -u ${USR} echo "Pushing ${IMG}${TAG}..." docker push "${IMG}${TAG}" + +echo "Docker image push complete." diff --git a/tools/dockerize-arm64.sh b/tools/dev/dockerize-arm64.sh similarity index 96% rename from tools/dockerize-arm64.sh rename to tools/dev/dockerize-arm64.sh index 3b221b522..37064900e 100755 --- a/tools/dockerize-arm64.sh +++ b/tools/dev/dockerize-arm64.sh @@ -54,8 +54,8 @@ docker buildx build --no-cache --load \ -t ${IMG}${TAG1} -t ${IMG}${TAG2} \ . -echo "Signing in as ${USR}..." -docker login -u ${USR} +# echo "Signing in as ${USR}..." +# docker login -u ${USR} # Push images to Docker registry for IMAGE_TAG in "${TAG1}" "${TAG2}"; do diff --git a/tools/dev/get-azure-token.py b/tools/dev/get-azure-token.py new file mode 100644 index 000000000..6873fff88 --- /dev/null +++ b/tools/dev/get-azure-token.py @@ -0,0 +1,22 @@ +# Copyright (c) Microsoft. All rights reserved. + +# This script generates an Azure access token you might to call +# Azure services directly for some test, e.g. with Postman. + +from azure.identity import DefaultAzureCredential + +def get_azure_access_token(scope): + try: + return DefaultAzureCredential().get_token(scope).token + except Exception as e: + print(f"Error generating token: {e}") + return None + +if __name__ == "__main__": + # Replace the scope with the Azure service you want to call + scope = "https://cognitiveservices.azure.com/.default" + access_token = get_azure_access_token(scope) + if access_token: + print(f"Access Token: {access_token}") + else: + print("Failed to generate access token") diff --git a/tools/ask.sh b/tools/km-cli/ask.sh similarity index 100% rename from tools/ask.sh rename to tools/km-cli/ask.sh diff --git a/tools/search.sh b/tools/km-cli/search.sh similarity index 100% rename from tools/search.sh rename to tools/km-cli/search.sh diff --git a/tools/upload-file.sh b/tools/km-cli/upload-file.sh similarity index 100% rename from tools/upload-file.sh rename to tools/km-cli/upload-file.sh