supeng 5 часов назад
Родитель
Сommit
3708eab66a

+ 18 - 0
examples/content_finder/content_finder.prompt

@@ -6,6 +6,11 @@ temperature: 0.3
 $system$
 你是一个专业的内容寻找助手,帮助运营人员在抖音平台上寻找符合要求的视频内容。
 
+**重要约束**:
+- 只在抖音平台搜索,不要切换到其他平台(小红书、B站等)
+- 只使用 douyin_search、douyin_user_videos、get_content_fans_portrait、get_account_fans_portrait 这4个工具
+- 不要使用浏览器工具、文件操作工具、或其他平台的搜索工具
+
 平台背景(仅供参考):
 - 平台载体:微信小程序
 - 核心用户群:95% 是 50 岁以上中老年人
@@ -50,6 +55,19 @@ $system$
 - 10000+: 高热度
 - 50000+: 爆款
 
+## 错误处理
+
+**如果遇到 HTTP 502/503/504 错误**:
+- 这是服务暂时不可用,不是参数问题
+- 不要重复尝试相同的调用(最多重试1次)
+- 如果持续失败,直接告知用户"抖音搜索服务暂时不可用,请稍后再试"
+- **不要切换到其他平台或使用其他工具**
+
+**如果遇到 HTTP 400/404 错误**:
+- 这是参数错误或资源不存在
+- 检查参数是否正确(ID格式、关键词等)
+- 调整参数后重试
+
 请按照 content_finding_strategy 和 content_filtering_strategy 中的方法论执行任务。
 
 $user$

+ 10 - 0
examples/content_finder/run.py

@@ -76,6 +76,15 @@ async def main():
     Path(trace_dir).mkdir(parents=True, exist_ok=True)
 
     store = FileSystemTraceStore(base_path=trace_dir)
+
+    # 限制工具范围:只使用抖音相关的4个工具
+    allowed_tools = [
+        "douyin_search",
+        "douyin_user_videos",
+        "get_content_fans_portrait",
+        "get_account_fans_portrait",
+    ]
+
     runner = AgentRunner(
         llm_call=create_openrouter_llm_call(model=model),
         trace_store=store,
@@ -86,6 +95,7 @@ async def main():
         model=model,
         temperature=temperature,
         max_iterations=max_iterations,
+        tools=allowed_tools,  # 限制工具范围
     )
 
     # 执行

+ 16 - 3
examples/content_finder/skills/content_finding_strategy.md

@@ -43,9 +43,22 @@
 **如果结果不满足要求**:调整搜索策略,再次尝试,而不是凑合推荐。
 
 **如果工具返回错误**:
-- 分析错误原因(API 超时、参数错误、资源不存在等)
-- 调整策略重试(换关键词、调整参数、使用其他工具)
-- 如果多次失败,如实告知用户并说明原因
+
+**服务级错误(HTTP 502/503/504)**:
+- 这是服务暂时不可用,不是你的参数问题
+- 不要重复尝试相同的调用(最多重试1次即可)
+- 不要尝试换关键词(关键词不是问题)
+- 直接告知用户"服务暂时不可用,请稍后再试"
+- 不要切换到其他平台或工具
+
+**参数错误(HTTP 400/404)**:
+- 检查参数格式是否正确
+- 检查 ID 是否存在
+- 调整参数后重试
+
+**网络错误(Timeout/Connection)**:
+- 可以重试1-2次
+- 如果持续失败,告知用户网络问题
 
 ## 关键原则
 

+ 18 - 17
examples/content_finder/tools/douyin_search.py

@@ -8,6 +8,7 @@ import json
 from typing import Optional
 
 import httpx
+import requests
 
 from agent.tools import tool, ToolResult
 
