接入前先明确:网站需要哪一种 AI 功能?
用户常说的“ChatGPT API”,在开发中通常指 OpenAI 提供的模型 API。网站问答、内容摘要、表单分类和带知识库的客服,前后端的业务流程并不相同。先选一个可以验收的场景,例如“根据公开产品资料回答使用问题”,再选当前账号可用、适合该任务的模型。
本文以 OpenAI 官方快速入门介绍的 Responses API 为调用入口,展示一个服务端接入思路。模型名、额度和费用以实际项目配置为准。
正确的数据路径:浏览器只访问自己的后端
网站输入框
→ POST /api/support
→ 网站后端:身份与权限校验、限流、校验消息
→ OpenAI Responses API
→ 网站后端:检查状态、整理结果
→ 网站界面:显示答案或明确的失败提示
密钥放入服务器环境变量或密钥管理服务,不放在 HTML、前端打包变量、浏览器请求参数或公开仓库。加密或压缩前端代码不能让浏览器中的密钥保密,参见 OpenAI 密钥管理建议。
服务端调用示例
下面是运行于支持内置 fetch 和 AbortSignal.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自动化开发可以据此评估接入范围、数据边界和验收方式。
