이 페이지는 Apigee에 적용되지만 Apigee Hybrid에는 적용되지 않습니다.
Apigee Edge 문서 보기
이 페이지에서는 시맨틱 유사성에 기반한 지능형 응답 재사용을 지원하기 위해 Apigee 시맨틱 캐싱 정책을 구성하고 사용하는 방법을 설명합니다. 이 예에서 정책은 비공개 (Private Service Connect) 엔드포인트에 배포된 벡터 검색 색인에 대해 유사성 검색을 실행합니다. 이러한 정책을 Apigee API 프록시에 사용하면 중복된 백엔드 API 호출을 최소화하고, 지연 시간을 줄이며, 운영 비용을 절감할 수 있습니다.
시작하기 전에
시작하기 전에 다음 작업을 완료하세요.
-
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 theresourcemanager.projects.createpermission. Learn how to grant roles.
-
Verify that billing is enabled for your Google Cloud project.
Enable the Compute Engine, AI Platform, and Cloud Storage APIs.
Roles required to enable APIs
To enable APIs, you need the
serviceusage.services.enablepermission. 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.- Google Cloud 프로젝트에서 Vertex AI 텍스트 임베딩 API를 사용 설정하고 구성합니다.
- 비공개(Private Service Connect) 엔드포인트에 배포된 벡터 검색 색인을 만들거나 액세스할 수 있어야 합니다. 이 튜토리얼에서는 벡터 검색 설정 단계를 중복하지 않습니다. SemanticCacheLookup 관련 요구사항과 벡터 검색 문서 링크는 벡터 검색 색인 기본 요건을 참고하세요.
- Apigee 인스턴스에서 중간 또는 포괄 환경을 사용할 수 있는지 확인합니다. 시맨틱 캐싱 정책은 중급 또는 종합 환경에만 배포할 수 있습니다.
- API 프록시에 요청을 전송하는 데 사용할 수 있는 런타임 호스트 이름이 있는 환경 그룹이 있는지 확인합니다.
필요한 역할
시맨틱 캐싱 정책을 만들고 사용하는 데 필요한 권한을 얻으려면 Apigee 프록시 배포에 사용하는 서비스 계정에 대한 AI Platform 사용자 (roles/aiplatform.user) IAM 역할을 부여해 달라고 관리자에게 요청하세요.
역할 부여에 대한 자세한 내용은 프로젝트, 폴더, 조직에 대한 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
환경 변수 설정하기
Apigee 인스턴스가 포함된 Google Cloud 프로젝트에서 다음 명령어를 사용하여 환경 변수를 설정합니다.
export PROJECT_ID=PROJECT_IDexport REGION=REGIONexport RUNTIME_HOSTNAME=RUNTIME_HOSTNAME
각 항목의 의미는 다음과 같습니다.
PROJECT_ID: Apigee 인스턴스가 있는 프로젝트의 IDREGION: Apigee 인스턴스의 Google Cloud 리전RUNTIME_HOSTNAME: Apigee 런타임의 호스트 이름
환경 변수가 올바르게 설정되었는지 확인하려면 다음 명령어를 실행하고 출력을 검토합니다.
echo $PROJECT_ID $REGION $RUNTIME_HOSTNAME
프로젝트 설정
개발 환경에서 Google Cloud 프로젝트를 설정합니다.
gcloud auth logingcloud config set project $PROJECT_ID
벡터 검색 색인 필수사항
이 튜토리얼에서는 비공개(Private Service Connect) 엔드포인트에 배포된 벡터 검색 색인이 이미 있거나 생성할 것으로 가정합니다. 벡터 검색 색인을 만들고, 형식을 지정하고, 배포하는 방법은 벡터 검색 가이드에 설명되어 있으므로 이 튜토리얼에서는 이러한 단계를 중복하지 않습니다. 벡터 검색 문서에 따라 다음을 수행하세요.
색인을 만들 때는 다음 SemanticCacheLookup 관련 요구사항을 충족해야 합니다.
- SemanticCachePopulate 정책의
upsertDatapoints호출이 거의 실시간으로 쿼리 가능하도록 색인은STREAM_UPDATE("indexUpdateMethod": "STREAM_UPDATE")를 사용해야 합니다. - 색인
dimensions는 SemanticCacheLookup 정책에서 사용하는 임베딩 모델의 출력 차원과 일치해야 합니다. 이 튜토리얼에서는 기본적으로 3072차원 임베딩을 생성하는gemini-embedding-001을 사용합니다. 출력을 더 낮은 차원 (예: 768 또는 1536)으로 자르는 경우dimensions를 동일한 값으로 설정합니다. - 정책의
<DistanceMeasureType>과 일치하는 거리 측정 (distanceMeasureType)으로 색인을 만듭니다. SemanticCacheLookup 정책의<SimilaritySearch><VertexAI><DistanceMeasureType>요소는 선택사항이며 기본값은DOT_PRODUCT_DISTANCE입니다.COSINE_DISTANCE도 지원됩니다. 인덱스 거리 측정과 정책<DistanceMeasureType>이 동일해야 합니다.
다음 최소 예시에서는 호환되는 색인을 만듭니다. 전체 요청 본문과 사용 가능한 모든 옵션은 색인 생성 및 관리를 참고하세요.
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" }'
응답에서 반환된 숫자 INDEX_ID를 확인합니다. 이는 SemanticCachePopulate 정책에서 사용됩니다. 색인을 만든 후 Private Service Connect 색인 엔드포인트를 만들고 색인을 여기에 배포합니다.
Private Service Connect 색인 엔드포인트를 만들 때는 다음 SemanticCacheLookup 관련 요구사항을 충족해야 합니다.
projectAllowlist에는 연결을 시작하는 Apigee 프로젝트가 포함되어야 합니다.- Apigee: Apigee 테넌트 프로젝트를 사용합니다. Organizations API(
apigeeProjectId필드)에서 테넌트 프로젝트 ID를 가져옵니다.
projectAllowlist를 수정할 수 없습니다. 잘못된 프로젝트를 허용 목록에 추가한 경우 색인 엔드포인트를 삭제하고 다시 만들어야 합니다.- Apigee: Apigee 테넌트 프로젝트를 사용합니다. Organizations API(
색인 엔드포인트의 숫자 INDEX_ENDPOINT_ID를 확인합니다.
Apigee 프록시의 서비스 계정 구성
Apigee 프록시는 Vertex AI REST 호출에 서비스 계정을 사용합니다. SemanticCacheLookup 정책의 Embeddings API, SemanticCachePopulate 정책의 upsertDatapoints, 모델 타겟이 이에 해당합니다. 서비스 계정에 AI Platform User(roles/aiplatform.user) 역할을 부여합니다.
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member="serviceAccount:SERVICE_ACCOUNT" \ --role="roles/aiplatform.user"
여기서 SERVICE_ACCOUNT은 프록시가 사용하는 서비스 계정의 이메일 주소입니다. 4단계: API 프록시 가져오기 및 배포에서 프록시를 배포할 때 이 서비스 계정을 참조합니다.
개요
시맨틱 캐싱 정책은 LLM 모델을 사용하는 Apigee 사용자가 동일하거나 의미적으로 유사한 프롬프트를 지능적으로 효율적으로 처리할 수 있도록 지원하며, 백엔드 API 호출을 최소화하고 리소스 소비를 줄여줍니다.
SemanticCacheLookup 및 SemanticCachePopulate 정책은 각각 Apigee API 프록시의 요청 흐름과 응답 흐름에 연결됩니다. 프록시가 요청을 수신하면, SemanticCacheLookup 정책이 요청에서 사용자 프롬프트를 추출하고 Text Embeddings API를 사용하여 프롬프트를 수치 표현으로 변환합니다. 유사한 프롬프트를 찾기 위해 벡터 검색을 사용하여 시맨틱 유사성 검색이 수행됩니다. 유사한 프롬프트 데이터 포인트가 발견되면 캐시 조회가 수행됩니다. 캐시된 데이터가 있으면 캐시된 응답이 클라이언트로 반환됩니다.
유사성 검색에서 이전의 유사한 프롬프트가 반환되지 않으면, LLM 모델이 사용자 프롬프트에 대한 응답을 생성하고 해당 응답으로 Apigee 캐시를 채웁니다. 향후 요청에 대비해 벡터 검색 색인 항목을 업데이트하기 위한 피드백 루프가 생성됩니다.
이 시나리오에서는 벡터 검색 색인이 gRPC를 통해 비공개 (Private Service Connect) 엔드포인트에 배포됩니다. 벡터 검색 Private Service Connect 지원에 관한 자세한 내용은 비공개 서비스 액세스 또는 Private Service Connect 색인 쿼리를 참고하세요.
다음 섹션에서는 시맨틱 캐싱 정책을 만들고 구성하는 단계를 설명합니다.
1단계: 리소스 확인 및 Apigee에 필요한 값 가져오기
Apigee를 구성하기 전에 벡터 검색 색인 엔드포인트가 Private Service Connect 지원이고 색인이 배포되었는지 확인합니다. 그런 다음 Apigee 프록시가 사용하는 두 값(서비스 연결 및 DEPLOYED_INDEX_ID)을 읽습니다.
색인이 배포되었고 엔드포인트가 Private Service Connect 서비스 연결을 노출하는지 확인합니다.
gcloud ai index-endpoints describe INDEX_ENDPOINT_ID \ --project=$PROJECT_ID --region=$REGION \ --format="value(deployedIndexes.privateEndpoints.serviceAttachment)"
이 명령어는 projects/TENANT_PROJECT/regions/REGION/serviceAttachments/SERVICE_ATTACHMENT_NAME 형식의 서비스 연결 리소스 이름을 반환합니다.
이 가이드에서는 이 값을 SERVICE_ATTACHMENT로 지칭합니다. 명령어가 빈 값을 반환하면 색인이 아직 Private Service Connect 엔드포인트에 배포되지 않은 것입니다. 벡터 검색 색인 기본 요건으로 돌아가 계속하기 전에 색인 배포를 완료합니다.
엔드포인트에 배포된 색인의 DEPLOYED_INDEX_ID을 읽습니다.
gcloud ai index-endpoints describe INDEX_ENDPOINT_ID \ --project=$PROJECT_ID --region=$REGION \ --format="value(deployedIndexes.id)"
이 가이드에서는 이 값을 DEPLOYED_INDEX_ID로 지칭합니다. 3단계: API 프록시 번들 빌드의 SemanticCacheLookup 정책에서 사용합니다.
비공개 인덱스 엔드포인트를 배포하고 쿼리하는 방법에 대한 자세한 내용은 Private Service Connect 엔드포인트에 인덱스 배포 및 비공개 서비스 액세스 또는 Private Service Connect 인덱스 쿼리를 참고하세요.
2단계: 서비스 연결에 연결
이 단계에서는 프록시의 <GrpcEndpoint> 호출을 위한 비공개 호스트를 제공합니다.
Apigee에서 Apigee 엔드포인트 연결을 만듭니다. 엔드포인트 연결은 Apigee의 Private Service Connect 소비자 측면입니다. 벡터 검색 서비스 연결에 연결되고 프록시가 호출하는 비공개 호스트를 제공합니다.
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"
첨부파일의 state가 ACTIVE이고 connectionState가 ACCEPTED가 될 때까지 폴링한 다음 호스트를 기록합니다.
curl -s -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://apigee.googleapis.com/v1/organizations/$PROJECT_ID/endpointAttachments/ENDPOINT_ATTACHMENT"
응답에는 host 필드에 호스트가 포함됩니다. 이 가이드에서는 이 값을 TARGET_HOST로 지칭합니다.
프록시에서 벡터 검색 서비스 연결에 연결하려면 다음 중 하나를 사용하면 됩니다.
- IP 주소:
host필드에 반환된 IP 주소를TARGET_HOST(예:7.0.3.4)로 직접 사용합니다. - 비공개 DNS 레코드: Apigee에 대한 DNS 피어링을 사용하여 Google Cloud 프로젝트에서 비공개 Cloud DNS 영역을 구성한 경우 엔드포인트 연결 IP 주소를 가리키는 비공개 영역에 A 레코드를 만들고 해당 도메인 이름 (예:
vectorsearch.example.com)을TARGET_HOST로 사용할 수 있습니다. 자세한 내용은 DNS 레코드 사용 및 비공개 DNS 피어링 영역으로 연결을 참고하세요.
3단계: API 프록시 번들 빌드
프록시 번들 만들기
다음 디렉터리 레이아웃을 만듭니다.
apiproxy/ ├── PROXY_NAME.xml ├── proxies/default.xml ├── targets/default.xml └── policies/ ├── SCL-1.xml └── SCP-1.xml
policies/SCL-1.xml: SemanticCacheLookup 정책입니다. <SimilaritySearch> 블록은 <PrivateServiceConnect><GrpcEndpoint>를 사용합니다(<URL> 없음).
참고: <GrpcEndpoint> 규칙:
- 형식은
grpc://TARGET_HOST:PORT이며 스키마는grpc://여야 합니다. 이 버전에서는grpcs://(TLS)가 지원되지 않습니다. - 벡터 검색의 포트는
10000입니다. Private Service Connect 데이터 플레인 엔드포인트는 포트 10000에서 gRPC를 제공하므로 엔드포인트는 항상grpc://TARGET_HOST:10000입니다. TARGET_HOST는 엔드포인트 연결 IP 주소 (2단계) 또는 비공개 DNS 영역에서 만든 맞춤 DNS 레코드일 수 있습니다.- gRPC 홉은 일반 텍스트이며 인증되지 않습니다 (네트워크 격리로 보호됨).
<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: SemanticCachePopulate 정책입니다. 채우기는 REST 전용이며 <URL>를 사용해야 합니다 (배포 시 <PrivateServiceConnect> 거부).
<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: 모델 타겟입니다. 타겟이 Google API를 호출하므로 토큰이 필요합니다. <GoogleAccessToken>는 배포의 서비스 계정을 사용합니다.
<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: 요청에 SemanticCacheLookup 정책을 실행하고 응답에 SemanticCachePopulate 정책을 실행합니다.
<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 - 번들 설명자
<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>
4단계: API 프록시 가져오기 및 배포
번들을 압축하고 가져와 새 버전을 만든 후 서비스 계정으로 버전을 배포합니다.
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"
각 항목의 의미는 다음과 같습니다.
BUNDLE_DIR은apiproxy/폴더가 포함된 디렉터리입니다. 보관 파일의 루트에apiproxy/폴더가 있어야 합니다.ENV은 프록시를 배포하는 Apigee 환경입니다. 환경은 중간 또는 종합 환경이어야 합니다.REVISION는 가져오기 호출에서 반환된 버전 번호입니다.SERVICE_ACCOUNT은 프록시를 배포하는 데 사용하는 서비스 계정의 이메일 주소입니다.
배포가 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
5단계: 시맨틱 캐싱 정책 테스트
새 프롬프트를 보냅니다. 이는 캐시 부적중입니다. 모델이 호출되고 답변이 캐시됩니다.
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."}]}]}'
동일한 프롬프트를 다시 보냅니다. 캐시 적중입니다. 응답이 캐시에서 제공되고 모델이 호출되지 않습니다.
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."}]}]}'
히트에서 응답에는 Cached-content: true 헤더, 동일한 답변, 눈에 띄게 낮은 지연 시간이 포함됩니다.
디버그 세션으로 캐싱을 확인할 수도 있습니다. 히트가 발생하면 SemanticCacheLookup 정책은 다음 흐름 변수를 설정합니다.
| 변수 | 조회수 값 |
|---|---|
SemanticCacheLookup.SCL-1.dense_embeddings |
프롬프트의 임베딩 벡터입니다. |
SemanticCacheLookup.SCL-1.is_nearest_neighbor_hit |
true |
SemanticCacheLookup.SCL-1.cache_hit |
true |
SemanticCacheLookup.SCL-1.cached_llm_response |
캐시된 답변입니다. |
적중 시 모델 타겟이 호출되지 않습니다. 흐름이 단락되고 캐시된 응답이 반환됩니다.
문제 해결
전체 오류 참조는 SemanticCacheLookup 정책을 참고하세요.
다음 단계
- 벡터 검색에서 비공개 서비스 액세스 또는 Private Service Connect 색인을 쿼리하는 방법을 알아봅니다.
- 시맨틱 캐싱 정책 시작하기에서 공개 엔드포인트에 대해 시맨틱 캐싱을 구성하는 방법을 알아보세요.
- Model Armor 정책을 시작하는 방법을 알아보세요.