Mise en cache sémantique avec un point de terminaison privé (Private Service Connect)

Cette page s'applique à Apigee, mais pas à Apigee hybrid.

Consultez la documentation d' Apigee Edge.

Cette page explique comment configurer et utiliser les règles de mise en cache sémantique Apigee pour permettre la réutilisation intelligente des réponses en fonction de la similarité sémantique. Dans cet exemple, les règles exécutent leur recherche de similarité par rapport à un index Vector Search déployé sur un point de terminaison privé (Private Service Connect). En utilisant ces règles dans votre proxy d'API Apigee, vous pouvez réduire les appels d'API backend redondants, abaisser la latence et diminuer les coûts opérationnels.

Avant de commencer

Avant de commencer, effectuez les tâches suivantes :

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. Enable the Compute Engine, AI Platform, and Cloud Storage APIs.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the APIs

  4. Activez et configurez l' API Vertex AI Text Embeddings dans votre projet Google Cloud .
  5. Créez (ou accédez à) un index Vector Search déployé sur un point de terminaison privé (Private Service Connect). Ce tutoriel ne duplique pas les étapes de configuration de Vector Search. Consultez Conditions préalables pour les index de recherche Vector Search pour connaître les exigences spécifiques à SemanticCacheLookup et accéder à la documentation Vector Search.
  6. Vérifiez que vous disposez d'un environnement intermédiaire ou complet dans votre instance Apigee. Les règles de mise en cache sémantique ne peuvent être déployées que dans des environnements intermédiaires ou complets.
  7. Vérifiez que vous disposez d'un groupe d'environnements avec un nom d'hôte d'exécution que vous pouvez utiliser pour envoyer des requêtes à votre proxy d'API.

Rôles requis

Pour obtenir les autorisations nécessaires pour créer et utiliser les règles de mise en cache sémantique, demandez à votre administrateur de vous accorder le rôle IAM Utilisateur AI Platform (roles/aiplatform.user) sur le compte de service que vous utilisez pour déployer les proxys Apigee. Pour en savoir plus sur l'attribution de rôles, consultez Gérer l'accès aux projets, aux dossiers et aux organisations.

Vous pouvez également obtenir les autorisations requises avec des rôles personnalisés ou d'autres rôles prédéfinis.

Définir des variables d'environnement

Dans le projet Google Cloud qui contient votre instance Apigee, utilisez la commande suivante pour définir les variables d'environnement :

export PROJECT_ID=PROJECT_ID
export REGION=REGION
export RUNTIME_HOSTNAME=RUNTIME_HOSTNAME

Où :

  • PROJECT_ID est l'ID du projet contenant votre instance Apigee.
  • REGION est la région Google Cloud de votre instance Apigee.
  • RUNTIME_HOSTNAME est le nom d'hôte de votre environnement d'exécution Apigee.

Pour vérifier que les variables d'environnement sont correctement définies, exécutez la commande suivante et examinez le résultat :

echo $PROJECT_ID $REGION $RUNTIME_HOSTNAME

Définir le projet

Définissez le projet Google Cloud dans votre environnement de développement :

    gcloud auth login
    gcloud config set project $PROJECT_ID

Conditions préalables pour l'index Vector Search

Ce tutoriel suppose que vous disposez déjà d'un index Vector Search déployé sur un point de terminaison privé (Private Service Connect) (ou que vous allez en créer un). La création, la mise en forme et le déploiement d'un index Vector Search sont documentés dans les guides Vector Search. Ce tutoriel ne reprend donc pas ces étapes. Consultez la documentation Vector Search pour effectuer les opérations suivantes :

Lorsque vous créez l'index, il doit répondre aux exigences spécifiques à SemanticCacheLookup suivantes :

  • L'index doit utiliser STREAM_UPDATE ("indexUpdateMethod": "STREAM_UPDATE") pour que les appels upsertDatapoints de la règle SemanticCachePopulate puissent être interrogés en temps quasi réel.
  • L'index dimensions doit correspondre à la dimensionnalité de sortie du modèle d'embedding que vous utilisez dans la règle SemanticCacheLookup. Ce tutoriel utilise gemini-embedding-001, qui produit par défaut des embeddings de dimension 3072. Si vous tronquez la sortie à une dimensionnalité inférieure (par exemple, 768 ou 1 536), définissez dimensions sur la même valeur.
  • Créez l'index avec la mesure de distance (distanceMeasureType) qui correspond à la <DistanceMeasureType> de votre règle. L'élément <SimilaritySearch><VertexAI><DistanceMeasureType> de la règle SemanticCacheLookup est facultatif et sa valeur par défaut est DOT_PRODUCT_DISTANCE. COSINE_DISTANCE est également accepté. La mesure de distance d'index et la stratégie <DistanceMeasureType> doivent être identiques.

L'exemple minimal suivant crée un index compatible. Pour obtenir le corps de requête complet et toutes les options disponibles, consultez Créer et gérer un index :

ACCESS_TOKEN=$(gcloud auth print-access-token) && curl -X POST \
  "https://$REGION-aiplatform.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/indexes" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "displayName": "semantic-cache-index",
    "metadata": {
      "config": {
        "dimensions": 3072,
        "distanceMeasureType": "DOT_PRODUCT_DISTANCE"
      }
    },
    "indexUpdateMethod": "STREAM_UPDATE"
  }'

Notez la valeur numérique INDEX_ID renvoyée dans la réponse. Vous l'utiliserez dans la règle SemanticCachePopulate. Après avoir créé l'index, créez un point de terminaison d'index Private Service Connect et déployez l'index sur celui-ci.

Lorsque vous créez le point de terminaison d'index Private Service Connect, il doit répondre aux exigences spécifiques à SemanticCacheLookup suivantes :

  • projectAllowlist doit inclure le projet Apigee qui lance la connexion :
    • Apigee : utilisez le projet locataire Apigee. Obtenez l'ID du projet locataire à partir de l'API Organizations (champ apigeeProjectId).
    Le projectAllowlist ne peut pas être modifié une fois le point de terminaison d'index créé. Si vous ajoutez le mauvais projet à la liste d'autorisation, vous devez supprimer le point de terminaison de l'index et le recréer.

Notez le INDEX_ENDPOINT_ID numérique du point de terminaison d'index.

Configurer le compte de service pour le proxy Apigee

Le proxy Apigee utilise un compte de service pour ses appels REST Vertex AI : l'API Embeddings dans la règle SemanticCacheLookup, upsertDatapoints dans la règle SemanticCachePopulate et la cible du modèle. Attribuez le rôle AI Platform User (roles/aiplatform.user) à ce compte de service :

gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:SERVICE_ACCOUNT" \
  --role="roles/aiplatform.user"

SERVICE_ACCOUNT est l'adresse e-mail du compte de service utilisé par le proxy. Vous référencez ce compte de service lorsque vous déployez le proxy à l'Étape 4 : Importer et déployer le proxy d'API.

Présentation

Les règles de mise en cache sémantique aident les utilisateurs d'Apigee avec des modèles LLM à traiter de manière intelligente et efficace les requêtes identiques ou présentant une similarité sémantique. Cela permet de minimiser les appels d'API de backend et de réduire la consommation de ressources.

Les règles SemanticCacheLookup et SemanticCachePopulate s'appliquent respectivement aux flux de requête et de réponse d'un proxy d'API Apigee. Lorsque le proxy reçoit une requête, la règle SemanticCacheLookup extrait le prompt utilisateur de la requête et le convertit en représentation numérique à l'aide de l'API Text embeddings. Une recherche de similarité sémantique est effectuée à l'aide de Vector Search pour trouver des requêtes similaires. Si un point de données de prompt semblable est trouvé, une recherche dans le cache est effectuée. Si des données mises en cache sont trouvées, la réponse mise en cache est renvoyée au client.

Si la recherche de similarité ne renvoie aucun prompt précédent similaire, le modèle LLM génère du contenu en réponse au prompt de l'utilisateur et remplit le cache Apigee avec la réponse. Une boucle de rétroaction est créée pour mettre à jour les entrées de l'index de recherche Vector Search en vue des futures requêtes.

Dans ce scénario, l'index Vector Search est déployé sur un point de terminaison privé (Private Service Connect), via gRPC. Pour en savoir plus sur la compatibilité de Vector Search avec Private Service Connect, consultez Interroger des index avec l'accès aux services privés ou Private Service Connect.

Les sections suivantes décrivent les étapes à suivre pour créer et configurer les règles de mise en cache sémantique :

  1. Vérifiez vos ressources et obtenez les valeurs dont Apigee a besoin.
  2. Connectez-vous au rattachement de service.
  3. Créez le bundle de proxy d'API.
  4. Importez et déployez le proxy d'API.
  5. Testez les règles de mise en cache sémantique.

Étape 1 : Vérifiez vos ressources et obtenez les valeurs dont Apigee a besoin

Avant de configurer Apigee, vérifiez que le point de terminaison de votre index Vector Search est compatible avec Private Service Connect et que votre index est déployé. Lisez ensuite les deux valeurs que le proxy Apigee consomme : l'association de service et le DEPLOYED_INDEX_ID.

Vérifiez que l'index est déployé et que le point de terminaison expose un rattachement de service Private Service Connect :

gcloud ai index-endpoints describe INDEX_ENDPOINT_ID \
  --project=$PROJECT_ID --region=$REGION \
  --format="value(deployedIndexes.privateEndpoints.serviceAttachment)"

La commande renvoie un nom de ressource de rattachement de service au format projects/TENANT_PROJECT/regions/REGION/serviceAttachments/SERVICE_ATTACHMENT_NAME. Dans ce guide, cette valeur est appelée SERVICE_ATTACHMENT. Si la commande renvoie une valeur vide, l'index n'est pas encore déployé sur un point de terminaison Private Service Connect. Revenez à Conditions préalables pour l'index Vector Search et terminez le déploiement de l'index avant de continuer.

Lisez le DEPLOYED_INDEX_ID de l'index déployé sur le point de terminaison :

gcloud ai index-endpoints describe INDEX_ENDPOINT_ID \
  --project=$PROJECT_ID --region=$REGION \
  --format="value(deployedIndexes.id)"

Dans ce guide, cette valeur est appelée DEPLOYED_INDEX_ID. Vous l'utiliserez dans la règle SemanticCacheLookup à l'étape 3 : Créer le bundle de proxy d'API.

Pour en savoir plus sur le déploiement et l'interrogation des points de terminaison d'index privés, consultez Déployer un index sur un point de terminaison Private Service Connect et Interroger les index Private Services Access ou Private Service Connect.

Étape 2 : Se connecter au rattachement de service

Cette étape vous fournit l'hôte privé que le proxy appelle <GrpcEndpoint>. Sur Apigee, créez un rattachement de point de terminaison Apigee. Le rattachement de point de terminaison correspond au côté client Private Service Connect d'Apigee. Il se connecte au rattachement de service Vector Search et vous fournit un hôte privé que le proxy appelle.

curl -X POST \
  -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{
        "location": "'"$REGION"'",
        "serviceAttachment": "SERVICE_ATTACHMENT"
      }' \
  "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/endpointAttachments?endpointAttachmentId=ENDPOINT_ATTACHMENT"

Interrogez jusqu'à ce que state de la pièce jointe soit ACTIVE et que son connectionState soit ACCEPTED, puis notez l'hôte :

curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \
  "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/endpointAttachments/ENDPOINT_ATTACHMENT"

La réponse contient l'hôte dans le champ host. Dans ce guide, cette valeur est appelée TARGET_HOST.

Pour vous connecter au rattachement de service Vector Search depuis votre proxy, vous pouvez utiliser :

  • Adresse IP : utilisez directement l'adresse IP renvoyée dans le champ host comme TARGET_HOST (par exemple, 7.0.3.4).
  • Enregistrement DNS privé : si vous avez configuré une zone Cloud DNS privée dans votre projet Google Cloud avec l'appairage DNS à Apigee, vous pouvez créer un enregistrement A dans votre zone privée pointant vers l'adresse IP de l'association de point de terminaison et utiliser ce nom de domaine (par exemple, vectorsearch.example.com) comme TARGET_HOST. Pour en savoir plus, consultez Utiliser un enregistrement DNS et Se connecter avec des zones d'appairage DNS privées.

