xueyiming 2 часов назад
Родитель
Сommit
b6c7e6c626

+ 0 - 0
examples/content_needs_generation/PRD/process.md → examples/content_needs_generation/PRD/business.md


+ 2 - 2
examples/content_needs_generation/config.py

@@ -21,11 +21,11 @@ RUN_CONFIG = RunConfig(
     # 知识管理配置
     knowledge=KnowledgeConfig(
         # 压缩时提取(消息量超阈值触发压缩时,用完整 history 反思)
-        enable_extraction=True,
+        enable_extraction=False,
         reflect_prompt="",  # 自定义反思 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:REFLECT_PROMPT
 
         # agent运行完成后提取(不代表任务完成,agent 可能中途退出等待人工评估)
-        enable_completion_extraction=True,
+        enable_completion_extraction=False,
         completion_reflect_prompt="",  # 自定义复盘 prompt;空则使用默认,见 agent/core/prompts/knowledge.py:COMPLETION_REFLECT_PROMPT
 
         # 知识注入(agent切换当前工作的goal时,自动注入相关知识)

+ 0 - 0
examples/content_needs_generation/data/trace_visualization.html → examples/content_needs_generation/result/trace_visualization.html


+ 0 - 0
examples/content_needs_generation/data/日期筛选结果.json → examples/content_needs_generation/result/日期筛选结果.json


+ 0 - 0
examples/content_needs_generation/data/最终推荐结果.json → examples/content_needs_generation/result/最终推荐结果.json


+ 0 - 0
examples/content_needs_generation/data/热榜筛选结果.json → examples/content_needs_generation/result/热榜筛选结果.json


+ 3 - 3
examples/content_needs_generation/run.py

@@ -174,11 +174,11 @@ def _apply_prompt_placeholders(base_dir: Path, prompt: SimplePrompt):
         if "system" in prompt._messages and "{system}" in prompt._messages["system"]:
             prompt._messages["system"] = prompt._messages["system"].replace("{system}", system_content)
 
-    create_process_md_path = base_dir / "PRD" / "process.md"
+    create_process_md_path = base_dir / "PRD" / "business.md"
     if create_process_md_path.exists():
         create_process_content = create_process_md_path.read_text(encoding="utf-8")
-        if "system" in prompt._messages and "{process}" in prompt._messages["system"]:
-            prompt._messages["system"] = prompt._messages["system"].replace("{process}", create_process_content)
+        if "system" in prompt._messages and "{business}" in prompt._messages["system"]:
+            prompt._messages["system"] = prompt._messages["system"].replace("{business}", create_process_content)
 
     output_md_path = base_dir / "PRD" / "output.md"
     if output_md_path.exists():

+ 28 - 0
examples/content_needs_generation/skills/content_deconstruction_search.md

@@ -0,0 +1,28 @@
+---
+name: query_content_deconstruction_by_keywords
+description: 根据关键词搜索视频标题和标题的解析结果
+---
+
+## 根据关键词搜索视频标题和解析结果
+
+你可以通过内容解析结果搜索工具 `query_content_deconstruction_by_keywords` 根据关键词搜索视频标题和标题的解析结果。
+
+### 使用场景
+
+- 需要查找包含特定关键词的视频内容
+- 需要获取视频标题的解析结果(包括选题、关键点、灵感点、目的点等)
+- 需要分析特定主题的视频内容结构
+
+### 参数说明
+
+- `keywords`: 关键词列表,例如:`["食用", "禁忌"]`
+
+### 返回结果
+
+工具会返回一个字典,其中:
+- 每个关键词作为键
+- 对应的值是该关键词匹配的视频列表
+- 每个视频包含:
+  - `contentId`: 内容ID
+  - `title`: 视频标题
+  - `description`: 解析结果数组,包含不同类型的描述信息(选题、关键点、灵感点、目的点等)

+ 143 - 0
examples/content_needs_generation/tool/content_deconstruction_search.py

@@ -0,0 +1,143 @@
+"""
+内容解析结果搜索工具 - 根据关键词搜索视频标题和标题的解析结果
+
+用于 Agent 执行时根据关键词搜索视频内容及其解析结果。
+"""
+import json
+import os
+from typing import Any, Dict, List, Optional
+
+import httpx
+
+from agent.tools import tool, ToolResult
+
+# API 配置
+CONTENT_DECONSTRUCTION_BASE_URL = os.getenv(
+    "CONTENT_DECONSTRUCTION_BASE_URL", "http://api.piaoquantv.com"
+)
+DEFAULT_TIMEOUT = 30.0
+
+
+async def _call_content_deconstruction_api(
+    keywords: List[str],
+) -> Optional[Dict[str, List[Dict[str, Any]]]]:
+    """调用内容解析结果搜索 API,返回结果字典。"""
+    url = f"{CONTENT_DECONSTRUCTION_BASE_URL.rstrip('/')}/supply-demand-engine-service/content/queryContentDeconstructionResultByKeywords"
+    payload = {"keywords": keywords}
+
+    try:
+        async with httpx.AsyncClient(timeout=DEFAULT_TIMEOUT) as client:
+            resp = await client.post(
+                url,
+                json=payload,
+                headers={"Content-Type": "application/json"},
+            )
+            resp.raise_for_status()
+            data = resp.json()
+    except httpx.HTTPStatusError as e:
+        raise RuntimeError(
+            f"API 请求失败: {e.response.status_code} - {e.response.text[:200]}"
+        )
+    except Exception as e:
+        raise RuntimeError(f"请求异常: {str(e)}")
+
+    # 解析响应格式: {'code': 0, 'msg': 'success', 'data': {...}, 'success': True}
+    if isinstance(data, dict):
+        # 检查 code 字段
+        code = data.get("code", 0)
+        if code != 0:
+            msg = data.get("msg", "未知错误")
+            raise RuntimeError(f"API 返回错误码: {code}, 消息: {msg}")
+
+        # 获取 data 字段
+        result_data = data.get("data", {})
+        if isinstance(result_data, dict):
+            return result_data
+
+        return {}
+
+    return {}
+
+
+@tool(
+    description="根据关键词搜索视频标题和标题的解析结果。支持传入多个关键词,返回每个关键词对应的视频列表及其解析信息。",
+    display={
+        "zh": {
+            "name": "内容解析结果搜索",
+            "params": {
+                "keywords": "关键词列表,例如:['食用', '禁忌']",
+            },
+        },
+    },
+)
+async def query_content_deconstruction_by_keywords(
+    keywords: List[str],
+) -> ToolResult:
+    """
+    根据关键词搜索视频标题和标题的解析结果。
+
+    Args:
+        keywords: 关键词列表,例如:['食用', '禁忌']
+
+    Returns:
+        ToolResult: 包含每个关键词对应的视频列表及其解析结果
+    """
+    # 验证关键词列表
+    if not keywords:
+        return ToolResult(
+            title="内容解析结果搜索失败",
+            output="",
+            error="关键词列表不能为空",
+        )
+
+    if not isinstance(keywords, list):
+        return ToolResult(
+            title="内容解析结果搜索失败",
+            output="",
+            error=f"关键词必须是列表类型,当前类型为: {type(keywords).__name__}",
+        )
+
+    # 过滤空字符串
+    keywords = [kw.strip() for kw in keywords if kw and kw.strip()]
+    if not keywords:
+        return ToolResult(
+            title="内容解析结果搜索失败",
+            output="",
+            error="关键词列表中没有有效的关键词",
+        )
+
+    try:
+        results = await _call_content_deconstruction_api(keywords=keywords)
+    except RuntimeError as e:
+        return ToolResult(
+            title="内容解析结果搜索失败",
+            output="",
+            error=str(e),
+        )
+
+    if not results:
+        return ToolResult(
+            title="内容解析结果搜索",
+            output=json.dumps(
+                {
+                    "message": "未找到相关内容",
+                    "keywords": keywords,
+                },
+                ensure_ascii=False,
+                indent=2,
+            ),
+        )
+
+    # 统计每个关键词的结果数量
+    keyword_counts = {
+        keyword: len(videos) if isinstance(videos, list) else 0
+        for keyword, videos in results.items()
+    }
+    total_count = sum(keyword_counts.values())
+
+    output = json.dumps(results, ensure_ascii=False, indent=2)
+    return ToolResult(
+        title=f"内容解析结果搜索 - {len(keywords)} 个关键词",
+        output=output,
+        long_term_memory=f"检索到内容解析结果,关键词: {', '.join(keywords)},共 {total_count} 条结果",
+    )

Разница между файлами не показана из-за своего большого размера
+ 0 - 249
examples/content_needs_generation/trace_visualization.html


Некоторые файлы не были показаны из-за большого количества измененных файлов