我们从 Lambda 开始。这里出了什么问题。

发布: (2026年3月3日 GMT+8 14:10)
12 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的完整文本内容,我将为您翻译成简体中文并保留原有的格式、Markdown 语法以及技术术语。谢谢!

Lambda 看起来非常适合 AI 工作负载

单一职责函数,自动扩展,仅为实际使用付费。我们在意识到错误之前已经构建了 7 个。

第一个 Lambda – 文档摘要器

import { APIGatewayProxyHandler } from 'aws-lambda';
import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

export const handler: APIGatewayProxyHandler = async (event) => {
  try {
    const { document } = JSON.parse(event.body || '{}');

    const response = await openai.chat.completions.create({
      model: 'gpt-4',
      messages: [
        {
          role: 'system',
          content: 'Summarize the following document in 2-3 sentences.'
        },
        {
          role: 'user',
          content: document
        }
      ],
      max_tokens: 150
    });

    return {
      statusCode: 200,
      body: JSON.stringify({
        summary: response.choices[0].message.content
      })
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: error.message })
    };
  }
};

简洁。简单。它运行得很好……直到它不再工作。


Source:

29秒墙

我们在构建一个能够 分析复杂文档 的代理时遇到了第一个重大问题。该代理需要:

  • 从文档中提取文本
  • 分析关键主题
  • 生成标签
  • 创建摘要
  • 推荐相关资源

每一步都需要 3–7 秒。总运行时间约为 ~25 秒。在 Lambda 的 15 分钟限制内,对吧?

错误。

2024-02-15 14:32:18 START RequestId: abc-123-def
2024-02-15 14:32:18 Calling OpenAI for document analysis...
2024-02-15 14:32:25 Analysis complete, generating tags...
2024-02-15 14:32:32 OpenAI inference still running...
2024-02-15 14:32:47 ERROR Task timed out after 29.00 seconds

API Gateway 有 29 秒的超时限制——而不是 Lambda。如果你通过 API Gateway 暴露函数(这很可能),就会在 29 秒处碰壁。

当此超时发生时:

  • 客户端收到 504 Gateway Timeout
  • Lambda 仍在运行并消耗费用
  • OpenAI/Bedrock 调用完成但结果丢失
  • 用户看到请求失败
  • 你会为完整的 Lambda 执行时间付费

我们有 30 % 的复杂代理请求因超时而失败。用户以为我们的 AI 出了问题。其实不是——只是太慢了。

流式传输?Lambda 不行

我们的用户希望获得实时聊天响应,类似 ChatGPT 的流式界面。我们尝试实现流式传输:

export const handler: APIGatewayProxyHandler = async (event) => {
  const stream = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [/* ... */],
    stream: true
  });

  // This is where it breaks
  for await (const chunk of stream) {
    // How do you stream through API Gateway?
    // You can't.
  }
};

API Gateway 会在将整个 Lambda 响应发送给客户端之前先进行缓冲。无法流式传输部分数据;客户端在 Lambda 完成之前什么也看不到。

变通办法: 使用 WebSockets,但这意味着:

  • 单独的 WebSocket API Gateway
  • 连接管理
  • 消息路由
  • 状态跟踪
  • 更多复杂性

我们尝试过;代码体积膨胀到原来的 3 倍,仅为实现一个简单的流式响应。

地狱般的冷启动

AI SDK 体积庞大。我们导入了以下内容:

import OpenAI from 'openai';                                   // 2.1 MB
import { BedrockRuntimeClient } from '@aws-sdk/client-bedrock-runtime'; // 1.8 MB
import Anthropic from '@anthropic-ai/sdk';                    // 1.9 MB
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';    // 1.2 MB
import PDFParse from 'pdf-parse';                             // 0.9 MB

总捆绑大小: ~8 MB
冷启动时间: 8–12 秒

当 Lambda 超过 5 分钟未运行时,AWS 会创建一个新容器。容器启动 + 代码初始化 = 用户需要 10+ 秒 才能得到首次响应。

由于我们的 AI 功能 使用不频繁,冷启动几乎是常态:

  • 文档分析:约 20 次 / 小时
  • 图像分类:5–10 次 / 小时
  • 内容生成:1–2 次 / 小时

每个函数每天都会多次进入冷状态。用户上传文档后,需要等待约 12 秒,便会误以为平台出现故障。

我们尝试了 预置并发(Provisioned Concurrency)。它确实有帮助,但仅为保持函数“热”就要花费 ≈ $50 / 月 每个函数。7 个函数合计 ≈ $350 / 月,而几乎没有处理任何请求。

无共享状态

多轮对话是不可行的。以下是我们的尝试:

// Turn 1: User asks about a document
export const chatHandler: APIGatewayProxyHandler = async (event) => {
  const { message, conversationId } = JSON.parse(event.body || '{}');

  // Get conversation history from DynamoDB
  const history = await getConversationHistory(conversationId);

  const response = await openai.chat.completions.create({
    model: 'gpt-4',
    messages: [
      ...history,
      { role: 'user', content: message }
    ]
  });

  // Save new messages to DynamoDB
  await saveMessage(conversationId, 'user', message);
  await saveMessage(conversationId, 'assistant', response.choices[0].message.content);

  return {
    statusCode: 200,
    body: JSON.stringify({ response: response.choices[0].message.content })
  };
};

每个请求都需要:

  • DynamoDB 读取 以获取对话历史
  • AI 推理
  • 两次 DynamoDB 写入 以持久化交流

对于一次 3 轮对话,这意味着 3 次读取 + 6 次写入,导致明显的延迟和成本增加。

成本激增的痛点

Lambda 按毫秒计费,但 AI 推理的延迟不可预测:

  • 简单问题: 2–3 秒
  • 复杂分析: 15–25 秒
  • 代码生成: 10–30 秒
  • 图像分析: 5–20 秒

一个高费用月份的成本细分

Document Summarizer:   1,200 requests × 8 s avg  = 2.7 h = $180
Image Classifier:        800 requests × 12 s avg = 2.7 h = $180
Content Generator:      400 requests × 18 s avg = 2.0 h = $135
Chat Agent:            2,000 requests × 15 s avg = 8.3 h = $560
Tag Suggester:         3,000 requests × 5 s avg  = 4.2 h = $280
PDF Analyzer:            200 requests × 22 s avg = 1.2 h = $80
Report Builder:          100 requests × 35 s avg = 1.0 h = $65
---------------------------------------------------------------
Total:                                          $1,480

我们为 AI “思考”时间支付了 Lambda 计算费用。一次 20 秒的 GPT‑4 调用实际上只使用了 50 毫秒的 CPU,但我们仍需为 Lambda 完整的 20 秒运行时间付费。

相比之下,使用可以在单个 AI 调用处理期间处理多个请求的长时间运行容器——成本要高效得多。

最糟糕的是?峰值使用放大了这个问题。业务时间内我们有 50+ 并发 Lambda 执行 正在等待 AI 响应。每个执行都在消耗金钱,而实际计算发生在 OpenAI 的服务器上。这就像在交通堵塞的出租车里付费——你付的是时间,而不是进度。

Source:

多轮代理循环

最终的关键点是构建一个能够帮助用户组织资产的代理。工作流程:

  1. 用户: “帮我整理我的产品照片。”
  2. 代理: 分析可用的照片,提出澄清性问题。
  3. 用户: 提供筛选标准。
  4. 代理: 建议文件夹结构。
  5. 用户: 批准或请求更改。
  6. 代理: 执行组织操作。

每一步都是一次独立的 Lambda 调用。状态管理如下所示:

// 步骤 1:初始请求
await saveToDynamoDB(sessionId, {
  step: 'analyzing',
  photos: userPhotos,
  status: 'in_progress'
});

// 步骤 2:代理响应
const session = await getFromDynamoDB(sessionId);
await openai.chat.completions.create(/* ... */);
await saveToDynamoDB(sessionId, {
  ...session,
  step: 'awaiting_criteria',
  analysis: result
});

// 步骤 3:用户提供标准
const session = await getFromDynamoDB(sessionId);
// ... 依此类推

到第 6 步时,我们已经有 12+ 次 DynamoDB 操作6 次 Lambda 调用,以及一个每次加载都变得昂贵的对话上下文。

用户体验很笨拙,因为每一步都需要一次新的 HTTP 请求。没有持久连接、没有实时更新、没有流式传输——只有请求‑响应循环,与 ChatGPT 相比显得支离破碎。

“这感觉像是 2010 年的软件,”我们的产品负责人在尝试了一遍工作流后说。他并没有说错。

临界点

我们的基于 Lambda 的 AI 平台存在根本性问题:

  • 29 秒超时 导致复杂工作流被中止
  • 没有流式传输 使聊天体验破碎
  • 冷启动 带来 10+ 秒的延迟
  • 成本低效 因为为 AI 等待时间付费
  • 状态管理复杂 让代理变得痛苦
  • 集成散乱 跨 7 个不同的函数

我们花在对抗基础设施上的时间比构建功能的时间还多。用户抱怨响应慢,而我们的 AWS 账单却不断攀升。

Lambdas:完美的 AI 工具,糟糕的 AI 代理

Tools 是单一用途、无状态且快速的:

  • 对图像进行分类
  • 对文档进行摘要
  • 从 PDF 中提取文本
  • 生成替代文字(alt text)

Agents 是多轮对话、带状态且复杂的:

  • 帮我整理照片
  • 分析数据并生成报告
  • 与我的文档聊天
  • 基于对话构建工作流

对于工具而言,Lambda 是理想选择。对于代理,则需要持久连接、共享状态和流式传输——这些正是 Lambda 在每一步都在抵制的。

我们最终构建的方案

我们创建了一个 网关:一个可以同时处理工具和代理的单一 API 端点,具备完善的流式传输、状态管理以及供应商灵活性。

架构概览

  • API 网关 → 将请求路由到轻量级 Lambda(网关逻辑)
  • 网关 Lambda → 将请求代理到执行实际 AI 处理的长运行容器

这让我们兼顾了两者的优势:API 层的无服务器弹性伸缩以及 AI 工作负载的持久连接。

在下一篇文章中,我将详细介绍网关模式,并展示我们如何将七个不同的 AI Lambda 统一为一个简洁的 API,能够兼容任何模型提供商。

这是一篇关于构建生产级 AI 平台的 8 部分系列的第 2 部分。完整代码示例可在此处找到。

0 浏览
Back to Blog

相关文章

阅读更多 »

当工作成为心理健康风险时

markdown !Ravi Mishrahttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fu...