Étape 3 : Créez le groupe de proxys d'API

Créer le bundle de proxy

Créez la structure de répertoire suivante :

apiproxy/
├── PROXY_NAME.xml
├── proxies/default.xml
├── targets/default.xml
└── policies/
    ├── SCL-1.xml
    └── SCP-1.xml

policies/SCL-1.xml : la règle SemanticCacheLookup. Le bloc <SimilaritySearch> utilise <PrivateServiceConnect><GrpcEndpoint> (sans <URL>).

Remarque : Règles <GrpcEndpoint> :

  • Le format est grpc://TARGET_HOST:PORT. Le schéma doit être grpc://. grpcs:// (TLS) n'est pas compatible avec cette version.
  • Le port est 10000 pour Vector Search. Les points de terminaison du plan de données Private Service Connect diffusent gRPC sur le port 10000. Le point de terminaison est donc toujours grpc://TARGET_HOST:10000.
  • TARGET_HOST peut être l'adresse IP du rattachement de point de terminaison (à partir de l'étape 2) ou un enregistrement DNS personnalisé créé dans votre zone DNS privée.
  • Le saut gRPC est en texte brut et non authentifié (sécurisé par l'isolation du réseau).
<SemanticCacheLookup async="false" continueOnError="false" enabled="true" name="SCL-1">
  <DisplayName>SCL-1</DisplayName>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <UserPromptSource>{jsonPath('$.contents[-1].parts[-1].text',request.content,true)}</UserPromptSource>
  <Embeddings>
    <VertexAI>
      <URL>https://REGION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/publishers/google/models/gemini-embedding-001:predict</URL>
    </VertexAI>
  </Embeddings>
  <SimilaritySearch>
    <VertexAI>
      <PrivateServiceConnect>
        <GrpcEndpoint>grpc://TARGET_HOST:10000</GrpcEndpoint>
      </PrivateServiceConnect>
      <DeployedIndexID>DEPLOYED_INDEX_ID</DeployedIndexID>
      <Threshold>0.95</Threshold>
    </VertexAI>
  </SimilaritySearch>
</SemanticCacheLookup>

policies/SCP-1.xml : règle SemanticCachePopulate. Populate est une méthode REST uniquement et doit utiliser <URL> (elle refuse <PrivateServiceConnect> au moment du déploiement) :

<SemanticCachePopulate async="false" continueOnError="true" enabled="true" name="SCP-1">
  <DisplayName>SCP-1</DisplayName>
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <SimilaritySearch>
    <VertexAI>
      <URL>https://REGION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/indexes/INDEX_ID:upsertDatapoints</URL>
    </VertexAI>
  </SimilaritySearch>
  <TTLInSeconds>3600</TTLInSeconds>
</SemanticCachePopulate>

targets/default.xml : la cible du modèle. La cible appelle une API Google. Elle a donc besoin d'un jeton. <GoogleAccessToken> utilise le compte de service du déploiement :

<TargetEndpoint name="default">
  <PreFlow name="PreFlow"><Request/><Response/></PreFlow>
  <PostFlow name="PostFlow"><Request/><Response/></PostFlow>
  <HTTPTargetConnection>
    <Authentication>
      <GoogleAccessToken>
        <Scopes>
          <Scope>https://www.googleapis.com/auth/cloud-platform</Scope>
        </Scopes>
      </GoogleAccessToken>
    </Authentication>
    <URL>https://REGION-aiplatform.googleapis.com/v1/projects/PROJECT_ID/locations/REGION/publishers/google/models/gemini-2.5-flash:generateContent</URL>
  </HTTPTargetConnection>
</TargetEndpoint>

proxies/default.xml : exécutez la règle SemanticCacheLookup sur la requête et la règle SemanticCachePopulate sur la réponse :

<ProxyEndpoint name="default">
  <PreFlow name="PreFlow">
    <Request><Step><Name>SCL-1</Name></Step></Request>
    <Response><Step><Name>SCP-1</Name></Step></Response>
  </PreFlow>
  <PostFlow name="PostFlow"><Request/><Response/></PostFlow>
  <HTTPProxyConnection>
    <BasePath>/PROXY_NAME</BasePath>
  </HTTPProxyConnection>
  <RouteRule name="default">
    <TargetEndpoint>default</TargetEndpoint>
  </RouteRule>
</ProxyEndpoint>

PROXY_NAME.xml : le descripteur de bundle

<APIProxy name="PROXY_NAME">
  <BasePaths>/PROXY_NAME</BasePaths>
  <Policies><Policy>SCL-1</Policy><Policy>SCP-1</Policy></Policies>
  <ProxyEndpoints><ProxyEndpoint>default</ProxyEndpoint></ProxyEndpoints>
  <TargetEndpoints><TargetEndpoint>default</TargetEndpoint></TargetEndpoints>
</APIProxy>

Étape 4 : Importer et déployer le proxy d'API

Compressez le bundle, importez-le pour créer une révision, puis déployez-la avec votre compte de service :

TOKEN=$(gcloud auth print-access-token)
(cd BUNDLE_DIR && zip -r ../PROXY_NAME.zip apiproxy)
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "file=@PROXY_NAME.zip" \
  "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/apis?action=import&name=PROXY_NAME"
curl -X POST -H "Authorization: Bearer $TOKEN" \
  "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/environments/ENV/apis/PROXY_NAME/revisions/REVISION/deployments?override=true&serviceAccount=SERVICE_ACCOUNT"

Où :

  • BUNDLE_DIR est le répertoire contenant le dossier apiproxy/. L'archive doit contenir le dossier apiproxy/ à la racine.
  • ENV est l'environnement Apigee dans lequel vous déployez le proxy. L'environnement doit être intermédiaire ou complet.
  • REVISION correspond au numéro de révision renvoyé par l'appel d'importation.
  • SERVICE_ACCOUNT est l'adresse e-mail du compte de service que vous utilisez pour déployer le proxy.

Attendez que le déploiement indique READY :

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/environments/ENV/apis/PROXY_NAME/revisions/REVISION/deployments" | jq .state

Étape 5 : Tester les règles de mise en cache sémantique

Envoyez une nouvelle requête. Il s'agit d'un défaut de cache (miss) : le modèle est appelé et la réponse est mise en cache.

curl -X POST "https://$RUNTIME_HOSTNAME/PROXY_NAME" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"role":"user","parts":[{"text":"Explain in one sentence why the sky appears blue."}]}]}'

