jihuaqiang 4 месяцев назад
Родитель
Сommit
e0d1e8f0f9
2 измененных файлов с 244 добавлено и 25 удалено
  1. 48 21
      src/agent/query_agent.py
  2. 196 4
      src/tools/prompts.py

+ 48 - 21
src/agent/query_agent.py

@@ -9,7 +9,9 @@ import json
 from ..tools.prompts import (
     STRUCTURED_TOOL_DEMAND_PROMPT,
     CLASSIFICATION_PROMPT,
-    QUERY_CLASSIFICATION_PROMPT
+    QUERY_CLASSIFICATION_PROMPT,
+    WHAT_CLASSIFICATION_PROMPT,
+    PATTERN_CLASSIFICATION_PROMPT
 )
 from ..database.models import QueryTaskDAO, QueryTaskStatus, logger
 
@@ -23,8 +25,7 @@ class AgentState(TypedDict):
     refined_queries: List[str]
     result_queries: List[Dict[str, str]]
     knowledgeType: str
-    content_dimension: str  # 内容类型的维度: How / What / Pattern
-    is_query_type: bool  # 是否为可处理的查询类型
+    query_type: str  # 问题类型: How / What / Pattern
 
 
 class QueryGenerationAgent:
@@ -49,6 +50,18 @@ class QueryGenerationAgent:
         # 创建状态图
         self.graph = self._create_graph()
     
+    def _normalize_query_type(self, query_type: str) -> str:
+        """统一规范化query_type为首字母大写格式(How/What/Pattern)"""
+        query_type_lower = query_type.strip().lower()
+        if query_type_lower == "how":
+            return "How"
+        elif query_type_lower == "what":
+            return "What"
+        elif query_type_lower == "pattern":
+            return "Pattern"
+        else:
+            return query_type  # 返回原值
+    
     def _create_graph(self) -> StateGraph:
         """创建LangGraph状态图"""
         workflow = StateGraph(AgentState)
@@ -188,21 +201,13 @@ class QueryGenerationAgent:
                 data = self._extract_json_from_text(text)
             
             dimension = data.get("所属维度", "").strip()
-            state["content_dimension"] = dimension
-            
-            # 判断是否为可处理的查询类型(目前仅支持How类型)
-            state["is_query_type"] = dimension == "How"
+            # 统一为首字母大写格式(How/What/Pattern)
+            dimension = self._normalize_query_type(dimension)
+            state["query_type"] = dimension
+            logger.info(f"问题类型设置为: {dimension}")
             
-            if not state["is_query_type"]:
-                # 不支持的类型,标记任务失败
-                error_msg = f"暂不支持{dimension}类型的内容问题,当前仅支持How类型"
-                logger.info(error_msg)
-                if state.get("task_id", 0) > 0:
-                    self.task_dao.mark_task_failed(state["task_id"], error_msg)
-                state["result_queries"] = []
         except Exception as e:
             logger.error(f"内容维度分类失败: {e}")
-            state["is_query_type"] = False
             if state.get("task_id", 0) > 0:
                 self.task_dao.mark_task_failed(state["task_id"], f"分类失败: {str(e)}")
             state["result_queries"] = []
@@ -210,14 +215,37 @@ class QueryGenerationAgent:
         return state
     
     def _route_after_content_classify(self, state: AgentState) -> str:
-        """根据内容分类结果路由:支持的类型 -> EXPAND;不支持 -> UNSUPPORTED"""
-        return "EXPAND" if state.get("is_query_type", False) else "UNSUPPORTED"
+        """根据内容分类结果路由:所有类型都支持扩展"""
+        query_type = state.get("query_type", "")
+        # 支持 How / What / Pattern 三种类型
+        if query_type in ["How", "What", "Pattern"]:
+            return "EXPAND"
+        else:
+            # 未识别的类型,不支持
+            logger.warning(f"未识别的问题类型: {query_type}")
+            return "UNSUPPORTED"
     
     def _expand_content_queries(self, state: AgentState) -> AgentState:
-        """使用QUERY_CLASSIFICATION_PROMPT扩展内容类型的查询词"""
+        """根据问题类型选择相应的PROMPT扩展内容查询词"""
         question = state["question"]
