Stagehand最佳实践:生产环境部署指南

Stagehand最佳实践:生产环境部署指南

【免费下载链接】stagehand An AI web browsing framework focused on simplicity and extensibility. 【免费下载链接】stagehand 项目地址: https://gitcode.com/GitHub_Trending/stag/stagehand

引言

还在为AI网页自动化在生产环境中的稳定性而头疼吗?Stagehand作为专注于简单性和可扩展性的AI网页浏览框架,提供了完整的生产环境部署解决方案。本文将深入解析Stagehand在生产环境中的最佳实践,帮助您构建可靠、高效、可扩展的浏览器自动化系统。

读完本文,您将掌握:

  • ✅ Stagehand生产环境架构设计原则
  • ✅ Browserbase云环境与本地环境的部署策略
  • ✅ Vercel无服务器函数部署完整指南
  • ✅ 环境变量管理与安全配置最佳实践
  • ✅ 性能优化与成本控制技巧
  • ✅ 监控与故障排查体系构建

环境选择策略

Stagehand支持两种主要部署环境,根据业务需求选择合适的方案至关重要:

Browserbase云环境 vs 本地环境对比

特性Browserbase云环境本地环境
扩展性高(云托管)有限(本地资源)
隐私特性高级指纹伪装基础隐私
代理支持内置住宅代理手动配置
会话持久化云上下文存储文件级用户数据
地理分布多区域部署单机部署
调试能力会话录制和日志直接DevTools访问
设置复杂度仅需环境变量需要浏览器安装
成本模型按使用量计费基础设施和维护成本
适用场景生产、规模化、合规开发、调试

环境选择决策树

mermaid

Vercel无服务器部署指南

项目结构规划

your-stagehand-app/
├── api/
│   └── run.ts              # 主处理函数
├── package.json            # 依赖配置
├── tsconfig.json          # TypeScript配置
├── vercel.json            # Vercel部署配置
└── .env.local             # 本地环境变量(不提交)

核心部署文件配置

1. API处理函数 (api/run.ts)
import type { VercelRequest, VercelResponse } from "@vercel/node";
import { Stagehand } from "@browserbasehq/stagehand";
import { z } from "zod";

export default async function handler(
  req: VercelRequest,
  res: VercelResponse
): Promise<void> {
  try {
    // 初始化Stagehand实例
    const stagehand = new Stagehand({
      env: "BROWSERBASE",
      apiKey: process.env.BROWSERBASE_API_KEY!,
      projectId: process.env.BROWSERBASE_PROJECT_ID!,
      modelName: "google/gemini-2.5-flash",
      modelClientOptions: {
        apiKey: process.env.GOOGLE_API_KEY!,
      },
      browserbaseSessionCreateParams: {
        projectId: process.env.BROWSERBASE_PROJECT_ID!,
        region: "us-west-2",  // 选择最近的区域
        browserSettings: {
          blockAds: true,     // 提升性能
          viewport: { width: 1920, height: 1080 },
        },
        timeout: 300,         // 5分钟超时
      },
    });

    await stagehand.init();
    const page = stagehand.page;

    // 执行自动化任务
    await page.goto("https://www.example.com/");
    await page.act("点击登录按钮");
    
    // 数据提取
    const { extraction } = await page.extract({
      instruction: "提取用户信息和状态",
      schema: z.object({
        username: z.string(),
        status: z.string(),
      }),
    });

    await stagehand.close();

    res.status(200).json({ 
      success: true, 
      data: extraction 
    });
  } catch (error: unknown) {
    const message = error instanceof Error ? error.message : String(error);
    res.status(500).json({ 
      success: false, 
      error: message 
    });
  }
}
2. 包管理配置 (package.json)
{
  "name": "stagehand-production-app",
  "private": true,
  "type": "module",
  "engines": { 
    "node": ">=18" 
  },
  "dependencies": {
    "@browserbasehq/stagehand": "^2.4.3",
    "zod": "^3.25.0"
  },
  "devDependencies": {
    "typescript": "^5.6.0",
    "@types/node": "^20.12.12",
    "@vercel/node": "^3.2.20"
  },
  "scripts": {
    "dev": "vercel dev",
    "deploy": "vercel --prod"
  }
}
3. TypeScript配置 (tsconfig.json)
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "moduleResolution": "node",
    "outDir": ".vercel/output/functions",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "types": ["node"],
    "resolveJsonModule": true
  },
  "include": ["api/**/*.ts", "src/**/*.ts"]
}
4. Vercel部署配置 (vercel.json)
{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "functions": {
    "api/run.ts": {
      "maxDuration": 60,
      "memory": 1024
    }
  },
  "crons": [
    {
      "path": "/api/run",
      "schedule": "0 * * * *"
    }
  ]
}

