From 462bb010be3429d00a95098dd2b0d791e0da300e Mon Sep 17 00:00:00 2001 From: LiuZhengYu <2777920394@qq.com> Date: Mon, 27 Apr 2026 16:46:44 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E4=BA=86500=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/admin/common.php | 9 +- web/admin/www/keywordManage.php | 254 ++++++++++++++++++++++++-------- zciyphp/openai.php | 51 +++---- 3 files changed, 217 insertions(+), 97 deletions(-) diff --git a/web/admin/common.php b/web/admin/common.php index ed6e4d5..9e930ca 100644 --- a/web/admin/common.php +++ b/web/admin/common.php @@ -80,6 +80,7 @@ function verifyuser() { } if ($onlinerow['usrchg'] == 2) { header('_re: true'); + exit; } if ($onlinerow['exptimes'] > time()) return $auth; @@ -91,10 +92,10 @@ function verifyuser() { $authstr = json_encode($auth, JSON_PARTIAL_OUTPUT_ON_ERROR); $enauth = encrypt($authstr, 'E', $_token['salt']); - if ($_token['type'] == 'cookie') { - $headercookie = 'Set-Cookie: ' . $_token['field'] . '=' . $enauth . '; expires=' . gmdate('D, d-M-Y H:i:s T', time() + $_token['swapsec'] + $_token['expsec']) . '; path=/; httponly; SameSite=None; Secure'; - header($headercookie); - } else { +if (!headers_sent() && $_token['type'] == 'cookie') { + $headercookie = 'Set-Cookie: ' . $_token['field'] . '=' . $enauth . '; expires=' . gmdate('D, d-M-Y H:i:s T', time() + $_token['swapsec'] + $_token['expsec']) . '; path=/; httponly; SameSite=None; Secure'; + header($headercookie); +} else { $_token['__ciyauth'] = $enauth; //header('_ciyauth: ' . $enauth); } diff --git a/web/admin/www/keywordManage.php b/web/admin/www/keywordManage.php index d541a45..29368c7 100644 --- a/web/admin/www/keywordManage.php +++ b/web/admin/www/keywordManage.php @@ -546,76 +546,204 @@ class keywordManage } //AI相关功能 - public static function json_AIFunction() - { - global $db; - $rsuser = verifyfast(); - $post = new \ciy\post(); +// public static function json_AIFunction() +// { +// global $db; +// $rsuser = verifyfast(); +// $post = new \ciy\post(); - $function_type = trim($post->get('param')); +// $function_type = trim($post->get('param')); - // AI配置 - $aiConfig = [ - 'baseurl' => 'https://dashscope.aliyuncs.com/compatible-mode/v1', - 'aikey' => 'sk-0cd7b8c72ae04d049306e345f17c6790', - 'model' => 'qwen-turbo', - 'maxtoken' => 2000 - ]; +// // AI配置 阿里云通义千问 +// $aiConfig = [ +// // https://dashscope-inner.aliyuncs.com +// 'baseurl' => 'https://dashscope.aliyuncs.com/compatible-mode/v1', +// 'aikey' => 'sk-0cd7b8c72ae04d049306e345f17c6790', +// 'model' => 'qwen-turbo', +// 'maxtoken' => 2000 +// ]; - try { - $openai = new \ciy\openai($aiConfig); - // 角色定位 - if ($function_type === '修改') { - $content = trim($post->get('content')); - if (empty($content)) { - return errjson('请先等待生成关键词后再操作'); - } - $system = '你是SEO关键词清洗优化助手,严格遵守: - 1. 核心词绝对不能修改、删除、替换; - 2. 只剔除不通顺、重复、无意义、垃圾关键词; - 3. 可优化前后修饰词,不改变核心; - 4. 输出严格一行一个,无解释、无符号、无序号; - 5. 只净化,不新增。'; +// try { +// $openai = new \ciy\openai($aiConfig); + +// // 角色定位 +// if ($function_type === '修改') { +// $content = trim($post->get('content')); +// if (empty($content)) { +// return errjson('请先等待生成关键词后再操作'); +// } +// $system = '你是SEO关键词清洗优化助手,严格遵守: +// 1. 核心词绝对不能修改、删除、替换; +// 2. 只剔除不通顺、重复、无意义、垃圾关键词; +// 3. 可优化前后修饰词,不改变核心; +// 4. 输出严格一行一个,无解释、无符号、无序号; +// 5. 只净化,不新增。'; - $prompt = "请清洗优化以下关键词:\n{$content}"; - } else { - $cateid = trim($post->get('cateid')); - $dim1 = trim($post->get('dim1')); - $new_dim1 = empty($dim1) ? "自行补充,与核心词高度关联" : $dim1; - $dim2 = trim($post->get('dim2')); +// $prompt = "请清洗优化以下关键词:\n{$content}"; +// } else { +// $cateid = trim($post->get('cateid')); +// $dim1 = trim($post->get('dim1')); +// $new_dim1 = empty($dim1) ? "自行补充,与核心词高度关联" : $dim1; +// $dim2 = trim($post->get('dim2')); - $core_words = explode("\n", $dim2); - $core_words = array_filter(array_map('trim', $core_words)); - $filter_str = implode('、', $core_words); - - $dim3 = trim($post->get('dim3')); - $new_dim3 = empty($dim3) ? "自行补充,与核心词高度关联" : $dim3;; - if (empty($cateid)) { - return errjson('请选择所属栏目'); - } - if(empty($dim2)){ - return errjson('请填写核心关键词'); - } - // AI 联想 - $system = '你是专业的SEO关键词生成助手,严格遵守: - 1. 核心词绝对不变; - 2. 根据核心词自动生成合理的前缀词+核心词+后缀词组合的关键词; - 3. 剔除不通顺、重复、无意义内容; - 4. 输出一行一个,无多余内容; - 5. 生成数量 7-12 个。'; +// $core_words = explode("\n", $dim2); +// $core_words = array_filter(array_map('trim', $core_words)); +// $filter_str = implode('、', $core_words); + +// $dim3 = trim($post->get('dim3')); +// $new_dim3 = empty($dim3) ? "自行补充,与核心词高度关联" : $dim3; + +// if (empty($cateid)) { +// return errjson('请选择所属栏目'); +// } +// if(empty($dim2)){ +// return errjson('请填写核心关键词'); +// } + +// // AI 联想 +// $system = '你是专业的SEO关键词生成助手,严格遵守: +// 1. 核心词绝对不变; +// 2. 根据核心词自动生成合理的前缀词+核心词+后缀词组合的关键词; +// 3. 剔除不通顺、重复、无意义内容; +// 4. 输出一行一个,无多余内容; +// 5. 生成数量 7-12 个。'; - $prompt = "前缀词:{$new_dim1} ,核心词:{$filter_str},后缀词:{$new_dim3}。请根据提供的前缀词、核心词、后缀词生成优质关键词"; - } - $openai->newsystem($system); - $res = $openai->completion($prompt); +// $prompt = "前缀词:{$new_dim1} ,核心词:{$filter_str},后缀词:{$new_dim3}。请根据提供的前缀词、核心词、后缀词生成优质关键词"; +// } - if (is_array($res) && !empty($res['content'])) { - return succjson(['data' => trim($res['content'])]); - } else { - return errjson('AI处理失败:' . $res); - } - } catch (\Exception $e) { - return errjson('接口异常:' . $e->getMessage()); +// // 发送请求 +// $openai->newsystem($system); +// $res = $openai->completion($prompt); + +// // 修复:统一处理返回值(字符串/数组都兼容) +// $resultContent = ''; +// if (is_array($res)) { +// $resultContent = isset($res['content']) ? trim($res['content']) : ''; +// } else { +// $resultContent = trim($res); +// } + +// if (!empty($resultContent)) { +// return succjson(['data' => $resultContent]); +// } else { +// return errjson('AI处理失败,未返回有效内容'); +// } + +// } catch (\Exception $e) { +// return errjson('接口异常:' . $e->getMessage()); +// } +// } +// } +public static function json_AIFunction() +{ + global $db; + $rsuser = verifyfast(); + $post = new \ciy\post(); + + $function_type = trim($post->get('param')); + + // 日志函数:把信息写到文件里 + $logPath = '/var/log/ai_debug.log'; + $writeLog = function ($msg) use ($logPath) { + $time = date('Y-m-d H:i:s'); + file_put_contents($logPath, "[{$time}] {$msg}\n", FILE_APPEND); + }; + + // 记录开始 + $writeLog("=== 开始执行AI联想 ==="); + + $aiConfig = [ + 'baseurl' => 'https://dashscope.aliyuncs.com/compatible-mode/v1', + 'aikey' => 'sk-0cd7b8c72ae04d049306e345f17c6790', + 'model' => 'qwen-turbo', + 'maxtoken' => 2000 + ]; + // ========================================================== + + $writeLog("配置加载完成,baseurl: " . $aiConfig['baseurl']); + + try { + // 1. 检查openai类是否存在 + if (!class_exists('\ciy\openai')) { + throw new \Exception("关键错误:\ciy\openai 类不存在!请检查文件是否加载"); } + $writeLog("openai类存在,准备实例化"); + + // 2. 实例化 + $openai = new \ciy\openai($aiConfig); + $writeLog("openai实例化成功"); + + // 3. 处理参数 + if ($function_type === '修改') { + $content = trim($post->get('content')); + if (empty($content)) { + return errjson('请先等待生成关键词后再操作'); + } + $system = '你是SEO关键词清洗优化助手,严格遵守: +1. 核心词绝对不能修改、删除、替换; +2. 只剔除不通顺、重复、无意义、垃圾关键词; +3. 可优化前后修饰词,不改变核心; +4. 输出严格一行一个,无解释、无符号、无序号; +5. 只净化,不新增。'; + $prompt = "请清洗优化以下关键词:\n{$content}"; + } else { + $cateid = trim($post->get('cateid')); + $dim1 = trim($post->get('dim1')); + $dim2 = trim($post->get('dim2')); + $dim3 = trim($post->get('dim3')); + + $new_dim1 = empty($dim1) ? "自行补充,与核心词高度关联" : $dim1; + $new_dim3 = empty($dim3) ? "自行补充,与核心词高度关联" : $dim3; + + $core_words = explode("\n", $dim2); + $core_words = array_filter(array_map('trim', $core_words)); + $filter_str = implode('、', $core_words); + + if (empty($cateid)) { + return errjson('请选择所属栏目'); + } + if (empty($dim2)) { + return errjson('请填写核心关键词'); + } + + $system = '你是专业的SEO关键词生成助手,严格遵守: +1. 核心词绝对不变; +2. 根据核心词自动生成合理的前缀词+核心词+后缀词组合的关键词; +3. 剔除不通顺、重复、无意义内容; +4. 输出一行一个,无多余内容; +5. 生成数量 7-12 个。'; + + $prompt = "前缀词:{$new_dim1},核心词:{$filter_str},后缀词:{$new_dim3}。请根据提供的内容生成优质关键词"; + } + $writeLog("参数处理完成,prompt长度:" . strlen($prompt)); + + // 4. 设置system并调用 + $openai->newsystem($system); + $writeLog("system设置完成"); + + $res = $openai->completion($prompt); + $writeLog("completion调用返回结果类型:" . gettype($res) . ",内容:" . json_encode($res)); + + // 5. 处理返回 + $resultContent = ''; + if (is_array($res)) { + $resultContent = isset($res['content']) ? trim($res['content']) : ''; + } elseif (is_string($res)) { + $resultContent = trim($res); + } + + if (!empty($resultContent)) { + $writeLog("成功获取内容,长度:" . strlen($resultContent)); + return succjson(['data' => $resultContent]); + } else { + throw new \Exception("AI处理失败,返回内容为空,原始结果:" . json_encode($res)); + } + + } catch (\Exception $e) { + // 把错误完整写入日志 + $errMsg = "异常捕获:" . $e->getMessage() . " 堆栈:" . $e->getTraceAsString(); + $writeLog($errMsg); + return errjson('接口异常:' . $e->getMessage()); } } +} \ No newline at end of file diff --git a/zciyphp/openai.php b/zciyphp/openai.php index f1ff7d7..c5f0ab7 100644 --- a/zciyphp/openai.php +++ b/zciyphp/openai.php @@ -96,7 +96,7 @@ class openai { $data['max_tokens'] = toint($this->aicfg['maxtoken']); if ($this->fp > -999) $data['frequency_penalty'] = $this->fp; - if ($this->pp > -999) + if ($pp > -999) $data['presence_penalty'] = $this->pp; if ($this->tt > -999) $data['temperature'] = $this->tt; @@ -119,17 +119,27 @@ class openai { ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + + // ====================== 修复:加了超时,不会再卡死!====================== + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); + // ===================================================================== + $response = curl_exec($ch); if ($this->debug) { savelogfile('openai', '--------------------------------'); savelogfile('openai', $response); savelogfile('openai', ''); } - curl_close($ch); + if ($response === false) { + $err = curl_error($ch); + $errno = curl_errno($ch); curl_close($ch); - return 'ERR: ' . curl_error($ch) . ' (' . curl_errno($ch) . ')'; + return 'ERR: '.$err.' ('.$errno.')'; } + curl_close($ch); + $json = json_decode($response, true); if (isset($json['error_msg'])) return 'ERR: ' . $json['error_msg']; @@ -159,31 +169,6 @@ class openai { if ($finish == 'length') { if ($isjson) { $message['content'] = self::fixjson($message['content']); - - //以下暂时AI能力有限 - // $context = mb_substr($content, -200, 200); - // $last_char = mb_substr($context, -1); - // $expected = ''; - // switch ($last_char) { - // case '{': $expected = '对象未闭合'; break; - // case '[': $expected = '数组未闭合'; break; - // case ':': $expected = '值未完成'; break; - // case ',': $expected = '需要下一个元素'; break; - // } - - // $tmp = <<messages[] = array('role' => 'user', 'content' => $tmp); } else { $resultcontent .= $message['content']; $this->messages[] = array('role' => 'user', 'content' => '请继续完成之前的对话'); @@ -242,6 +227,12 @@ class openai { ]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + + // ====================== 修复:加了超时 ====================== + curl_setopt($ch, CURLOPT_TIMEOUT, 10); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); + // ========================================================== + curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) use ($cb) { if ($this->debug) { savelogfile('openai', substr($data, 6, -2)); @@ -249,7 +240,7 @@ class openai { $cb($data); return strlen($data); }); - curl_exec($ch); + $response = curl_exec($ch); if (curl_errno($ch)) return '错误: ' . curl_error($ch); curl_close($ch); @@ -299,4 +290,4 @@ class openai { ); return $fixed; } -} +} \ No newline at end of file