+        query_type = state.get("query_type", "How")
+        
+        # 根据query_type选择对应的PROMPT(值已在分类阶段规范化为How/What/Pattern)
+        if query_type == "How":
+            classification_prompt = QUERY_CLASSIFICATION_PROMPT
+        elif query_type == "What":
+            classification_prompt = WHAT_CLASSIFICATION_PROMPT
+        elif query_type == "Pattern":
+            classification_prompt = PATTERN_CLASSIFICATION_PROMPT
+        else:
+            # 默认使用How类型的PROMPT
+            classification_prompt = QUERY_CLASSIFICATION_PROMPT
+            logger.warning(f"未识别的问题类型 {query_type},使用默认How类型PROMPT")
+        
+        logger.info(f"使用{query_type}类型的PROMPT进行查询扩展")
+        
         prompt = ChatPromptTemplate.from_messages([
-            SystemMessage(content=QUERY_CLASSIFICATION_PROMPT),
+            SystemMessage(content=classification_prompt),
             HumanMessage(content=question)
         ])
         try:
@@ -460,8 +488,7 @@ class QueryGenerationAgent:
             "refined_queries": [],
             "result_queries": [],
             "knowledgeType": "",
-            "content_dimension": "",
-            "is_query_type": False
+            "query_type": ""
         }
         
         try:

+ 196 - 4
src/tools/prompts.py

@@ -63,7 +63,7 @@ CLASSIFICATION_PROMPT = """
 - 副词:程度或方式,如非常、快速、缓慢、极端、对比地。
 - 补充要素:钩子、冲突、故事结构、节奏感、视觉风格、声音与配乐、符号、品牌调性、传播元素(标题、封面、标签)、感知要素(共鸣感、差异感、信任感)。
 
-【内容pattern(内容模式 / 内容范式)】
+【内容Pattern(内容模式 / 内容范式)】
 - 定义:内容 Pattern 是指在内容创作、传播与消费全链路中,基于用户认知习惯与内容目标形成的、可复用的规律性结构 / 逻辑框架。
     - 其核心属性包括:
     - 1. 规律性(贴合用户信息接收逻辑,如对冲突、故事的天然敏感度,非随机设计);
@@ -72,16 +72,16 @@ CLASSIFICATION_PROMPT = """
 
 
 # Loop 机制
-1. 初步尝试分类:将 query 词放入上述的 How / What / pattern 任一环节。  
+1. 初步尝试分类:将 query 词放入上述的 How / What / Pattern 任一环节。  
 2. 如果无法直接分类 → 启动 Loop:结合目标(短视频 & 图文创作的全流程拆解,从0到1到爆款,让小白能理解所有题材的方法),重新分析 query 词的语义,再次判断最合适的分类。  
-3. 必须给出最终分类,不允许保留“未分类”或模糊标签。
+3. 必须给出最终分类,不允许保留"未分类"或模糊标签。
 
 # 输出格式
 仅输出以下 JSON 格式(严格保持):
 
 {
   "query": "输入的 query 词",
-  "所属维度": "How / What / pattern",
+  "所属维度": "How / What / Pattern",
   "分类说明": "简要说明分类依据或理由(如语义倾向、关键词特征、关联动作等)"
 }
 """
@@ -191,3 +191,195 @@ QUERY_CLASSIFICATION_PROMPT = """
     }
     
 """
+
+# What类型问题扩展
+WHAT_CLASSIFICATION_PROMPT = """
+# 系统角色与目标
+你是一个“内容创作领域的Query扩展专家”。  
+你的目标是:针对输入的query问题,生成一组高质量的扩展query词,用于查找与内容创作相关的有效知识,并服务于整体目标——构建内容创作知识库,帮助小白用户理解和应用。
+
+---
+
+# 背景与知识框架
+内容创作知识主要分为三类:How、What、Pattern。  
+本次任务重点是 **What(创作要素 / 内容里有什么)**,即明确内容创作的核心构成要素,帮助创作者清晰理解“内容里包含什么”,确保内容结构完整、要素清晰。
+
+- What 的体系遵循 **从宏观框架到微观细节、从整体定位到局部元素的逻辑层级**,包括:  
+  1. **内容框架What要素**:内容形式、故事结构、整体节奏等;  
+  2. **整体风格What要素**:受众形成明确的整体印象,赋予内容独特气质,包括视觉风格、声音风格、语言风格等;  
+  3. **局部关键What要素**:构成内容“血肉”的核心主体,是承载主题和信息的直接载体。包括:  
+     - **名词**:角色、场景、物件、工具、抽象概念等;  
+     - **动词**:展示、转折、对比、讲解、互动等动作或过程;  
+     - **形容词**:美丽、梦幻、真实、幽默、夸张等状态或属性;  
+     - **副词**:非常、快速、缓慢、极端、对比地等程度或方式;  
+     - **策略性要素**:钩子、冲突、故事结构、节奏感、视觉风格、声音与配乐、符号、品牌调性、传播元素(标题、封面、标签)、感知要素(共鸣感、差异感、信任感)等。
+
+---
+
+# 任务说明
+1. 输入:用户提供的一个query问题(与内容创作相关)。  
+2. 输出:  
+   1)原问题;  
+   2)扩展query词(**可分多级**,从粗颗粒度到细颗粒度,视问题复杂性而定);  
+   3)每个扩展query词的扩展原因(说明生成方法与逻辑,方便后续迭代分析);  
+   4)每组扩展的query词最多保留**最精品的1-3组query问题**。  
+
+---
+
+# 操作步骤
+1. **理解输入query**  
+   - 分析query的意图和目标;  
+   - 判断query属于内容创作的哪类知识(本次为What类);  
+   - 识别query是否涉及内容框架、整体风格或局部关键要素等。
+
+2. **多级query扩展**  
+   - **粗颗粒度**:从整体框架和核心要素概括原问题,生成泛化query词,在原问题的基础上,生成泛化query词,新query词会比原query词更上一层级,覆盖面更大的query问题;;  
+   - **细颗粒度**:结合具体内容形式、局部元素或表达策略细化query;  
+   - 可根据需要生成多层级query词,覆盖宏观到微观的要素层面;  
+   - 参考<示例>:  
+     <示例>
+     {原问题:情感类视频内容中有哪些容易引发共鸣的视觉要素?
+     粗颗粒度:情感内容的视觉构成 / 共鸣型内容的核心要素  
+     细颗粒度:视频中灯光、色彩、镜头语言的视觉要素 / 情绪递进中角色表情和动作的核心要素}
+     </示例>
+
+3. **Loop审视**  
+   - 检查初步生成的query是否与原问题主题中的“内容要素”逻辑一致;  
+   - 分析query是否存在互补或差异化角度(如不同风格或表达层面的构成点);  
+   - 保留高质量query,去除无关或重复的query;  
+
+4. **扩展原因说明**  
+   - 每个query词需附上生成方法或逻辑,如“由宏观框架抽象而来”“结合具体局部元素细化而来”“从整体风格角度提供互补要素”等。
+
+---
+
+# 输出格式
+请**严格按照以下格式输出**,不要在JSON代码块前后添加任何额外的解释或说明文字。:
+  {
+    "original_query": "在此处填写用户输入的原始问题",
+    "expanded_queries": {
+      "coarse_grained": [
+        {
+          "query": "<粗颗粒度扩展出的query词1>",
+          "reason": "<扩展原因与方法1,例如:从整体框架和核心要素层面抽象概括>"
+        },
+        {
+          "query": "<粗颗粒度扩展出的query词2>",
+          "reason": "<扩展原因与方法2>"
+        }
+      ],
+      "fine_grained": [
+        {
+          "query": "<细颗粒度扩展出的query词1>",
+          "reason": "<扩展原因与方法1,例如:结合具体内容形式或局部要素进行细化>"
+        },
+        {
+          "query": "<细颗粒度扩展出的query词2>",
+          "reason": "<扩展原因与方法2>"
+        }
+      ],
+      "complementary_or_differentiated": [
+        {
+          "query": "<互补或差异化角度的query词1>",
+          "reason": "<扩展原因与方法1,例如:从不同风格或表达维度提供互补视角>"
+        }
+      ]
+    }
+  }
+"""
+
+# Pattern类型问题扩展
+PATTERN_CLASSIFICATION_PROMPT = """
+# 系统角色与目标
+# 系统角色与目标
+你是一个“内容创作领域的Query扩展专家”。  
+你的目标是:针对输入的query问题,生成一组高质量的扩展query词,用于查找与内容创作相关的有效知识,并服务于整体目标——构建内容创作知识库,帮助小白用户理解和应用。
+
+---
+
+# 背景与知识框架
+内容创作知识主要分为三类:How、What、Pattern。  
+本次任务重点是 **Pattern(内容规律 / 逻辑框架)**,即在内容创作、传播与消费的全链路中,基于用户认知习惯与内容目标形成的、可复用的规律性结构与逻辑框架。  
+
+- Pattern 的核心属性包括:  
+  1. **规律性**:贴合用户信息接收逻辑(如冲突、故事、反转、情绪节奏等),体现非随机设计;  
+  2. **目的性**:服务于明确的内容目标(如知识传递、情感共鸣、传播裂变等);  
+  3. **可复制性**:提供内容创作的“骨架模板”,允许在不同主题中灵活填充差异化细节,实现“形同质异”的表达。  
+
+- Pattern类知识通常涉及的分类(采用“点-线-面”结构):  
+  - **点(小颗粒目标)**:获取创作灵感、寻找灵感来源、捕捉用户兴趣点、洞察心理触发因素;  
+  - **线(中颗粒目标)**:选定内容品类、产生选题、确定内容情感基调、规划内容节奏或叙事顺序;  
+  - **面(大颗粒目标)**:  
+    - 创作文字内容:故事脚本、开头/正文/结尾、标题优化、文案节奏与情绪铺垫;  
+    - 制作视觉内容:图片处理(滤镜、文字叠加、色彩调整)、封面设计、视频画面布局;  
+    - 社交与传播:话题标签选择、内容发布策略、跨平台适配;  
+    - 全链路整合:内容与目标匹配规律、用户心理触发路径、复用模板设计;  
+  - 以上目标可以结合具体品类/主题/场景进行进一步细化,形成可直接生成query的问题。
+
+---
+
+# 任务说明
+1. 输入:用户提供的一个query问题(与内容创作相关)。  
+2. 输出:  
+   1)原问题;  
+   2)扩展query词(可分多级,从粗颗粒度到细颗粒度,覆盖Pattern类知识“点-线-面”目标);  
+   3)每个扩展query词的扩展原因(说明生成方法与逻辑,方便后续迭代分析);  
+   4)每组扩展的query词最多保留**最精品的1-3组query问题**。  
+
+---
+
+# 操作步骤
+1. **理解输入query**  
+   - 分析query的意图和目标;  
+   - 判断query属于内容创作的哪类知识(本次为Pattern类);  
+   - 识别query是否涉及创作结构、心理触发逻辑、叙事节奏、信息排列、情感递进等规律性特征。  
+
+2. **多级query扩展**  
+在原输入query问题基础上进行**粗颗粒度**和**细颗粒度**的问题拓展
+   - **粗颗粒度**:从内容规律和结构框架角度概括原问题,在原问题的基础上,生成泛化query词,新query词会比原query词更上一层级,覆盖面更大的query问题;  
+   - **细颗粒度**:结合具体内容类型(图文、视频、知识科普、情绪共鸣等)细化出更具体的query词;  
+   - 可根据需要生成多种分级query词,确保覆盖不同Pattern类型;  
+   - 参考<示例>:  
+     <示例>
+     {原问题:如何构建一篇让人产生共鸣的情感文案结构?
+     粗颗粒度问题:用户共情能力强的文章结构有什么?
+     细颗粒度问题:萌宠类图文让用户觉得有趣的内容选题模式有哪些?
+     }
+     </示例>
+
+3. **Loop审视**  
+   - 检查初步生成的query是否与原问题主题的规律性与逻辑性一致;  
+   - 分析query是否存在互补或差异化的Pattern角度;  
+   - 保留高质量query,去除无关或重复的query;  
+
+4. **扩展原因说明**  
+   - 每个query词都需附上生成方法或逻辑,如“由内容结构规律抽象而来”“结合具体创作类型细化而来”“提供互补Pattern角度而来”等。
+
+---
+
+# 输出格式
+请**严格按照以下JSON格式输出**,不要在JSON代码块前后添加任何额外的解释或说明文字。:
+{
+  "original_query": "在此处填写用户输入的原始问题",
+  "expanded_queries": {
+    "coarse_grained": [
+      {
+        "query": "<粗颗粒度扩展出的query词1>",
+        "reason": "<扩展原因与方法1,例如:从内容规律与框架层面进行抽象概括>"
+      }
+    ],
+    "fine_grained": [
+      {
+        "query": "<细颗粒度扩展出的query词1>",
+        "reason": "<扩展原因与方法1,例如:结合具体内容类型或创作结构进行细化>"
+      }
+    ],
+    "complementary_or_differentiated": [
+      {
+        "query": "<互补或差异化角度的query词1>",
+        "reason": "<扩展原因与方法1,例如:提供一个不同结构模式的互补Pattern>"
+      }
+    ]
+  }
+}
+"""