Embedding cache
AI_EMBEDDING_CACHE enables params.cache=true for exact-content caching. Identical inputs return vectors directly without a model call. This is suitable for FAQ imports and frequently repeated queries. If the cache is unavailable, the service falls back to real-time computation. Business logic should not depend on cache hits.
Syntax
REST API
POST /v2/vectordb/ai/embedding
Content-Type: application/json
{
"model_name": "text-embedding-v4",
"texts": ["<text>"],
"params": {
"dim": 1024,
"cache": {
"enabled": true,
"exact_cache": {"enabled": true, "backend": "redis", "ttl_hours": 24}
}
}
}Python
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("content", DataType.VARCHAR, max_length=4096)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=1024)
schema.add_function(
Function(
name="embed_content_with_cache",
function_type=FunctionType.TEXTEMBEDDING,
input_field_names=["content"],
output_field_names=["embedding"],
params={
"provider": "aliyun_milvus",
"model_name": "text-embedding-v4",
"dim": 1024,
"cache": json.dumps({
"enabled": True,
"exact_cache": {
"enabled": True,
"backend": "redis",
"ttl_hours": 24,
},
}),
},
)
)Parameters
Parameter | Description |
| Same as AI_EMBEDDING. Caching changes only the generation path, not the model, fields, or response format. |
| The master cache switch. Default: |
| The cache read/write timeout in seconds. Default: |
| The Redis exact-cache switch. This and |
| Currently, only |
| The cache lifetime in hours. Default: |
| Whether to temporarily bypass the cache backend after consecutive slow reads or failures. Default: |
| Required when read-latency degradation is enabled. The slow-read threshold in milliseconds. |
| Optional. The number of consecutive slow reads that triggers degradation and the degradation duration. Defaults: |
Return values
The response has the same structure as a regular Embedding response. Vectors are at data.output.embeddings[].embedding. The response also includes data.usage (such as total_tokens) and data.request_id. On a cache hit, the model is not called: total_tokens is 0 and no request_id is returned. If the cache is unavailable or times out, the model is called directly. Business correctness should therefore not depend on cache hits.
{"code":0,"data":{"output":{"embeddings":[{"text_index":0,"embedding":[0.01,0.02]}]},"usage":{"total_tokens":22},"request_id":"xxxxxxxx"}}Example: Verify cache reuse for a customer service refund FAQ
A customer service knowledge base may process the same "refund arrival time" FAQ during staging and production imports. The following code defines one request body and sends the exact same content in two independent calls, rather than including two identical texts in a single request, to observe whether the second request hits the cache.
REST API
#!/usr/bin/env bash
set -euo pipefail
MILVUS_REST_BASE_URL="http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_AUTH_TOKEN="<yourUsername>:<yourPassword>"
post_json() {
local path="$1"
local body="$2"
curl -X POST "$MILVUS_REST_BASE_URL$path" \
-H "Authorization: Bearer $MILVUS_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d "$body"
}
MODEL_NAME="text-embedding-v4"
BODY=$(cat <<JSON
{
"model_name": "$MODEL_NAME",
"texts": [
"Milvus is an open-source vector database.",
"Milvus is an open-source vector database."
],
"params": {
"dim": 1024,
"cache": {
"enabled": true,
"exact_cache": {"enabled": true, "backend": "redis", "ttl_hours": 24}
}
}
}
JSON
)
# Send the same BODY in two independent requests: a first cache miss calls the model (usage.total_tokens > 0 and request_id is returned),
# a second cache hit returns vectors directly (usage.total_tokens = 0 and no request_id).
for attempt in 1 2; do
echo "Attempt ${attempt}: request embeddings with the same BODY."
RESPONSE_BODY="$(post_json "/v2/vectordb/ai/embedding" "$BODY")"
if command -v jq >/dev/null 2>&1; then
echo "$RESPONSE_BODY" | jq '{code, total_tokens: .data.usage.total_tokens, request_id: .data.request_id}'
[ "$(echo "$RESPONSE_BODY" | jq -r '.code // -1')" = "0" ] || exit 1
else
echo "$RESPONSE_BODY"
fi
donePython
from __future__ import annotations
import json
import os
from typing import Any
from pymilvus import DataType, Function, FunctionType, MilvusClient
MILVUS_URI = "http://c-xxxx.milvus.aliyuncs.com:19530"
MILVUS_TOKEN = "<yourUsername>:<yourPassword>"
def add_id(schema: Any) -> None:
schema.add_field("id", DataType.INT64, is_primary=True)
MODEL_NAME = "text-embedding-v4"
VECTOR_DIM = int(os.getenv("AIFUNC_EMBEDDING_DIM", "1024"))
client = MilvusClient(uri=MILVUS_URI, token=MILVUS_TOKEN)
collection_name = "simple_ai_embedding_cache"
if client.has_collection(collection_name):
client.drop_collection(collection_name)
schema = MilvusClient.create_schema(auto_id=True, enable_dynamic_field=False)
add_id(schema)
schema.add_field("content", DataType.VARCHAR, max_length=4096)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=VECTOR_DIM)
schema.add_function(
Function(
name="embed_content_with_cache",
function_type=FunctionType.TEXTEMBEDDING,
input_field_names=["content"],
output_field_names=["embedding"],
params={
"provider": "aliyun_milvus",
"model_name": MODEL_NAME,
"dim": VECTOR_DIM,
"cache": json.dumps(
{"enabled": True, "exact_cache": {"enabled": True, "backend": "redis", "ttl_hours": 24}}
),
},
)
)
index_params = client.prepare_index_params()
index_params.add_index(field_name="embedding", index_type="AUTOINDEX", metric_type="COSINE")
client.create_collection(collection_name=collection_name, schema=schema, index_params=index_params)
body = {"content": "Milvus is an open-source vector database."}
print("Insert the same body for the first time.")
client.insert(collection_name, [body])
client.flush(collection_name)
print("Insert the same body for the second time.")
client.insert(collection_name, [body])
client.flush(collection_name)
print(client.query(collection_name, filter="", output_fields=["content"], limit=10))Do not use identical vectors in two responses or the latency of one request as evidence of a cache hit. For managed instances, compare the response fields data.usage.total_tokens and data.request_id: on a cache miss, total_tokens is greater than 0 and request_id is returned; on a cache hit, total_tokens is 0 and no request_id is returned, indicating that the model was not called again. If you can access the underlying Redis instance, first record the INFO stats keyspace_hits baseline during a quiet period, and then send two identical requests in sequence to compare the increase. Redis failures or timeouts fall back to model calls. Do not make cache hits a business success condition or promise a fixed latency improvement.