From 9b9eec24c2c5448956f1f47841d38c27a7443886 Mon Sep 17 00:00:00 2001 From: wyn <1074145239@qq.com> Date: Thu, 16 Jul 2026 17:02:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=82=E8=80=83=E6=96=87=E7=8C=AE=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- application/api/controller/References.php | 3 +- .../common/ReferenceRelevanceCheckService.php | 59 ++++++++++--------- .../service/ReferenceRelevanceLlmService.php | 21 +++---- 3 files changed, 44 insertions(+), 39 deletions(-) diff --git a/application/api/controller/References.php b/application/api/controller/References.php index 165a278b..292e3de7 100644 --- a/application/api/controller/References.php +++ b/application/api/controller/References.php @@ -1504,8 +1504,7 @@ class References extends Base } /** - * 仅重跑某篇文章下 status=3(校对失败)的相关性记录(不清空,不抓摘要,不清洗文献内容) - * 联合引用组会整组重跑。 + * 仅重跑某篇文章下 status=3(校对失败)的相关性记录:先将 status 重置为 0,其余与 referenceRelevanceCheckRecheckPendingAI 相同。 * POST: p_article_id */ public function referenceRelevanceCheckRecheckFailedAI() diff --git a/application/common/ReferenceRelevanceCheckService.php b/application/common/ReferenceRelevanceCheckService.php index 788bdf9a..9376932b 100644 --- a/application/common/ReferenceRelevanceCheckService.php +++ b/application/common/ReferenceRelevanceCheckService.php @@ -205,11 +205,10 @@ class ReferenceRelevanceCheckService } /** - * 仅重新校对某篇文章下 status=3(失败)的记录;不刷新 refer_text / 文献摘要,只重置结果字段后入队。 - * 联合引用组会整组重跑(与 enqueueRecheckFailedByPReferIdWithGroup 一致)。 + * 仅重新校对某篇文章下 status=3(失败)的记录:先将 status 重置为 0,其余与 recheckPendingOnlyByArticle 相同。 * * @param int $pArticleId - * @return array{p_article_id:int,reset:int,queued:int,check_ids:int[],transport:string,queue:string} + * @return array{p_article_id:int,queued:int,check_ids:int[],transport:string,queue:string} */ public function recheckFailedOnlyByArticle($pArticleId) { @@ -222,12 +221,12 @@ class ReferenceRelevanceCheckService $rows = Db::name('article_reference_relevance_check_result') ->where('p_article_id', $pArticleId) ->where('status', self::RECORD_FAILED) + ->field('id,reference_no,am_id,text_start') ->order('reference_no asc,am_id asc,text_start asc,id asc') ->select(); if (empty($rows)) { return [ 'p_article_id' => $pArticleId, - 'reset' => 0, 'queued' => 0, 'check_ids' => [], 'transport' => self::TRANSPORT_RABBITMQ, @@ -235,26 +234,14 @@ class ReferenceRelevanceCheckService ]; } - $now = date('Y-m-d H:i:s'); - $resetFields = $this->relevanceCheckResultResetFields([ - 'updated_at' => $now, - ]); - - $targetRows = []; - foreach ($rows as $row) { - $groupRows = $this->findCitationGroupRows($row); - foreach ($groupRows as $gr) { - $checkId = $this->resolveCheckRowId($gr); - if ($checkId > 0) { - $targetRows[$checkId] = $gr; - } - } - } - $pendingJobs = []; - foreach ($targetRows as $row) { - $checkId = $this->resolveCheckRowId($row); - Db::name('article_reference_relevance_check_result')->where('id', $checkId)->update($resetFields); + $checkIds = []; + foreach ($rows as $row) { + $checkId = intval($row['id']); + if ($checkId <= 0) { + continue; + } + $checkIds[] = $checkId; $pendingJobs[] = [ 'check_id' => $checkId, 'reference_no' => intval($row['reference_no']), @@ -262,14 +249,32 @@ class ReferenceRelevanceCheckService 'text_start' => intval($row['text_start']), ]; } + if (empty($checkIds)) { + return [ + 'p_article_id' => $pArticleId, + 'queued' => 0, + 'check_ids' => [], + 'transport' => self::TRANSPORT_RABBITMQ, + 'queue' => self::TRANSPORT_RABBITMQ, + ]; + } - $checkIds = $this->enqueueChecksSortedByReferenceNo($pendingJobs, $pArticleId, 'recheck_failed'); + Db::name('article_reference_relevance_check_result') + ->whereIn('id', $checkIds) + ->update([ + 'status' => self::RECORD_PENDING, + 'queue_status' => self::QUEUE_PENDING, + 'retry_count' => 0, + 'error_msg' => '', + 'updated_at' => date('Y-m-d H:i:s'), + ]); + + $queuedIds = $this->enqueueChecksSortedByReferenceNo($pendingJobs, $pArticleId, 'recheck_failed'); return [ 'p_article_id' => $pArticleId, - 'reset' => count($targetRows), - 'queued' => count($checkIds), - 'check_ids' => $checkIds, + 'queued' => count($queuedIds), + 'check_ids' => $queuedIds, 'transport' => self::TRANSPORT_RABBITMQ, 'queue' => self::TRANSPORT_RABBITMQ, ]; diff --git a/application/common/service/ReferenceRelevanceLlmService.php b/application/common/service/ReferenceRelevanceLlmService.php index c8d00878..219cff23 100644 --- a/application/common/service/ReferenceRelevanceLlmService.php +++ b/application/common/service/ReferenceRelevanceLlmService.php @@ -464,7 +464,7 @@ Claim 具体内容见顶层 `claims`,combined_reason **只用字母指代**( "is_relevant": 0, "relevance_score": 0.45, "reason": "系统综述,主语一致。Claim覆盖:A✔ B✔ C部分 D✘。类型部分匹配。因缺 D 且 C 仅背景,未达 0.65,故 0.45。", - "author_comment": "该文献与正文主张仅部分匹配,仍缺关键论点支撑。建议补充更直接覆盖核心结论的参考文献。" + "author_comment": "编辑意见:该文献与正文主张仅部分对应,关键论点仍缺直接证据。请改引更能支撑核心结论的文献,或补充说明引用依据。" }, { "reference_no": 2, @@ -478,8 +478,8 @@ Claim 具体内容见顶层 `claims`,combined_reason **只用字母指代**( **顶层 claims**:本引用组共用,只写一次;键为 A/B/C…(按实际拆解数量),值为各 Claim 中文具体内容。 **results 每条仅含**:reference_no、is_relevant、relevance_score、reason、author_comment。 -`author_comment` 规则:当 `relevance_score <= 0.65` 时必须生成(中文、礼貌、适合展示给作者、可执行,≤90字);当 `relevance_score > 0.65` 时必须返回空字符串 `""`。 -注意:`author_comment` 禁止出现 A/B/C/D、✔/✘、"Claim覆盖"、具体分值(如 0.65)等技术表达,需改写为作者易读总结。 +`author_comment` 规则:当 `relevance_score <= 0.65` 时必须生成(中文、**以期刊编辑审稿口吻**、礼貌可执行,**80–100字**);当 `relevance_score > 0.65` 时必须返回空字符串 `""`。 +注意:`author_comment` 禁止出现 A/B/C/D、✔/✘、"Claim覆盖"、具体分值(如 0.65)等技术表达,需改写为作者易读的编辑批注。 **禁止**在 results 各条中写 combined_relevance_score、combined_reason、cite_group_refs、claims。 PROMPT; } @@ -502,7 +502,7 @@ PROMPT; if ($abstractText !== '') { $parts[] = "【文献摘要/清洗后内容(Europe PMC·PubMed·Crossref·PDF)】\n" . $abstractText; } - $tail = '请严格按六步标准校对流程执行:①提取Claim→②提取文献证据→③Claim Mapping(✔/部分/✘)→④计算覆盖率→⑤判断支持类型→⑥输出分值与理由。先在 JSON 顶层 claims 写出各 Claim 具体内容(多事实背景句须拆出比较型/成因型/进展型/数据型独立 Claim),再对每篇文献给出单条 relevance_score(弱相关文献不得因联合抬高),最后写顶层 combined_relevance_score 与 combined_reason。results 每条只写 reference_no、is_relevant、relevance_score、reason、author_comment。author_comment 规则:score<=0.65 时输出给作者看的中文批注(礼貌、可执行,≤90字);score>0.65 时固定空字符串;author_comment 禁止出现 A/B/C/D、✔/✘、Claim覆盖、具体分值。禁止 reason_en、combined_reason_en、relevance_level、relevance_role、combined_is_relevant 等多余字段。'; + $tail = '请严格按六步标准校对流程执行:①提取Claim→②提取文献证据→③Claim Mapping(✔/部分/✘)→④计算覆盖率→⑤判断支持类型→⑥输出分值与理由。先在 JSON 顶层 claims 写出各 Claim 具体内容(多事实背景句须拆出比较型/成因型/进展型/数据型独立 Claim),再对每篇文献给出单条 relevance_score(弱相关文献不得因联合抬高),最后写顶层 combined_relevance_score 与 combined_reason。results 每条只写 reference_no、is_relevant、relevance_score、reason、author_comment。author_comment 规则:score<=0.65 时输出以期刊编辑审稿口吻的中文批注(礼貌、可执行,80–100字);score>0.65 时固定空字符串;author_comment 禁止出现 A/B/C/D、✔/✘、Claim覆盖、具体分值。禁止 reason_en、combined_reason_en、relevance_level、relevance_role、combined_is_relevant 等多余字段。'; if ($this->hasMixedReferTypes($referTypeMap)) { $tail .= ' 注意:本组为图书与期刊混排引用,务必按上方【各编号文献类型标注】分轨判断——图书/教材走「书目推断」轨(据书名、副标题、作者、ISBN、出版社判断主题,缺摘要不得默认 0.25);期刊/原始研究走「摘要核对」轨(据摘要/清洗内容逐项核对 claim)。同组内两类分别按各自标准独立打分,切勿用同一把尺子。'; } elseif ($this->allReferType($referTypeMap, 'book')) { @@ -1612,27 +1612,28 @@ PROMPT; if ($authorComment !== '') { $authorComment = $this->sanitizeAuthorCommentText($authorComment); if ($authorComment !== '') { - return mb_substr($authorComment, 0, 120); + return mb_substr($authorComment, 0, 100); } } + $fallback = '编辑意见:该条参考文献与正文匹配度有限,关键论点仍缺直接证据。请改引更能支撑核心结论的文献,或补充说明引用依据。'; $reason = trim((string)$reason); if ($reason === '') { - return '该条参考文献与正文匹配度有限,建议补充更直接支持该论点的文献。'; + return $fallback; } - // 去掉显式分数结论,保留给作者可读的改进建议 + // 去掉显式分数结论,保留给作者可读的编辑批注 $reason = preg_replace('/Claim覆盖[::].*/u', '', $reason); $reason = preg_replace('/故\s*(?:联合分?)?\s*[01](?:\.\d+)?[。.]?/u', '', $reason); $reason = trim((string)$reason); if ($reason === '') { - return '该条参考文献与正文匹配度有限,建议补充更直接支持该论点的文献。'; + return $fallback; } $reason = $this->sanitizeAuthorCommentText($reason); if ($reason === '') { - return '该条参考文献与正文匹配度有限,建议补充更直接支持该论点的文献。'; + return $fallback; } - return mb_substr('建议:' . $reason, 0, 120); + return mb_substr('编辑意见:' . $reason, 0, 100); } private function sanitizeAuthorCommentText($text)