ChatGPT API怎么接入自己的网站?完整开发思路

把ChatGPT能力接入网站,通常是由网站后端调用OpenAI API,再把结果返回聊天界面。API Key必须保存在服务端,浏览器只访问自己的业务接口。上线还需补齐身份校验、限流、上下文隔离、超时反馈与费用控制;如果回答公司业务问题,还应接入有效资料和人工入口。先验证单一场景。

接入前先明确:网站需要哪一种 AI 功能?

用户常说的“ChatGPT API”,在开发中通常指 OpenAI 提供的模型 API。网站问答、内容摘要、表单分类和带知识库的客服,前后端的业务流程并不相同。先选一个可以验收的场景,例如“根据公开产品资料回答使用问题”,再选当前账号可用、适合该任务的模型。

本文以 OpenAI 官方快速入门介绍的 Responses API 为调用入口,展示一个服务端接入思路。模型名、额度和费用以实际项目配置为准。

正确的数据路径:浏览器只访问自己的后端

网站输入框
  → POST /api/support
  → 网站后端:身份与权限校验、限流、校验消息
  → OpenAI Responses API
  → 网站后端:检查状态、整理结果
  → 网站界面:显示答案或明确的失败提示

密钥放入服务器环境变量或密钥管理服务,不放在 HTML、前端打包变量、浏览器请求参数或公开仓库。加密或压缩前端代码不能让浏览器中的密钥保密,参见 OpenAI 密钥管理建议

服务端调用示例

下面是运行于支持内置 fetchAbortSignal.timeout 的现代 Node.js 服务端的调用函数。它不是公开 HTTP 服务;应由已经完成登录或访客会话校验、限流和请求大小限制的路由调用。模型名由服务端环境变量指定,不能让浏览器任意选择昂贵模型。

// 只在服务器配置,以下均为占位值:
// OPENAI_API_KEY=YOUR_OPENAI_API_KEY
// OPENAI_MODEL=YOUR_AVAILABLE_MODEL_ID

export async function answerWebsiteQuestion(message) {
  if (typeof message !== "string" || !message.trim()
      || message.length > 2000) {
    return { ok: false, code: "INVALID_MESSAGE" };
  }
  const key = process.env.OPENAI_API_KEY;
  const model = process.env.OPENAI_MODEL;
  if (!key || !model) {
    return { ok: false, code: "SERVER_NOT_CONFIGURED" };
  }

  try {
    const response = await fetch("https://api.openai.com/v1/responses", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${key}`,
        "Content-Type": "application/json"
      },
      signal: AbortSignal.timeout(20000),
      body: JSON.stringify({
        model,
        input: message.trim(),
        instructions: "简明回答;缺少依据时说明不确定,不编造公司事实。",
        max_output_tokens: 800,
        store: false
      })
    });
    if (!response.ok) {
      // 状态码和请求 ID 可进入受控日志,不记录密钥或原始会话。
      return { ok: false, code: "UPSTREAM_UNAVAILABLE" };
    }
    const data = await response.json();
    if (data.status !== "completed") {
      return { ok: false, code: "INCOMPLETE_RESPONSE" };
    }
    const text = (data.output || [])
      .filter(item => item.type === "message")
      .flatMap(item => item.content || [])
      .filter(part => part.type === "output_text")
      .map(part => part.text)
      .join("\n").trim();
    return text ? { ok: true, text }
      : { ok: false, code: "NO_TEXT_RESPONSE" };
  } catch {
    return { ok: false, code: "REQUEST_FAILED" };
  }
}

示例中的 2,000 字符、20 秒和 800 输出 token 是演示限制,不是通用生产参数。输出预算过小可能导致未完成结果;应按实际模型、回答长度和响应时间测试。生产日志可记录内部请求编号、状态码、耗时和供应方请求 ID;不要把完整上游错误或敏感输入直接显示给访客。

store:false 用于控制相应响应状态的存储,并不等于所有日志、缓存和服务商数据都零保留;具体应核对 OpenAI 数据控制说明与所用功能。

前端交互要处理等待、失败和重复点击

  • 提交时显示等待状态,避免同一问题重复发送。
  • 接口失败时保留用户输入,提供重试或人工咨询入口。
  • 纯文本答案使用 textContent 等安全方式呈现;若支持 Markdown 或 HTML,使用经过维护的渲染与清理方案。
  • 长回答可以按需采用流式输出,同时处理断流、取消与未完成状态。
  • 手机端检查键盘弹出、滚动、输入框和发送按钮是否可用。

多轮上下文和知识库怎样增加?

这个函数演示单轮调用。多轮对话需要按当前用户与会话保存必要的历史,或采用合适的 API 会话机制;服务端验证会话归属后再读取,不能信任浏览器传来的任意历史角色。具体方式见 OpenAI 会话状态文档

公司业务问答应先整理资料、检索相关片段,再附带来源交给模型;实时业务数据通过独立的授权查询提供。提示词不能代替登录认证、数据库权限和人工审批。

常见错误应该怎么定位?

现象优先检查
401 / 403服务端密钥、项目权限、模型访问条件及服务地区;不要让用户重复重试配置错误
429区分请求限流与余额或额度问题;限流遵循退避,余额问题先处理账户配置
5xx / 网络超时服务状态、网络和总超时;只对适合重试的请求设置有限次数的退避
HTTP 成功但无完整文字响应状态、拒绝信息、输出预算和返回内容类型
回答不符合公司业务资料是否有效、检索是否命中、是否本来就不应由模型推断

状态分类可参考 OpenAI 错误码说明。重试前要考虑重复调用费用;涉及外部业务动作时还需要幂等控制。

上线检查与费用边界

开发费取决于界面、知识库、业务接口与后台;模型费用则与模型、输入输出、调用次数和所用工具有关。上线前检查登录和访客限流、每日用量告警、异常告警、日志脱敏、资料更新及人工接管。不要把 API 请求成功当成完整客服系统已通过验收。

接入常见问题

静态网站可以增加 AI 问答吗?

可以增加独立后端或合适的服务端函数,由页面调用。静态页面本身不应持有真实 API Key;还需要防滥用、错误反馈和运行预算。

把 Key 放进前端环境变量就安全吗?

如果变量被打包进浏览器代码,访客仍可以获得它。真实密钥只保存在服务端运行环境,不进入前端构建产物。

示例代码能直接当作完整客服上线吗?

不能。它仅演示模型调用,公开接口还需要身份、权限、限流、日志和界面处理;业务客服还需要知识资料、测试和人工承接。

什么时候需要完整开发?

如果你希望把 AI 放进现有网站、会员后台或业务流程,可以先提供当前技术栈、使用入口与一个目标问题。AI自动化开发可以据此评估接入范围、数据边界和验收方式。

参考与核对依据

把下一步说清楚。

带上现状、目标与需要解决的问题,先确认实施范围和验收方式。