Skip to content
Snippets Groups Projects
Commit 58594d47 authored by jamescalam's avatar jamescalam
Browse files

fix: update to first aurelio sparse example

parent 2d4395db
No related branches found
No related tags found
No related merge requests found
%% Cell type:markdown id: tags:
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/aurelio-labs/semantic-router/blob/main/docs/encoders/aurelio-bm25.ipynb) [![Open nbviewer](https://raw.githubusercontent.com/pinecone-io/examples/master/assets/nbviewer-shield.svg)](https://nbviewer.org/github/aurelio-labs/semantic-router/blob/main/docs/encoders/aurelio-bm25.ipynb)
%% Cell type:markdown id: tags:
# Using Aurelio AI BM25 Encoder
%% Cell type:markdown id: tags:
The 3rd generation embedding models from OpenAI (`text-embedding-3-small` and `text-embedding-3-large`) can both be used with our `OpenAIEncoder` and usage is primarily the same as with the 2nd generation `text-embedding-ada-002`. However, there is a new `dimensions` parameter — which we will discuss below.
Hybrid indexes combine both sparse and dense encodings to produce more accurate results. The dense encoder allows us to search based on semantic meaning, while the sparse encoder allows us to search based on text matches. Merging both dense and sparse into a single hybrid retrieval step allows us to step up our performance beyond what dense-only or sparse-only could achieve.
%% Cell type:markdown id: tags:
## Getting Started
%% Cell type:markdown id: tags:
We start by installing semantic-router. Support for the new `dimensions` parameter was added in `semantic-router==0.0.19` and `openai==1.10.0`.
We start by installing semantic-router. Support for the new `AurelioSparseEncoder` parameter was added in `semantic-router==0.1.0`.
%% Cell type:code id: tags:
``` python
!pip install -qU "semantic-router==0.1.0.dev2"
!pip install -qU semantic-router==0.1.0
```
%% Cell type:markdown id: tags:
We start by defining a dictionary mapping routes to example phrases that should trigger those routes.
%% Cell type:code id: tags:
``` python
from semantic_router import Route
politics = Route(
name="politics",
utterances=[
"isn't politics the best thing ever",
"why don't you tell me about your political opinions",
"don't you just love the president",
"don't you just hate the president",
"they're going to destroy this country!",
"they will save the country!",
],
)
```
%% Output
/Users/jamesbriggs/Library/Caches/pypoetry/virtualenvs/semantic-router-C1zr4a78-py3.12/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
%% Cell type:markdown id: tags:
Let's define another for good measure:
%% Cell type:code id: tags:
``` python
chitchat = Route(
name="chitchat",
utterances=[
"how's the weather today?",
"how are things going?",
"lovely weather today",
"the weather is horrendous",
"let's go to the chippy",
],
)
routes = [politics, chitchat]
```
%% Cell type:markdown id: tags:
Now we initialize our embedding model, we will use the `-3-large` model alongside a `dimensions` value of `256`. This will produce _tiny_ 256-dimensional vectors that — according to OpenAI — outperform the 1536-dimensional vectors produced by `text-embedding-ada-002`.
Now we initialize our embedding models. We are going to use a hybrid index which requires both a dense and sparse encoder. For the sparse encoder we will use the pretrained `bm25` model from the Aurelio Platform and OpenAI's `text-embedding-3-small` for the dense encoder.
To get an API key for the Aurelio Platform, we head to the [Aurelio Platform](https://platform.aurelio.ai/settings/api-keys).
%% Cell type:code id: tags:
``` python
import os
from getpass import getpass
from semantic_router.encoders.aurelio import AurelioSparseEncoder
os.environ["AURELIO_API_KEY"] = os.getenv("AURELIO_API_KEY") or getpass(
"Enter Aurelio API Key: "
)
sparse_encoder = AurelioSparseEncoder(name="bm25")
```
%% Cell type:markdown id: tags:
Sparse encoders return dictionaries containing the the indices and values of the non-zero elements in the sparse matrix.
%% Cell type:code id: tags:
``` python
import os
from getpass import getpass
from semantic_router.encoders import OpenAIEncoder
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY") or getpass(
"Enter OpenAI API Key: "
)
encoder = OpenAIEncoder(
name="text-embedding-3-large", score_threshold=0.5, dimensions=256
name="text-embedding-3-small", score_threshold=0.3
)
```
%% Cell type:markdown id: tags:
We will specify our index:
We now have both our sparse and dense encoders. When using both sparse and dense encoders we need to initialize an index that supports hybrid, such as the `HybridLocalIndex` or `PineconeIndex`.
%% Cell type:code id: tags:
``` python
from semantic_router.index.hybrid_local import HybridLocalIndex
index = HybridLocalIndex()
```
%% Cell type:markdown id: tags:
Now we define the `RouteLayer`. When called, the route layer will consume text (a query) and output the category (`Route`) it belongs to — to initialize a `RouteLayer` we need our `encoder` model and a list of `routes`.
Now we define the `HybridRouter`. When called, the router will consume text (a query) and output the category (`Route`) it belongs to — to initialize a `HybridRouter` we need an `encoder`, `sparse_encoder` our `routes`, and the hybrid `index` we just define.
%% Cell type:code id: tags:
``` python
from semantic_router.routers import HybridRouter
router = HybridRouter(
encoder=encoder,
sparse_encoder=sparse_encoder,
routes=routes,
index=index,
)
```
%% Output
2024-11-24 12:25:32 - semantic_router.utils.logger - INFO - hybrid.py:157 - add() - Encoding route politics
2024-11-24 12:25:32 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 12:25:33 - semantic_router.utils.logger - INFO - hybrid.py:157 - add() - Encoding route chitchat
2024-11-24 12:25:33 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 18:12:29 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 18:12:31 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
%% Cell type:markdown id: tags:
We can check the dimensionality of our vectors by looking at the `index` attribute of the `RouteLayer`.
We can check the dimensionality and number of dense vector records by looking at the `index` attribute of the `HybridRouter`.
%% Cell type:code id: tags:
``` python
router.index.index.shape
```
%% Output
(11, 256)
(11, 1536)
%% Cell type:markdown id: tags:
To find the number of sparse vector records we can look at the `sparse_index` attribute of the `HybridRouter`.
%% Cell type:code id: tags:
``` python
len(router.index.sparse_index)
```
%% Output
11
%% Cell type:markdown id: tags:
We do have 256-dimensional vectors. Now let's test them:
%% Cell type:code id: tags:
``` python
router("don't you love politics?")
```
%% Output
2024-11-24 12:25:37 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 18:12:34 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
RouteChoice(name='politics', function_call=None, similarity_score=1.2995813276471633)
RouteChoice(name='politics', function_call=None, similarity_score=1.2837569119668175)
%% Cell type:code id: tags:
``` python
router("how's the weather today?")
```
%% Output
2024-11-24 12:25:38 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 18:12:36 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
RouteChoice(name='chitchat', function_call=None, similarity_score=1.8563758628277611)
RouteChoice(name='chitchat', function_call=None, similarity_score=1.856375862827761)
%% Cell type:markdown id: tags:
Both are classified accurately, what if we send a query that is unrelated to our existing `Route` objects?
%% Cell type:code id: tags:
``` python
router("I'm interested in learning about llama 2")
```
%% Output
2024-11-24 12:25:41 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
2024-11-24 18:12:37 - httpx - INFO - _client.py:1013 - _send_single_request() - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"
RouteChoice(name=None, function_call=None, similarity_score=None)
%% Cell type:markdown id: tags:
In this case, we return `None` because no matches were identified. We always recommend optimizing your `RouteLayer` for optimal performance, you can see how in [this notebook](https://github.com/aurelio-labs/semantic-router/blob/main/docs/06-threshold-optimization.ipynb).
%% Cell type:markdown id: tags:
---
......
......@@ -154,7 +154,6 @@ class HybridRouter(BaseRouter):
route_names = [route.name] * len(route.utterances)
# create embeddings for all routes
logger.info(f"Encoding route {route.name}")
dense_embeds, sparse_embeds = self._encode(route.utterances)
self.index.add(
embeddings=dense_embeds,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment