diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3135ea6dd675..9b83abf2739e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -22,10 +22,12 @@ updates: interval: "weekly" day: "monday" ignore: - # For all System.* and Microsoft.Extensions.* packages, ignore all major version updates + # For all System.* and Microsoft.Extensions/Bcl.* packages, ignore all major version updates - dependency-name: "System.*" update-types: ["version-update:semver-major"] - dependency-name: "Microsoft.Extensions.*" + update-types: ["version-update:semver-major"] + - dependency-name: "Microsoft.Bcl.*" update-types: ["version-update:semver-major"] labels: - ".NET" diff --git a/.github/workflows/dotnet-pr.yml b/.github/workflows/dotnet-pr.yml index 05efaa0b30a0..688a01aa1e0d 100644 --- a/.github/workflows/dotnet-pr.yml +++ b/.github/workflows/dotnet-pr.yml @@ -11,8 +11,6 @@ on: paths: - 'dotnet/**' - 'samples/dotnet/**' - - '**.cs' - - '**.csproj' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/label-title-prefix.yml b/.github/workflows/label-title-prefix.yml index 0ab1aabd42ad..4686e4977c64 100644 --- a/.github/workflows/label-title-prefix.yml +++ b/.github/workflows/label-title-prefix.yml @@ -1,4 +1,4 @@ -name: Add title prefix +name: Label title prefix on: issues: types: [ labeled ] @@ -31,14 +31,22 @@ jobs: const label = '${{ matrix.label }}' const prefix = '${{ matrix.prefix }}' - labelAdded = '${{ github.event.label.name }}' + labelAdded = context.payload.label.name + + // Write the contents of context to console + core.info(JSON.stringify(context, null, 2)) // Get the event name, title and labels let title - if (context.event_name == 'issues') { - title = context.payload.issue.title - } else { - title = context.payload.pull_request.title + switch(context.eventName) { + case 'issues': + title = context.payload.issue.title + break + case 'pull_request': + title = context.payload.pull_request.title + break + default: + core.setFailed('Unrecognited eventName: ' + context.eventName) } let originalTitle = title @@ -61,19 +69,29 @@ jobs: // Update the issue or PR title, if changed if (title != originalTitle ) { - if (context.event_name == 'issues') { - github.rest.issues.update({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - title: title - }); - } else { - github.rest.pulls.update({ - pull_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - title: title - }); + switch(context.eventName) { + case 'issues': + github.rest.issues.update({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: title + }); + break + case 'pull_request': + try { + github.rest.pulls.update({ + pull_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + title: title + }); + } + catch (err) { + core.info("Update PR title failed: " + err.message) + } + break + default: + core.setFailed('Unrecognited eventName: ' + context.eventName) } } diff --git a/.github/workflows/python-integration-tests.yml b/.github/workflows/python-integration-tests.yml index ad77410c9397..78e576d4c7b8 100644 --- a/.github/workflows/python-integration-tests.yml +++ b/.github/workflows/python-integration-tests.yml @@ -7,12 +7,11 @@ name: Python Integration Tests on: workflow_dispatch: push: - branches: [ "main"] - paths: - - 'python/**' + branches: ["main"] + paths: + - "python/**" schedule: - - cron: '0 */12 * * *' # Run every 12 hours: midnight UTC and noon UTC - + - cron: "0 */12 * * *" # Run every 12 hours: midnight UTC and noon UTC permissions: contents: read @@ -25,44 +24,45 @@ jobs: fail-fast: false matrix: python-version: ["3.8", "3.9", "3.10", "3.11"] - os: [ ubuntu-latest, windows-latest, macos-latest ] - + os: [ubuntu-latest, windows-latest, macos-latest] + steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies wtih hnswlib native disabled - if: matrix.os == 'macos-latest' && matrix.python-version == '3.11' - run: | - export HNSWLIB_NO_NATIVE=1 - python -m pip install --upgrade pip setuptools wheel - python -m pip install poetry pytest - cd python && poetry install --with hugging_face --with chromadb --with weaviate - - name: Install dependencies wtih hnswlib native enabled - if: matrix.os != 'macos-latest' || matrix.python-version != '3.11' - run: | - python -m pip install --upgrade pip setuptools wheel - python -m pip install poetry pytest - cd python && poetry install --with hugging_face --with chromadb --with weaviate - - name: Run Integration Tests - shell: bash - env: # Set Azure credentials secret as an input - HNSWLIB_NO_NATIVE: 1 - Python_Integration_Tests: Python_Integration_Tests - AzureOpenAI__Label: azure-text-davinci-003 - AzureOpenAIEmbedding__Label: azure-text-embedding-ada-002 - AzureOpenAI__DeploymentName: ${{ vars.AZUREOPENAI__DEPLOYMENTNAME }} - AzureOpenAIChat__DeploymentName: ${{ vars.AZUREOPENAI__CHAT__DEPLOYMENTNAME }} - AzureOpenAIEmbeddings__DeploymentName: ${{ vars.AZUREOPENAIEMBEDDING__DEPLOYMENTNAME }} - AzureOpenAI__Endpoint: ${{ secrets.AZUREOPENAI__ENDPOINT }} - AzureOpenAIEmbeddings__Endpoint: ${{ secrets.AZUREOPENAI__ENDPOINT }} - AzureOpenAI__ApiKey: ${{ secrets.AZUREOPENAI__APIKEY }} - AzureOpenAIEmbeddings__ApiKey: ${{ secrets.AZUREOPENAI__APIKEY }} - Bing__ApiKey: ${{ secrets.BING__APIKEY }} - OpenAI__ApiKey: ${{ secrets.OPENAI__APIKEY }} - run: | - cd python - poetry run pytest ./tests/integration - + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies with hnswlib native disabled + if: matrix.os == 'macos-latest' && matrix.python-version == '3.11' + run: | + export HNSWLIB_NO_NATIVE=1 + python -m pip install --upgrade pip setuptools wheel + python -m pip install poetry pytest + cd python && poetry install --with hugging_face --with chromadb --with weaviate + - name: Install dependencies with hnswlib native enabled + if: matrix.os != 'macos-latest' || matrix.python-version != '3.11' + run: | + python -m pip install --upgrade pip setuptools wheel + python -m pip install poetry pytest + cd python && poetry install --with hugging_face --with chromadb --with weaviate + - name: Run Integration Tests + shell: bash + env: # Set Azure credentials secret as an input + HNSWLIB_NO_NATIVE: 1 + Python_Integration_Tests: Python_Integration_Tests + AzureOpenAI__Label: azure-text-davinci-003 + AzureOpenAIEmbedding__Label: azure-text-embedding-ada-002 + AzureOpenAI__DeploymentName: ${{ vars.AZUREOPENAI__DEPLOYMENTNAME }} + AzureOpenAIChat__DeploymentName: ${{ vars.AZUREOPENAI__CHAT__DEPLOYMENTNAME }} + AzureOpenAIEmbeddings__DeploymentName: ${{ vars.AZUREOPENAIEMBEDDING__DEPLOYMENTNAME }} + AzureOpenAI__Endpoint: ${{ secrets.AZUREOPENAI__ENDPOINT }} + AzureOpenAIEmbeddings__Endpoint: ${{ secrets.AZUREOPENAI__ENDPOINT }} + AzureOpenAI__ApiKey: ${{ secrets.AZUREOPENAI__APIKEY }} + AzureOpenAIEmbeddings__ApiKey: ${{ secrets.AZUREOPENAI__APIKEY }} + Bing__ApiKey: ${{ secrets.BING__APIKEY }} + OpenAI__ApiKey: ${{ secrets.OPENAI__APIKEY }} + Pinecone__ApiKey: ${{ secrets.PINECONE__APIKEY }} + Pinecone__Environment: ${{ secrets.PINECONE__ENVIRONMENT }} + run: | + cd python + poetry run pytest ./tests/integration diff --git a/.gitignore b/.gitignore index 431046016861..530b14105f74 100644 --- a/.gitignore +++ b/.gitignore @@ -476,4 +476,5 @@ playwright-report/ # Static Web App deployment config swa-cli.config.json -**/copilot-chat-app/webapp/build \ No newline at end of file +**/copilot-chat-app/webapp/build +**/copilot-chat-app/webapp/node_modules \ No newline at end of file diff --git a/README.md b/README.md index 90d2ff27d1d7..4298994ed035 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,12 @@ [![Python package](https://img.shields.io/pypi/v/semantic-kernel)](https://pypi.org/project/semantic-kernel/) [![Nuget package](https://img.shields.io/nuget/vpre/Microsoft.SemanticKernel)](https://www.nuget.org/packages/Microsoft.SemanticKernel/) -[![dotnet](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci.yml/badge.svg?branch=main)](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci.yml) +[![dotnet Docker](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci-docker.yml/badge.svg?branch=main)](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci-docker.yml) +[![dotnet Windows](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci-windows.yml/badge.svg?branch=main)](https://github.com/microsoft/semantic-kernel/actions/workflows/dotnet-ci-windows.yml) [![License: MIT](https://img.shields.io/github/license/microsoft/semantic-kernel)](https://github.com/microsoft/semantic-kernel/blob/main/LICENSE) [![Discord](https://img.shields.io/discord/1063152441819942922?label=Discord&logo=discord&logoColor=white&color=d82679)](https://aka.ms/SKDiscord) -> ℹ️ **NOTE**:This project is just like AI and will evolve quickly. +> ℹ️ **NOTE**: This project is just like AI and will evolve quickly. > We invite you to join us in developing the Semantic Kernel together! > Please contribute by > using GitHub [Discussions](https://github.com/microsoft/semantic-kernel/discussions), @@ -43,16 +44,24 @@ in the history of computing. Semantic Kernel is available to explore AI and build apps with C# and Python: -
- -Using Semantic Kernel in C#. -
- -
- -Using Semantic Kernel in Python. -
-
+ + + + + + + +
+ +
+ Using Semantic Kernel in C#   +
+
+ +
+ Using Semantic Kernel in Python +
+
See the [Feature Matrix](FEATURE_MATRIX.md) to see a breakdown of feature parity between C# and Python. @@ -60,14 +69,16 @@ The quickest way to get started with the basics is to get an API key (OpenAI or Azure OpenAI) and to run one of the C# or Python console applications/scripts: -For C#: +### For C#: + 1. Create a new console app. 2. Add the semantic kernel nuget `Microsoft.SemanticKernel`. 3. Copy the code from [here](dotnet/README.md) into the app `Program.cs` file. 4. Replace the configuration placeholders for API key and other params with your key and settings. 5. Run with `F5` or `dotnet run` -For Python: +### For Python: + 1. Install the pip package: `python -m pip install semantic-kernel`. 2. Create a new script e.g. `hello-world.py`. 3. Store your API key and settings in an `.env` file as described [here](python/README.md). diff --git a/dotnet/Directory.Packages.props b/dotnet/Directory.Packages.props index ffc5453ed78b..465f3f3711e9 100644 --- a/dotnet/Directory.Packages.props +++ b/dotnet/Directory.Packages.props @@ -44,7 +44,7 @@ - + diff --git a/dotnet/SK-dotnet.sln b/dotnet/SK-dotnet.sln index c2e04a6b16e7..f6f1bfd35c2f 100644 --- a/dotnet/SK-dotnet.sln +++ b/dotnet/SK-dotnet.sln @@ -62,8 +62,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "connectors", "connectors", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.UnitTests", "src\Connectors\Connectors.UnitTests\Connectors.UnitTests.csproj", "{EB3FC57F-E591-4C88-BCD5-B6A1BC635168}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CopilotChatWebApi", "..\samples\apps\copilot-chat-app\webapi\CopilotChatWebApi.csproj", "{CCABF515-2C79-453E-A5A2-69C69B8D172E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.Qdrant", "src\Connectors\Connectors.Memory.Qdrant\Connectors.Memory.Qdrant.csproj", "{5DEBAA62-F117-496A-8778-FED3604B70E2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Connectors.Memory.Sqlite", "src\Connectors\Connectors.Memory.Sqlite\Connectors.Memory.Sqlite.csproj", "{EC004F12-2F60-4EDD-B3CD-3A504900D929}" @@ -243,9 +241,6 @@ Global {EB3FC57F-E591-4C88-BCD5-B6A1BC635168}.Publish|Any CPU.Build.0 = Release|Any CPU {EB3FC57F-E591-4C88-BCD5-B6A1BC635168}.Release|Any CPU.ActiveCfg = Release|Any CPU {EB3FC57F-E591-4C88-BCD5-B6A1BC635168}.Release|Any CPU.Build.0 = Release|Any CPU - {CCABF515-2C79-453E-A5A2-69C69B8D172E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CCABF515-2C79-453E-A5A2-69C69B8D172E}.Publish|Any CPU.ActiveCfg = Release|Any CPU - {CCABF515-2C79-453E-A5A2-69C69B8D172E}.Release|Any CPU.ActiveCfg = Release|Any CPU {5DEBAA62-F117-496A-8778-FED3604B70E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5DEBAA62-F117-496A-8778-FED3604B70E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {5DEBAA62-F117-496A-8778-FED3604B70E2}.Publish|Any CPU.ActiveCfg = Publish|Any CPU @@ -403,7 +398,6 @@ Global {BC70A5D8-2125-4C37-8C0E-C903EAFA9772} = {FA3720F1-C99A-49B2-9577-A940257098BF} {0247C2C9-86C3-45BA-8873-28B0948EDC0C} = {831DDCA2-7D2C-4C31-80DB-6BDB3E1F7AE0} {EB3FC57F-E591-4C88-BCD5-B6A1BC635168} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} - {CCABF515-2C79-453E-A5A2-69C69B8D172E} = {FA3720F1-C99A-49B2-9577-A940257098BF} {5DEBAA62-F117-496A-8778-FED3604B70E2} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} {EC004F12-2F60-4EDD-B3CD-3A504900D929} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} {EA61C289-7928-4B78-A9C1-7AAD61F907CD} = {0247C2C9-86C3-45BA-8873-28B0948EDC0C} diff --git a/dotnet/src/Connectors/Connectors.Memory.Redis/README.md b/dotnet/src/Connectors/Connectors.Memory.Redis/README.md index 48352222ff60..4d7c62bbe2ba 100644 --- a/dotnet/src/Connectors/Connectors.Memory.Redis/README.md +++ b/dotnet/src/Connectors/Connectors.Memory.Redis/README.md @@ -1,15 +1,15 @@ # Microsoft.SemanticKernel.Connectors.Memory.Redis -This connector uses Redis to implement Semantic Memory. It requires the [RediSearch](https://redis.io/docs/stack/search) module to be enabled on Redis to implement vector similarity search. +This connector uses Redis to implement Semantic Memory. It requires the [RediSearch](https://redis.io/docs/interact/search-and-query/) module to be enabled on Redis to implement vector similarity search. ## What is RediSearch? -[RediSearch](https://redis.io/docs/stack/search) is a source-available Redis module that enables querying, secondary indexing, and full-text search for Redis. These features enable multi-field queries, aggregation, exact phrase matching, numeric filtering, geo filtering and vector similarity semantic search on top of text queries. +[RediSearch](https://redis.io/docs/interact/search-and-query/) is a source-available Redis module that enables querying, secondary indexing, and full-text search for Redis. These features enable multi-field queries, aggregation, exact phrase matching, numeric filtering, geo filtering and vector similarity semantic search on top of text queries. Ways to get RediSearch: 1. You can create an [Azure Cache for Redis Enterpise instance](https://learn.microsoft.com/azure/azure-cache-for-redis/quickstart-create-redis-enterprise) and [enable RediSearch module](https://learn.microsoft.com/azure/azure-cache-for-redis/cache-redis-modules). -1. Set up the RediSearch on your self-managed Redis, please refer to its [documentation](https://redis.io/docs/stack/search/quick_start/). +1. Set up the RediSearch on your self-managed Redis, please refer to its [documentation](https://redis.io/docs/interact/search-and-query/quickstart/). 1. Use the [Redis Enterprise](https://redis.io/docs/about/redis-enterprise/), see [Azure Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/apps/garantiadata.redis_enterprise_1sp_public_preview?tab=Overview), [AWS Marketplace](https://aws.amazon.com/marketplace/pp/prodview-e6y7ork67pjwg?sr=0-2&ref_=beagle&applicationId=AWSMPContessa), or [Google Marketplace](https://console.cloud.google.com/marketplace/details/redislabs-public/redis-enterprise?pli=1). diff --git a/python/poetry.lock b/python/poetry.lock index 9c0e2b93b1c7..a29c4d7b0c45 100644 --- a/python/poetry.lock +++ b/python/poetry.lock @@ -2892,28 +2892,28 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.0.276" +version = "0.0.277" description = "An extremely fast Python linter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.0.276-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:c150912b8ebde843c10b33db90705d4fee48db6f05441e5d143be9f4c2f35df5"}, - {file = "ruff-0.0.276-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:5e9cd7238d34f24d7ccfadcce4dc6807b8c5a390f547dd7236d06488d9d6f40f"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc7dc557cc3fa2a03a88e99425ceee91429cc7432e5a41087850c1629294faed"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13e5983836ae383c04de213954da731f14ea884aaf74467abc47e1d79d8cf1b7"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4ac65df96be3e2f4b10bc97bbb624152281611b06ef1068d5bb064b7ad35d800"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d070a64de4affd17e006d6986ef25601dbbc6b373844ece5396c33900f8b8563"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2edcd6948a21fa7fb4594094da37a1aa1d205b7abaa718bd27d48ba1d7977348"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57c49b525d8ca3838d8b614f42e342077bed95aedd9fe6e6ec419f39320c214e"}, - {file = "ruff-0.0.276-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5980960a748ada3ddfe4ea7ff3a01b9113c456a14cb1a39b4c30783012d4cba6"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:12be4f007114cf5ed1242e522762651539521ec32ae0210cc4b8dfe434a872f0"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:6ed8fc729b3e7b9f20a4e2aa6f24c798b06912f8a94cb3e8fd590eba055780df"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_i686.whl", hash = "sha256:735d724031212c2ab63fafdea49d4581ae866a1180d06c29b0b5481228ca6bb9"}, - {file = "ruff-0.0.276-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:100ad9055d50977c2b4ab3de0db62d6e525bcd4aafbb660a842733bdbf650be9"}, - {file = "ruff-0.0.276-py3-none-win32.whl", hash = "sha256:1b34a3673b2e5d97df8f7f04090c0b74e9ae6d3d172921d0e0781192954afddf"}, - {file = "ruff-0.0.276-py3-none-win_amd64.whl", hash = "sha256:02deadc0f6abead6cc2d38ddd7100a52aba27a0d90315facaa44b8b4acdba162"}, - {file = "ruff-0.0.276-py3-none-win_arm64.whl", hash = "sha256:a6bd5b53ac689a43c7afc45bd574a7b3efe0ceb192e26e95a055c770ef2045b9"}, - {file = "ruff-0.0.276.tar.gz", hash = "sha256:d456c86eb6ce9225507f24fcc7bf72fa031bb7cc750023310e62889bf4ad4b6a"}, + {file = "ruff-0.0.277-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:3250b24333ef419b7a232080d9724ccc4d2da1dbbe4ce85c4caa2290d83200f8"}, + {file = "ruff-0.0.277-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:3e60605e07482183ba1c1b7237eca827bd6cbd3535fe8a4ede28cbe2a323cb97"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7baa97c3d7186e5ed4d5d4f6834d759a27e56cf7d5874b98c507335f0ad5aadb"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74e4b206cb24f2e98a615f87dbe0bde18105217cbcc8eb785bb05a644855ba50"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:479864a3ccd8a6a20a37a6e7577bdc2406868ee80b1e65605478ad3b8eb2ba0b"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:468bfb0a7567443cec3d03cf408d6f562b52f30c3c29df19927f1e0e13a40cd7"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f32ec416c24542ca2f9cc8c8b65b84560530d338aaf247a4a78e74b99cd476b4"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14a7b2f00f149c5a295f188a643ac25226ff8a4d08f7a62b1d4b0a1dc9f9b85c"}, + {file = "ruff-0.0.277-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9879f59f763cc5628aa01c31ad256a0f4dc61a29355c7315b83c2a5aac932b5"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f612e0a14b3d145d90eb6ead990064e22f6f27281d847237560b4e10bf2251f3"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:323b674c98078be9aaded5b8b51c0d9c424486566fb6ec18439b496ce79e5998"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3a43fbe026ca1a2a8c45aa0d600a0116bec4dfa6f8bf0c3b871ecda51ef2b5dd"}, + {file = "ruff-0.0.277-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:734165ea8feb81b0d53e3bf523adc2413fdb76f1264cde99555161dd5a725522"}, + {file = "ruff-0.0.277-py3-none-win32.whl", hash = "sha256:88d0f2afb2e0c26ac1120e7061ddda2a566196ec4007bd66d558f13b374b9efc"}, + {file = "ruff-0.0.277-py3-none-win_amd64.whl", hash = "sha256:6fe81732f788894a00f6ade1fe69e996cc9e485b7c35b0f53fb00284397284b2"}, + {file = "ruff-0.0.277-py3-none-win_arm64.whl", hash = "sha256:2d4444c60f2e705c14cd802b55cd2b561d25bf4311702c463a002392d3116b22"}, + {file = "ruff-0.0.277.tar.gz", hash = "sha256:2dab13cdedbf3af6d4427c07f47143746b6b95d9e4a254ac369a0edb9280a0d2"}, ] [[package]] @@ -4030,4 +4030,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "c6ee54067fdd4be0d299566b56523b15240ea16adbefa1269b561854bd503cfa" +content-hash = "9ae4e4236289823b370e24a704d54c886e213a81e03a96bb6381db4e24442ebe" diff --git a/python/pyproject.toml b/python/pyproject.toml index 67783805d8a7..6c6998c71bc3 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -19,7 +19,7 @@ pre-commit = "3.3.3" black = {version = "23.3.0", allow-prereleases = true} ipykernel = "^6.21.1" pytest = "7.4.0" -ruff = "0.0.276" +ruff = "0.0.277" pytest-asyncio = "0.21.0" [tool.poetry.group.hugging_face.dependencies] diff --git a/python/tests/integration/connectors/memory/test_pinecone.py b/python/tests/integration/connectors/memory/test_pinecone.py index 6e0427b940fa..f73a91617aea 100644 --- a/python/tests/integration/connectors/memory/test_pinecone.py +++ b/python/tests/integration/connectors/memory/test_pinecone.py @@ -25,12 +25,12 @@ def get_pinecone_config(): if "Python_Integration_Tests" in os.environ: api_key = os.environ["Pinecone__ApiKey"] - org_id = None + environment = os.environ["Pinecone__Environment"] else: # Load credentials from .env file - api_key, org_id = sk.pinecone_settings_from_dot_env() + api_key, environment = sk.pinecone_settings_from_dot_env() - return api_key, org_id + return api_key, environment @pytest.fixture diff --git a/samples/apps/copilot-chat-app/CopilotChat.sln b/samples/apps/copilot-chat-app/CopilotChat.sln new file mode 100644 index 000000000000..1135cca43bdc --- /dev/null +++ b/samples/apps/copilot-chat-app/CopilotChat.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33706.43 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CopilotChatWebApi", "webapi\CopilotChatWebApi.csproj", "{5252E68F-B653-44CE-9A32-360A75C54E0E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5252E68F-B653-44CE-9A32-360A75C54E0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5252E68F-B653-44CE-9A32-360A75C54E0E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5252E68F-B653-44CE-9A32-360A75C54E0E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5252E68F-B653-44CE-9A32-360A75C54E0E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {971570D3-60EA-4EE4-980C-0BDA3E66E741} + EndGlobalSection +EndGlobal diff --git a/samples/apps/copilot-chat-app/deploy/README.md b/samples/apps/copilot-chat-app/deploy/README.md index 498c4606324f..95753a2f1883 100644 --- a/samples/apps/copilot-chat-app/deploy/README.md +++ b/samples/apps/copilot-chat-app/deploy/README.md @@ -76,7 +76,7 @@ chmod +x ./deploy-webapi.sh ### App registration (identity) You will need an Azure Active Directory (AAD) application registration. > For details on creating an application registration, go [here](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app). -- Select `Single-page application (SPA)` as platform type, and set the Web redirect URI to `http://localhost:3000` +- Select `Single-page application (SPA)` as platform type, and set the redirect URI to `http://localhost:3000` - Select `Accounts in any organizational directory and personal Microsoft Accounts` as supported account types for this sample. - Make a note of the `Application (client) ID` from the Azure Portal for use in the `Deploy` below. @@ -98,7 +98,7 @@ npm install -g @azure/static-web-apps-cli ./deploy-webapp.sh --subscription {YOUR_SUBSCRIPTION_ID} --resource-group rg-{YOUR_DEPLOYMENT_NAME} --deployment-name {YOUR_DEPLOYMENT_NAME} --application-id {YOUR_APPLICATION_ID} ``` -Your CoplitChat application is now deployed! +Your CopilotChat application is now deployed! # Appendix diff --git a/samples/apps/copilot-chat-app/deploy/deploy-webapp.ps1 b/samples/apps/copilot-chat-app/deploy/deploy-webapp.ps1 index 67eb21f38513..e9997946bdcb 100644 --- a/samples/apps/copilot-chat-app/deploy/deploy-webapp.ps1 +++ b/samples/apps/copilot-chat-app/deploy/deploy-webapp.ps1 @@ -35,16 +35,16 @@ if ($LASTEXITCODE -ne 0) { Write-Host "Setting subscription to '$Subscription'..." az account set -s $Subscription if ($LASTEXITCODE -ne 0) { - exit $LASTEXITCODE + exit $LASTEXITCODE } Write-Host "Getting deployment outputs..." -$deployment=$(az deployment group show --name $DeploymentName --resource-group $ResourceGroupName --output json | ConvertFrom-Json) -$webappUrl=$deployment.properties.outputs.webappUrl.value -$webappName=$deployment.properties.outputs.webappName.value -$webapiUrl=$deployment.properties.outputs.webapiUrl.value -$webapiName=$deployment.properties.outputs.webapiName.value -$webapiApiKey=($(az webapp config appsettings list --name $webapiName --resource-group $ResourceGroupName | ConvertFrom-JSON) | Where-Object -Property name -EQ -Value Authorization:ApiKey).value +$deployment = $(az deployment group show --name $DeploymentName --resource-group $ResourceGroupName --output json | ConvertFrom-Json) +$webappUrl = $deployment.properties.outputs.webappUrl.value +$webappName = $deployment.properties.outputs.webappName.value +$webapiUrl = $deployment.properties.outputs.webapiUrl.value +$webapiName = $deployment.properties.outputs.webapiName.value +$webapiApiKey = ($(az webapp config appsettings list --name $webapiName --resource-group $ResourceGroupName | ConvertFrom-JSON) | Where-Object -Property name -EQ -Value Authorization:ApiKey).value Write-Host "webappUrl: $webappUrl" Write-Host "webappName: $webappName" Write-Host "webapiName: $webapiName" @@ -53,7 +53,7 @@ Write-Host "webapiUrl: $webapiUrl" # Set UTF8 as default encoding for Out-File $PSDefaultParameterValues['Out-File:Encoding'] = 'ascii' -$envFilePath="$PSScriptRoot/../webapp/.env" +$envFilePath = "$PSScriptRoot/../webapp/.env" Write-Host "Writing environment variables to '$envFilePath'..." "REACT_APP_BACKEND_URI=https://$webapiUrl/" | Out-File -FilePath $envFilePath "REACT_APP_AAD_AUTHORITY=https://login.microsoftonline.com/common" | Out-File -FilePath $envFilePath -Append @@ -74,7 +74,7 @@ Push-Location -Path "$PSScriptRoot/../webapp" Write-Host "Installing yarn dependencies..." yarn install if ($LASTEXITCODE -ne 0) { - exit $LASTEXITCODE + exit $LASTEXITCODE } Write-Host "Building webapp..." @@ -89,19 +89,34 @@ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } -Write-Host "Updating AAD App registration..." -az ad app update --id $ApplicationClientId --web-redirect-uris "https://$webappUrl" -if ($LASTEXITCODE -ne 0) { - exit $LASTEXITCODE -} - - $origin = "https://$webappUrl" Write-Host "Ensuring CORS origin '$origin' to webapi '$webapiName'..." if (-not ((az webapp cors show --name $webapiName --resource-group $ResourceGroupName --subscription $Subscription | ConvertFrom-Json).allowedOrigins -contains $origin)) { az webapp cors add --name $webapiName --resource-group $ResourceGroupName --subscription $Subscription --allowed-origins $origin } +Write-Host "Ensuring '$origin' is included in AAD app registration's redirect URIs..." +$objectId = (az ad app show --id $ApplicationClientId | ConvertFrom-Json).id +$redirectUris = (az rest --method GET --uri "https://graph.microsoft.com/v1.0/applications/$objectId" --headers 'Content-Type=application/json' | ConvertFrom-Json).spa.redirectUris +if ($redirectUris -notcontains "$origin") { + $redirectUris += "$origin" + + $body = "{spa:{redirectUris:[" + foreach ($uri in $redirectUris) { + $body += "'$uri'," + } + $body += "]}}" + + az rest ` + --method PATCH ` + --uri "https://graph.microsoft.com/v1.0/applications/$objectId" ` + --headers 'Content-Type=application/json' ` + --body $body +} +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} + Pop-Location Write-Host "To verify your deployment, go to 'https://$webappUrl' in your browser." diff --git a/samples/apps/copilot-chat-app/deploy/deploy-webapp.sh b/samples/apps/copilot-chat-app/deploy/deploy-webapp.sh index 7452ccce5307..13b49c6e46b4 100644 --- a/samples/apps/copilot-chat-app/deploy/deploy-webapp.sh +++ b/samples/apps/copilot-chat-app/deploy/deploy-webapp.sh @@ -90,9 +90,6 @@ cat $SWA_CONFIG_FILE_PATH pushd "$SCRIPT_ROOT/../webapp" -ORIGIN="https://$WEB_APP_URL" -echo "Ensuring CORS origin '$ORIGIN' to webapi '$WEB_API_NAME'..." - echo "Installing yarn dependencies..." yarn install if [ $? -ne 0 ]; then @@ -114,21 +111,32 @@ if [ $? -ne 0 ]; then exit 1 fi -echo "Updating AAD App registration..." -az ad app update --id $ApplicationClientId --web-redirect-uris "https://$webappUrl" -if [ $? -ne 0 ]; then - echo "update the AAD App registration failed" - exit 1 -fi - - - ORIGIN="https://$WEB_APP_URL" echo "Ensuring CORS origin '$ORIGIN' to webapi '$WEB_API_NAME'..." CORS_RESULT=$(az webapp cors show --name $WEB_API_NAME --resource-group $RESOURCE_GROUP --subscription $SUBSCRIPTION | jq '.allowedOrigins | index("$ORIGIN")') if [[ "$CORS_RESULT" == "null" ]]; then echo "Adding CORS origin '$ORIGIN' to webapi '$WEB_API_NAME'..." - az webapp cors add --name $WEB_API_NAME --resource-group $RESOURCE_GROUP --subscription $SUBSCRIPTION --allowed-origins $origin + az webapp cors add --name $WEB_API_NAME --resource-group $RESOURCE_GROUP --subscription $SUBSCRIPTION --allowed-origins $ORIGIN +fi + +echo "Ensuring '$ORIGIN' is included in AAD app registration's redirect URIs..." +eval OBJECT_ID=$(az ad app show --id $APPLICATION_ID | jq -r '.id') + +REDIRECT_URIS=$(az rest --method GET --uri "https://graph.microsoft.com/v1.0/applications/$OBJECT_ID" --headers 'Content-Type=application/json' | jq -r '.spa.redirectUris') +if [[ ! "$REDIRECT_URIS" =~ "$ORIGIN" ]]; then + BODY="{spa:{redirectUris:['" + eval BODY+=$(echo $REDIRECT_URIS | jq $'join("\',\'")') + BODY+="','$ORIGIN']}}" + + az rest \ + --method PATCH \ + --uri "https://graph.microsoft.com/v1.0/applications/$OBJECT_ID" \ + --headers 'Content-Type=application/json' \ + --body $BODY +fi +if [ $? -ne 0 ]; then + echo "Failed to update app registration" + exit 1 fi popd diff --git a/samples/apps/copilot-chat-app/webapi/ConfigurationExtensions.cs b/samples/apps/copilot-chat-app/webapi/ConfigurationExtensions.cs index 5edc161465c4..81e7bf3697a4 100644 --- a/samples/apps/copilot-chat-app/webapi/ConfigurationExtensions.cs +++ b/samples/apps/copilot-chat-app/webapi/ConfigurationExtensions.cs @@ -37,7 +37,7 @@ public static IHostBuilder AddConfiguration(this IHostBuilder host) reloadOnChange: true); // For settings from Key Vault, see https://learn.microsoft.com/en-us/aspnet/core/security/key-vault-configuration?view=aspnetcore-8.0 - string? keyVaultUri = builderContext.Configuration["KeyVaultUri"]; + string? keyVaultUri = builderContext.Configuration["Service:KeyVault"]; if (!string.IsNullOrWhiteSpace(keyVaultUri)) { configBuilder.AddAzureKeyVault( diff --git a/samples/apps/copilot-chat-app/webapi/Options/ServiceOptions.cs b/samples/apps/copilot-chat-app/webapi/Options/ServiceOptions.cs index 58c05547297b..31f7d6d81ef2 100644 --- a/samples/apps/copilot-chat-app/webapi/Options/ServiceOptions.cs +++ b/samples/apps/copilot-chat-app/webapi/Options/ServiceOptions.cs @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -using System; using System.ComponentModel.DataAnnotations; namespace SemanticKernel.Service.Options; @@ -16,7 +15,7 @@ public class ServiceOptions /// Configuration Key Vault URI /// [Url] - public Uri? KeyVaultUri { get; set; } + public string? KeyVault { get; set; } /// /// Local directory in which to load semantic skills. diff --git a/samples/apps/copilot-chat-app/webapi/appsettings.json b/samples/apps/copilot-chat-app/webapi/appsettings.json index a48432da495f..224678239fdc 100644 --- a/samples/apps/copilot-chat-app/webapi/appsettings.json +++ b/samples/apps/copilot-chat-app/webapi/appsettings.json @@ -17,7 +17,7 @@ // "Service": { // "SemanticSkillsDirectory": "", - // "KeyVaultUri": "" + // "KeyVault": "" }, // diff --git a/samples/apps/copilot-chat-app/webapp/src/App.tsx b/samples/apps/copilot-chat-app/webapp/src/App.tsx index e1fbb3268803..0492afc80176 100644 --- a/samples/apps/copilot-chat-app/webapp/src/App.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/App.tsx @@ -12,11 +12,11 @@ import BackendProbe from './components/views/BackendProbe'; import { ChatView } from './components/views/ChatView'; import Loading from './components/views/Loading'; import { Login } from './components/views/Login'; +import { AlertType } from './libs/models/AlertType'; import { useChat } from './libs/useChat'; import { useAppDispatch, useAppSelector } from './redux/app/hooks'; import { RootState } from './redux/app/store'; -import { removeAlert } from './redux/features/app/appSlice'; -import { setLoggedInUserId } from './redux/features/conversations/conversationsSlice'; +import { addAlert, removeAlert, setActiveUserInfo } from './redux/features/app/appSlice'; import { CopilotChatTokens } from './styles'; export const useClasses = makeStyles({ @@ -64,14 +64,29 @@ const App: FC = () => { const dispatch = useAppDispatch(); const { instance, inProgress } = useMsal(); - const account = instance.getActiveAccount(); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); const isAuthenticated = useIsAuthenticated(); const chat = useChat(); useEffect(() => { - if (isAuthenticated && account) { - dispatch(setLoggedInUserId(account.homeAccountId)); + if (isAuthenticated) { + let isActiveUserInfoSet = activeUserInfo !== undefined; + if (!isActiveUserInfoSet) { + const account = instance.getActiveAccount(); + if (!account) { + dispatch(addAlert({ type: AlertType.Error, message: 'Unable to get active logged in account.' })); + } else { + dispatch( + setActiveUserInfo({ + id: account.homeAccountId, + email: account.username, // username in an AccountInfo object is the email address + username: account.name ?? account.username, + }), + ); + } + isActiveUserInfoSet = true; + } if (appState === AppState.LoadingChats) { // Load all chats from memory @@ -82,6 +97,7 @@ const App: FC = () => { }); } } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [instance, inProgress, isAuthenticated, appState]); diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx index 22e21ce95f5f..83127310903b 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx @@ -76,7 +76,6 @@ interface ChatInputProps { export const ChatInput: React.FC = ({ isDraggingOver, onDragLeave, onSubmit }) => { const classes = useClasses(); const { instance, inProgress } = useMsal(); - const account = instance.getActiveAccount(); const chat = useChat(); const dispatch = useAppDispatch(); const [value, setValue] = React.useState(''); @@ -85,6 +84,7 @@ export const ChatInput: React.FC = ({ isDraggingOver, onDragLeav const [documentImporting, setDocumentImporting] = React.useState(false); const documentFileRef = useRef(null); const { conversations, selectedId } = useAppSelector((state: RootState) => state.conversations); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); React.useEffect(() => { async function initSpeechRecognizer() { @@ -189,7 +189,7 @@ export const ChatInput: React.FC = ({ isDraggingOver, onDragLeav } // User is considered typing if the input is in focus dispatch( - updateUserIsTyping({ userId: account?.homeAccountId, chatId: selectedId, isTyping: true }), + updateUserIsTyping({ userId: activeUserInfo?.id, chatId: selectedId, isTyping: true }), ); }} onChange={(_event, data) => { @@ -209,7 +209,7 @@ export const ChatInput: React.FC = ({ isDraggingOver, onDragLeav onBlur={() => { // User is considered not typing if the input is not in focus dispatch( - updateUserIsTyping({ userId: account?.homeAccountId, chatId: selectedId, isTyping: false }), + updateUserIsTyping({ userId: activeUserInfo?.id, chatId: selectedId, isTyping: false }), ); }} /> diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatRoom.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatRoom.tsx index 0cfa432885f3..6ae524d39aa8 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatRoom.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatRoom.tsx @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -import { useMsal } from '@azure/msal-react'; import { makeStyles, shorthands, tokens } from '@fluentui/react-components'; import debug from 'debug'; import React from 'react'; @@ -42,12 +41,11 @@ const useClasses = makeStyles({ export const ChatRoom: React.FC = () => { const { conversations, selectedId } = useAppSelector((state: RootState) => state.conversations); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); + const messages = conversations[selectedId].messages; const classes = useClasses(); - const { instance } = useMsal(); - const account = instance.getActiveAccount(); - const dispatch = useAppDispatch(); const scrollViewTargetRef = React.useRef(null); const scrollTargetRef = React.useRef(null); @@ -88,17 +86,13 @@ export const ChatRoom: React.FC = () => { }; }, []); - if (!account) { - return null; - } - const handleSubmit = async (options: GetResponseOptions) => { log('submitting user chat message'); const chatInput: IChatMessage = { timestamp: new Date().getTime(), - userId: account.homeAccountId, - userName: account.name ?? account.username, + userId: activeUserInfo?.id as string, + userName: activeUserInfo?.username as string, content: options.value, type: options.messageType, authorRole: AuthorRoles.User, diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatStatus.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatStatus.tsx index f186a31a3b82..8cd3971d8d32 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatStatus.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatStatus.tsx @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -import { useMsal } from '@azure/msal-react'; import React from 'react'; import { IChatUser } from '../../libs/models/ChatUser'; import { useAppSelector } from '../../redux/app/hooks'; @@ -8,24 +7,23 @@ import { RootState } from '../../redux/app/store'; import { TypingIndicatorRenderer } from './typing-indicator/TypingIndicatorRenderer'; export const ChatStatus: React.FC = () => { - const { instance } = useMsal(); - const account = instance.getActiveAccount(); const { conversations, selectedId } = useAppSelector((state: RootState) => state.conversations); const { users } = conversations[selectedId]; + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); const [typingUserList, setTypingUserList] = React.useState([]); React.useEffect(() => { const checkAreTyping = () => { const updatedTypingUsers: IChatUser[] = users.filter( (chatUser: IChatUser) => - chatUser.id !== account?.homeAccountId && + chatUser.id !== activeUserInfo?.id && chatUser.isTyping, ); setTypingUserList(updatedTypingUsers); }; checkAreTyping(); - }, [account?.homeAccountId, users]); + }, [activeUserInfo, users]); return ( diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/chat-history/ChatHistoryItem.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/chat-history/ChatHistoryItem.tsx index 8ce454b90028..7c7aa248897b 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/chat-history/ChatHistoryItem.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/chat-history/ChatHistoryItem.tsx @@ -1,6 +1,5 @@ // Copyright (c) Microsoft. All rights reserved. -import { useMsal } from '@azure/msal-react'; import { Persona, Text, makeStyles, mergeClasses, shorthands, tokens } from '@fluentui/react-components'; import React from 'react'; import { AuthorRoles, ChatMessageType, IChatMessage } from '../../../libs/models/ChatMessage'; @@ -69,13 +68,11 @@ interface ChatHistoryItemProps { export const ChatHistoryItem: React.FC = ({ message, getResponse, messageIndex }) => { const classes = useClasses(); - const { instance } = useMsal(); - const account = instance.getActiveAccount(); - const chat = useChat(); const { conversations, selectedId } = useAppSelector((state: RootState) => state.conversations); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); - const isMe = message.authorRole === AuthorRoles.User && message.userId === account?.homeAccountId; + const isMe = message.authorRole === AuthorRoles.User && message.userId === activeUserInfo?.id; const isBot = message.authorRole === AuthorRoles.Bot; const user = chat.getChatUserById(message.userName, selectedId, conversations[selectedId].users); const fullName = user?.fullName ?? message.userName; diff --git a/samples/apps/copilot-chat-app/webapp/src/components/header/UserSettings.tsx b/samples/apps/copilot-chat-app/webapp/src/components/header/UserSettings.tsx index 4484e241ec6c..62a8784ea729 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/header/UserSettings.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/header/UserSettings.tsx @@ -17,7 +17,8 @@ import { tokens, } from '@fluentui/react-components'; import { AuthHelper } from '../../libs/auth/AuthHelper'; -import { resetState } from '../../redux/app/store'; +import { useAppSelector } from '../../redux/app/hooks'; +import { RootState, resetState } from '../../redux/app/store'; export const useClasses = makeStyles({ root: { @@ -37,7 +38,7 @@ export const UserSettings: FC = ({ setLoadingState }) => { const classes = useClasses(); const { instance } = useMsal(); - const account = instance.getActiveAccount(); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); const onLogout = useCallback(() => { setLoadingState(); @@ -51,8 +52,8 @@ export const UserSettings: FC = ({ setLoadingState }) => { { @@ -62,8 +63,8 @@ export const UserSettings: FC = ({ setLoadingState }) => { diff --git a/samples/apps/copilot-chat-app/webapp/src/libs/useChat.ts b/samples/apps/copilot-chat-app/webapp/src/libs/useChat.ts index cf2782bca736..1c11cc333e14 100644 --- a/samples/apps/copilot-chat-app/webapp/src/libs/useChat.ts +++ b/samples/apps/copilot-chat-app/webapp/src/libs/useChat.ts @@ -40,8 +40,8 @@ export interface GetResponseOptions { export const useChat = () => { const dispatch = useAppDispatch(); const { instance, inProgress } = useMsal(); - const account = instance.getActiveAccount(); const { conversations } = useAppSelector((state: RootState) => state.conversations); + const { activeUserInfo } = useAppSelector((state: RootState) => state.app); const botService = new BotService(process.env.REACT_APP_BACKEND_URI as string); const chatService = new ChatService(process.env.REACT_APP_BACKEND_URI as string); @@ -49,11 +49,11 @@ export const useChat = () => { const botProfilePictures: string[] = [botIcon1, botIcon2, botIcon3, botIcon4, botIcon5]; - const homeAccountId = account?.homeAccountId ?? ''; - const emailAddress = account?.username ?? ''; - const fullName = account?.name ?? emailAddress; + const userId = activeUserInfo?.id ?? ''; + const fullName = activeUserInfo?.username ?? ''; + const emailAddress = activeUserInfo?.email ?? ''; const loggedInUser: IChatUser = { - id: homeAccountId, + id: userId, fullName, emailAddress, photo: undefined, // TODO: Make call to Graph /me endpoint to load photo @@ -72,24 +72,22 @@ export const useChat = () => { const chatTitle = `Copilot @ ${new Date().toLocaleString()}`; const accessToken = await AuthHelper.getSKaaSAccessToken(instance, inProgress); try { - await chatService - .createChatAsync(homeAccountId, chatTitle, accessToken) - .then(async (result: IChatSession) => { - const chatMessages = await chatService.getChatMessagesAsync(result.id, 0, 1, accessToken); - - const newChat: ChatState = { - id: result.id, - title: result.title, - messages: chatMessages, - users: [loggedInUser], - botProfilePicture: getBotProfilePicture(Object.keys(conversations).length), - input: '', - isBotTyping: false, - }; + await chatService.createChatAsync(userId, chatTitle, accessToken).then(async (result: IChatSession) => { + const chatMessages = await chatService.getChatMessagesAsync(result.id, 0, 1, accessToken); + + const newChat: ChatState = { + id: result.id, + title: result.title, + messages: chatMessages, + users: [loggedInUser], + botProfilePicture: getBotProfilePicture(Object.keys(conversations).length), + input: '', + isBotTyping: false, + }; - dispatch(addConversation(newChat)); - return newChat.id; - }); + dispatch(addConversation(newChat)); + return newChat.id; + }); } catch (e: any) { const errorMessage = `Unable to create new chat. Details: ${getErrorDetails(e)}`; dispatch(addAlert({ message: errorMessage, type: AlertType.Error })); @@ -102,7 +100,7 @@ export const useChat = () => { variables: [ { key: 'userId', - value: homeAccountId, + value: userId, }, { key: 'userName', @@ -138,7 +136,7 @@ export const useChat = () => { const loadChats = async () => { const accessToken = await AuthHelper.getSKaaSAccessToken(instance, inProgress); try { - const chatSessions = await chatService.getAllChatsAsync(homeAccountId, accessToken); + const chatSessions = await chatService.getAllChatsAsync(userId, accessToken); if (chatSessions.length > 0) { const loadedConversations: Conversations = {}; @@ -188,7 +186,7 @@ export const useChat = () => { const uploadBot = async (bot: Bot) => { const accessToken = await AuthHelper.getSKaaSAccessToken(instance, inProgress); botService - .uploadAsync(bot, homeAccountId, accessToken) + .uploadAsync(bot, userId, accessToken) .then(async (chatSession: IChatSession) => { const chatMessages = await chatService.getChatMessagesAsync(chatSession.id, 0, 100, accessToken); @@ -230,7 +228,7 @@ export const useChat = () => { const importDocument = async (chatId: string, file: File) => { try { await documentImportService.importDocumentAsync( - homeAccountId, + userId, fullName, chatId, file, @@ -254,7 +252,7 @@ export const useChat = () => { const joinChat = async (chatId: string) => { const accessToken = await AuthHelper.getSKaaSAccessToken(instance, inProgress); try { - await chatService.joinChatAsync(homeAccountId, chatId, accessToken).then(async (result: IChatSession) => { + await chatService.joinChatAsync(userId, chatId, accessToken).then(async (result: IChatSession) => { // Get chat messages const chatMessages = await chatService.getChatMessagesAsync(result.id, 0, 100, accessToken); diff --git a/samples/apps/copilot-chat-app/webapp/src/redux/features/app/AppState.ts b/samples/apps/copilot-chat-app/webapp/src/redux/features/app/AppState.ts index 49dde3a791ea..536c5e32fb2f 100644 --- a/samples/apps/copilot-chat-app/webapp/src/redux/features/app/AppState.ts +++ b/samples/apps/copilot-chat-app/webapp/src/redux/features/app/AppState.ts @@ -4,6 +4,13 @@ import { AlertType } from '../../../libs/models/AlertType'; export interface AppState { alerts: Alert[]; + activeUserInfo?: ActiveUserInfo; +} + +export interface ActiveUserInfo { + id: string; + email: string; + username: string; } export interface Alert { diff --git a/samples/apps/copilot-chat-app/webapp/src/redux/features/app/appSlice.ts b/samples/apps/copilot-chat-app/webapp/src/redux/features/app/appSlice.ts index eea744ba46c1..42c516bd0135 100644 --- a/samples/apps/copilot-chat-app/webapp/src/redux/features/app/appSlice.ts +++ b/samples/apps/copilot-chat-app/webapp/src/redux/features/app/appSlice.ts @@ -2,7 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { AlertType } from '../../../libs/models/AlertType'; -import { Alert, AppState } from './AppState'; +import { ActiveUserInfo, Alert, AppState } from './AppState'; const initialState: AppState = { alerts: [ @@ -30,9 +30,12 @@ export const appSlice = createSlice({ removeAlert: (state: AppState, action: PayloadAction) => { state.alerts.splice(action.payload, 1); }, + setActiveUserInfo: (state: AppState, action: PayloadAction) => { + state.activeUserInfo = action.payload; + }, }, }); -export const { addAlert, removeAlert, setAlerts } = appSlice.actions; +export const { addAlert, removeAlert, setAlerts, setActiveUserInfo } = appSlice.actions; export default appSlice.reducer; diff --git a/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/ConversationsState.ts b/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/ConversationsState.ts index a0d574acdd70..939fd6eecc2e 100644 --- a/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/ConversationsState.ts +++ b/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/ConversationsState.ts @@ -8,13 +8,11 @@ export type Conversations = Record; export interface ConversationsState { conversations: Conversations; selectedId: string; - loggedInUserId: string; } export const initialState: ConversationsState = { conversations: {}, selectedId: '', - loggedInUserId: '', }; export interface UpdateConversationPayload { diff --git a/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/conversationsSlice.ts b/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/conversationsSlice.ts index 1f2cb2063ccc..bcfe7ec6616d 100644 --- a/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/conversationsSlice.ts +++ b/samples/apps/copilot-chat-app/webapp/src/redux/features/conversations/conversationsSlice.ts @@ -10,7 +10,7 @@ import { Conversations, ConversationsState, ConversationTitleChange, - initialState, + initialState } from './ConversationsState'; export const conversationsSlice: Slice = createSlice({ @@ -20,9 +20,6 @@ export const conversationsSlice: Slice = createSlice({ setConversations: (state: ConversationsState, action: PayloadAction) => { state.conversations = action.payload; }, - setLoggedInUserId: (state: ConversationsState, action: PayloadAction) => { - state.loggedInUserId = action.payload; - }, editConversationTitle: (state: ConversationsState, action: PayloadAction) => { const id = action.payload.id; const newTitle = action.payload.newTitle; @@ -116,7 +113,6 @@ export const conversationsSlice: Slice = createSlice({ export const { setConversations, - setLoggedInUserId, editConversationTitle, editConversationInput, setSelectedConversation, diff --git a/samples/apps/copilot-chat-app/webapp/src/redux/features/message-relay/signalRMiddleware.ts b/samples/apps/copilot-chat-app/webapp/src/redux/features/message-relay/signalRMiddleware.ts index dffd7afdb071..df7ebf0ba4ed 100644 --- a/samples/apps/copilot-chat-app/webapp/src/redux/features/message-relay/signalRMiddleware.ts +++ b/samples/apps/copilot-chat-app/webapp/src/redux/features/message-relay/signalRMiddleware.ts @@ -151,7 +151,7 @@ export const registerSignalREvents = (store: Store) => { }); hubConnection.on(SignalRCallbackMethods.ReceiveResponse, (askResult: IAskResult, chatId: string) => { - const loggedInUserId: string = store.getState().conversations.loggedInUserId; + const loggedInUserId = store.getState().app.activeUserInfo?.id; const originalMessageUserId: string | undefined = askResult.variables.find((v) => v.key === 'userId')?.value; const isPlanForLoggedInUser = loggedInUserId === originalMessageUserId; const messageType = Number(askResult.variables.find((v) => v.key === 'messageType')?.value) as ChatMessageType; diff --git a/samples/notebooks/dotnet/00-getting-started.ipynb b/samples/notebooks/dotnet/00-getting-started.ipynb index 9dd2bd42024d..e7aafd66d1fe 100644 --- a/samples/notebooks/dotnet/00-getting-started.ipynb +++ b/samples/notebooks/dotnet/00-getting-started.ipynb @@ -61,7 +61,7 @@ "outputs": [], "source": [ "// Import Semantic Kernel\n", - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"" + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"" ] }, { diff --git a/samples/notebooks/dotnet/01-basic-loading-the-kernel.ipynb b/samples/notebooks/dotnet/01-basic-loading-the-kernel.ipynb index 3ec75aaf7f81..0fa6310aa649 100644 --- a/samples/notebooks/dotnet/01-basic-loading-the-kernel.ipynb +++ b/samples/notebooks/dotnet/01-basic-loading-the-kernel.ipynb @@ -32,7 +32,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"" + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"" ] }, { diff --git a/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb b/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb index 5517066f4cc6..a3d141291375 100644 --- a/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb +++ b/samples/notebooks/dotnet/02-running-prompts-from-file.ipynb @@ -90,7 +90,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "\n", "#!import config/Settings.cs\n", "\n", diff --git a/samples/notebooks/dotnet/03-semantic-function-inline.ipynb b/samples/notebooks/dotnet/03-semantic-function-inline.ipynb index 07f856b685db..b3e949fdc3dd 100644 --- a/samples/notebooks/dotnet/03-semantic-function-inline.ipynb +++ b/samples/notebooks/dotnet/03-semantic-function-inline.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -30,6 +31,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -49,7 +51,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "\n", "#!import config/Settings.cs\n", "\n", @@ -69,6 +71,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -96,6 +99,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -127,6 +131,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -155,6 +160,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -180,6 +186,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -213,6 +220,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -273,6 +281,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/samples/notebooks/dotnet/04-context-variables-chat.ipynb b/samples/notebooks/dotnet/04-context-variables-chat.ipynb index ca4120ad5c80..32a61bb71a2c 100644 --- a/samples/notebooks/dotnet/04-context-variables-chat.ipynb +++ b/samples/notebooks/dotnet/04-context-variables-chat.ipynb @@ -34,8 +34,7 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", - "\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "#!import config/Settings.cs\n", "\n", "using Microsoft.SemanticKernel;\n", diff --git a/samples/notebooks/dotnet/05-using-the-planner.ipynb b/samples/notebooks/dotnet/05-using-the-planner.ipynb index 5461a35faf74..183df27e4d59 100644 --- a/samples/notebooks/dotnet/05-using-the-planner.ipynb +++ b/samples/notebooks/dotnet/05-using-the-planner.ipynb @@ -25,13 +25,13 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "\n", "#!import config/Settings.cs\n", "#!import config/Utils.cs\n", "\n", "using Microsoft.SemanticKernel;\n", - "using Microsoft.SemanticKernel.CoreSkills;\n", + "using Microsoft.SemanticKernel.Skills.Core;\n", "using Microsoft.SemanticKernel.Orchestration;\n", "using Microsoft.SemanticKernel.Planning;\n", "using Microsoft.SemanticKernel.Planning.Sequential;\n", @@ -123,7 +123,7 @@ }, "outputs": [], "source": [ - "var ask = \"Tomorrow is Valentine's day. I need to come up with a few date ideas and e-mail them to my significant other.\";\n", + "var ask = \"Tomorrow is Valentine's day. I need to come up with a few date ideas. My significant other likes poems so write them in the form of a poem.\";\n", "var originalPlan = await planner.CreatePlanAsync(ask);\n", "\n", "Console.WriteLine(\"Original plan:\\n\");\n", @@ -194,7 +194,7 @@ "outputs": [], "source": [ "var ask = @\"Tomorrow is Valentine's day. I need to come up with a few date ideas.\n", - "She likes Shakespeare so write using his style. E-mail these ideas to my significant other\";\n", + "She likes Shakespeare so write using his style. Write them in the form of a poem.\";\n", "\n", "var newPlan = await planner.CreatePlanAsync(ask);\n", "\n", diff --git a/samples/notebooks/dotnet/06-memory-and-embeddings.ipynb b/samples/notebooks/dotnet/06-memory-and-embeddings.ipynb index 0f06ceba9b70..e123e9010010 100644 --- a/samples/notebooks/dotnet/06-memory-and-embeddings.ipynb +++ b/samples/notebooks/dotnet/06-memory-and-embeddings.ipynb @@ -33,7 +33,8 @@ }, "outputs": [], "source": [ - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", + "#r \"nuget: System.Linq.Async, 6.0.1\"\n", "\n", "#!import config/Settings.cs\n", "\n", diff --git a/samples/notebooks/dotnet/07-DALL-E-2.ipynb b/samples/notebooks/dotnet/07-DALL-E-2.ipynb index c645706de47b..9254acaf6260 100644 --- a/samples/notebooks/dotnet/07-DALL-E-2.ipynb +++ b/samples/notebooks/dotnet/07-DALL-E-2.ipynb @@ -33,7 +33,7 @@ "source": [ "// Usual setup: importing Semantic Kernel SDK and SkiaSharp, used to display images inline.\n", "\n", - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "#r \"nuget: SkiaSharp, 2.88.3\"\n", "\n", "#!import config/Settings.cs\n", diff --git a/samples/notebooks/dotnet/08-chatGPT-with-DALL-E-2.ipynb b/samples/notebooks/dotnet/08-chatGPT-with-DALL-E-2.ipynb index 7f30f82cd0b6..85d875738009 100644 --- a/samples/notebooks/dotnet/08-chatGPT-with-DALL-E-2.ipynb +++ b/samples/notebooks/dotnet/08-chatGPT-with-DALL-E-2.ipynb @@ -28,6 +28,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -55,7 +56,7 @@ "source": [ "// Usual setup: importing Semantic Kernel SDK and SkiaSharp, used to display images inline.\n", "\n", - "#r \"nuget: Microsoft.SemanticKernel, 0.15.230531.5-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", "#r \"nuget: SkiaSharp, 2.88.3\"\n", "\n", "#!import config/Settings.cs\n", diff --git a/samples/notebooks/dotnet/10-BingSearch-using-kernel.ipynb b/samples/notebooks/dotnet/10-BingSearch-using-kernel.ipynb new file mode 100644 index 000000000000..1d9108a51edf --- /dev/null +++ b/samples/notebooks/dotnet/10-BingSearch-using-kernel.ipynb @@ -0,0 +1,245 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BingSearch using Kernel \n", + "\n", + "This notebook explains how to integrate Bing Search with the Semantic Kernel to get the latest information from the internet.\n", + "\n", + "To use Bing Search you simply need a Bing Search API key. You can get the API key by creating a [Bing Search resource](https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/create-bing-search-service-resource) in Azure. \n", + "\n", + "To learn more read the following [documentation](https://learn.microsoft.com/en-us/bing/search-apis/bing-web-search/overview)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Prepare a Semantic Kernel instance first, loading also the AI backend settings defined in the [Setup notebook](0-AI-settings.ipynb):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "#r \"nuget: Microsoft.SemanticKernel, 0.17.230626.1-preview\"\n", + "#r \"nuget: Microsoft.SemanticKernel.Skills.Web, 0.17.230626.1-preview\"\n", + "\n", + "#!import config/Settings.cs\n", + "#!import config/Utils.cs\n", + "\n", + "using Microsoft.SemanticKernel;\n", + "using Microsoft.SemanticKernel.Skills.Core;\n", + "using Microsoft.SemanticKernel.SkillDefinition;\n", + "using Microsoft.SemanticKernel.Orchestration;\n", + "using Microsoft.SemanticKernel.Planning;\n", + "using Microsoft.SemanticKernel.Planning.Sequential;\n", + "using Microsoft.SemanticKernel.TemplateEngine;\n", + "using InteractiveKernel = Microsoft.DotNet.Interactive.Kernel;\n", + "var builder = new KernelBuilder();\n", + "\n", + "// Configure AI backend used by the kernel\n", + "var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();\n", + "\n", + "if (useAzureOpenAI)\n", + " builder.WithAzureTextCompletionService(model, azureEndpoint, apiKey);\n", + "else\n", + " builder.WithOpenAITextCompletionService(model, apiKey, orgId);\n", + "\n", + "var kernel = builder.Build();" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Add the following namespaces to use the Bing Search connector." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "using Microsoft.SemanticKernel.Skills.Web;\n", + "using Microsoft.SemanticKernel.Skills.Web.Bing;" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Enter your Bing Search Key in BING_KEY using `InteractiveKernel` method as introduced in [`.NET Interactive`](https://github.com/dotnet/interactive/blob/main/docs/kernels-overview.md)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "using InteractiveKernel = Microsoft.DotNet.Interactive.Kernel;\n", + "\n", + "string BING_KEY = await InteractiveKernel.GetPasswordAsync(\"Please enter your Bing Search Key\");" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Below are some examples on how [`WebSearchEngineSkill`](../../../dotnet/src/Skills/Skills.Web/WebSearchEngineSkill.cs) can be used in SK. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "private static async Task Example1Async(IKernel kernel)\n", + "{\n", + " Console.WriteLine(\"Example 1\");\n", + "\n", + " // Run \n", + " var question = \"What is quantum tunnelling\";\n", + " var bingResult = await kernel.Func(\"bing\", \"search\").InvokeAsync(question);\n", + "\n", + " Console.WriteLine(question);\n", + " Console.WriteLine(\"----\");\n", + " Console.WriteLine(bingResult);\n", + " Console.WriteLine();\n", + "\n", + " /* OUTPUT:\n", + "\n", + " What is quantum tunnelling\n", + " ----\n", + " In physics, quantum tunnelling, barrier penetration, or simply tunnelling is a quantum mechanical\n", + " phenomenon in which an object such as an electron or atom passes through a potential energy \n", + " barrier that, according to classical mechanics, the object does not have sufficient energy to\n", + " enter or surmount.\n", + " \n", + " */\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "private static async Task Example2Async(IKernel kernel)\n", + "{\n", + " Console.WriteLine(\"Example 2\");\n", + "\n", + " //The following function only works in interactive notebooks\n", + " string question = await InteractiveKernel.GetInputAsync(\"Please ask your question\"); \n", + "\n", + " var bingResult = await kernel.Func(\"bing\", \"search\").InvokeAsync(question);\n", + "\n", + " Console.WriteLine(bingResult);\n", + "}" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Just uncomment the examples to run them in the following code:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "dotnet_interactive": { + "language": "csharp" + }, + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [], + "source": [ + "// Load Bing skill\n", + "using (var bingConnector = new BingConnector(BING_KEY))\n", + "{\n", + " kernel.ImportSkill(new WebSearchEngineSkill(bingConnector), \"bing\");\n", + "\n", + " //await Example1Async(kernel);\n", + " //await Example2Async(kernel);\n", + "}" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "name": "polyglot-notebook" + }, + "orig_nbformat": 4, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/samples/notebooks/python/00-getting-started.ipynb b/samples/notebooks/python/00-getting-started.ipynb index 6d1ac7e1ecf6..26b8a2e1d15f 100644 --- a/samples/notebooks/python/00-getting-started.ipynb +++ b/samples/notebooks/python/00-getting-started.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -15,7 +16,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -30,6 +31,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -59,6 +61,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -89,6 +92,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/samples/notebooks/python/01-basic-loading-the-kernel.ipynb b/samples/notebooks/python/01-basic-loading-the-kernel.ipynb index c8e542b4127f..9f8fc82cfb13 100644 --- a/samples/notebooks/python/01-basic-loading-the-kernel.ipynb +++ b/samples/notebooks/python/01-basic-loading-the-kernel.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -8,6 +9,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -23,7 +25,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -37,6 +39,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -65,6 +68,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -103,6 +107,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -125,6 +130,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/samples/notebooks/python/02-running-prompts-from-file.ipynb b/samples/notebooks/python/02-running-prompts-from-file.ipynb index 1b7a7ac18e78..04a4ec1c1d23 100644 --- a/samples/notebooks/python/02-running-prompts-from-file.ipynb +++ b/samples/notebooks/python/02-running-prompts-from-file.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "692e361b", "metadata": {}, @@ -18,6 +19,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "f3ce1efe", "metadata": {}, @@ -36,6 +38,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "afdb96d6", "metadata": {}, @@ -46,6 +49,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "c3bd5134", "metadata": {}, @@ -68,6 +72,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "384ff07f", "metadata": {}, @@ -84,7 +89,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -111,6 +116,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "fd5ff1f4", "metadata": {}, @@ -134,6 +140,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "edd99fa0", "metadata": {}, @@ -158,6 +165,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "2281a1fc", "metadata": {}, @@ -187,4 +195,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/samples/notebooks/python/03-semantic-function-inline.ipynb b/samples/notebooks/python/03-semantic-function-inline.ipynb index f8cd881a27c7..c48b1d86a517 100644 --- a/samples/notebooks/python/03-semantic-function-inline.ipynb +++ b/samples/notebooks/python/03-semantic-function-inline.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "3c93ac5b", "metadata": {}, @@ -9,12 +10,14 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "ebcabb91", "metadata": {}, "source": [] }, { + "attachments": {}, "cell_type": "markdown", "id": "40201641", "metadata": {}, @@ -37,6 +40,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "d90b0c13", "metadata": {}, @@ -51,7 +55,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -78,6 +82,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "589733c5", "metadata": {}, @@ -102,6 +107,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "f26b90c4", "metadata": {}, @@ -130,6 +136,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "bf0f2330", "metadata": {}, @@ -151,6 +158,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "1c2c1262", "metadata": {}, @@ -159,6 +167,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "29b59b28", "metadata": {}, @@ -167,6 +176,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "4777f447", "metadata": {}, diff --git a/samples/notebooks/python/04-context-variables-chat.ipynb b/samples/notebooks/python/04-context-variables-chat.ipynb index 267551b278d4..de79d4b41a13 100644 --- a/samples/notebooks/python/04-context-variables-chat.ipynb +++ b/samples/notebooks/python/04-context-variables-chat.ipynb @@ -26,7 +26,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { diff --git a/samples/notebooks/python/05-using-the-planner.ipynb b/samples/notebooks/python/05-using-the-planner.ipynb index 1f379583363b..3827e69fed43 100644 --- a/samples/notebooks/python/05-using-the-planner.ipynb +++ b/samples/notebooks/python/05-using-the-planner.ipynb @@ -24,7 +24,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { diff --git a/samples/notebooks/python/06-memory-and-embeddings.ipynb b/samples/notebooks/python/06-memory-and-embeddings.ipynb index 65f1765948fa..6ea4e4416afe 100644 --- a/samples/notebooks/python/06-memory-and-embeddings.ipynb +++ b/samples/notebooks/python/06-memory-and-embeddings.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "68e1c158", "metadata": {}, @@ -27,7 +28,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -44,6 +45,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "d8ddffc1", "metadata": {}, @@ -81,6 +83,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "e7fefb6a", "metadata": {}, @@ -91,6 +94,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "2a7e7ca4", "metadata": {}, @@ -126,6 +130,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "2calf857", "metadata": {}, @@ -156,6 +161,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "e70c2b22", "metadata": {}, @@ -165,6 +171,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "1ed54a32", "metadata": {}, @@ -220,6 +227,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "1ac62457", "metadata": {}, @@ -228,6 +236,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "645b55a1", "metadata": {}, @@ -290,6 +299,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "0a51542b", "metadata": {}, @@ -326,6 +336,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "75f3ea5e", "metadata": {}, @@ -378,6 +389,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "59294dac", "metadata": {}, diff --git a/samples/notebooks/python/07-hugging-face-for-skills.ipynb b/samples/notebooks/python/07-hugging-face-for-skills.ipynb index da2201d8e067..91e7f7dbfe85 100644 --- a/samples/notebooks/python/07-hugging-face-for-skills.ipynb +++ b/samples/notebooks/python/07-hugging-face-for-skills.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "68e1c158", "metadata": {}, @@ -19,7 +20,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0\n", + "!python -m pip install semantic-kernel==0.3.1.dev0\n", "\n", "# Note that additional dependencies are required for the Hugging Face connectors:\n", "!python -m pip install torch==2.0.0\n", @@ -39,6 +40,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "d8ddffc1", "metadata": {}, @@ -73,6 +75,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "2a7e7ca4", "metadata": {}, @@ -115,6 +118,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "2calf857", "metadata": {}, diff --git a/samples/notebooks/python/08-native-function-inline.ipynb b/samples/notebooks/python/08-native-function-inline.ipynb index a09ae177ac63..6772d11aefac 100644 --- a/samples/notebooks/python/08-native-function-inline.ipynb +++ b/samples/notebooks/python/08-native-function-inline.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "id": "3c93ac5b", "metadata": {}, @@ -9,6 +10,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "40201641", "metadata": {}, @@ -29,6 +31,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "d90b0c13", "metadata": {}, @@ -43,7 +46,7 @@ "metadata": {}, "outputs": [], "source": [ - "!python -m pip install semantic-kernel==0.2.7.dev0" + "!python -m pip install semantic-kernel==0.3.1.dev0" ] }, { @@ -73,6 +76,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "186767f8", "metadata": {}, @@ -81,6 +85,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "589733c5", "metadata": {}, @@ -125,6 +130,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "f26b90c4", "metadata": {}, @@ -195,6 +201,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "8ef29d16", "metadata": {}, @@ -235,6 +242,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "091f45e4", "metadata": {}, @@ -294,6 +302,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "6ad068d6", "metadata": {}, @@ -328,6 +337,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "fdce1872", "metadata": {}, @@ -350,6 +360,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "c8778bad", "metadata": {}, @@ -394,6 +405,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "fb786c54", "metadata": {}, @@ -537,6 +549,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "id": "42f0c472", "metadata": {},