

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon SageMaker AI 模型的有状态会话
<a name="stateful-sessions"></a>

向 Amazon SageMaker AI 推理端点发送请求时，您可以选择将请求路由到*有状态会话*。在有状态会话期间，您会向同一个 ML 实例发送多个推理请求，而该实例会促进会话的进行。

通常，当您调用推理端点时，Amazon SageMaker AI 会将您的请求路由到端点所托管的多个实例中的任意一个 ML 实例。这种路由行为通过均匀分配推理流量，有助于最大限度地减少延迟。不过，路由行为的一个结果是，您无法预测哪个实例将为您的请求提供服务。

如果您打算将请求发送到*有状态模型*，那么这种不可预测性就是一种限制。有状态模型有一个容器，用于缓存从推理请求中接收到的上下文数据。由于数据是缓存的，因此您可以通过发送多个请求与容器进行交互，而在每个请求中，您都不需要包含交互的完整上下文。相反，该模型从缓存的上下文数据中获取预测信息。

当交互的上下文数据非常庞大时，例如包括以下内容时，有状态模型是理想的选择：
+ 大型文本文件
+ 冗长的聊天记录 
+ 用于多模态模型的多媒体数据（映像、视频和音频）

在这种情况下，如果每次提示都传递完整的上下文，请求的网络延迟就会减慢，应用程序的响应速度也会降低。

在推理端点支持有状态会话之前，它必须托管一个有状态模型。有状态模型的实施由您自己掌握。Amazon SageMaker AI 可让您将请求路由到有状态会话，但不提供可部署和使用的有状态模型。

有关演示如何实现有状态交互的笔记本和模型容器示例，请参阅 [实施示例](#stateful-sessions-example-notebook)。

有关使用 TorchServe 实现有状态模型的信息，请参阅 TorchServe GitHub 存储库中的[有状态推理](https://github.com/pytorch/serve/tree/master/examples/stateful/sequence_continuous_batching)。

## 有状态会话如何工作
<a name="stateful-sessions-running"></a>

在有状态会话期间，应用程序通过以下方式与模型容器交互。

**启动有状态会话**

1. 要使用 Amazon SageMaker AI 托管的有状态模型启动会话，客户端需要使用 SageMaker API 发送 [https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpoint.html](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_runtime_InvokeEndpoint.html) 请求。对于 `SessionID` 请求参数，客户端通过指定 `NEW_SESSION` 值来告诉 SageMaker AI 启动一个新会话。在请求有效载荷中，客户端还会告诉容器启动一个新会话。该语句的语法因容器实现而异。这取决于容器代码如何处理请求有效载荷。

   下面的示例使用 Python SDK (Boto3) 启动了一个新会话：

   ```
   import boto3
   import sagemaker
   import json
   
   payload = {
   "requestType":"NEW_SESSION"
   }
   payload = json.dumps(payload)
   
   smr = boto3.client(
       'sagemaker-runtime',
       region_name="region_name",
       endpoint_url="endoint_url")
   
   create_session_response = smr.invoke_endpoint(
       EndpointName="endpoint_name",
       Body=payload,
       ContentType="application/json",
       SessionId="NEW_SESSION")
   ```

1. 您的模型容器会通过启动一个新会话来处理客户的请求。对于会话，它会缓存客户端在请求有效载荷中发送的数据。它还会创建会话 ID，并设置生存时间（TTL）时间戳。该时间戳表示会话过期时间。容器必须通过在响应中设置以下 HTTP 标头，向 Amazon SageMaker AI 提供会话 ID 和时间戳：

   ```
   X-Amzn-SageMaker-Session-Id: session_id; Expires=yyyy-mm-ddThh:mm:ssZ
   ```

1. 在对 `InvokeEndpoint` 请求的响应中，Amazon SageMaker AI 会为 `NewSessionID` 响应参数提供会话 ID 和 TTL 时间戳。

   下面的示例将从 `invoke_endpoint` 响应中提取会话 ID：

   ```
   session_id = create_session_response['ResponseMetadata']['HTTPHeaders']['x-amzn-sagemaker-new-session-id'].split(';')[0]
   ```

**继续有状态会话**
+ 要在后续推理请求中使用同一会话，客户端需要发送另一个 `InvokeEndpoint` 请求。对于 `SessionID` 请求参数，它指定了会话的 ID。有了这个 ID，SageMaker AI 就会将请求路由到在其中启动会话的同一个 ML 实例。由于容器已经缓存了原始请求有效载荷，因此客户端无需再传递与原始请求相同的上下文数据。

  下面的示例通过 `SessionId` 请求参数传递会话 ID 来继续会话：

  ```
  smr.invoke_endpoint(
      EndpointName="endpoint_name",
      Body=payload,
      ContentType="application/json",
      SessionId=session_id)
  ```

**关闭有状态会话**

1. 要关闭会话，客户端会发送最后一个 `InvokeEndpoint` 请求。对于 `SessionID` 请求参数，客户端会提供会话 ID。在请求正文的有效负载中，客户机指出容器应关闭会话。该语句的语法因容器实现而异。

   下面的示例关闭了一个会话：

   ```
   payload = {
       "requestType":"CLOSE"
   }
   payload = json.dumps(payload)
   
   closeSessionResponse = smr.invoke_endpoint(
       EndpointName="endpoint_name",
       Body=payload,
       ContentType="application/json",
       SessionId=session_id)
   ```

1. 当它关闭会话时，容器会通过在响应中设置以下 HTTP 标头将会话 ID 返回给 SageMaker AI：

   ```
   X-Amzn-SageMaker-Closed-Session-Id: session_id
   ```

1. 在响应来自客户端的 `InvokeEndpoint` 请求时，SageMaker AI 会为 `ClosedSessionId` 响应参数提供会话 ID。

   下面的示例将从 `invoke_endpoint` 响应中提取已关闭的会话 ID：

   ```
   closed_session_id = closeSessionResponse['ResponseMetadata']['HTTPHeaders']['x-amzn-sagemaker-closed-session-id'].split(';')[0]
   ```

## 实施示例
<a name="stateful-sessions-example-notebook"></a>

下面的笔记本示例演示了如何为有状态模型实现容器。它还演示了客户端应用程序如何启动、继续和关闭有状态会话。

[LLaVA stateful inference with SageMaker AI](https://github.com/aws-samples/sagemaker-genai-hosting-examples/blob/main/LLava/torchserve/workspace/llava_stateful_deploy_infer.ipynb)

该笔记本使用 [LLaVA：大型语言和视觉助手](https://github.com/haotian-liu/LLaVA/tree/main)模型，可接受映像和文本提示。笔记本电脑将映像上传到模型中，然后就映像提出问题，而不必每次都重新发送映像。模型容器使用 TorchServe 框架。它将映像数据缓存在 GPU 内存中。