构建具有路由、Model Armor 和语义缓存的 AI 网关

本页面适用于 Apigee 和 Apigee Hybrid。

查看 Apigee Edge 文档。

本教程介绍了如何配置和使用 Apigee 作为 AI 网关,根据灵活的、由政策驱动的路由规则,将大语言模型 (LLM) 请求路由到不同的后端模型。AI 网关可帮助您保护、治理和优化模型流量,从而管理成本并防止模型泛滥。

本教程的每个阶段都通过可重复使用的 Apigee 功能模板 (AFT) 文件添加特定功能,从而在上一个配置的基础上进行构建:

  • 第 1 阶段:部署一个最小 API 代理,该代理位于单个 LLM 提供商的前端。
  • 第 2 阶段:添加 Model Armor 提示和回答清理功能,以过滤恶意输入并防止敏感数据泄露。
  • 第 3 阶段:添加由 Agent Platform Vector Search 支持的跨提供商模型路由和语义缓存。
  • 第 4 阶段:配置跨提供商回退,以便在主要目标返回 4xx 或 5xx HTTP 状态代码时,自动针对次要提供商重试请求。

如需添加功能,请在模板中的 features 块中附加一行。如需查看或下载整套示例文件(包括 AFT 文件和辅助脚本),请参阅 GitHub 上的 Apigee 模板代码库。

准备工作

在完成本教程之前,请确保您具备以下条件:

  • 启用了结算功能的有效 Google Cloud 项目。
  • Apigee 实例中的全面环境。您只能在全面环境中部署 Model Armor、SemanticCacheLookup 和 SemanticCachePopulate 政策。
  • 已安装 Google Cloud CLI (gcloud) 并配置了应用默认凭据 (ADC)。如需生成凭据,请运行 gcloud auth application-default login。
  • 具有以下 IAM 角色的运行时服务账号:
    • roles/aiplatform.user
    • roles/modelarmor.user
    服务账号还需要有权访问任何提供商特定的凭据。
  • 对于第 2、3 和 4 阶段,请指定 Model Armor 模板资源路径。例如,projects/YOUR_PROJECT/locations/us-central1/templates/apigee-aft-demo-ma。
  • 对于第 3 阶段和第 4 阶段:您的环境中名为 openai-credentials 的 Apigee 键值对映射 (KVM),其中包含具有有效 OpenAI API 密钥的 api-key 条目。
  • 对于第 3 阶段和第 4 阶段:为语义缓存部署的 Vertex AI Vector Search 搜索索引端点。如需了解有关如何逐步设置索引,请参阅 GitHub 上的 Apigee 模板代码库自述文件。

概览

