在ASM中实现LLM请求缓存功能

LLM应用在提供强大功能的同时,往往也伴随着巨大的计算成本和延迟。为了解决这些问题,提高模型调用效率并降低延迟,越来越多的LLM应用开始采用缓存。LLM Cache通过在一定期间内存储和重用LLM的计算结果,可以大幅减少重复计算,优化响应时间,从而提升整体系统性能。本文将介绍如何在服务网格 ASM(Service Mesh)中快速接入LLM Cache。

功能介绍

ASM的LLM Cache功能基于Wasm扩展实现。在网格代理处理LLM请求时,LLM Cache插件首先会查询您自定义的缓存服务,如果查询到缓存的结果,就直接返回该信息,不会将LLM请求发送给外部的LLM服务。如果在缓存服务中没有获取到缓存的结果,则会将该请求标记为“需要更新缓存”,在外部LLM服务返回响应时,LLM Cache插件会将响应的内容发送给缓存服务。下图以网关为例,演示LLM Cache插件的原理:

image

为了方便您快速接入缓存,ASM提供了默认的基于字符串匹配的缓存服务实现(底层存储基于Redis)。网格代理会通过标准的HTTP方式调用您自定义的缓存服务,您可以完全自定义LLM Cache的匹配方案以及存储形式。本文也将以该缓存服务为例,演示如何在ASM中实现LLM请求缓存功能。

前提条件

步骤一:部署ASM提供的默认LLM Cache服务

  1. 使用以下内容,创建cache.yaml。

    展开查看YAML内容

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: asm-wasm-cache-service-example
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: asm-wasm-cache-service-example
      labels:
        app: asm-wasm-cache-service-example
        service: asm-wasm-cache-service-example
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: asm-wasm-cache-service-example
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: asm-wasm-cache-service-example
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: asm-wasm-cache-service-example
          version: v1
      template:
        metadata:
          labels:
            app: asm-wasm-cache-service-example
            version: v1
          annotations:
            sidecar.istio.io/inject: "true"
        spec:
          tolerations:
          - key: "node.kubernetes.io/disk-pressure"
            operator: "Equal"
            value: ""
            effect: "NoSchedule"
          serviceAccountName: asm-wasm-cache-service-example
          containers:
          - image: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-wasm-cache-service-example:v1.22.6.9-g6fc05c9-aliyun # ASM提供的默认Redis实现的示例镜像地址。
            imagePullPolicy: IfNotPresent
            name: asm-wasm-cache-service-example
            ports:
            - containerPort: 8080
            env:
            - name: REDIS_ADDRESS
              value: ${自定义的Redis地址以及端口}
            - name: REDIS_PASSWORD
              value: ${自定义的Redis密钥}
            - name: REDIS_EXPIRED_SECONDS
              value: ${Redis中的过期时间,比如"600"}
            resources:
              limits:
                memory: 256Mi
                cpu: 200m
              requests:
                memory: 64Mi
                cpu: 50m
  2. 使用数据面集群的kubeconfig,执行以下命令。

    kubectl apply -f cache.yaml

    ASM支持自定义LLM Cache服务,并且提供了基于Redis精准匹配的默认实现。更多信息,请参见代码仓库。如果您有其他定制化需求,可以仿照该示例自行开发对应的LLM Cache服务。

步骤二:部署ASM LLM Cache插件

  1. 使用以下内容,创建wasm.yaml.

    apiVersion: extensions.istio.io/v1alpha1
    kind: WasmPlugin
    metadata:
      name: llm-cache
      namespace: istio-system
    spec:
      selector:
        matchLabels:
          istio: ingressgateway
      failStrategy: FAIL_OPEN
      imagePullPolicy: IfNotPresent
      match:
      - mode: CLIENT
        ports:
        - number: 80
      phase: STATS
      pluginConfig:
        host_match: "dashscope.aliyuncs.com" # 支持正则匹配
        path_match: ".*" # 支持正则匹配
        service: "asm-wasm-cache-service-example.default.svc.cluster.local"
        port: "80"
      priority: -10
      url: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-wasm-llm-cache:v1.22.6.9-g6fc05c9-aliyun
  2. 在网关上部署缓存插件。

    kubectl apply -f wasm.yaml

步骤三:测试

连续执行两次以下命令进行测试。

time curl --location '${ASM网关IP}:80' \
--header 'Content-Type: application/json' \
--header "host: test.com" \
--data '{
    "messages": [
        {"role": "user", "content": "请介绍你自己"}
    ]
}'

预期输出:

{"choices":[{"message":{"role":"assistant","content":"我是来自阿里云的大规模语言模型,我叫通义千问。作为一个AI助手,我的主要功能是理解和回答各种问题。我可以根据你的需求提供准确的信息和建议,并且可以根据你的喜好调整内容和风格。无论你有什么问题或需要帮助,请随时告诉我,我会尽力为你提供支持。"},"finish_reason":"stop","index":0,"logprobs":null}],"object":"chat.completion","usage":{"prompt_tokens":12,"completion_tokens":65,"total_tokens":77},"created":1732068820,"system_fingerprint":null,"model":"qwen-1.8b-chat","id":"chatcmpl-30581ce8-e120-97ea-b9ac-488dbd346a75"}
real    0m 4.09s
user    0m 0.00s
sys     0m 0.00s
{"choices":[{"message":{"role":"assistant","content":"我是来自阿里云的大规模语言模型,我叫通义千问。作为一个AI助手,我的主要功能是理解和回答各种问题。我可以根据你的需求提供准确的信息和建议,并且可以根据你的喜好调整内容和风格。无论你有什么问题或需要帮助,请随时告诉我,我会尽力为你提供支持。"},"finish_reason":"stop","index":0,"logprobs":null}],"object":"chat.completion","usage":{"prompt_tokens":12,"completion_tokens":65,"total_tokens":77},"created":1732068820,"system_fingerprint":null,"model":"qwen-1.8b-chat","id":"chatcmpl-30581ce8-e120-97ea-b9ac-488dbd346a75"}
real    0m 0.00s
user    0m 0.00s
sys     0m 0.00s

可以看到,第二次开始的请求响应速度大大加快,缓存已经生效。