diff --git a/application/api/controller/Aireview.php b/application/api/controller/Aireview.php index 32116d9..6f32817 100644 --- a/application/api/controller/Aireview.php +++ b/application/api/controller/Aireview.php @@ -4,7 +4,7 @@ namespace app\api\controller; use app\api\controller\Base; use think\Db; - +use app\common\OpenAi; /** * @title AI审核文章 * @description 对接OPENAI接口 @@ -12,69 +12,6 @@ use think\Db; class Aireview extends Base { - protected $sApiKey; - protected $proxy; - protected $sUrl; - protected $curl; - protected $sResponesData; - protected $sError; - protected $timeout = 60; - - public function __construct(\think\Request $request = null) { - // 从配置读取敏感信息(非硬编码) - $this->sApiKey = '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'; - $this->proxy = ''; - $this->sUrl = 'https://api.openai.com/v1/chat/completions'; - - parent::__construct($request); - } - - /** - * CURL 发送请求到 OpenAI - * @param $messages 内容 - * @param $model 模型类型 - */ - protected function curlOpenAI($messages, $model = 'gpt-4o'){ - - $sUrl = $this->sUrl; - - $data = [ - 'model' => $model, - 'messages' => $messages, - 'temperature' => 0.7 - ]; - - $this->curl = curl_init(); - - - // 通用配置 - curl_setopt($this->curl, CURLOPT_URL, $sUrl); - // 设置头信息 - curl_setopt($this->curl, CURLOPT_HTTPHEADER, [ - 'Content-Type: application/json', - 'Authorization: Bearer ' . $this->sApiKey - ]); - curl_setopt($this->curl, CURLOPT_PROXY,$this->proxy); - curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER,true); - curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST,2); - curl_setopt($this->curl, CURLOPT_POST, true); //设置为POST方式 - curl_setopt($this->curl, CURLOPT_POSTFIELDS,json_encode($data)); - curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, TRUE) ; // 获取数据返回 - // curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout); - - $result = curl_exec($this->curl); - - //请求失败 - if (curl_errno($this->curl)){ - $this->sError = curl_errno($this->curl); - curl_close($this->curl); - return FALSE; - } - $this->sResponesData = json_decode($result); - curl_close($this->curl); - return TRUE; - } - /** * @title AI审核文章 * @param article_id 文章ID @@ -83,82 +20,72 @@ class Aireview extends Base * @param model 接口模型 * @param stream 是否流式输出 true是false否 */ - public function review(){ + public function review(){ //获取参数 $aParam = $this->request->post(); - if(empty($aParam['article_id'])){ - exit(json_encode(array('status' => 2,'msg' => 'Please select an article' ))); + $iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id']; + if(empty($iArticleId)){ + return json_encode(array('status' => 2,'msg' => 'Please select an article' )); } - // if(empty($aParam['abstrart'])){ - // exit(json_encode(array('status' => 2,'msg' => 'abstrart cannot be empty' ))); - // } - // if(empty($aParam['keywords'])){ - // exit(json_encode(array('status' => 2,'msg' => 'keywords cannot be empty' ))); - // } //查询文章 - $aArticle = Db::table('t_article')->field('article_id,abstrart,keywords,journal_id')->where('article_id',$aParam['article_id'])->find(); + $aWhere = ['article_id' => $aParam['article_id']]; + $aArticle = Db::name('article')->field('article_id,abstrart,keywords,journal_id')->where('article_id',$aParam['article_id'])->find(); if(empty($aArticle)){ - exit(json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ))); + return json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' )); } - //获取文章评测内容 - $aAiReview = Db::table('t_article_ai_review')->field('article_id,content')->where('article_id',$aParam['article_id'])->find(); + $aAiReview = Db::table('t_article_ai_review')->where('article_id',$aParam['article_id'])->find(); if(!empty($aAiReview)){ - exit(json_encode(array('status' => 1,'msg' => 'AI has been reviewed','data' => $aAiReview))); + return json_encode(array('status' => 1,'msg' => 'AI has been reviewed','data' => $aAiReview)); } - $aParam['abstrart'] = empty($aParam['abstrart']) ? $aArticle['abstrart'] : $aParam['abstrart'];//简介 - $aParam['keywords'] = empty($aParam['keywords']) ? $aArticle['keywords'] : $aParam['keywords'];//关键词 - - //根据期刊ID查询期刊信息 $aJournal = Db::table('t_journal')->field('zname')->where('journal_id',$aArticle['journal_id'])->find(); if(empty($aJournal)){ - exit(json_encode(array('status' => 4,'msg' => 'This article is not associated with a journal' ))); - } - //组织参数 - $sContent = ''; - $sContent .= '摘要:'.$aParam['abstrart']; - $sContent .= '关键词:'.$aParam['keywords']; - $sContent .= '以上这篇文章是否符合'.$aJournal['zname'].'?是否具有科学前沿性和创新性?请返回中文解释'; - $messages = [ - [ - 'role' => 'user', //角色:platform:平台;developer:开发者;user:用户;guideline:模型规范“指南”部分:连接:https://model-spec.openai.com/2025-02-12.html#chain_of_command - 'content' => $sContent - ] - ]; - //请求接口 - $sModel = $aParam['api_model'] ?? 'gpt-4o'; - $result = $this->curlOpenAI($messages,$sModel); - if($result == FALSE){ - exit(json_encode(array('status' => 4,'msg' => 'Interface request failed'.$this->sError))); + return json_encode(array('status' => 4,'msg' => 'This article is not associated with a journal' )); } + //查询文章内容 + $aWhere['type'] = 0; + $aWhere['content'] = ['<>','']; + $aWhere['state'] = 0; + $aArticleMain = Db::table('t_article_main')->where($aWhere)->column('content'); + + //获取提问AI的内容 + $aSearch = []; + $aSearch['{abstrart}'] = empty($aArticle['abstrart']) ? '' : $aArticle['abstrart'];//简介 + $aSearch['{keywords}'] = empty($aArticle['keywords']) ? '' : $aArticle['keywords'];//关键词 + $aSearch['{content}'] = empty($aArticleMain) ? '' : strip_tags(implode('', array_unique($aArticleMain)));//文章内容 + $aSearch['{journal_name}'] = empty($aJournal['zname']) ? '' : $aJournal['zname'];//期刊名 + //获取问答内容 + $oOpenAi = new OpenAi; + $aMessage = $oOpenAi->buildReviewArticlePrompt($aSearch); + if(empty($aMessage)){ + return json_encode(['status' => 5,'msg' => 'AI Q&A content not obtained']); + } + + //请求OPENAI接口 + $aParam = ['messages' => $aMessage,'model' => empty($aParam['api_model']) ? 'gpt-4.1' : $aParam['api_model']]; + $aResult = json_decode($oOpenAi->curlOpenAI($aParam),true); + $iStatus = empty($aResult['status']) ? 0 : $aResult['status']; + if($iStatus != 1){ + return json_encode($aResult); + } //处理返回信息 - $data = $this->sResponesData; - if(!is_object($data)){ - exit(json_encode(array('status' => 5,'msg' => 'There is a misunderstanding in the data returned by the interface'))); + $aData = empty($aResult['data']) ? [] : $aResult['data']; + if(empty($aData)){ + return json_encode(['status' => 6,'msg' => 'OPENAI returns empty content']); } - $data = object_to_array($data); - $aChoices = $data['choices'] ?? []; - if(empty($aChoices)){ - exit(json_encode(array('status' => 6,'msg' => 'OPENAI did not return data'))); + if(empty($aData)){ + return json_encode(array('status' => 10,'msg' => 'OPENAI did not return data')); } - $aChoicesInfo = $aChoices[0] ?? []; - $aMessage = $aChoicesInfo['message'] ?? []; - if(empty($aMessage['content'])){ - exit(json_encode(array('status' => 7,'msg' => 'OPENAI returns empty data'))); - } - //执行数据入库 - $param = []; - $param['content'] = addslashes($aMessage['content']); - $param['article_id'] = $aParam['article_id']; - $aResult = $this->addAiReview($param); - exit(json_encode($aResult)); + $aData['article_id'] = $iArticleId; + $aResult = $this->addAiReview($aData); + return json_encode($aResult); } @@ -171,25 +98,40 @@ class Aireview extends Base protected function addAiReview($aParam = array()){ //返回数组 - $aResult = ['status' => 1,'msg' => 'AI review successful','data' => $aParam]; + $aResult = ['status' => 1,'msg' => 'AI review successful']; //必填参数验证 - $aFields = ['article_id','content']; - $bStatus = true; + $aFields = ['journal_scope','attribute','contradiction','unreasonable','ethics','academic','conclusion','fund_number','hotspot','submit_direction','overall_evaluation','article_id','references_past_three','references_past_five','references_ratio_JCR1','references_ratio_JCR2','registration_assessment','cite_rate']; + $aInsert = ['create_time' => date('Y-m-d H:i:s')]; foreach($aFields as $val){ - if(empty($aParam[$val])){ - $aResult = ['status' => 2,'msg' => $val.'cannot be empty']; - $bStatus = false; - break; + $aValue = empty($aParam[$val]) ? [] : $aParam[$val]; + if(!isset($aValue)){ + continue; + } + if(is_array($aValue)){ + foreach ($aValue as $key => $value) { + $sField = $val.'_'.$key; + $aInsert[$sField] = empty($value) ? '' : addslashes($value); + } + }else{ + $aInsert[$val] = empty($aValue) ? '' : addslashes($aValue); } } - if($bStatus == false){ - return $aResult; - } //执行入库 - $aParam['create_time'] = date('Y-m-d H:i:s'); - if(!Db::name('article_ai_review')->insert($aParam)){ + if(empty($aInsert['article_id'])){ + return ['status' => 2,'msg' => 'Please select the article to be reviewed']; + } + + //判断是否生成 + $aAiReview = Db::table('t_article_ai_review')->where('article_id',$aInsert['article_id'])->find(); + if(!empty($aAiReview)){ + return json_encode(array('status' => 1,'msg' => 'AI has been reviewed','data' => $aAiReview)); + } + + $aInsert['content'] = $aInsert['article_id']; + if(!Db::name('article_ai_review')->insert($aInsert)){ $aResult = ['status' => 2,'msg' => 'Failed to add AI audit content']; } + $aResult['data'] = $aInsert; return $aResult; } @@ -202,42 +144,16 @@ class Aireview extends Base //获取参数 $aParam = $this->request->post(); if(empty($aParam['article_id'])){ - exit(json_encode(array('status' => 2,'msg' => 'Please select an article' ))); + return json_encode(array('status' => 2,'msg' => 'Please select an article' )); } //查询文章 $aArticle = Db::table('t_article')->field('article_id')->where('article_id',$aParam['article_id'])->find(); if(empty($aArticle)){ - exit(json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ))); + return json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' )); } //查询文章审核内容 - $aAiReview = Db::table('t_article_ai_review')->field('content')->where('article_id',$aParam['article_id'])->find(); - exit(json_encode(array('status' => 1,'msg' => 'Successfully obtained article review content','data' => $aAiReview))); - } - - public function test(){ - //获取参数 - $aParam = $this->request->post(); - if(empty($aParam['content'])){ - exit(json_encode(array('status' => 2,'msg' => '请输入需要验证的字符串' ))); - } - if(!$this->checkMinChars($aParam['content'],200)){ - exit(json_encode(array('status' => 3,'msg' => '字符串长度未满足配置' ))); - } - exit(json_encode(array('status' => 1,'msg' => '验证成功' ))); - } - /** - * 验证字符长度 - * @param $str 字符串 - * @param $num 字符长度 - * @return void - */ - private function checkMinChars($str = '',$num = 200) { - // 过滤非汉字和英文的字符(保留汉字、大小写字母) - $filteredStr = preg_replace('/[^\x{4e00}-\x{9fa5}a-zA-Z0-9]/u', '', $str); - - // 计算有效字符总数(汉字按1个字符计,英文和数字同理) - $total = mb_strlen($filteredStr, 'UTF-8'); - return $total >= $num; + $aAiReview = Db::table('t_article_ai_review')->where('article_id',$aParam['article_id'])->find(); + return json_encode(array('status' => 1,'msg' => 'Successfully obtained article review content','data' => $aAiReview)); } }