Просмотр исходного кода

the batch_size of cal title quality score decreases from 20 to 10

luojunhui 5 дней назад
Родитель
Сommit
799d79b7c8

+ 9 - 3
src/domains/content_quality/_const.py

@@ -44,7 +44,8 @@ class ContentQualityConst:
     # LLM 参数
     # ═══════════════════════════════════════════════════════════════
 
-    LLM_BATCH_SIZE = 20
+    LLM_BATCH_SIZE = 20  # 品类识别:ID 显式绑定,20 条安全
+    TITLE_BATCH_SIZE = 10  # 标题评分:对齐精度要求高,控制在 10 条/批
     LLM_INTERVAL_SEC = 2
 
     # ═══════════════════════════════════════════════════════════════
@@ -69,8 +70,13 @@ class ContentQualityConst:
 7.阵营对立:7分
 8.军事危机暗示:5分
 
-基于以上的爆款标题特征分评分标准,如果下列标题符合某个特征的、那么就加上这个特征对应的权重,标题最终的得分是各个特征分的总和。请直接输出最终的分数,不用给任何理由和描述、解释。
-待评分的标题为:
+基于以上的爆款标题特征分评分标准,如果下列标题符合某个特征的、那么就加上这个特征对应的权重,标题最终的得分是各个特征分的总和。如果标题完全不符合任何特征,则分数为0。
+
+输入是一个 LIST,每个元素是一个元组,元组的第一个元素是标题的 ID,第二个元素是标题的文本。
+输出格式为 JSON 对象,key 为标题 id(数字),value 为评分(0-100 的整数)。
+仅输出 JSON,不要 markdown 包裹,不要任何其他内容。
+
+输入的 LIST 是:
 {title_list}"""
 
     PROMPT_TITLE_CATEGORY = """

+ 20 - 15
src/domains/content_quality/_utils.py

@@ -1,7 +1,6 @@
 """内容质量评估工具函数 —— Prompt 构建 + LLM 响应解析"""
 
 import hashlib
-import re
 import logging
 from typing import Dict, List
 
@@ -22,10 +21,10 @@ def md5(text: str) -> str:
 
 
 def build_title_quality_prompt(titles: List[Dict]) -> str:
-    """构造标题质量评分 prompt,每行一个标题"""
-    lines = [t["title"] for t in titles]
+    """构造标题质量评分 prompt,格式: [(id, title), ...] 元组列表"""
+    tuples = [(t["id"], t["title"]) for t in titles]
     return ContentQualityConst.PROMPT_TITLE_QUALITY.format(
-        title_list="\n".join(lines),
+        title_list=str(tuples),
     )
 
 
@@ -46,7 +45,10 @@ def parse_title_quality_response(
     raw: str | None,
     batch_titles: List[Dict],
 ) -> List[Dict]:
-    """解析 prompt1 返回值:LLM 按行输出纯数字分数,按顺序对应输入标题
+    """解析标题质量评分返回值:{id: score} JSON 对象,key 为标题 id
+
+    与品类识别 prompt 对齐——ID 显式绑定,消除位置依赖导致的分数错位。
+    如果某条标题在 LLM 响应中缺失 key 或值非法,则静默跳过(不影响同批次其他标题)。
 
     返回: [{"id": 1, "score": 85}, ...]
     """
@@ -55,18 +57,21 @@ def parse_title_quality_response(
         logger.warning("LLM 标题质量返回为空")
         return result
 
-    # 从文本中提取所有数字
-    scores = re.findall(r"\d+", raw)
-    if not scores:
-        logger.warning("LLM 标题质量未提取到分数: %s", raw[:200])
+    parsed = safe_json_parse(raw)
+    if not isinstance(parsed, dict):
+        logger.warning("LLM 标题质量返回非 JSON 对象: %s", raw[:200])
         return result
 
-    for i, s in enumerate(scores):
-        if i >= len(batch_titles):
-            break
-        score = int(s)
-        if 0 <= score <= 100:
-            result.append({"id": batch_titles[i]["id"], "score": score})
+    for t in batch_titles:
+        score_val = parsed.get(str(t["id"]))
+        if score_val is None:
+            continue
+        try:
+            score = int(score_val)
+            if 0 <= score <= 100:
+                result.append({"id": t["id"], "score": score})
+        except (ValueError, TypeError):
+            pass
 
     return result
 

+ 2 - 2
src/domains/content_quality/article_quality_title.py

@@ -47,8 +47,8 @@ class ArticleQualityTitle(ContentQualityConst):
 
         # 拆批
         batches = []
-        for start in range(0, len(rows), self.LLM_BATCH_SIZE):
-            batch = rows[start : start + self.LLM_BATCH_SIZE]
+        for start in range(0, len(rows), self.TITLE_BATCH_SIZE):
+            batch = rows[start : start + self.TITLE_BATCH_SIZE]
             batch_ids = [r["id"] for r in batch]
             titles = [{"id": r["id"], "title": r["title"]} for r in batch]
             prompt = build_title_quality_prompt(titles)