@@ -54,14 +55,14 @@ async def douyin_search(
 
         request_timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
 
-        async with httpx.AsyncClient(timeout=request_timeout) as client:
-            response = await client.post(
-                DOUYIN_SEARCH_API,
-                json=payload,
-                headers={"Content-Type": "application/json"},
-            )
-            response.raise_for_status()
-            data = response.json()
+        response = requests.post(
+            DOUYIN_SEARCH_API,
+            json=payload,
+            headers={"Content-Type": "application/json"},
+            timeout=request_timeout
+        )
+        response.raise_for_status()
+        data = response.json()
 
         # 格式化输出摘要
         summary_lines = [f"搜索关键词「{keyword}」"]
@@ -118,12 +119,12 @@ async def douyin_search(
 
 
 #
-# async def main():
-#     result = await douyin_search(
-#         keyword="宁艺卓",
-#         account_id = "771431186"
-#     )
-#     print(result.output)
-#
-# if __name__ == "__main__":
-#     asyncio.run(main())
+async def main():
+    result = await douyin_search(
+        keyword="宁艺卓",
+        account_id = "771431186"
+    )
+    print(result.output)
+
+if __name__ == "__main__":
+    asyncio.run(main())

+ 18 - 8
examples/content_finder/tools/douyin_user_videos.py

@@ -8,6 +8,7 @@ from typing import Optional
 
 import asyncio
 import httpx
+import requests
 
 from agent.tools import tool, ToolResult
 
@@ -45,14 +46,23 @@ async def douyin_user_videos(
 
         request_timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
 
-        async with httpx.AsyncClient(timeout=request_timeout) as client:
-            response = await client.post(
-                DOUYIN_BLOGGER_API,
-                json=payload,
-                headers={"Content-Type": "application/json"},
-            )
-            response.raise_for_status()
-            data = response.json()
+        # async with httpx.AsyncClient(timeout=request_timeout) as client:
+        #     response = await client.post(
+        #         DOUYIN_BLOGGER_API,
+        #         json=payload,
+        #         headers={"Content-Type": "application/json"},
+        #     )
+        #     response.raise_for_status()
+        #     data = response.json()
+
+        response = requests.post(
+            DOUYIN_BLOGGER_API,
+            json=payload,
+            headers={"Content-Type": "application/json"},
+            timeout=request_timeout
+        )
+        response.raise_for_status()
+        data = response.json()
 
         # 格式化输出摘要
         summary_lines = [f"账号 {account_id} 的作品列表"]

+ 35 - 16
examples/content_finder/tools/hotspot_profile.py

@@ -8,6 +8,7 @@ import json
 from typing import Optional
 
 import httpx
+import requests
 
 from agent.tools import tool, ToolResult
 
@@ -46,14 +47,23 @@ async def get_account_fans_portrait(
 
         request_timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
 
-        async with httpx.AsyncClient(timeout=request_timeout) as client:
-            response = await client.post(
-                ACCOUNT_FANS_PORTRAIT_API,
-                json=payload,
-                headers={"Content-Type": "application/json"},
-            )
-            response.raise_for_status()
-            data = response.json()
+        # async with httpx.AsyncClient(timeout=request_timeout) as client:
+        #     response = await client.post(
+        #         ACCOUNT_FANS_PORTRAIT_API,
+        #         json=payload,
+        #         headers={"Content-Type": "application/json"},
+        #     )
+        #     response.raise_for_status()
+        #     data = response.json()
+
+        response = requests.post(
+            ACCOUNT_FANS_PORTRAIT_API,
+            json=payload,
+            headers={"Content-Type": "application/json"},
+            timeout=request_timeout
+        )
+        response.raise_for_status()
+        data = response.json()
 
         # 格式化输出摘要
         summary_lines = [f"账号 {account_id} 的粉丝画像"]
@@ -152,14 +162,23 @@ async def get_content_fans_portrait(
 
         request_timeout = timeout if timeout is not None else DEFAULT_TIMEOUT
 
-        async with httpx.AsyncClient(timeout=request_timeout) as client:
-            response = await client.post(
-                CONTENT_FANS_PORTRAIT_API,
-                json=payload,
-                headers={"Content-Type": "application/json"},
-            )
-            response.raise_for_status()
-            data = response.json()
+        # async with httpx.AsyncClient(timeout=request_timeout) as client:
+        #     response = await client.post(
+        #         CONTENT_FANS_PORTRAIT_API,
+        #         json=payload,
+        #         headers={"Content-Type": "application/json"},
+        #     )
+        #     response.raise_for_status()
+        #     data = response.json()
+
+        response = requests.post(
+            CONTENT_FANS_PORTRAIT_API,
+            json=payload,
+            headers={"Content-Type": "application/json"},
+            timeout=request_timeout
+        )
+        response.raise_for_status()
+        data = response.json()
 
         # 格式化输出摘要
         summary_lines = [f"内容 {content_id} 的点赞用户画像"]