Files
tougao/application/api/controller/Aitest.php
2025-07-04 15:09:09 +08:00

265 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\api\controller;
use app\api\controller\Base;
use think\Db;
use app\common\OpenAi;
use app\common\QueueJob;
/**
* @title AI审核文章
* @description 对接OPENAI接口
*/
class Aitest extends Base
{
/**
* @title AI审核文章
* @param article_id 文章ID
* @param abstrart 摘要
* @param keywords 关键词
* @param model 接口模型
* @param stream 是否流式输出 true是false否
*/
public function review(){
//获取参数
$aParam = $this->request->post();
$iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id'];
if(empty($iArticleId)){
return json_encode(array('status' => 2,'msg' => 'Please select an article' ));
}
//查询文章
$aWhere = ['article_id' => $aParam['article_id']];
$aArticle = Db::name('article')->field('article_id,abstrart,keywords,journal_id,title,state')->where('article_id',$aParam['article_id'])->find();
if(empty($aArticle)){
return json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ));
}
//获取文章评测内容
$aAiReview = Db::table('t_article_ai_review')->where('article_id',$aParam['article_id'])->find();
if(!empty($aAiReview)){
return json_encode(array('status' => 1,'msg' => 'AI has been reviewed','data' => $aAiReview));
}
//根据期刊ID查询期刊信息
$aJournal = Db::table('t_journal')->field('zname,scope,issn,journal_id')->where('journal_id',$aArticle['journal_id'])->find();
if(empty($aJournal)){
return json_encode(array('status' => 4,'msg' => 'This article is not associated with a journal' ));
}
//实例化公共方法
$oOpenAi = new OpenAi;
if($aArticle['state'] > 4 ){
//查询文章内容
$aWhere['type'] = 0;
$aWhere['content'] = ['<>',''];
$aWhere['state'] = 0;
$aArticleMain = Db::table('t_article_main')->where($aWhere)->column('content');
//查询参考文献
$aWhere = ['state' => ['in',[0,2]],'article_id' => $iArticleId];
$aProductionArticle = Db::name('production_article')->field('p_article_id')->where($aWhere)->find();
if(!empty($aProductionArticle)){
$aWhere = ['state' => 0,'p_article_id' => $aProductionArticle['p_article_id']];
$aRefer = Db::name('production_article_refer')->field('refer_content')->where($aWhere)->column('refer_content');
$aArticleMain = empty($aRefer) ? $aArticleMain : array_merge($aRefer,$aArticleMain);
}
}else{
$aFile = json_decode($oOpenAi->getFileContent(['article_id' => $iArticleId]),true);
$aFile = empty($aFile['data']) ? [] : $aFile['data'];
$aArticleMain = empty($aFile['mains']) ? [] : $aFile['mains'];
}
//获取提问AI的内容
$aSearch = [];
$title = empty($aArticle['title']) ? '' : $aArticle['title'];//简介
$abstrart = empty($aArticle['abstrart']) ? '' : $aArticle['abstrart'];//简介
$keywords = empty($aArticle['keywords']) ? '' : $aArticle['keywords'];//关键词
//文章内容
$sContent = '文章标题:'.$title.'文章摘要:'.$abstrart.'文章关键词:'.$keywords."文章内容";
$sContent .= empty($aArticleMain) ? '' : implode('', array_unique($aArticleMain));
$sContent = preg_replace('/[\r\n]+/', '', $sContent);
$sContent = preg_replace('/ +/', ' ', $sContent); // 合并连续空格
$aSearch['{content}'] = $sContent;
$aSearch['{journal_name}'] = empty($aJournal['zname']) ? '' : $aJournal['zname'];//期刊名
if($aJournal['journal_id'] == 1){
$aSearch['{journal_name}'] = '传统医学研究';
}
//查询期刊内容
$aJournalPaperArt = json_decode($oOpenAi->getJournalPaperArt($aJournal),true);
$sJournalContent = empty($aJournalPaperArt['data']) ? '' : implode('', $aJournalPaperArt['data']);
$sJournalContent = empty($sJournalContent) ? $aJournal['scope'] : $sJournalContent;
$aSearch['{scope}'] = $sJournalContent;//期刊范围
//获取问答内容
$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);
echo '<pre>';var_dump($aResult);exit;
$iStatus = empty($aResult['status']) ? 0 : $aResult['status'];
if($iStatus != 1){
return json_encode($aResult);
}
//处理返回信息
$aData = empty($aResult['data']) ? [] : $aResult['data'];
if(empty($aData)){
return json_encode(['status' => 6,'msg' => 'OPENAI returns empty content']);
}
if(empty($aData)){
return json_encode(array('status' => 10,'msg' => 'OPENAI did not return data'));
}
//执行数据入库
$aData['article_id'] = $iArticleId;
$aResult = $this->addAiReview($aData);
return json_encode($aResult);
}
/**
* 保留内容中的文字和图片移除其他HTML标签
* @param string $content 原始富文本内容
* @return string 处理后的内容
*/
private function keepTextAndImages($content)
{
if (empty($content)) {
return '';
}
// 步骤1保留<img>标签和文本移除其他所有HTML标签
// 使用strip_tags保留<img>标签,其他标签全部移除
// $filtered = strip_tags($content, '<img>');
// 步骤2处理特殊字符和冗余空白
$filtered = html_entity_decode($content); // 解码HTML实体如&nbsp;
$filtered = preg_replace('/\s+/', ' ', $filtered); // 合并连续空白为单个空格
$filtered = trim($filtered); // 去除首尾空格
// 步骤3修复可能被破坏的<img>标签格式(如属性缺失引号)
$filtered = preg_replace('/<img ([^>]+)>/i', '<img $1>', $filtered);
$filtered = preg_replace('/src=([^\s>]+)/i', 'src="$1"', $filtered); // 确保src属性带引号
return $filtered;
}
/**
* @title AI审核内容入库
* @param article_id 文章ID
* @param content 内容
*/
protected function addAiReview($aParam = array()){
//返回数组
$aResult = ['status' => 1,'msg' => 'AI review successful'];
//必填参数验证
$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){
$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(empty($aInsert['article_id'])){
return ['status' => 2,'msg' => 'Please select the article to be reviewed'];
}
if(!Db::name('article_ai_review')->insert($aInsert)){
$aResult = ['status' => 2,'msg' => 'Failed to add AI audit content'];
}
$aResult['data'] = $aInsert;
return $aResult;
}
/**
* @title 文章AI审核内容查询
* @param article_id 文章ID
*/
public function get(){
//获取参数
$aParam = $this->request->post();
if(empty($aParam['article_id'])){
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)){
return json_encode(array('status' => 3,'msg' => 'No articles requiring review were found' ));
}
//查询文章审核内容
$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));
}
/**
* 批量处理待审核的文章自动推荐审稿人
*
* @return void
*/
public function recommendedReviewer(){
//获取参数
$aParam = $this->request->post();
if(empty($aParam['article_id'])){
return json_encode(array('status' => 2,'msg' => 'Please select an article' ));
}
// //查询条件
// $aWhere = ['article_id' => $aParam['article_id']];
// $aArticle = Db::name('article')->field('article_id,accept_sn')->where($aWhere)->limit(1)->select();
// if(empty($aArticle)){
// exit('未查询到需要处理的待审核的文章');
// }
//数据处理
$sMsg = '';
// foreach ($aArticle as $key => $value) {
// $iArticleId = empty($value['article_id']) ? 0 : $value['article_id'];
// if(empty($iArticleId)){
// continue;
// }
// $sQueueId = \think\Queue::push('app\api\job\ArticleAiCreateContent@fire',$aParam, 'ArticleAiCreateContent');
// $sQueueId = \think\Queue::push('app\api\job\RecommendReviewer@fire',$aParam, 'RecommendReviewer');
// $sQueueId = \think\Queue::push('app\api\job\RelatedArticle@fire',$aParam, 'RelatedArticle');
// $sQueueId = \think\Queue::push('app\api\job\ReviewerScore@fire',$aParam, 'ReviewerScore');
// $sQueueId = \think\Queue::push('app\api\job\RevisionReviewer@fire',$aParam, 'RevisionReviewer');
// $sQueueId = \think\Queue::push('app\api\job\SendRelatedArticleEmail@fire',$aParam, 'SendRelatedArticleEmail');
// $sQueueId = \think\Queue::push('app\api\job\SendReviewEmail@fire',$aParam, 'SendReviewEmail');
// $sQueueId = \think\Queue::push('app\api\job\WechatDraft@fire',$aParam, 'WechatDraft');
// $sQueueId = \think\Queue::push('app\api\job\WechatDraftPublish@fire',$aParam, 'WechatDraftPublish');
// $sQueueId = \think\Queue::push('app\api\job\WechatMaterial@fire',$aParam, 'WechatMaterial');
// $sQueueId = \think\Queue::push('app\api\job\WechatQueryStatus@fire',$aParam, 'WechatQueryStatus');
$sQueueId = \think\Queue::push('app\api\job\RecommendReviewer@fire',$aParam, 'RecommendReviewer');
var_dump($sQueueId);exit;
// if($sQueueId === false){
// $sMsg .= '文章入队失败,文章ID:'.$value['article_id'].'['.$value['accept_sn']."]\n";
// }else{
// $sMsg .= '文章入队成功,文章ID:'.$value['article_id'].'['.$value['accept_sn']."]\n";
// }
// }
exit($sMsg);
}
}