When using the `PineconeIndex`, our `RouteLayer` is stored in two places:
* We keep route layer metadata locally.
* Vectors alongside a backup of our metadata is stored remotely in Pinecone.
By storing some data locally and some remotely we achieve improved persistence and the ability to recover our local state if lost. However, it does come with challenges around keep our local and remote instances synchronized. Fortunately, we have [several synchronization options](https://docs.aurelio.ai/semantic-router/route_layer/sync.html). In this example, we'll see how to use these options to keep our local and remote Pinecone instances synchronized.
%% Cell type:code id: tags:
``` python
fromsemantic_routerimportRoute
# we could use this as a guide for our chatbot to avoid political conversations
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!",
],
)
# this could be used as an indicator to our chatbot to switch to a more
# conversational prompt
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",
],
)
# we place both of our decisions together into single list
We can use the `get_utterance_diff` method to see exactly _why_ our local and remote are not synced
%% Cell type:code id: tags:
``` python
rl.get_utterance_diff()
```
%% Output
["- politics: don't you just hate the president",
"- politics: don't you just love the president",
"- politics: isn't politics the best thing ever",
'- politics: they will save the country!',
"- politics: they're going to destroy this country!",
"- politics: why don't you tell me about your political opinions",
'+ Route 1: Hello',
'+ Route 1: Hi',
'+ Route 2: Au revoir',
'+ Route 2: Bye',
'+ Route 2: Goodbye',
'+ Route 3: Boo']
%% Cell type:markdown id: tags:
## Handling Synchronization
%% Cell type:markdown id: tags:
We may want to handle the resynchronization ourselves and to do that we ideally want a more structured version of the utterance diff returned above. To create that we first need to get a list of utterance objects from our remote and local instances:
%% Cell type:code id: tags:
``` python
remote_utterances=rl.index.get_utterances()
remote_utterances
```
%% Cell type:code id: tags:
``` python
local_utterances=rl.to_config().to_utterances()
local_utterances
```
%% Cell type:markdown id: tags:
We can add the `diff_tag` attribute to each of these utterances by loading both lists into a `UtteranceDiff` object:
`UtteranceDiff` objects include all diff information inside the `diff` attribute (which is a list of `Utterance` objects):
%% Cell type:code id: tags:
``` python
diff.diff
```
%% Cell type:markdown id: tags:
Each of our `Utterance` objects now contains a populate `diff_tag` attribute. Where:
*`diff_tag='+'` means the utterance exists in the remote instance *only*
*`diff_tag='-'` means the utterance exists in the local instance *only*
*`diff_tag=' '` means the utterance exists in both remote and local instances
So, to collect utterances missing from our local instance we can run:
%% Cell type:code id: tags:
``` python
diff.get_tag("+")
```
%% Cell type:markdown id: tags:
To collect utterances missing from our remote instance we can run:
%% Cell type:code id: tags:
``` python
diff.get_tag("-")
```
%% Cell type:markdown id: tags:
And, if needed, we can get all utterances that exist in both with:
%% Cell type:code id: tags:
``` python
diff.get_tag("")
```
%% Cell type:markdown id: tags:
## Synchronization
%% Cell type:markdown id: tags:
There are six synchronization methods that we can use, those are:
*`error`: Raise an error if local and remote are not synchronized.
*`remote`: Take remote as the source of truth and update local to align.
*`local`: Take local as the source of truth and update remote to align.
*`merge-force-remote`: Merge both local and remote keeping local as the priority. Remote utterances are only merged into local *if* a matching route for the utterance is found in local, all other route-utterances are dropped. Where a route exists in both local and remote, but each contains different `function_schema` or `metadata` information, the local version takes priority and local `function_schemas` and `metadata` is propogated to all remote utterances belonging to the given route.
*`merge-force-local`: Merge both local and remote keeping remote as the priority. Local utterances are only merged into remote *if* a matching route for the utterance is found in the remote, all other route-utterances are dropped. Where a route exists in both local and remote, but each contains different `function_schema` or `metadata` information, the remote version takes priotity and remote `function_schemas` and `metadata` are propogated to all local routes.
*`merge`: Merge both local and remote, merging also local and remote utterances when a route with same route name is present both locally and remotely. If a route exists in both local and remote but contains different `function_schemas` or `metadata` information, the local version takes priority and local `function_schemas` and `metadata` are propogated to all remote routes.
We can get the synchronization strategy for each of these (with the exception of `error`) using the `diff.get_sync_strategy` method.
%% Cell type:code id: tags:
``` python
diff.get_sync_strategy("local")
```
%% Cell type:code id: tags:
``` python
diff.get_sync_strategy("remote")
```
%% Cell type:code id: tags:
``` python
diff.get_sync_strategy("merge-force-remote")
```
%% Cell type:code id: tags:
``` python
diff.get_sync_strategy("merge-force-local")
```
%% Cell type:code id: tags:
``` python
diff.get_sync_strategy("merge")
```
%% Cell type:markdown id: tags:
Each of these sync strategies can be fed to our route layer via the `rl._execute_sync_strategy` method:
%% Cell type:code id: tags:
``` python
strategy=diff.get_sync_strategy("local")
rl._execute_sync_strategy(strategy=strategy)
```
%% Cell type:code id: tags:
``` python
time.sleep(3)
rl.is_synced()
```
%% Cell type:markdown id: tags:
We can check our diff method to see what the `local` sync did:
%% Cell type:code id: tags:
``` python
rl.get_utterance_diff()
```
%% Cell type:markdown id: tags:
As expected, it took all local utterances and applied them to the remote instance, removing all utterances that were only present in the remote instance.
We can simplify this process significantly by running the `rl.sync` method with our chosen `sync_mode`: