Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4a2c0fb

Browse files
authored
example: add semantic cache demo built with jinaai and tidb vector (#39)
1 parent 1b8c290 commit 4a2c0fb

File tree

5 files changed

+224
-1
lines changed

5 files changed

+224
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,5 +247,6 @@ There are some examples to show how to use the tidb-vector-python to interact wi
247247
- [GraphRAG Step by Step Tutorial](./examples/graphrag-step-by-step-tutorial/README.md): Step by step tutorial to build a Knowledge Graph based RAG application with Colab notebook. In this tutorial, you will learn how to extract knowledge from a text corpus, build a Knowledge Graph, store the Knowledge Graph in TiDB Serverless, and search from the Knowledge Graph.
248248
- [Vector Search Notebook with SQLAlchemy](https://colab.research.google.com/drive/1LuJn4mtKsjr3lHbzMa2RM-oroUvpy83y?usp=sharing): use [SQLAlchemy](https://www.sqlalchemy.org/) to interact with TiDB Serverless: connect db, index&store data and then search vectors.
249249
- [Build RAG with Jina AI Embeddings](./examples/jina-ai-embeddings-demo/README.md): use Jina AI to generate embeddings for text data, store the embeddings in TiDB Vector Storage, and search for similar embeddings.
250+
- [Semantic Cache](./examples/semantic-cache/README.md): build a semantic cache with Jina AI and TiDB Vector.
250251

251-
for more examples, see the [examples](./examples) directory.
252+
for more examples, see the [examples](./examples) directory.

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Please make sure you have created a TiDB Serverless cluster with vector support
3333
- [GraphRAG Step by Step Tutorial](./graphrag-step-by-step-tutorial/README.md): Step by step tutorial to build a Knowledge Graph based RAG application with Colab notebook. In this tutorial, you will learn how to extract knowledge from a text corpus, build a Knowledge Graph, store the Knowledge Graph in TiDB Serverless, and search from the Knowledge Graph.
3434
- [Vector Search Notebook with SQLAlchemy](https://colab.research.google.com/drive/1LuJn4mtKsjr3lHbzMa2RM-oroUvpy83y?usp=sharing): use [SQLAlchemy](https://www.sqlalchemy.org/) to interact with TiDB Serverless: connect db, index&store data and then search vectors.
3535
- [Build RAG with Jina AI Embeddings](./jina-ai-embeddings-demo/README.md): use Jina AI to generate embeddings for text data, store the embeddings in TiDB Vector Storage, and search for similar embeddings.
36+
- [Semantic Cache](./semantic-cache/README.md): build a semantic cache with Jina AI and TiDB Vector.
3637

3738
## Real World Applications
3839

examples/semantic-cache/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Semantic Cache with Jina AI and TiDB Vector
2+
Semantic cache is a cache that stores the semantic information of the data. It can be used to speed up the search process by storing the embeddings of the data and searching for similar embeddings. This example demonstrates how to use Jina AI to generate embeddings for text data and store the embeddings in TiDB Vector Storage. It also shows how to search for similar embeddings in TiDB Vector Storage.
3+
4+
## Prerequisites
5+
6+
- A running TiDB Serverless cluster with vector search enabled
7+
- Python 3.8 or later
8+
- Jina AI API key
9+
10+
## Run the example
11+
12+
### Clone this repo
13+
14+
```bash
15+
git clone https://github.com/pingcap/tidb-vector-python.git
16+
```
17+
18+
### Create a virtual environment
19+
20+
```bash
21+
cd tidb-vector-python/examples/semantic-cache
22+
python3 -m venv .venv
23+
source .venv/bin/activate
24+
```
25+
26+
### Install dependencies
27+
28+
```bash
29+
pip install -r requirements.txt
30+
```
31+
32+
### Set the environment variables
33+
34+
Get the `HOST`, `PORT`, `USERNAME`, `PASSWORD`, and `DATABASE` from the TiDB Cloud console, as described in the [Prerequisites](../README.md#prerequisites) section. Then set the following environment variables:
35+
36+
```bash
37+
export DATABASE_URI="mysql+pymysql://34u7xMnnDLSkjV1.root:<PASSWORD>@gateway01.eu-central-1.prod.aws.tidbcloud.com:4000/test?ssl_ca=/etc/ssl/cert.pem&ssl_verify_cert=true&ssl_verify_identity=true"
38+
```
39+
or create a `.env` file with the above environment variables.
40+
41+
42+
### Run this example
43+
44+
45+
#### Start the semantic cache server
46+
47+
```bash
48+
fastapi dev cache.py
49+
```
50+
51+
#### Test the API
52+
53+
Get the Jina AI API key from the [Jina AI Embedding API](https://jina.ai/embeddings/) page, and save it somewhere safe for later use.
54+
55+
`POST /set`
56+
57+
```bash
58+
curl --location ':8000/set' \
59+
--header 'Content-Type: application/json' \
60+
--header 'Authorization: Bearer <your jina token>' \
61+
--data '{
62+
"key": "what is tidb",
63+
"value": "tidb is a mysql-compatible and htap database"
64+
}'
65+
```
66+
67+
`GET /get/<key>`
68+
69+
```bash
70+
curl --location ':8000/get/what%27s%20tidb%20and%20tikv?max_distance=0.5' \
71+
--header 'Content-Type: application/json' \
72+
--header 'Authorization: Bearer <your jina token>'
73+
```

examples/semantic-cache/cache.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import os
2+
from datetime import datetime
3+
from typing import Optional, Annotated
4+
5+
import requests
6+
import dotenv
7+
from fastapi import Depends, FastAPI
8+
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
9+
from sqlmodel import (
10+
SQLModel,
11+
Session,
12+
create_engine,
13+
select,
14+
Field,
15+
Column,
16+
String,
17+
Text,
18+
DateTime,
19+
)
20+
from sqlalchemy import func
21+
from tidb_vector.sqlalchemy import VectorType
22+
dotenv.load_dotenv()
23+
24+
25+
# Configuration from .env
26+
# Example: "mysql+pymysql://<username>:<password>@<host>:<port>/<database>?ssl_mode=VERIFY_IDENTITY&ssl_ca=/etc/ssl/cert.pem"
27+
DATABASE_URI = os.getenv('DATABASE_URI')
28+
# Ref: https://docs.pingcap.com/tidb/stable/time-to-live
29+
# Default: 604800 SECOND (1 week)
30+
TIME_TO_LIVE = os.getenv('TIME_TO_LIVE')
31+
32+
33+
# Get Embeddings from Jina AI
34+
def generate_embeddings(jinaai_api_key: str, text: str):
35+
JINAAI_API_URL = 'https://api.jina.ai/v1/embeddings'
36+
JINAAI_HEADERS = {
37+
'Content-Type': 'application/json',
38+
'Authorization': f'Bearer {jinaai_api_key}'
39+
}
40+
JINAAI_REQUEST_DATA = {
41+
'input': [text],
42+
'model': 'jina-embeddings-v2-base-en' # with dimisions 768
43+
}
44+
response = requests.post(JINAAI_API_URL, headers=JINAAI_HEADERS, json=JINAAI_REQUEST_DATA)
45+
return response.json()['data'][0]['embedding']
46+
47+
48+
class Cache(SQLModel, table=True):
49+
__table_args__ = {
50+
# Ref: https://docs.pingcap.com/tidb/stable/time-to-live
51+
'mysql_TTL': f'created_at + INTERVAL {TIME_TO_LIVE} SECOND',
52+
}
53+
54+
id: Optional[int] = Field(default=None, primary_key=True)
55+
key: str = Field(sa_column=Column(String(255), unique=True, nullable=False))
56+
key_vec: Optional[list[float]]= Field(
57+
sa_column=Column(
58+
VectorType(768),
59+
default=None,
60+
comment="hnsw(distance=l2)",
61+
nullable=False,
62+
)
63+
)
64+
value: Optional[str] = Field(sa_column=Column(Text))
65+
created_at: datetime = Field(
66+
sa_column=Column(DateTime, server_default=func.now(), nullable=False)
67+
)
68+
updated_at: datetime = Field(
69+
sa_column=Column(
70+
DateTime, server_default=func.now(), onupdate=func.now(), nullable=False
71+
)
72+
)
73+
74+
engine = create_engine(DATABASE_URI)
75+
SQLModel.metadata.create_all(engine)
76+
77+
app = FastAPI()
78+
security = HTTPBearer()
79+
80+
@app.get("/")
81+
def index():
82+
return {
83+
"message": "Welcome to Semantic Cache API, it is built using Jina AI Embeddings API and TiDB Vector",
84+
"docs": "/docs",
85+
"redoc": "/redoc",
86+
"about": "https://github.com/pingcap/tidb-vector-python/blob/main/examples/semantic-cache/README.md",
87+
"config": {
88+
"TIME_TO_LIVE": int(TIME_TO_LIVE),
89+
"EMBEDDING_DIMENSIONS": 768,
90+
"EMBEDDING_PROVIDER": "Jina AI",
91+
"EMBEDDING_MODEL": "jina-embeddings-v2-base-en",
92+
}
93+
}
94+
95+
96+
# /set method of Semantic Cache
97+
@app.post("/set")
98+
def set(
99+
credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
100+
cache: Cache,
101+
):
102+
cache.key_vec = generate_embeddings(credentials.credentials, cache.key)
103+
104+
with Session(engine) as session:
105+
session.add(cache)
106+
session.commit()
107+
108+
return {'message': 'Cache has been set'}
109+
110+
111+
@app.get("/get/{key}")
112+
def get(
113+
credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
114+
key: str,
115+
max_distance: Optional[float] = 0.1,
116+
):
117+
key_vec = generate_embeddings(credentials.credentials, key)
118+
# The max value of distance is 0.3
119+
max_distance = min(max_distance, 0.3)
120+
121+
with Session(engine) as session:
122+
result = session.exec(
123+
select(
124+
Cache,
125+
Cache.key_vec.cosine_distance(key_vec).label('distance')
126+
).order_by(
127+
'distance'
128+
).limit(1)
129+
).first()
130+
131+
if result is None:
132+
return {"message": "Cache not found"}, 404
133+
134+
cache, distance = result
135+
if distance > max_distance:
136+
return {"message": "Cache not found"}, 404
137+
138+
return {
139+
"key": cache.key,
140+
"value": cache.value,
141+
"distance": distance
142+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
requests
2+
PyMySQL
3+
sqlmodel==0.0.19
4+
tidb-vector>=0.0.9
5+
python-dotenv
6+
fastapi

0 commit comments

Comments
 (0)