diff --git a/python/poetry.lock b/python/poetry.lock index ad85a1689abe..b569a983797c 100644 --- a/python/poetry.lock +++ b/python/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -439,6 +439,45 @@ files = [ tests = ["pytest (>=3.2.1,!=3.3.0)"] typecheck = ["mypy"] +[[package]] +name = "beautifulsoup4" +version = "4.12.3" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.6.0" +files = [ + {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, + {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, +] + +[package.dependencies] +soupsieve = ">1.2" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] + [[package]] name = "build" version = "1.2.1" @@ -1163,6 +1202,20 @@ typer = ">=0.12.3" [package.extras] standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] +[[package]] +name = "fastjsonschema" +version = "2.19.1" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = "*" +files = [ + {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, + {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + [[package]] name = "filelock" version = "3.14.0" @@ -2087,6 +2140,17 @@ traitlets = ">=5.3" docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, +] + [[package]] name = "kubernetes" version = "29.0.0" @@ -2439,6 +2503,17 @@ pycryptodome = "*" typing-extensions = "*" urllib3 = "*" +[[package]] +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, +] + [[package]] name = "mkl" version = "2021.4.0" @@ -2852,6 +2927,86 @@ files = [ {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, ] +[[package]] +name = "nbclient" +version = "0.10.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "nbclient-0.10.0-py3-none-any.whl", hash = "sha256:f13e3529332a1f1f81d82a53210322476a168bb7090a0289c795fe9cc11c9d3f"}, + {file = "nbclient-0.10.0.tar.gz", hash = "sha256:4b3f1b7dba531e498449c4db4f53da339c91d449dc11e9af3a43b4eb5c5abb09"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.16.4" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbconvert-7.16.4-py3-none-any.whl", hash = "sha256:05873c620fe520b6322bf8a5ad562692343fe3452abda5765c7a34b7d1aa3eb3"}, + {file = "nbconvert-7.16.4.tar.gz", hash = "sha256:86ca91ba266b0a448dc96fa6c5b9d98affabde2867b363258703536807f9f7f4"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" + +[package.extras] +all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.10.4" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, + {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, +] + +[package.dependencies] +fastjsonschema = ">=2.15" +jsonschema = ">=2.6" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + [[package]] name = "nest-asyncio" version = "1.6.0" @@ -3538,6 +3693,17 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] xml = ["lxml (>=4.9.2)"] +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, +] + [[package]] name = "parse" version = "1.20.1" @@ -4782,7 +4948,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -5676,6 +5841,17 @@ six = "*" [package.extras] tests = ["Django", "birdseye", "littleutils", "numpy (>=1.16.5)", "pandas (>=0.24.2)", "pprintpp", "prettyprinter", "pytest", "pytest-order", "pytest-order (<=0.11.0)"] +[[package]] +name = "soupsieve" +version = "2.5" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +files = [ + {file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"}, + {file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"}, +] + [[package]] name = "stack-data" version = "0.6.3" @@ -5776,6 +5952,24 @@ files = [ {file = "threadpoolctl-3.5.0.tar.gz", hash = "sha256:082433502dd922bf738de0d8bcc4fdcbf0979ff44c42bd40f5af8a282f6fa107"}, ] +[[package]] +name = "tinycss2" +version = "1.3.0" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tinycss2-1.3.0-py3-none-any.whl", hash = "sha256:54a8dbdffb334d536851be0226030e9505965bb2f30f21a4a82c55fb2a80fae7"}, + {file = "tinycss2-1.3.0.tar.gz", hash = "sha256:152f9acabd296a8375fbca5b84c961ff95971fcfc32e79550c8df8e29118c54d"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["pytest", "ruff"] + [[package]] name = "tokenizers" version = "0.19.1" @@ -6539,6 +6733,17 @@ pydantic = ">=2.5.0,<3.0.0" requests = ">=2.30.0,<3.0.0" validators = "0.28.1" +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + [[package]] name = "websocket-client" version = "1.8.0" @@ -6868,4 +7073,4 @@ weaviate = ["weaviate-client"] [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "8684feb2ffcdd5fe104c32eab1a9fa2da230e8e9d72d48e79ea0b99e9aa27b14" +content-hash = "7a15b7b247630eb2e80c14421aadeab951d290de1e90360c52ce191c5b21be00" diff --git a/python/pyproject.toml b/python/pyproject.toml index 3eec4a19e7f1..610a349427ca 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -60,6 +60,7 @@ pyarrow = { version = ">=12.0.1,<16.0.0", optional = true} pre-commit = ">=3.7.1" ruff = ">=0.4.5" ipykernel = "^6.29.4" +nbconvert = "^7.16.4" pytest = "^8.2.1" pytest-asyncio = "^0.23.7" snoop = "^0.4.3" diff --git a/python/samples/getting_started/00-getting-started.ipynb b/python/samples/getting_started/00-getting-started.ipynb index 8451b8d810a1..f641d8dff9de 100644 --- a/python/samples/getting_started/00-getting-started.ipynb +++ b/python/samples/getting_started/00-getting-started.ipynb @@ -146,7 +146,10 @@ "\n", "joke_function = plugin[\"Joke\"]\n", "\n", - "joke = await kernel.invoke(joke_function, KernelArguments(input=\"time travel to dinosaur age\", style=\"super silly\"))\n", + "joke = await kernel.invoke(\n", + " joke_function,\n", + " KernelArguments(input=\"time travel to dinosaur age\", style=\"super silly\"),\n", + ")\n", "print(joke)" ] } diff --git a/python/samples/getting_started/06-memory-and-embeddings.ipynb b/python/samples/getting_started/06-memory-and-embeddings.ipynb index 546d06aa443f..0e03cbb5850a 100644 --- a/python/samples/getting_started/06-memory-and-embeddings.ipynb +++ b/python/samples/getting_started/06-memory-and-embeddings.ipynb @@ -65,10 +65,18 @@ "metadata": {}, "outputs": [], "source": [ - "from semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion import AzureChatCompletion\n", - "from semantic_kernel.connectors.ai.open_ai.services.azure_text_embedding import AzureTextEmbedding\n", - "from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import OpenAIChatCompletion\n", - "from semantic_kernel.connectors.ai.open_ai.services.open_ai_text_embedding import OpenAITextEmbedding\n", + "from semantic_kernel.connectors.ai.open_ai.services.azure_chat_completion import (\n", + " AzureChatCompletion,\n", + ")\n", + "from semantic_kernel.connectors.ai.open_ai.services.azure_text_embedding import (\n", + " AzureTextEmbedding,\n", + ")\n", + "from semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion import (\n", + " OpenAIChatCompletion,\n", + ")\n", + "from semantic_kernel.connectors.ai.open_ai.services.open_ai_text_embedding import (\n", + " OpenAITextEmbedding,\n", + ")\n", "from semantic_kernel.core_plugins.text_memory_plugin import TextMemoryPlugin\n", "from semantic_kernel.kernel import Kernel\n", "from semantic_kernel.memory.semantic_text_memory import SemanticTextMemory\n", @@ -161,7 +169,11 @@ "outputs": [], "source": [ "async def search_memory_examples(memory: SemanticTextMemory) -> None:\n", - " questions = [\"What is my budget for 2024?\", \"What are my savings from 2023?\", \"What are my investments?\"]\n", + " questions = [\n", + " \"What is my budget for 2024?\",\n", + " \"What are my savings from 2023?\",\n", + " \"What are my investments?\",\n", + " ]\n", "\n", " for question in questions:\n", " print(f\"Question: {question}\")\n", @@ -263,33 +275,6 @@ "Now that we've included our memories, let's chat!\n" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "75267a2f", - "metadata": {}, - "outputs": [], - "source": [ - "async def chat(kernel: Kernel, chat_func: KernelFunction) -> bool:\n", - " try:\n", - " user_input = input(\"User:> \")\n", - " except KeyboardInterrupt:\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - " except EOFError:\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - "\n", - " if user_input == \"exit\":\n", - " print(\"\\n\\nExiting chat...\")\n", - " return False\n", - "\n", - " answer = await kernel.invoke(chat_func, request=user_input)\n", - "\n", - " print(f\"ChatBot:> {answer}\")\n", - " return True" - ] - }, { "cell_type": "code", "execution_count": null, @@ -312,9 +297,32 @@ " \\n Type 'exit' to exit.\\\n", " \\n Try asking a question about your finances (i.e. \\\"talk to me about my finances\\\").\"\n", ")\n", - "chatting = True\n", - "while chatting:\n", - " chatting = await chat(kernel, chat_func)" + "\n", + "\n", + "async def chat(user_input: str):\n", + " print(f\"User: {user_input}\")\n", + " answer = await kernel.invoke(chat_func, request=user_input)\n", + " print(f\"ChatBot:> {answer}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b55f64f", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"What is my budget for 2024?\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "243f9eb2", + "metadata": {}, + "outputs": [], + "source": [ + "await chat(\"talk to me about my finances\")" ] }, { @@ -426,11 +434,7 @@ "source": [ "from semantic_kernel.connectors.memory.azure_cognitive_search import AzureCognitiveSearchMemoryStore\n", "\n", - "acs_memory_store = AzureCognitiveSearchMemoryStore(\n", - " vector_size=1536,\n", - " search_endpoint=azure_ai_search_url,\n", - " admin_key=azure_ai_search_api_key,\n", - ")\n", + "acs_memory_store = AzureCognitiveSearchMemoryStore(vector_size=1536)\n", "\n", "memory = SemanticTextMemory(storage=acs_memory_store, embeddings_generator=embedding_gen)\n", "kernel.add_plugin(TextMemoryPlugin(memory), \"TextMemoryPluginACS\")" @@ -497,7 +501,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/python/samples/getting_started/10-multiple-results-per-prompt.ipynb b/python/samples/getting_started/10-multiple-results-per-prompt.ipynb index af38664f6dcf..961ffdbcd98d 100644 --- a/python/samples/getting_started/10-multiple-results-per-prompt.ipynb +++ b/python/samples/getting_started/10-multiple-results-per-prompt.ipynb @@ -151,9 +151,7 @@ "if selectedService == Service.OpenAI:\n", " prompt = \"What is the purpose of a rubber duck?\"\n", "\n", - " results = await oai_text_service.get_text_contents_contents(\n", - " prompt=prompt, settings=oai_text_prompt_execution_settings\n", - " )\n", + " results = await oai_text_service.get_text_contents(prompt=prompt, settings=oai_text_prompt_execution_settings)\n", " i = 1\n", " for result in results:\n", " print(f\"Result {i}: {result}\")\n", @@ -364,10 +362,10 @@ " chat = ChatHistory()\n", " chat.add_user_message(\"what is the purpose of a rubber duck?\")\n", "\n", - " stream = oai_text_service.get_streaming_chat_message_contents(\n", - " chat_history=chat, settings=oai_text_prompt_execution_settings\n", + " stream = oai_chat_service.get_streaming_chat_message_contents(\n", + " chat_history=chat, settings=oai_chat_prompt_execution_settings\n", " )\n", - " number_of_responses = oai_text_prompt_execution_settings.number_of_responses\n", + " number_of_responses = oai_chat_prompt_execution_settings.number_of_responses\n", " texts = [\"\"] * number_of_responses\n", "\n", " last_clear_time = time.time()\n", @@ -412,9 +410,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.3" + "version": "3.10.12" } }, "nbformat": 4, "nbformat_minor": 5 -} \ No newline at end of file +} diff --git a/python/tests/samples/test_getting_started.py b/python/tests/samples/test_getting_started.py new file mode 100644 index 000000000000..0845da1915b2 --- /dev/null +++ b/python/tests/samples/test_getting_started.py @@ -0,0 +1,39 @@ +# Copyright (c) Microsoft. All rights reserved. + +import nbformat +from nbconvert.preprocessors import ExecutePreprocessor +from pytest import mark +from traitlets.config import Config + +c = Config() + +c.RegexRemovePreprocessor.patterns = ["^!pip .*"] +c.ExecutePreprocessor.exclude_input_prompt = True + + +def run_notebook(notebook_name: str): + with open(f"samples/getting_started/{notebook_name}") as f: + nb = nbformat.read(f, as_version=4) + ep = ExecutePreprocessor(timeout=600, kernel_name="python3", config=c) + ep.preprocess(nb, {"metadata": {"path": "samples/getting_started/"}}) + + +@mark.parametrize( + "name", + [ + "00-getting-started.ipynb", + "01-basic-loading-the-kernel.ipynb", + "02-running-prompts-from-file.ipynb", + "03-prompt-function-inline.ipynb", + "04-kernel-arguments-chat.ipynb", + "05-using-the-planner.ipynb", + "06-memory-and-embeddings.ipynb", + "07-hugging-face-for-plugins.ipynb", + "08-native-function-inline.ipynb", + "09-groundedness-checking.ipynb", + "10-multiple-results-per-prompt.ipynb", + "11-streaming-completions.ipynb", + ], +) +def test_notebooks(name): + run_notebook(name) diff --git a/python/tests/samples/test_learn_resources.py b/python/tests/samples/test_learn_resources.py index 869d710c91cb..2f7f00ce8507 100644 --- a/python/tests/samples/test_learn_resources.py +++ b/python/tests/samples/test_learn_resources.py @@ -2,88 +2,49 @@ from pytest import mark - -@mark.asyncio -async def test_ai_service_sample(): - from samples.learn_resources.ai_services import main - - await main() - - -@mark.asyncio -async def test_configuring_prompts(monkeypatch): - from samples.learn_resources.configuring_prompts import main - - responses = ["Hello, who are you?", "exit"] - - monkeypatch.setattr("builtins.input", lambda _: responses.pop(0)) - await main() - - -@mark.asyncio -async def test_creating_functions(monkeypatch): - from samples.learn_resources.creating_functions import main - - responses = ["What is 3+3?", "exit"] - - monkeypatch.setattr("builtins.input", lambda _: responses.pop(0)) - await main() - - -@mark.asyncio -async def test_functions_within_prompts(monkeypatch): - from samples.learn_resources.functions_within_prompts import main - - responses = ["Hello, who are you?", "exit"] - - monkeypatch.setattr("builtins.input", lambda _: responses.pop(0)) - await main() - - -@mark.asyncio -async def test_planner(): - from samples.learn_resources.planner import main - - await main() - - -@mark.asyncio -async def test_plugin(): - from samples.learn_resources.plugin import main - - await main() - - -@mark.asyncio -async def test_serializing_prompts(monkeypatch): - from samples.learn_resources.serializing_prompts import main - - responses = ["Hello, who are you?", "exit"] - - monkeypatch.setattr("builtins.input", lambda _: responses.pop(0)) - await main() - - -@mark.asyncio -async def test_templates(monkeypatch): - from samples.learn_resources.templates import main - - responses = ["Hello, who are you?", "Thanks, see you next time!"] - +from samples.learn_resources.ai_services import main as ai_services +from samples.learn_resources.configuring_prompts import main as configuring_prompts +from samples.learn_resources.creating_functions import main as creating_functions +from samples.learn_resources.functions_within_prompts import main as functions_within_prompts +from samples.learn_resources.planner import main as planner +from samples.learn_resources.plugin import main as plugin +from samples.learn_resources.serializing_prompts import main as serializing_prompts +from samples.learn_resources.templates import main as templates +from samples.learn_resources.using_the_kernel import main as using_the_kernel +from samples.learn_resources.your_first_prompt import main as your_first_prompt + + +@mark.asyncio +@mark.parametrize( + "func,responses", + [ + (ai_services, []), + (configuring_prompts, ["Hello, who are you?", "exit"]), + (creating_functions, ["What is 3+3?", "exit"]), + (functions_within_prompts, ["Hello, who are you?", "exit"]), + (planner, []), + (plugin, []), + (serializing_prompts, ["Hello, who are you?", "exit"]), + (templates, ["Hello, who are you?", "Thanks, see you next time!"]), + (using_the_kernel, []), + (your_first_prompt, ["I want to send an email to my manager!"]), + ], + ids=[ + "ai_services", + "configuring_prompts", + "creating_functions", + "functions_within_prompts", + "planner", + "plugin", + "serializing_prompts", + "templates", + "using_the_kernel", + "your_first_prompt", + ], +) +async def test_learn_resources(func, responses, monkeypatch): monkeypatch.setattr("builtins.input", lambda _: responses.pop(0)) - await main() - - -@mark.asyncio -async def test_using_the_kernel(): - from samples.learn_resources.using_the_kernel import main - - await main() - - -@mark.asyncio -async def test_your_first_prompt(monkeypatch): - from samples.learn_resources.your_first_prompt import main - - monkeypatch.setattr("builtins.input", lambda _: "I want to send an email to my manager!") - await main(delay=10) + if func.__module__ == "samples.learn_resources.your_first_prompt": + await func(delay=10) + return + await func()