{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install -qU \"semantic-router[pinecone]==0.1.0\"" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from semantic_router import Route\n", "\n", "# we could use this as a guide for our chatbot to avoid political conversations\n", "politics = Route(\n", " name=\"politics\",\n", " utterances=[\n", " \"isn't politics the best thing ever\",\n", " \"why don't you tell me about your political opinions\",\n", " \"don't you just love the president\" \"don't you just hate the president\",\n", " \"they're going to destroy this country!\",\n", " \"they will save the country!\",\n", " ],\n", ")\n", "\n", "# this could be used as an indicator to our chatbot to switch to a more\n", "# conversational prompt\n", "chitchat = Route(\n", " name=\"chitchat\",\n", " utterances=[\n", " \"how's the weather today?\",\n", " \"how are things going?\",\n", " \"lovely weather today\",\n", " \"the weather is horrendous\",\n", " \"let's go to the chippy\",\n", " ],\n", ")\n", "\n", "# we place both of our decisions together into single list\n", "routes = [politics, chitchat]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As of 13 June 2024, two encoders support async functionality:\n", "\n", "* `AzureOpenAIEncoder`\n", "* `OpenAIEncoder`\n", "\n", "To use either of these encoders in async mode we simply initialize them as we usually would. When we then include them within a `RouteLayer` and run `acall` the route layer will automatically run the encoders in async mode.\n", "\n", "**Azure OpenAI:**\n", "\n", "```python\n", "from semantic_router.encoders import AzureOpenAIEncoder\n", "\n", "encoder = AzureOpenAIEncoder(\n", " api_key=\"YOUR_AZURE_OPENAI_API_KEY\",\n", " deployment_name=\"YOUR_DEPLOYMENT_NAME\",\n", " azure_endpoint=\"YOUR_ENDPOINT\",\n", " api_version=\"2024-02-01\",\n", " model=\"text-embedding-3-small\",\n", ")\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**OpenAI:**" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import os\n", "from getpass import getpass\n", "from semantic_router.encoders import OpenAIEncoder\n", "\n", "# get at platform.openai.com\n", "os.environ[\"OPENAI_API_KEY\"] = os.environ.get(\"OPENAI_API_KEY\") or getpass(\n", " \"Enter OpenAI API key: \"\n", ")\n", "encoder = OpenAIEncoder(name=\"text-embedding-3-small\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see encoder details, including default `score_threshold` like so:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OpenAIEncoder(name='text-embedding-3-small', score_threshold=0.3, type='openai', client=, async_client=, dimensions=NOT_GIVEN, token_limit=8192)" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "encoder" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can create embeddings asynchronously via our encoder using the `encoder.acall` method:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[[-0.009877119213342667,\n", " 0.0015331337926909328,\n", " 0.015642808750271797,\n", " -0.05476367473602295,\n", " -0.006405937951058149,\n", " ...],\n", " [0.012598802335560322,\n", " -0.0037690235767513514,\n", " 0.025685198605060577,\n", " -0.08883649855852127,\n", " 0.0013644769787788391,\n", " ...]]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await encoder.acall(docs=[\"test\", \"test 2\"])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For our `PineconeIndex` we do the exact same thing, ie we initialize as usual:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "import os\n", "from semantic_router.index.pinecone import PineconeIndex\n", "\n", "# get at app.pinecone.io\n", "os.environ[\"PINECONE_API_KEY\"] = os.environ.get(\"PINECONE_API_KEY\") or getpass(\n", " \"Enter Pinecone API key: \"\n", ")\n", "pc_index = PineconeIndex(dimensions=1536, init_async_index=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are several async methods we can call directly:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'indexes': []}" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "await pc_index._async_list_indexes()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But unless we're using the index directly, we don't need to use these. As with the encoder, once we pass the `PineconeIndex` to our route layer, the route layer will call all async methods automatically when we hit the `acall` method." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Async RouteLayer" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `RouteLayer` class supports both sync and async operations by default, so we initialize as usual:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "from semantic_router.layer import RouteLayer\n", "\n", "rl = RouteLayer(encoder=encoder, routes=routes, index=pc_index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can check our route layer and index information as usual:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['politics', 'chitchat']" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl.list_route_names()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(rl.index)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also view all of the records for a given route:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['politics#64069085d9d6e98e5a80915f69fabe82bac6c742f801bc305c5001dce88f0d19',\n", " 'politics#af8b76111f260cf44fb34f04fcf82927dcbe08e8f47c30f4d571379c1512fac8',\n", " 'politics#d1bb40236c3d95b9c695bfa86b314b6da4eb87e136699563fccae47fccea23e2',\n", " 'politics#ed0f3dd7bd5dea12e55b1953bcd2c562a5ab19f501f6d5ff8c8927652c3904b8',\n", " 'politics#fc6d15f9e6075e6de82b3fbef6722b64353e4eadc8d663b7312a4ed60c43e6f6']" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl.index._get_route_ids(route_name=\"politics\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And now for async vs. sync usage! To call in synchronous mode we simply hit `rl(...)`, to switch to async mode we hit `rl.acall(...)`:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'politics'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl(\"don't you love politics\").name # SYNC mode" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'politics'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "out = await rl.acall(\"don't you love politics?\") # ASYNC mode\n", "out.name" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's try a few more sync and async requests:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'chitchat'" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl(\"how's the weather today?\").name" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'chitchat'" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "out = await rl.acall(\"how's the weather today?\")\n", "out.name" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "rl(\"I'm interested in learning about llama 2\").name" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "out = await rl.acall(\"I'm interested in learning about llama 2\")\n", "out.name" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can delete or update routes using the usual synchronous methods:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(rl.index)" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "5" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import time\n", "\n", "rl.delete(route_name=\"chitchat\")\n", "time.sleep(3)\n", "len(rl.index)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "out = await rl.acall(\"how's the weather today?\")\n", "out.name" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[('politics', \"why don't you tell me about your political opinions\"),\n", " ('politics',\n", " \"don't you just love the presidentdon't you just hate the president\"),\n", " ('politics', \"isn't politics the best thing ever\"),\n", " ('politics', \"they're going to destroy this country!\"),\n", " ('politics', 'they will save the country!')]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl.index.get_routes()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'type': 'pinecone', 'dimensions': 1536, 'vectors': 5}" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rl.index.describe()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "---" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" } }, "nbformat": 4, "nbformat_minor": 2 }