Renvoyez le même prompt. Il s'agit d'un succès de cache (hit) : la réponse est diffusée à partir du cache et le modèle n'est pas appelé.

curl -i -X POST "https://$RUNTIME_HOSTNAME/PROXY_NAME" \
  -H "Content-Type: application/json" \
  -d '{"contents":[{"role":"user","parts":[{"text":"Explain in one sentence why the sky appears blue."}]}]}'

Sur le hit, la réponse inclut l'en-tête Cached-content: true, la même réponse et une latence nettement inférieure.

Vous pouvez également vérifier la mise en cache à l'aide d'une session de débogage. En cas de correspondance, la règle SemanticCacheLookup définit les variables de flux suivantes :

Variable Valeur d'un résultat
SemanticCacheLookup.SCL-1.dense_embeddings Vecteur d'embedding de la requête.
SemanticCacheLookup.SCL-1.is_nearest_neighbor_hit true
SemanticCacheLookup.SCL-1.cache_hit true
SemanticCacheLookup.SCL-1.cached_llm_response Réponse mise en cache.

En cas de succès, la cible du modèle n'est pas appelée. Le flux est court-circuité et renvoie la réponse mise en cache.

Dépannage

Pour obtenir la documentation de référence complète sur les erreurs, consultez la règle SemanticCacheLookup.

Étapes suivantes