所有四个阶段都接受 /v1/chat/completions[-stageN] 的 OpenAI Chat Completions 请求格式,因此相同的客户端 SDK 可在每个阶段使用。model 字段前缀会驱动模型路由决策:对 google/* 模型的请求会路由到 Agent Platform 上的 Gemini,而所有其他请求都会路由到 OpenAI。这种反转的默认设置可确保新的 OpenAI 模型系列(例如 o1-*、o3-* 和 chatgpt-*)能够正确路由,而不是默默地缺少 gpt-* 前缀匹配。

阶段 已添加功能 基本路径
1 Hello LLM(向 Agent Platform 上的 Gemini 发出 OpenAI 格式的请求) /v1/chat/completions
2 Model Armor(提示注入、Responsible AI 和 Sensitive Data Protection 过滤器) /v1/chat/completions-stage2
3 跨提供商路由和 Agent Platform Vector Search 语义缓存 /v1/chat/completions-stage3
4 跨提供商后备(完整的 AI 网关) /v1/chat/completions-stage4

第 1 阶段:Hello LLM

该最小代理通过其 OpenAI 兼容端点前端单个 Gemini 目标。两个小型功能文件提供基本代理框架和 JSON 提取器。提取器会将 $.model 和 $.messages[-1].content 复制到 llm.model 和 llm.prompt 流变量中,以便后续阶段获得一致的输入。

llm-base.yaml 定义基本代理骨架:

gateway: apigee
schemaVersion: 1.0.0
name: llm-base
type: feature
parameters:
  - name: BASE_PATH
    default: /v1/chat/completions
endpoints:
  - name: default
    basePath: "{BASE_PATH}"
    routes:
      - name: primary
        target: gemini-target

llm-openai-format.yaml 提取 OpenAI 格式的请求字段:

gateway: apigee
schemaVersion: 1.0.0
name: llm-openai-format
type: feature
defaultEndpoint:
  name: default
  flows:
    - name: PreFlow
      mode: Request
      steps:
        - name: EV-ExtractOpenAIRequest
policies:
  - name: EV-ExtractOpenAIRequest
    type: ExtractVariables
    content:
      ExtractVariables:
        metadata:
          name: EV-ExtractOpenAIRequest
          continueOnError: "true"
        Source:
          _text: request
        JSONPayload:
          Variable:
            - metadata:
                name: model
              JSONPath:
                _text: "$.model"
            - metadata:
                name: prompt
              JSONPath:
                _text: "$.messages[-1].content"
        VariablePrefix:
          _text: llm

target-vertex-gemini.yaml 定义了一个使用 OpenAI 兼容端点的 Agent Platform 目标:

gateway: apigee
schemaVersion: 1.0.0
name: target-vertex-gemini
type: feature
targets:
  - name: gemini-target
    httpTargetConnection:
      URL: https://aiplatform.googleapis.com/v1/projects/{organization.name}/locations/global/endpoints/openapi/chat/completions
      Authentication:
        GoogleAccessToken:
          Scopes:
            Scope: https://www.googleapis.com/auth/cloud-platform

将功能文件组合到第 1 阶段模板 01-hello-llm.yaml 中:

gateway: apigee
schemaVersion: 1.0.0
name: aft-demo-01-hello-llm
features:
  - llm-base.yaml
  - llm-openai-format.yaml
  - target-vertex-gemini.yaml

部署模板:

gcloud beta apigee apis import aft-demo-01-hello-llm \
  --from-template=01-hello-llm.yaml \
  --organization=APIGEE_ORG

测试代理:

curl -X POST https://APIGEE_HOSTNAME/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"google/gemini-2.5-flash",
       "messages":[{"role":"user","content":"Explain how AI works in a few words"}]}'

替换以下内容:

  • APIGEE_ORG:您的 Apigee 组织名称。
  • APIGEE_HOSTNAME:Apigee 环境组的主机名,通常是 Google Cloud 负载均衡器。

第 2 阶段:添加 Model Armor

Model Armor 会在目标调用之前检查传入的提示中是否存在提示注入、不允许的内容和敏感数据。然后,它会在模型回答到达客户端之前对其进行扫描。

向模板添加一个功能文件,即 llm-model-armor.yaml:

gateway: apigee
schemaVersion: 1.0.0
name: llm-model-armor
type: feature
parameters:
  - name: MA_TEMPLATE_PATH
    default: projects/{organization.name}/locations/us-central1/templates/apigee-aft-demo-ma
defaultEndpoint:
  name: default
  flows:
    - name: PreFlow
      mode: Request
      steps:
        - name: MA-SanitizeUserPrompt
    - name: PostFlow
      mode: Response
      steps:
        - name: MA-SanitizeModelResponse
policies:
  - name: MA-SanitizeUserPrompt
    type: SanitizeUserPrompt
    content:
      SanitizeUserPrompt:
        metadata:
          name: MA-SanitizeUserPrompt
        ModelArmor:
          TemplateName:
            _text: "{MA_TEMPLATE_PATH}"
        UserPromptSource:
          _text: "{llm.prompt}"
  - name: MA-SanitizeModelResponse
    type: SanitizeModelResponse
    content:
      SanitizeModelResponse:
        metadata:
          name: MA-SanitizeModelResponse
        ModelArmor:
          TemplateName:
            _text: "{MA_TEMPLATE_PATH}"
        UserPromptSource:
          _text: "{llm.prompt}"
        LLMResponseSource:
          _text: "{jsonPath('$.choices[-1].message.content',response.content,true)}"

第 2 阶段模板 02-add-model-armor.yaml 添加了一行:

gateway: apigee
schemaVersion: 1.0.0
name: aft-demo-02-add-model-armor
features:
  - llm-base.yaml
  - llm-openai-format.yaml
  - target-vertex-gemini.yaml
  - llm-model-armor.yaml           # <-- the change from Stage 1
parameters:
  - name: BASE_PATH
    default: /v1/chat/completions-stage2

MA_TEMPLATE_PATH 参数默认设置为 us-central1 中名为 apigee-aft-demo-ma 的模板。如需使用您自己的 Model Armor 模板,请替换模板 parameters 块中的参数。

第 3 阶段:添加跨提供商路由和语义缓存

在第 3 阶段,您将添加第二个目标 (OpenAI),将单路由规则替换为基于模型的路由,并在两个目标之前配置由 Agent Platform Vector Search 支持的语义缓存。

如需配置第 3 阶段,请将三个功能文件附加到模板中的 features 块:

  • target-openai-gpt.yaml:将 OpenAI 添加为辅助目标端点。
  • llm-routing.yaml:根据请求的模型名称动态路由请求。
  • llm-semantic-cache.yaml:在两个提供商前面添加语义缓存。

以下示例展示了 llm-routing.yaml 功能文件如何定义路由逻辑:

gateway: apigee
schemaVersion: 1.0.0
name: llm-routing
type: feature
parameters:
  - name: BASE_PATH
    default: /v1/chat/completions
endpoints:
  - name: default
    basePath: "{BASE_PATH}"
    routes:
      - name: gemini
        condition: llm.model StartsWith "google/"
        target: gemini-target
      - name: openai
        target: openai-target      # default when the condition is false

语义缓存在请求 PreFlow 中运行 SemanticCacheLookup,在响应 PostFlow 中运行 SemanticCachePopulate,仅在缓存未命中时运行。这两种政策都使用您单独预配的 Agent Platform Vector Search 搜索索引端点。以下摘录显示了政策定义的关键部分:

policies:
  - name: SCLLookup
    type: SemanticCacheLookup
    content:
      SemanticCacheLookup:
        UserPromptSource:
          _text: "{llm.prompt}"
        Embeddings:
          VertexAI:
            URL:
              _text: "https://{EMBEDDINGS_LOCATION}-aiplatform.googleapis.com/v1/projects/{organization.name}/locations/{EMBEDDINGS_LOCATION}/publishers/google/models/{EMBEDDINGS_MODEL}:predict"
        SimilaritySearch:
          VertexAI:
            URL:
              _text: "https://{VECTOR_INDEX_ENDPOINT_SUBDOMAIN}.{EMBEDDINGS_LOCATION}-{PROJECT_NUMBER}.vdb.vertexai.goog/v1/projects/{organization.name}/locations/{EMBEDDINGS_LOCATION}/indexEndpoints/{VECTOR_INDEX_ENDPOINT_ID}:findNeighbors"
            DeployedIndexID:
              _text: "{DEPLOYED_INDEX_ID}"
            Threshold:
              _text: "{THRESHOLD}"
  - name: SCPPopulate
    type: SemanticCachePopulate
    # ... (see the GitHub repository for the full definition)

第 3 阶段模板会组合所有特征文件:

gateway: apigee
schemaVersion: 1.0.0
name: aft-demo-03-add-routing-and-cache
features:
  - llm-base.yaml
  - llm-openai-format.yaml
  - target-vertex-gemini.yaml
  - llm-model-armor.yaml
  - target-openai-gpt.yaml         # <-- add OpenAI target
  - llm-routing.yaml               # <-- add model-name routing
  - llm-semantic-cache.yaml        # <-- add semantic cache
parameters:
  - name: BASE_PATH
    default: /v1/chat/completions-stage3
  - name: VECTOR_INDEX_ENDPOINT_ID
    default: "YOUR_INDEX_ENDPOINT_ID"
  - name: VECTOR_INDEX_ID
    default: "YOUR_INDEX_ID"
  - name: VECTOR_INDEX_ENDPOINT_SUBDOMAIN
    default: "YOUR_SUBDOMAIN"
  - name: PROJECT_NUMBER
    default: "YOUR_PROJECT_NUMBER"
  - name: DEPLOYED_INDEX_ID
    default: "YOUR_DEPLOYED_INDEX_ID"

使用您在第 1 阶段中使用的带有 --from-template 标志的 gcloud beta apigee apis import 命令来部署模板。

第 4 阶段:添加跨提供商后备

第 4 阶段会向两个目标都附加 DefaultFaultRule。当主要目标返回任何 4xx 或 5xx 状态时,故障规则会向其他提供商发送包含相同提示的 ServiceCallout,并将该响应返回给客户端。客户端会收到成功的 200 响应,其中包含正常完成,并且不需要自己的重试逻辑或错误处理。

llm-fallback.yaml 功能文件会添加此行为。以下示例是简略版。如需查看完整文件,请参阅 GitHub 代码库。

gateway: apigee
schemaVersion: 1.0.0
name: llm-fallback
type: feature
targets:
  # Vertex primary; on 4xx/5xx, fall back to OpenAI.
  - name: gemini-target
    httpTargetConnection:
      Properties:
        Property:
          metadata:
            name: success.codes
          _text: "2XX"
      URL: https://aiplatform.googleapis.com/v1/projects/{organization.name}/locations/global/endpoints/openapi/chat/completions
      Authentication:
        GoogleAccessToken:
          Scopes:
            Scope: https://www.googleapis.com/auth/cloud-platform
    flows:
      - name: PostFlow
        mode: Response
        steps:
          - name: RF-TargetErrorToFault
            condition: response.status.code >= 400
    defaultFaultRule:
      name: FallbackToOpenAI
      steps:
        - name: KVM-GetOpenAIKey
        - name: AM-BuildOpenAIFallbackRequest
        - name: SC-FallbackToOpenAI
        - name: AM-CopyOpenAIFallbackResponse
  # OpenAI primary; on 4xx/5xx, fall back to Vertex.
  - name: openai-target
    httpTargetConnection:
      Properties:
        Property:
          metadata:
            name: success.codes
          _text: "2XX"
      URL: https://api.openai.com/v1/chat/completions
    flows:
      - name: PreFlow
        mode: Request
        steps:
          - name: JS-StripOpenAIModelPrefix
          - name: KVM-GetOpenAIKey
          - name: AM-SetOpenAIAuth
      - name: PostFlow
        mode: Response
        steps:
          - name: RF-TargetErrorToFault
            condition: response.status.code >= 400
    defaultFaultRule:
      name: FallbackToVertex
      steps:
        - name: AM-BuildVertexFallbackRequest
        - name: SC-FallbackToVertex
        - name: AM-CopyVertexFallbackResponse
policies:
  # RaiseFault converts a target 4xx/5xx into a fault so DefaultFaultRule fires.
  - name: RF-TargetErrorToFault
    type: RaiseFault
    content:
      RaiseFault:
        IgnoreUnresolvedVariables: "true"
        # empty FaultResponse -- DefaultFaultRule builds the real response
  # ... AM-Build*, SC-Fallback*, AM-Copy* policies -- see GitHub repository

回退依赖于两项设置:

  • success.codes: 2XXhttpTargetConnection 。Apigee 会将任何非 2xx 目标响应视为目标失败,并直接转换到故障流。
  • 每个目标的响应 PostFlow 中的 RaiseFault 政策,由 response.status.code >= 400 控制。此政策可保证 DefaultFaultRule 针对每个错误响应运行。

编写第 4 阶段模板,该模板会向第 3 阶段模板添加一行:

gateway: apigee
schemaVersion: 1.0.0
name: aft-demo-04-add-fallback
features:
  - llm-base.yaml
  - llm-openai-format.yaml
  - target-vertex-gemini.yaml
  - llm-model-armor.yaml
  - target-openai-gpt.yaml
  - llm-routing.yaml
  - llm-semantic-cache.yaml
  - llm-fallback.yaml              # <-- the change from Stage 3
parameters:
  - name: BASE_PATH
    default: /v1/chat/completions-stage4
  # ... Model Armor and Vector Search parameters as in Stage 3

部署模板:

gcloud beta apigee apis import aft-demo-04-add-fallback \
  --from-template=04-add-fallback.yaml \
  --organization=APIGEE_ORG

验证端到端行为

GitHub 代码库包含一个 routing-diagnostic.sh 脚本,该脚本通过主题多样的提示来测试所有路由和回退路径。由于语义缓存会短路相似的提示,因此每个测试提示的措辞必须不同。

STAGE=4 ./routing-diagnostic.sh

该脚本通过第 4 阶段代理发送 5 个请求:

  • 规范的 OpenAI 模型
  • 带有 google/ 前缀的 Gemini 模型
  • 不带前缀的 Gemini 模型名称,在反向默认设置下会路由到 OpenAI
  • OpenAI 推理模型
  • 带有 openai/ 前缀的模型名称

对于每个请求,脚本都会报告哪个上游提供商提供了响应,以及是否发生了回退。

如需查看单个请求的每个政策步骤、目标调用和故障规则转换,请针对已部署的修订版本创建 Apigee 调试会话:

DEBUG_URL="https://apigee.googleapis.com/v1/organizations/APIGEE_ORG/environments/APIGEE_ENV/apis/aft-demo-04-add-fallback/revisions/REVISION/debugsessions"
curl -X POST -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \
  -H "Content-Type: application/json" \
  -d '{"filter":"","count":10,"timeout":"600","validity":600}' \
  "$DEBUG_URL"

替换以下内容:

  • APIGEE_ORG:您的 Apigee 组织名称。
  • APIGEE_ENV:您在其中部署代理的环境。
  • REVISION:aft-demo-04-add-fallback 代理的已部署修订版本号。

然后,发送一个会触发回退的请求:

curl -X POST https://APIGEE_HOSTNAME/v1/chat/completions-stage4 \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini",
       "messages":[{"role":"user","content":"Describe nuclear fusion in stars in two sentences."}]}'

当您使用 Apigee API 检索捕获的调试会话消息时,跟踪会显示以下执行流程:

  1. 提取请求变量:Apigee 从传入载荷中提取 llm.model 和 llm.prompt 变量。
  2. 评估安全政策:请求通过 Model Armor 安全过滤。
  3. 检查语义缓存:查找未命中语义缓存,因此请求继续发送到目标。
  4. 评估路由条件:条件 llm.model StartsWith "google/" 的评估结果为 false。
  5. 路由到主要目标:Apigee 会将请求转发到 openai-target。
  6. 处理目标错误:OpenAI 目标返回非 2xx HTTP 状态代码,这会导致 Apigee 抛出目标错误。
  7. 运行故障规则:DefaultFaultRule 通过运行 AM-BuildVertexFallbackRequest、SC-FallbackToVertex 和 AM-CopyVertexFallbackResponse 触发回退序列。
  8. 返回回答:客户端会收到 HTTP 200 响应,其中包含由 Gemini on Agent Platform 生成的载荷。

后续步骤

  • 配置身份验证:在代理前面实现联合 JWT、OpenID Connect (OIDC) 或 Apigee API 密钥,以强制执行租户特定的令牌配额和提供商访问权限控制。
  • 监控费用和延迟时间:将 Apigee 分析信息中心附加到 API 代理,以跟踪每个模型的延迟时间和运营费用。
  • 应用特定于租户的安全政策:使用 MA_TEMPLATE_PATH 参数配置每个租户的 Model Armor 模板,以便在企业、开发者和公共流量中应用量身定制的清理规则。
  • 探索示例配置:如需下载完整的示例集,包括 llm-fallback.yaml 模板、八个功能文件、routing-diagnostic.sh 脚本以及 KVM、Model Armor 和 Agent Platform Vector Search 的预配脚本,请参阅 GitHub 上的 Apigee 渐进式 AI 网关代码库。