环境变量安全管理

必需的环境变量
# Browserbase配置
BROWSERBASE_API_KEY=your_browserbase_api_key
BROWSERBASE_PROJECT_ID=your_project_id

# AI模型配置(根据使用的模型选择)
OPENAI_API_KEY=your_openai_key          # 使用GPT模型时
GOOGLE_API_KEY=your_google_key          # 使用Gemini模型时
ANTHROPIC_API_KEY=your_anthropic_key    # 使用Claude模型时
安全的变量管理流程

mermaid

部署执行流程

# 1. 安装Vercel CLI
npm install -g vercel

# 2. 登录Vercel
vercel login

# 3. 链接项目
vercel link

# 4. 设置环境变量
vercel env add BROWSERBASE_API_KEY
vercel env add BROWSERBASE_PROJECT_ID
vercel env add GOOGLE_API_KEY

# 5. 本地测试
vercel dev --listen 3000

# 6. 部署到生产环境
vercel --prod

高级生产配置

Browserbase高级会话配置

const advancedConfig = {
  env: "BROWSERBASE",
  browserbaseSessionCreateParams: {
    projectId: process.env.BROWSERBASE_PROJECT_ID!,
    region: "us-west-2",           // 选择最优区域
    proxies: true,                 // 启用代理支持
    timeout: 3600,                 // 1小时会话超时
    keepAlive: true,               // 保持会话活跃
    browserSettings: {
      advancedPrivacy: false,      // 企业版功能
      blockAds: true,              // 提升性能
      solveCaptchas: true,         // 自动验证码处理
      recordSession: true,         // 录制会话用于调试
      viewport: { width: 1920, height: 1080 },
      fingerprint: {
        browsers: ["chrome", "edge"],
        devices: ["desktop"],
        operatingSystems: ["windows", "macos"],
        locales: ["en-US", "en-GB"],
        httpVersion: 2,
      },
    },
    userMetadata: {
      userId: "automation-user-123",
      environment: "production",
      version: "1.0.0"
    },
  },
};

性能优化策略

缓存机制实现
// 动作缓存实现
interface ActionCache {
  [key: string]: ObserveResult;
}

class StagehandCache {
  private cache: ActionCache = {};

  // 生成缓存键(基于页面内容和指令)
  private generateCacheKey(pageContent: string, instruction: string): string {
    return `${hash(pageContent)}-${hash(instruction)}`;
  }

  // 获取缓存动作
  async getCachedAction(page: Page, instruction: string): Promise<ObserveResult | null> {
    const pageContent = await page.content();
    const cacheKey = this.generateCacheKey(pageContent, instruction);
    return this.cache[cacheKey] || null;
  }

  // 缓存动作
  async cacheAction(page: Page, instruction: string, action: ObserveResult): Promise<void> {
    const pageContent = await page.content();
    const cacheKey = this.generateCacheKey(pageContent, instruction);
    this.cache[cacheKey] = action;
  }
}
会话复用策略
// 会话管理类
class SessionManager {
  private activeSessions: Map<string, Stagehand> = new Map();

  // 获取或创建会话
  async getSession(sessionId?: string): Promise<Stagehand> {
    if (sessionId && this.activeSessions.has(sessionId)) {
      return this.activeSessions.get(sessionId)!;
    }

    const stagehand = new Stagehand({
      env: "BROWSERBASE",
      browserbaseSessionID: sessionId,
      // ...其他配置
    });

    await stagehand.init();
    
    if (stagehand.sessionId) {
      this.activeSessions.set(stagehand.sessionId, stagehand);
    }

    return stagehand;
  }

  // 清理过期会话
  cleanupSessions(timeout: number = 3600000): void {
    setInterval(() => {
      const now = Date.now();
      for (const [sessionId, session] of this.activeSessions) {
        // 实现会话超时逻辑
      }
    }, timeout);
  }
}

监控与日志体系

结构化日志配置

// 高级日志配置
import { createLogger, format, transports } from 'winston';

const logger = createLogger({
  level: process.env.LOG_LEVEL || 'info',
  format: format.combine(
    format.timestamp(),
    format.json()
  ),
  transports: [
    new transports.Console(),
    new transports.File({ 
      filename: 'logs/stagehand-production.log',
      maxsize: 10485760, // 10MB
      maxFiles: 5
    })
  ]
});

// 集成到Stagehand
const stagehand = new Stagehand({
  // ...其他配置
  onLog: (level, message, metadata) => {
    logger.log(level, message, metadata);
  }
});

关键监控指标

指标类别具体指标监控频率告警阈值
性能指标会话初始化时间实时> 5秒
性能指标动作执行时间实时> 10秒
成本指标Token使用量每小时超预算80%
成本指标Browserbase费用每日超预算90%
可用性成功率每5分钟< 95%
可用性错误率实时> 5%

故障排查与恢复

常见问题解决方案

mermaid

自愈机制实现

// 智能重试机制
class SelfHealingExecutor {
  private maxRetries: number = 3;
  private retryDelay: number = 1000;

  async executeWithRetry(
    page: Page,
    action: string | ObserveResult,
    context?: string
  ): Promise<void> {
    let attempt = 0;
    
    while (attempt < this.maxRetries) {
      try {
        if (typeof action === 'string') {
          await page.act(action);
        } else {
          await page.act(action);
        }
        return; // 成功执行
      } catch (error) {
        attempt++;
        
        if (attempt === this.maxRetries) {
          throw new Error(`Action failed after ${this.maxRetries} attempts: ${error.message}`);
        }
        
        // 等待后重试
        await new Promise(resolve => setTimeout(resolve, this.retryDelay * attempt));
        
        // 可选:刷新页面或重新获取DOM状态
        if (context === 'navigation') {
          await page.reload();
        }
      }
    }
  }
}

安全最佳实践

敏感信息处理

// 安全配置管理器
class SecurityConfig {
  private static secrets: Map<string, string> = new Map();

  // 从安全存储加载配置
  static async loadSecrets(): Promise<void> {
    // 实现从AWS Secrets Manager、HashiCorp Vault等加载
    this.secrets.set('BROWSERBASE_API_KEY', process.env.BROWSERBASE_API_KEY!);
    this.secrets.set('OPENAI_API_KEY', process.env.OPENAI_API_KEY!);
  }

  // 安全获取配置
  static getSecret(key: string): string {
    const value = this.secrets.get(key);
    if (!value) {
      throw new Error(`Secret ${key} not found`);
    }
    return value;
  }
}

// 使用安全配置
const stagehand = new Stagehand({
  env: "BROWSERBASE",
  apiKey: SecurityConfig.getSecret('BROWSERBASE_API_KEY'),
  // ...其他配置
});

访问控制策略

// 基于角色的访问控制
class AccessController {
  private userRoles: Map<string, string[]> = new Map();

  canExecuteAction(userId: string, action: string): boolean {
    const roles = this.userRoles.get(userId) || [];
    
    // 定义动作权限映射
    const actionPermissions: { [key: string]: string[] } = {
      'extract_sensitive_data': ['admin', 'data_analyst'],
      'modify_content': ['admin', 'content_manager'],
      'basic_navigation': ['user', 'admin', 'content_manager', 'data_analyst']
    };

    const requiredRoles = actionPermissions[action] || ['user'];
    return requiredRoles.some(role => roles.includes(role));
  }
}

成本优化策略

资源使用监控表

资源类型优化策略预期节省实施难度
LLM Token动作缓存40-60%
Browserbase会话复用30-50%
计算资源智能超时20-30%
网络流量数据压缩10-20%

成本控制实现

// 成本监控器
class CostMonitor {
  private tokenUsage: number = 0;
  private sessionCost: number = 0;
  private budget: number;

  constructor(budget: number) {
    this.budget = budget;
  }

  // 记录Token使用
  recordTokenUsage(tokens: number): void {
    this.tokenUsage += tokens;
    this.checkBudget();
  }

  // 记录会话成本
  recordSessionCost(cost: number): void {
    this.sessionCost += cost;
    this.checkBudget();
  }

  // 检查预算
  private checkBudget(): void {
    const totalCost = this.tokenUsage * 0.001 + this.sessionCost; // 假设Token价格
    if (totalCost > this.budget * 0.8) {
      console.warn(`预算警告: 已使用80%的预算`);
    }
    if (totalCost > this.budget) {
      throw new Error(`超出预算: 当前成本 ${totalCost}, 预算 ${this.budget}`);
    }
  }

  // 生成成本报告
  generateReport(): CostReport {
    return {
      tokenUsage: this.tokenUsage,
      sessionCost: this.sessionCost,
      totalCost: this.tokenUsage * 0.001 + this.sessionCost,
      budgetRemaining: this.budget - (this.tokenUsage * 0.001 + this.sessionCost)
    };
  }
}

总结与展望

Stagehand在生产

【免费下载链接】stagehand An AI web browsing framework focused on simplicity and extensibility. 【免费下载链接】stagehand 项目地址: https://gitcode.com/GitHub_Trending/stag/stagehand

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值