如何自建免费ChatGPT网站:从API接入到前端优化的全栈实践

2次阅读
没有评论

共计 2308 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点

直接调用 OpenAI 官方 API 存在两个主要问题:

如何自建免费 ChatGPT 网站:从 API 接入到前端优化的全栈实践

  • 高昂成本 :GPT-3.5 每 1000 tokens 约 0.002 美元,高频使用时账单增长极快
  • 响应延迟 :国内直连 API 平均延迟超过 800ms,且常有超时现象

技术选型对比

针对无服务器方案,我们对比了两种主流选择:

  1. Cloudflare Workers
  2. 优势:全球网络加速、免费调用额度高(10 万次 / 天)
  3. 劣势:需要处理 KV 存储的异步问题

  4. Vercel Edge Functions

  5. 优势:与 Next.js 无缝集成、自动 CDN 分发
  6. 劣势:免费版有执行时长限制(50ms CPU 时间)

最终选择 Cloudflare Workers 作为代理层,因其更适合高并发场景。

核心实现

Next.js 流式响应实现

/**
 * 处理流式数据的 React Hook
 * @param endpoint 代理 API 地址
 * @param initialMessage 初始对话消息
 */
function useStreamingResponse(
  endpoint: string,
  initialMessage: string
) {const [response, setResponse] = useState('');

  useEffect(() => {const controller = new AbortController();

    const fetchData = async () => {
      try {
        const res = await fetch(endpoint, {
          method: 'POST',
          headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({message: initialMessage}),
          signal: controller.signal
        });

        const reader = res.body?.getReader();
        if (!reader) return;

        while (true) {const { done, value} = await reader.read();
          if (done) break;

          const chunk = new TextDecoder().decode(value);
          setResponse(prev => prev + chunk);
        }
      } catch (error) {console.error('Stream error:', error);
      }
    };

    fetchData();
    return () => controller.abort();
  }, [endpoint, initialMessage]);

  return response;
}

Nginx 反向代理配置

location /api/proxy {
  proxy_pass https://api.openai.com/v1/chat/completions;

  # 缓存高频问答对
  proxy_cache my_cache;
  proxy_cache_key "$request_uri|$request_body";
  proxy_cache_valid 200 10m;

  # 防止 API Key 泄露
  proxy_set_header Authorization "Bearer $hidden_api_key";
  proxy_hide_header Authorization;
}

性能优化实战

对话存储方案对比

方案 容量上限 读写速度 持久性
LocalStorage 5MB 同步 标签页独立
IndexedDB 浏览器限制 异步 全站共享

推荐使用 IndexedDB 存储长对话历史,因其支持事务操作和更大存储空间。

TTFB 优化技巧

  1. 预连接 DNS:<link rel="dns-prefetch" href="//your-proxy.domain">
  2. 启用 HTTP/ 2 服务端推送
  3. 压缩 API 响应:gzip_min_length 1k;

常见问题处理

应对 429 限流

// 指数退避重试机制
async function retryWithBackoff(fn: () => Promise<any>,
  retries = 3,
  delay = 1000
) {
  try {return await fn();
  } catch (error) {if (retries <= 0 || error.status !== 429) throw error;

    await new Promise(res => setTimeout(res, delay));
    return retryWithBackoff(fn, retries - 1, delay * 2);
  }
}

敏感词过滤

/** 匹配政治敏感词(示例)*/
const SENSITIVE_REGEX = /(某敏感词 1 | 某敏感词 2)/gi;

function sanitizeInput(text: string) {
  return text.replace(SENSITIVE_REGEX, match => 
    '*'.repeat(match.length)
  );
}

安全加固方案

API Key 多层防护

  1. 环境变量加密:使用 wrangler secret put API_KEY
  2. 请求频率限制:limit_req zone=apilimit burst=5 nodelay;
  3. IP 白名单过滤

CSP 策略示例

Content-Security-Policy: 
  default-src 'self';
  connect-src 'self' api.openai.com;
  script-src 'unsafe-inline' 'unsafe-eval';

开放性问题

在零服务器成本的前提下,可以考虑:
1. 使用浏览器 Service Worker 缓存历史对话
2. 将记忆加密后存储在 URL hash 中
3. 利用 Cloudflare D1 实现边缘数据库

哪种方案更适合长期对话场景?欢迎在评论区分享你的见解。

正文完
 0
评论(没有评论)