PHP实现智能客服本质是调用外部AI API,核心在于HTTP请求封装、会话管理与流式响应处理,需绕过认证头缺失、JSON格式错误、缓冲干扰三大卡点,并通过SSE+Redis等方案解决上下文与状态问题。

PHP 本身不直接处理 AI 推理,所谓“PHP 结合 AI 做智能客服”,本质是 PHP 作为后端胶水层,调用外部 AI 服务(如 OpenAI、Ollama、千问、讯飞星火等)的 API,再对接前端对话界面。别被“智能”二字带偏——核心是 HTTP 请求封装、会话状态管理、流式响应处理,不是在 PHP 里训模型。
如何用 PHP 调通 OpenAI 的 chat/completions 接口
这是最常见起点。关键不是写得多炫,而是绕过三个实际卡点:
-
curl_setopt($ch, CURLOPT_HTTPHEADER, [...])必须带Content-Type: application/json和Authorization: Bearer sk-xxx,漏任意一个都返回401 Unauthorized或400 Bad Request - 请求体必须是严格 JSON 格式:
json_encode(['model' => 'gpt-3.5-turbo', 'messages' => [['role' => 'user', 'content' => '你好']]]),messages是数组,不是字符串,PHP 数组键名大小写敏感(role不是Role) - 别用
file_get_contents()直接 POST JSON——它不支持设置 header,容易 silently 失败;坚持用curl或stream_context_create()配置完整选项
为什么不能直接在 PHP-FPM 里用 sleep() 实现流式响应
用户看到“打字机效果”,背后是服务端逐 chunk 返回数据。但 PHP-FPM 默认缓冲整个响应体,flush() 和 ob_flush() 在多数 Nginx + PHP-FPM 组合下根本不起作用——Nginx 自己还有一层 buffer。
- 必须关掉 Nginx 的
proxy_buffering off;(在 location 块里) - PHP 脚本开头加
if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); }不行,那是为“后台任务”设计的,不是为流式输出 - 真正可行路径:用
SSE(Server-Sent Events)+text/event-stream响应头,PHP 每次echo "data: ...\n\n"; ob_flush(); flush();,前端用EventSource接收 - 注意:SSE 不支持 POST,所以得把 prompt 放 query string 或提前用普通 POST 存到 session,再用 GET SSE 拉取
怎么让多次对话“记住上下文”,又不炸内存
AI 模型本身无状态,所有记忆靠你传 messages 数组。但全量传历史记录,很快超 token 限制(比如 gpt-3.5-turbo 最多 16k)。硬拼数组不是办法。
立即学习“PHP免费学习笔记(深入)”;
- 别存原始 HTML 或富文本进
messages,先用strip_tags()清洗,再用mb_substr()截断单条内容(比如只留最近 5 轮,每轮 content ≤ 200 字) - 用 PHP
$_SESSION存精简后的对话摘要,但 session 文件大了会拖慢请求;更稳的是存 Redis,用hSet("conv:{$uid}", $timestamp, json_encode($msg)),再用hGetAll()+array_slice()拿最新几条 - 警惕“角色注入”:用户输入里如果含
"role": "system"这种字符串,直接塞进 messages 可能被模型误读——得做基础转义或白名单过滤role值(只允许user/assistant)
真正的难点不在调哪个 API,而在于错误怎么透出给前端(比如 API key 过期时,OpenAI 返回 401 但 body 是 JSON,PHP 后端得解析并转成前端能识别的错误码)、对话中断后怎么续(token 超限没报错,只是截断,得检查响应里 finish_reason === "length")、还有审核——别让客服接口变成越狱入口。这些细节不压到每个请求里测,上线就翻车。



















