【开源实战】基于likeadmin-PHP的ChatGPT智能对话系统开发指南
1. 从零开始:为什么选择likeadmin-PHP来打造你的AI聊天系统?
大家好,我是老张,一个在PHP和AI领域摸爬滚打了十来年的老码农。最近几年,AI聊天机器人火得一塌糊涂,从客服到内容创作,再到个人助手,应用场景遍地开花。很多PHP开发者朋友都来问我:“老张,我也想给自己的项目加个智能聊天功能,但感觉门槛好高,从哪入手啊?”
我的回答通常是:“别自己从轮子造起,找个趁手的框架,快速集成才是王道。” 而今天我要跟大家分享的,就是基于 likeadmin-PHP 这个免费开源的后台管理系统,来快速开发一个功能完整的ChatGPT智能对话系统。你可能听说过ThinkPHP、Laravel,但likeadmin-PHP的优势在于,它不仅仅是一个PHP框架,更是一个开箱即用、前后端分离的通用后台解决方案。它已经帮你把管理员权限、角色管理、菜单配置、素材库这些后台的“脏活累活”都干完了,你只需要专注于最核心的AI对话业务逻辑开发。
这就像你要开个餐厅,likeadmin已经给你准备好了装修好的店面、全套的厨具和基础的服务员(后台管理功能),你只需要研究你的招牌菜(AI对话)怎么做就行了。对于中小型团队或个人开发者来说,这能节省至少70%的前期开发时间。我实测过,用likeadmin-PHP为基础,从零搭建一个具备后台管理、用户体系、对话记录和付费套餐的AI聊天应用,熟练的话一周内就能看到可运行的Demo。接下来,我就手把手带你走一遍这个开发旅程,把每一步的细节和踩过的坑都分享给你。
2. 环境准备与项目初始化:5分钟跑起来
工欲善其事,必先利其器。在开始写代码之前,我们得先把开发环境搭好。别担心,整个过程非常 straightforward。
2.1 基础环境清单
首先,确保你的电脑或服务器上已经安装了以下软件,版本不要太老:
- PHP >= 7.4(推荐8.0或以上,性能更好)。记得开启
curl、openssl、json这些常用扩展,调用OpenAI API全靠它们。 - Composer:PHP的包依赖管理器,没有它寸步难行。
- MySQL >= 5.7 或 MariaDB:用来存用户数据、对话记录、订单信息。
- Node.js & NPM/Yarn:如果你需要自己定制或编译前端页面(Vue3那一套),这个就需要。如果直接用likeadmin编译好的后台前端,初期可以跳过。
- 一个OpenAI的API Key:这是让系统“智能”起来的核心燃料。你需要去OpenAI平台注册账号,并创建一个API Key。注意保管好它,别泄露到公开代码里。
2.2 获取likeadmin-PHP并初始化
likeadmin-PHP的代码托管在Gitee上,获取非常方便。打开你的终端,找一个你喜欢的项目目录,执行以下命令:
# 克隆后端代码(服务器端)
git clone https://gitee.com/likeadmin/likeadmin.git your-ai-chat-project
cd your-ai-chat-project
# 安装PHP依赖包
composer install
这个过程会下载ThinkPHP6核心、以及likeadmin封装好的各种工具类。完成后,你需要配置数据库。复制项目根目录下的 .env.example 文件,重命名为 .env,然后编辑它:
# 数据库配置
DATABASE_HOST=127.0.0.1
DATABASE_PORT=3306
DATABASE_NAME=likeadmin_ai_chat # 你提前在MySQL里创建好的数据库名
DATABASE_USERNAME=root
DATABASE_PASSWORD=your_password
# 应用密钥,用于加密
APP_KEY=你的随机密钥字符串
接下来,初始化数据库。likeadmin提供了数据库迁移和种子数据填充的功能,一键就能创建出管理员表、权限表等基础结构。
# 生成数据库表结构
php think migrate:run
# 填充初始管理员账号等数据(可选,但建议执行)
php think seed:run
执行成功后,你的数据库里就会出现几十张设计好的表。此时,后端API服务其实已经可以运行了。你可以使用 php think run 启动一个内置的Web服务器,或者更常见的,配置一个Nginx或Apache虚拟主机,指向项目的 public 目录。
2.3 部署管理后台前端
likeadmin采用前后端分离架构,后端是PHP提供API,前端是Vue3 + Element Plus构建的管理后台。对于刚起步的我们,最快捷的方式是直接使用官方已经编译好的前端代码。你可以在项目的 public/admin 目录下找到它。这意味着,在你完成上述后端部署后,理论上通过 你的域名/public/admin 就能访问到管理后台的登录界面。
当然,如果你想进行深度定制,比如修改后台的界面布局、增加菜单图标,那就需要拉取前端的源代码进行开发。这个过程涉及Node环境、安装依赖和打包编译,步骤会多一些,但对于大多数想要快速验证功能的开发者来说,直接用编译版是最高效的选择。至此,一个具备完整后台管理功能(用户、角色、权限、菜单)的骨架系统就已经立起来了。是不是比想象中简单?接下来,我们就要往这个骨架里注入“AI灵魂”了。
3. 核心模块设计:如何构建一个健壮的AI对话引擎?
系统跑起来了,现在进入最核心的部分:设计AI对话模块。我们不能简单地把OpenAI的API调用一下就算了,那样做出来的东西很脆弱,用户体验也不好。一个好的AI对话系统,至少应该包含以下几个关键模块,我把它画成了一个简单的架构图(在脑子里):用户交互层 -> 业务逻辑层 -> AI服务层 -> 数据持久层。下面我们来逐一拆解。
3.1 对话会话管理
用户每次打开聊天窗口,都应该被视为一个独立的“会话”。就像微信里的一个聊天对话框。我们需要在数据库里设计一张 chat_session 表,用来记录每个会话的元信息:
session_id:唯一会话标识。user_id:关联的用户ID,未登录用户可以用临时ID。title:会话标题,可以自动用第一条用户消息生成,比如“帮我写一份周报”。model_used:本次会话使用的AI模型,比如gpt-3.5-turbo或gpt-4。created_at和updated_at:创建和更新时间。
这样设计的好处是,用户可以在“对话记录”页面看到自己所有的历史会话列表,点进去能继续聊。这比把所有对话记录混在一起要清晰得多。在likeadmin中,你可以在 app/common/model 目录下创建这个模型,然后通过已有的CRUD生成器快速创建对应的管理后台页面,非常方便。
3.2 消息记录与上下文维护
这是AI对话的“记忆”所在。每个会话下会有多条消息记录,对应一张 chat_message 表。每条消息需要包含:
session_id:属于哪个会话。role:消息角色,是user(用户)、assistant(AI)还是system(系统指令)。content:消息内容。tokens:这条消息消耗的token数,用于后续的成本核算和用量统计。created_at:发送时间。
最关键的是上下文维护。 OpenAI的Chat API要求以消息数组的形式发送历史记录。为了不让上下文无限增长(会导致token消耗剧增和API响应变慢),我们必须实现一个“上下文窗口”管理。我的经验是,通常保留最近10-20轮对话,或者设定一个总token数上限(比如4096 tokens)。每次用户发起新提问时,业务逻辑层需要从数据库中取出这个会话最近的、在窗口限制内的历史消息,组装成数组发给OpenAI。这个“组装历史消息”的函数,是整个对话逻辑的核心,一定要写好,处理好可能的截断问题。
3.3 技能与创作模板
如果系统只是简单的问答,那就太单薄了。我们可以借鉴一些成熟产品的思路,引入“技能”和“创作”的概念。这其实是给用户提供了预设的、更专业的对话场景。
- 技能大全:比如“翻译助手”、“代码解释器”、“小红书文案生成器”。每个技能背后,其实是一个精心设计的
system提示词(prompt)。在数据库里设计一张skill表,记录技能名称、图标、分类和对应的系统提示词。当用户选择一个技能时,实际上是在新会话的开头,插入了一条固定的role: system消息,内容是:“你是一个专业的翻译助手,请将用户输入的内容准确、流畅地翻译成目标语言。” - 创作中心:这和技能类似,但可能更侧重于内容生成,比如“生成公众号文章大纲”、“写一首七言诗”。可以设计不同的“创作模型”,每个模型对应不同的温度(temperature)、最大生成长度等参数,以控制AI输出的创造性和格式。
在后台管理中,我们可以很方便地管理这些技能和创作分类,让运营人员随时调整提示词,而无需改动代码。这就是likeadmin后台管理能力的体现,增删改查配置项变得极其简单。
4. 实战集成OpenAI API:代码怎么写才稳健?
理论说了一大堆,是时候上硬菜了——写代码调用OpenAI。这里我分享几个我踩过坑之后总结的最佳实践。
4.1 封装一个可靠的API客户端
不要在控制器里到处写 curl 调用,一定要封装一个独立的服务类。我通常在 app/common/service 目录下创建一个 OpenAIService.php。
<?php
namespace app\common\service;
use think\facade\Config;
use think\facade\Log;
class OpenAIService
{
protected $apiKey;
protected $baseUrl = 'https://api.openai.com/v1';
protected $timeout = 30; // 超时时间,AI响应慢,设长一点
public function __construct()
{
// 从配置文件读取API Key,不要硬编码!
$this->apiKey = Config::get('ai.openai_api_key');
if (empty($this->apiKey)) {
throw new \Exception('OpenAI API Key 未配置');
}
}
/**
* 发送聊天补全请求
* @param array $messages 消息数组
* @param string $model 模型名称
* @param float $temperature 温度
* @return array
*/
public function createChatCompletion(array $messages, string $model = 'gpt-3.5-turbo', float $temperature = 0.7): array
{
$data = [
'model' => $model,
'messages' => $messages,
'temperature' => $temperature,
'max_tokens' => 2000, // 根据你的需求调整
];
$url = $this->baseUrl . '/chat/completions';
$response = $this->httpPost($url, $data);
if (isset($response['error'])) {
// 记录错误日志,非常重要!
Log::error('OpenAI API调用失败', ['error' => $response['error'], 'request' => $data]);
throw new \Exception('AI服务暂时不可用: ' . ($response['error']['message'] ?? '未知错误'));
}
return [
'content' => $response['choices'][0]['message']['content'] ?? '',
'tokens_used' => $response['usage']['total_tokens'] ?? 0,
];
}
/**
* 封装的HTTP POST请求
*/
private function httpPost(string $url, array $data): array
{
$ch = curl_init();
$jsonData = json_encode($data);
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $jsonData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->apiKey,
],
CURLOPT_TIMEOUT => $this->timeout,
CURLOPT_SSL_VERIFYPEER => false, // 根据你的服务器环境决定是否验证SSL
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
return ['error' => ['message' => 'CURL错误: ' . $error]];
}
$result = json_decode($response, true);
if ($httpCode !== 200) {
return ['error' => $result['error'] ?? ['message' => "HTTP {$httpCode} 错误"]];
}
return $result;
}
}
这个封装类做了几件关键事:集中管理API Key、统一错误处理和日志记录、设置合理的超时。AI服务不稳定是常事,没有完善的错误处理,用户面前就是白屏或奇怪的报错。
4.2 在控制器中调用并处理业务逻辑
有了服务类,在负责处理用户提问的控制器里,逻辑就清晰多了。假设我们有一个 ChatController:
public function sendMessage()
{
$sessionId = $this->request->post('session_id');
$userMessage = trim($this->request->post('message'));
$model = $this->request->post('model', 'gpt-3.5-turbo');
// 1. 参数校验
if (empty($userMessage)) {
return json(['code' => 0, 'msg' => '消息不能为空']);
}
// 2. 获取或创建会话
$session = ChatSessionModel::getOrCreate($sessionId, $this->userId);
// 3. 保存用户消息到数据库
$userMsgRecord = ChatMessageModel::create([
'session_id' => $session->id,
'role' => 'user',
'content' => $userMessage,
]);
try {
// 4. 组装历史消息上下文(这里调用一个上下文管理方法)
$historyMessages = $this->buildMessageContext($session->id, $model);
// 5. 调用OpenAI服务
$openaiService = new OpenAIService();
$result = $openaiService->createChatCompletion($historyMessages, $model);
// 6. 保存AI回复到数据库
$aiMsgRecord = ChatMessageModel::create([
'session_id' => $session->id,
'role' => 'assistant',
'content' => $result['content'],
'tokens' => $result['tokens_used'],
]);
// 7. 更新会话的token消耗和更新时间
$session->tokens_used += $result['tokens_used'];
$session->save();
// 8. 返回结果给前端
return json([
'code' => 1,
'msg' => 'success',
'data' => [
'reply' => $result['content'],
'session_id' => $session->session_id,
]
]);
} catch (\Exception $e) {
// 捕获所有异常,返回友好的错误信息
return json(['code' => 0, 'msg' => 'AI思考中出了点小差,请稍后再试']);
}
}
这段代码体现了完整的业务闭环:接收输入 -> 保存 -> 调用AI -> 保存结果 -> 返回。其中的 buildMessageContext 方法就是前面提到的上下文管理器的实现,它负责从数据库捞取历史记录,并确保总长度不超过限制。
4.3 处理流式响应(Streaming)
上面的例子是等AI完全生成完再返回,用户需要等待。更高级的体验是像ChatGPT官网那样,一个字一个字地实时显示。这需要用到OpenAI API的流式响应(stream)功能。实现起来稍复杂,需要后端保持连接,并以前端能理解的格式(如Server-Sent Events)推送数据片段。在ThinkPHP/likeadmin中,你需要确保输出不被缓冲,并正确设置响应头。这是一个提升用户体验的关键点,如果用户需要长时间等待,流失率会很高。我建议在基础功能稳定后,一定要把流式响应加上。
5. 后台管理功能实战:用likeadmin快速搭建控制面板
likeadmin最大的优势就在于其强大的后台管理生成能力。我们前面设计的各种数据模型,几乎都可以通过后台进行可视化管理。这里我以管理“技能大全”为例,展示一下如何快速实现。
5.1 利用CRUD生成器
likeadmin通常配套有代码生成器工具(可能是命令行工具,也可能是后台在线生成)。你只需要填写数据表名(如 skill)和字段信息,它就能自动生成对应的模型(Model)、控制器(Controller)、验证器(Validator)以及前端的Vue页面组件。
生成后的技能管理页面,天然就具备了列表展示、分页、新增、编辑、删除、批量操作等功能。你几乎不需要写一行后台界面的代码。运营人员登录后台后,就可以在左侧菜单找到“技能管理”,然后像操作Excel表格一样,添加一个新的技能,比如“法律文书助手”,并填写对应的系统提示词:“你是一名专业的法律顾问,请用严谨的法律语言回答用户问题...”。
5.2 自定义复杂业务逻辑
当然,并非所有功能都能靠生成器。比如我们的“对话记录”页面,可能不仅需要展示,还需要支持管理员查看完整的对话内容,甚至手动标注或删除不当对话。这时,我们就需要手动编写或修改控制器和前端页面。
好在likeadmin的前后端结构非常清晰。后端你只需要在 app/adminapi/controller 下创建对应的控制器,继承基础控制器,然后编写你的业务逻辑方法。前端方面,如果你用的是编译版,可能不支持深度定制;但如果你是自己开发前端,那么可以在 admin/src/views 目录下创建对应的Vue文件,使用likeadmin已经封装好的表格、表单、弹窗等组件,开发效率也非常高。
例如,在对话记录列表,我们想增加一个“查看详情”按钮,点击后弹窗展示该会话的所有消息记录。这个功能就需要你手动实现一个API接口(返回某个session_id的所有消息),并在前端写一个弹窗组件来渲染这些消息。这个过程,就是典型的基于成熟框架的二次开发,比从零开始要轻松太多。
5.3 数据统计与仪表盘
一个完整的系统离不开数据可视化。likeadmin的工作台(Dashboard)模块可以很方便地定制。我们可以在工作台上展示一些关键数据,比如:
- 今日AI对话次数
- 累计消耗的Token总数(折合成本)
- 活跃用户数
- 订单收入趋势图
这些数据都需要我们编写对应的统计逻辑。例如,在 app/adminapi/controller/DashboardController.php 中,新增一个方法 getAIChatStats,里面写SQL或使用模型统计今日的 chat_message 记录数。然后,在前端工作台的组件里,调用这个新的API接口,将数据展示出来。这样,管理员每天一登录,就能对整个AI聊天系统的运行状况一目了然。
6. 高级功能与优化:让你的系统更专业、更稳定
基础功能跑通后,我们可以考虑一些高级功能和优化点,让系统从“能用”变得“好用”、“耐用”。
6.1 多API Key轮询与负载均衡
如果你用户量上来,或者担心单个API Key有额度限制或速率限制,可以实现多Key轮询。在配置文件里配置一个API Key数组,然后在 OpenAIService 的构造函数中随机或按顺序选取一个Key使用。更高级的做法是记录每个Key的消耗和错误次数,实现简单的负载均衡和故障转移。
6.2 敏感词过滤与内容安全
AI什么都能聊,这既是优点也是风险。我们必须对用户输入和AI输出进行基本的敏感词过滤,防止产生违法违规内容。可以在调用OpenAI API之前,对用户消息做一个简单的本地过滤。更稳妥的做法是,在保存AI回复到数据库之前,也做一次过滤,甚至可以考虑接入第三方内容安全API进行审核。这是保护你的项目安全运营的必要措施。
6.3 异步队列处理
如果用户量大,同步等待AI响应可能会阻塞Web服务器进程。一个更好的架构是将AI调用任务丢入消息队列(如Redis、RabbitMQ)。当用户发送消息时,控制器只负责将任务入队,并立即返回“消息已接收,正在处理”。然后由后台的队列工作进程(Worker)去实际调用OpenAI API,拿到结果后再通过WebSocket或长轮询通知前端。ThinkPHP官方有队列支持,集成起来不难。这能极大提升系统的并发能力和用户体验。
6.4 成本控制与用户套餐
AI调用是实实在在要花钱的。我们需要设计用户套餐体系。比如:
- 免费用户:每天可问5次,使用GPT-3.5模型。
- 会员用户:每月不限次数(或很高次数),可以使用GPT-4模型。
这就需要我们建立 user 表与套餐的关联,并在每次对话前检查用户剩余额度。在 ChatController 的 sendMessage 方法最开始,就要加入额度校验逻辑。同时,要有一套完整的订单管理系统(充值订单、会员订单),likeadmin的后台非常适合快速搭建这套体系,营销中心的“充值套餐”、“会员套餐”模块就是干这个的。
7. 部署上线与持续迭代
开发完成,最后一步就是部署到生产环境。我个人的经验是,使用宝塔面板可以极大简化PHP项目的部署流程。
- 服务器准备:购买一台云服务器,安装好宝塔面板。
- 环境安装:在宝塔的软件商店里安装Nginx、MySQL、PHP(记得安装对应扩展)、Redis(如果你用了队列或缓存)。
- 网站部署:添加一个PHP站点,将你的likeadmin项目代码上传到网站根目录(或通过Git拉取)。配置网站运行目录为
public,并配置伪静态规则(ThinkPHP规则)。 - 数据库配置:在宝塔创建数据库,然后将本地开发环境的
.env文件中的数据库连接信息修改为生产环境的。 - 前端部署:如果你有独立的前端项目(如Nuxt.js开发的PC聊天页面),可以单独部署,并通过Nginx反向代理到后端API地址。
- 配置定时任务:有些任务需要定时执行,比如每天凌晨重置免费用户的对话次数。可以在宝塔的“计划任务”里添加PHP命令行脚本。
系统上线后,收集用户反馈至关重要。观察用户最喜欢用什么技能,哪些问题AI回答得不好,然后持续优化你的提示词模板和系统逻辑。AI技术本身也在快速迭代,保持对OpenAI等平台新模型、新API的关注,适时将你的系统升级,比如支持最新的 o1 推理模型,就能始终保持竞争力。
走完这一整套流程,你不仅得到了一个可运营的AI智能对话系统,更重要的是,你掌握了基于优秀开源框架进行AI应用开发的完整方法论。这套方法不仅可以用于聊天,稍加改造,就能用于开发AI绘画平台、智能客服系统、AI代码助手等等。技术的乐趣就在于,用一个支点,撬动无限的可能。希望这篇指南能帮你少走弯路,快速把想法变成现实。如果在实际操作中遇到具体问题,不妨多翻翻likeadmin和ThinkPHP的官方文档,或者到开源社区里和大家一起讨论,很多时候,你遇到的坑,别人已经踩过并填平了。
更多推荐

所有评论(0)