Search Layer v2.2 — 意图感知多源检索协议 四源同级:Brave ( ) + Exa + Tavily + Grok。按意图自动选策略、调权重、做合成。 执行流程 --- Phase 1: 意图分类 收到搜索请求后, 先判断意图类型 ,再决定搜索策略。不要问用户用哪种模式。 | 意图 | 识别信号 | Mode | Freshness | 权重偏向 | |------|---------|------|-----------|---------| | Factual | "什么是 X"、"X 的定义"、"What is X" | answer | — | 权威 0.5 | | Status | "X 最新进展"、"X 现状"、"latest X" | deep | pw/pm | 新鲜度 0.5 | | Comparison | "X vs Y"、"X 和 Y 区别" | deep | py | 关键词 0.4 + 权威 0.4 | | Tutorial | "怎么做 X"、"X 教程"、"how to X" | answer | py | 权威 0.5 | | Exploratory | "深入了解 X"、"X 生态"、"about X" | deep | — | 权威 0.5 | | News | "X 新闻"、"本周 X"、"X this week" |…

, '', content)\n\n # Extract JSON object if surrounded by non-JSON text\n content = content.strip()\n if not content.startswith(\"{\"):\n # Find the first { and match to its closing }\n start_idx = content.find(\"{\")\n if start_idx != -1:\n # Use json.JSONDecoder to find the end of the JSON object\n try:\n decoder = json.JSONDecoder()\n parsed_obj, end_idx = decoder.raw_decode(content, start_idx)\n content = content[start_idx:start_idx + end_idx]\n except json.JSONDecodeError:\n # Fallback: take from first { to last }\n last_brace = content.rfind(\"}\")\n if last_brace != -1:\n content = content[start_idx:last_brace + 1]\n\n parsed = json.loads(content)\n results = []\n for res in parsed.get(\"results\", []):\n url = res.get(\"url\", \"\")\n # Validate URL: only accept http/https schemes\n try:\n pu = urlparse(url)\n if pu.scheme not in (\"http\", \"https\") or not pu.netloc:\n continue\n except Exception:\n continue\n results.append({\n \"title\": res.get(\"title\", \"\"),\n \"url\": url,\n \"snippet\": res.get(\"snippet\", \"\"),\n \"published_date\": res.get(\"published_date\", \"\"),\n \"source\": \"grok\",\n })\n return results\n except Exception as e:\n print(f\"[grok] error: {e}\", file=sys.stderr)\n return []\n\n\n@_throttled\ndef search_exa(query: str, key: str, num: int = 5) -> list:\n try:\n r = requests.post(\n \"https://api.exa.ai/search\",\n headers={\"x-api-key\": key, \"Content-Type\": \"application/json\"},\n json={\"query\": query, \"numResults\": num, \"type\": \"auto\"},\n timeout=20,\n )\n r.raise_for_status()\n results = []\n for res in r.json().get(\"results\", []):\n url = res.get(\"url\")\n if not url:\n continue\n results.append({\n \"title\": res.get(\"title\", \"\"),\n \"url\": url,\n \"snippet\": res.get(\"text\", res.get(\"snippet\", \"\")),\n \"published_date\": res.get(\"publishedDate\", \"\"),\n \"source\": \"exa\",\n })\n return results\n except Exception as e:\n print(f\"[exa] error: {e}\", file=sys.stderr)\n return []\n\n\n@_throttled\ndef search_tavily(query: str, key: str, num: int = 5,\n include_answer: bool = False,\n freshness: str = None) -> dict:\n \"\"\"Returns {\"results\": [...], \"answer\": str|None}.\"\"\"\n try:\n payload = {\n \"query\": query,\n \"max_results\": num,\n \"include_answer\": include_answer,\n }\n # Tavily supports time-based filtering via topic + days\n if freshness:\n days_map = {\"pd\": 1, \"pw\": 7, \"pm\": 30, \"py\": 365}\n if freshness in days_map:\n payload[\"days\"] = days_map[freshness]\n r = requests.post(\n \"https://api.tavily.com/search\",\n headers={\"Content-Type\": \"application/json\"},\n json={\"api_key\": key, **payload},\n timeout=20,\n )\n r.raise_for_status()\n data = r.json()\n results = []\n for res in data.get(\"results\", []):\n url = res.get(\"url\")\n if not url:\n continue\n results.append({\n \"title\": res.get(\"title\", \"\"),\n \"url\": url,\n \"snippet\": res.get(\"content\", \"\"),\n \"published_date\": res.get(\"published_date\", \"\"),\n \"source\": \"tavily\",\n })\n return {\"results\": results, \"answer\": data.get(\"answer\")}\n except Exception as e:\n print(f\"[tavily] error: {e}\", file=sys.stderr)\n return {\"results\": [], \"answer\": None}\n\n\n# ---------------------------------------------------------------------------\n# Dedup\n# ---------------------------------------------------------------------------\ndef dedup(results: list) -> list:\n seen = {}\n out = []\n for r in results:\n key = normalize_url(r[\"url\"])\n if key not in seen:\n seen[key] = r\n out.append(r)\n else:\n existing = seen[key]\n src = existing[\"source\"]\n if r[\"source\"] not in src:\n existing[\"source\"] = f\"{src}, {r['source']}\"\n return out\n\n\n# ---------------------------------------------------------------------------\n# Single-query search execution\n# ---------------------------------------------------------------------------\ndef execute_search(query: str, mode: str, keys: dict, num: int,\n include_answer: bool = False,\n freshness: str = None,\n sources: set = None) -> tuple:\n \"\"\"Execute search for a single query. Returns (results_list, answer_text).\n If sources is set, only run those sources (e.g. {'grok', 'exa', 'tavily'}).\"\"\"\n all_results = []\n answer_text = None\n\n # Source filter helper\n def _want(name: str) -> bool:\n return sources is None or name in sources\n\n # Grok config\n grok_url = keys.get(\"grok_url\")\n grok_key = keys.get(\"grok_key\")\n grok_model = keys.get(\"grok_model\", \"grok-4.1-fast\")\n has_grok = bool(grok_url and grok_key)\n\n if mode == \"fast\":\n if \"exa\" in keys and _want(\"exa\"):\n all_results = search_exa(query, keys[\"exa\"], num)\n elif has_grok and _want(\"grok\"):\n all_results = search_grok(query, grok_url, grok_key, grok_model, num, freshness)\n else:\n print('{\"warning\": \"No API keys found for fast mode\"}',\n file=sys.stderr)\n\n elif mode == \"deep\":\n with concurrent.futures.ThreadPoolExecutor(max_workers=3) as pool:\n futures = {}\n if \"exa\" in keys and _want(\"exa\"):\n futures[pool.submit(search_exa, query, keys[\"exa\"], num)] = \"exa\"\n if \"tavily\" in keys and _want(\"tavily\"):\n futures[pool.submit(\n search_tavily, query, keys[\"tavily\"], num,\n freshness=freshness)] = \"tavily\"\n if has_grok and _want(\"grok\"):\n futures[pool.submit(\n search_grok, query, grok_url, grok_key, grok_model, num, freshness)] = \"grok\"\n for fut in concurrent.futures.as_completed(futures):\n name = futures[fut]\n try:\n res = fut.result()\n except Exception as e:\n print(f\"[{name}] error: {e}\", file=sys.stderr)\n continue\n if isinstance(res, dict):\n all_results.extend(res.get(\"results\", []))\n else:\n all_results.extend(res)\n\n elif mode == \"answer\":\n if \"tavily\" not in keys or not _want(\"tavily\"):\n print('{\"warning\": \"Tavily API key not found\"}', file=sys.stderr)\n else:\n tav = search_tavily(query, keys[\"tavily\"], num,\n include_answer=True, freshness=freshness)\n all_results = tav[\"results\"]\n answer_text = tav.get(\"answer\")\n\n return all_results, answer_text\n\n\n# ---------------------------------------------------------------------------\n# Extract refs integration (uses fetch_thread module)\n# ---------------------------------------------------------------------------\ndef _load_fetch_thread():\n \"\"\"Dynamically import fetch_thread from the same directory.\"\"\"\n ft_path = Path(__file__).parent / \"fetch_thread.py\"\n if not ft_path.exists():\n print(f\"[extract-refs] fetch_thread.py not found at {ft_path}\", file=sys.stderr)\n return None\n spec = importlib.util.spec_from_file_location(\"fetch_thread\", str(ft_path))\n mod = importlib.util.module_from_spec(spec)\n spec.loader.exec_module(mod)\n return mod\n\n\ndef _run_extract_refs(urls: list) -> list:\n \"\"\"For each URL, fetch content and extract references.\n Returns list of {source_url, refs: [{type, url, context}]}.\"\"\"\n ft = _load_fetch_thread()\n if not ft:\n return [{\"error\": \"fetch_thread module not available\"}]\n\n results = []\n\n def _fetch_one(url: str) -> dict:\n try:\n gh = ft._parse_github_url(url)\n token = ft._find_github_token()\n if gh and gh[\"type\"] in (\"issue\", \"pr\"):\n data = ft.fetch_github_issue(\n gh[\"owner\"], gh[\"repo\"], gh[\"number\"], token, max_comments=50)\n else:\n data = ft.fetch_web_page(url)\n return {\n \"source_url\": url,\n \"refs\": data.get(\"refs\", []),\n \"ref_count\": len(data.get(\"refs\", [])),\n }\n except Exception as e:\n return {\"source_url\": url, \"refs\": [], \"ref_count\": 0,\n \"error\": str(e)}\n\n # Parallel fetch with bounded concurrency\n with concurrent.futures.ThreadPoolExecutor(max_workers=4) as pool:\n futures = {pool.submit(_fetch_one, u): u for u in urls[:20]} # Cap at 20 URLs\n for fut in concurrent.futures.as_completed(futures):\n results.append(fut.result())\n\n return results\n\n\n# ---------------------------------------------------------------------------\n# Main\n# ---------------------------------------------------------------------------\ndef main():\n ap = argparse.ArgumentParser(\n description=\"Multi-source search v2 (Exa + Tavily) with intent-aware scoring\")\n ap.add_argument(\"query\", nargs=\"?\", default=None, help=\"Search query (single)\")\n ap.add_argument(\"--queries\", nargs=\"+\", default=None,\n help=\"Multiple queries to execute in parallel\")\n ap.add_argument(\"--mode\", choices=[\"fast\", \"deep\", \"answer\"], default=\"deep\",\n help=\"fast=Exa only | deep=Exa+Tavily | answer=Tavily with AI answer\")\n ap.add_argument(\"--num\", type=int, default=5,\n help=\"Results per source per query (default 5)\")\n ap.add_argument(\"--intent\",\n choices=[\"factual\", \"status\", \"comparison\", \"tutorial\",\n \"exploratory\", \"news\", \"resource\"],\n default=None,\n help=\"Query intent type for scoring (default: no intent scoring)\")\n ap.add_argument(\"--freshness\", choices=[\"pd\", \"pw\", \"pm\", \"py\"], default=None,\n help=\"Freshness filter (pd=24h, pw=week, pm=month, py=year)\")\n ap.add_argument(\"--domain-boost\", default=None,\n help=\"Comma-separated domains to boost in scoring\")\n ap.add_argument(\"--source\", default=None,\n help=\"Comma-separated sources to use (exa,tavily,grok). Default: all available\")\n ap.add_argument(\"--extract-refs\", action=\"store_true\",\n help=\"After search, fetch each result URL and extract structured references\")\n ap.add_argument(\"--extract-refs-urls\", nargs=\"+\", default=None,\n help=\"Extract refs from these URLs directly (skip search)\")\n args = ap.parse_args()\n\n # Determine queries\n queries = []\n if args.queries:\n queries = args.queries\n elif args.query:\n queries = [args.query]\n elif args.extract_refs_urls:\n # No search needed, just extract refs from provided URLs\n output = {\n \"mode\": \"extract-refs-only\",\n \"intent\": args.intent,\n \"queries\": [],\n \"count\": 0,\n \"results\": [],\n \"refs\": _run_extract_refs(args.extract_refs_urls),\n }\n print(json.dumps(output, ensure_ascii=False, indent=2))\n return\n else:\n ap.error(\"Provide a query positional argument, --queries, or --extract-refs-urls\")\n\n keys = get_keys()\n boost_domains = set()\n if args.domain_boost:\n boost_domains = {d.strip() for d in args.domain_boost.split(\",\")}\n source_filter = None\n if args.source:\n source_filter = {s.strip() for s in args.source.split(\",\")}\n\n # Execute all queries (parallel if multiple)\n all_results = []\n answer_text = None\n\n if len(queries) == 1:\n results, answer_text = execute_search(\n queries[0], args.mode, keys, args.num,\n include_answer=(args.mode == \"answer\"),\n freshness=args.freshness,\n sources=source_filter)\n all_results = results\n else:\n # Cap outer concurrency: each query may spawn up to 3 inner threads (deep mode),\n # so limit outer workers to avoid thread explosion (outer × inner ≤ semaphore cap)\n max_workers = min(len(queries), 3)\n with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as pool:\n futures = {\n pool.submit(execute_search, q, args.mode, keys, args.num,\n freshness=args.freshness,\n sources=source_filter): q\n for q in queries\n }\n for fut in concurrent.futures.as_completed(futures):\n results, ans = fut.result()\n all_results.extend(results)\n if ans and not answer_text:\n answer_text = ans\n\n # Dedup\n deduped = dedup(all_results)\n\n # Score and sort if intent is specified\n if args.intent:\n primary_query = queries[0] # Use first query for keyword scoring\n for r in deduped:\n r[\"score\"] = score_result(r, primary_query, args.intent, boost_domains)\n deduped.sort(key=lambda x: x.get(\"score\", 0), reverse=True)\n\n # Build output\n output = {\n \"mode\": args.mode,\n \"intent\": args.intent,\n \"queries\": queries,\n \"count\": len(deduped),\n \"results\": deduped,\n }\n if answer_text:\n output[\"answer\"] = answer_text\n if args.freshness:\n output[\"freshness_filter\"] = args.freshness\n\n # --extract-refs: extract references from result URLs or explicit URL list\n if args.extract_refs or args.extract_refs_urls:\n output[\"refs\"] = _run_extract_refs(\n urls=args.extract_refs_urls or [r[\"url\"] for r in deduped],\n )\n\n print(json.dumps(output, ensure_ascii=False, indent=2))\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":32115,"content_sha256":"96da9e677d18e4f712d791ab8e5ccea29b4cd7b4a459d402d7aea71bd32b4ffd"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Search Layer v2.2 — 意图感知多源检索协议","type":"text"}]},{"type":"paragraph","content":[{"text":"四源同级:Brave (","type":"text"},{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":") + Exa + Tavily + Grok。按意图自动选策略、调权重、做合成。","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"执行流程","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"用户查询\n ↓\n[Phase 1] 意图分类 → 确定搜索策略\n ↓\n[Phase 2] 查询分解 & 扩展 → 生成子查询\n ↓\n[Phase 3] 多源并行检索 → Brave + search.py (Exa + Tavily + Grok)\n ↓\n[Phase 4] 结果合并 & 排序 → 去重 + 意图加权评分\n ↓\n[Phase 5] 知识合成 → 结构化输出","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 1: 意图分类","type":"text"}]},{"type":"paragraph","content":[{"text":"收到搜索请求后,","type":"text"},{"text":"先判断意图类型","type":"text","marks":[{"type":"strong"}]},{"text":",再决定搜索策略。不要问用户用哪种模式。","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"意图","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"识别信号","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Mode","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Freshness","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"权重偏向","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Factual","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"什么是 X\"、\"X 的定义\"、\"What is X\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"answer","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"权威 0.5","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Status","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"X 最新进展\"、\"X 现状\"、\"latest X\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"deep","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pw/pm","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"新鲜度 0.5","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Comparison","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"X vs Y\"、\"X 和 Y 区别\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"deep","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"py","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"关键词 0.4 + 权威 0.4","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tutorial","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"怎么做 X\"、\"X 教程\"、\"how to X\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"answer","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"py","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"权威 0.5","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exploratory","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"深入了解 X\"、\"X 生态\"、\"about X\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"deep","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"权威 0.5","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"News","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"X 新闻\"、\"本周 X\"、\"X this week\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"deep","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pd/pw","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"新鲜度 0.6","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resource","type":"text","marks":[{"type":"strong"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"X 官网\"、\"X GitHub\"、\"X 文档\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fast","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"—","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"关键词 0.5","type":"text"}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"详细分类指南见 ","type":"text"},{"text":"references/intent-guide.md","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"paragraph","content":[{"text":"判断规则","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"扫描查询中的信号词","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"多个类型匹配时选最具体的","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"无法判断时默认 ","type":"text"},{"text":"exploratory","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 2: 查询分解 & 扩展","type":"text"}]},{"type":"paragraph","content":[{"text":"根据意图类型,将用户查询扩展为一组子查询:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"通用规则","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"技术同义词自动扩展","type":"text","marks":[{"type":"strong"}]},{"text":":k8s→Kubernetes, JS→JavaScript, Go→Golang, Postgres→PostgreSQL","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"中文技术查询","type":"text","marks":[{"type":"strong"}]},{"text":":同时生成英文变体(如 \"Rust 异步编程\" → 额外搜 \"Rust async programming\")","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"按意图扩展","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"意图","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"扩展策略","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"示例","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Factual","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"加 \"definition\"、\"explained\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"WebTransport\" → \"WebTransport\", \"WebTransport explained overview\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Status","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"加年份、\"latest\"、\"update\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Deno 进展\" → \"Deno 2.0 latest 2026\", \"Deno update release\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Comparison","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"拆成 3 个子查询","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Bun vs Deno\" → \"Bun vs Deno\", \"Bun advantages\", \"Deno advantages\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tutorial","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"加 \"tutorial\"、\"guide\"、\"step by step\"","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Rust CLI\" → \"Rust CLI tutorial\", \"Rust CLI guide step by step\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exploratory","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"拆成 2-3 个角度","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"RISC-V\" → \"RISC-V overview\", \"RISC-V ecosystem\", \"RISC-V use cases\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"News","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"加 \"news\"、\"announcement\"、日期","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"AI 新闻\" → \"AI news this week 2026\", \"AI announcement latest\"","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resource","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"加具体资源类型","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\"Anthropic MCP\" → \"Anthropic MCP official documentation\"","type":"text"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 3: 多源并行检索","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1: Brave(所有模式)","type":"text"}]},{"type":"paragraph","content":[{"text":"对每个子查询调用 ","type":"text"},{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":"。如果意图有 freshness 要求,传 ","type":"text"},{"text":"freshness","type":"text","marks":[{"type":"code_inline"}]},{"text":" 参数:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"web_search(query=\"Deno 2.0 latest 2026\", freshness=\"pw\")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2: Exa + Tavily + Grok(Deep / Answer 模式)","type":"text"}]},{"type":"paragraph","content":[{"text":"对子查询调用 search.py,传入意图和 freshness:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 /home/node/.openclaw/workspace/skills/search-layer/scripts/search.py \\\n --queries \"子查询1\" \"子查询2\" \"子查询3\" \\\n --mode deep \\\n --intent status \\\n --freshness pw \\\n --num 5","type":"text"}]},{"type":"paragraph","content":[{"text":"各模式源参与矩阵","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"模式","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exa","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tavily","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Grok","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"说明","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fast","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fallback","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Exa 优先;无 Exa key 时用 Grok","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"deep","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"三源并行","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"answer","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"✅","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"❌","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"仅 Tavily(含 AI answer)","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"参数说明","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"参数","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"说明","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--queries","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"多个子查询并行执行(也可用位置参数传单个查询)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--mode","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"fast / deep / answer","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--intent","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"意图类型,影响评分权重(不传则不评分,行为与 v1 一致)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--freshness","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"pd(24h) / pw(周) / pm(月) / py(年)","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--domain-boost","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"逗号分隔的域名,匹配的结果权威分 +0.2","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--num","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"每源每查询的结果数","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"Grok 源说明","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"通过 completions API 调用 Grok 模型(","type":"text"},{"text":"grok-4.1-fast","type":"text","marks":[{"type":"code_inline"}]},{"text":"),利用其实时知识返回结构化搜索结果","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"自动检测时间敏感查询并注入当前时间上下文","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"在 deep 模式下与 Exa、Tavily 并行执行","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"需要在 ","type":"text"},{"text":"~/.openclaw/credentials/search.json","type":"text","marks":[{"type":"code_inline"}]},{"text":" 中配置 Grok 的 ","type":"text"},{"text":"apiUrl","type":"text","marks":[{"type":"code_inline"}]},{"text":"、","type":"text"},{"text":"apiKey","type":"text","marks":[{"type":"code_inline"}]},{"text":"、","type":"text"},{"text":"model","type":"text","marks":[{"type":"code_inline"}]},{"text":"(或通过环境变量 ","type":"text"},{"text":"GROK_API_URL","type":"text","marks":[{"type":"code_inline"}]},{"text":"、","type":"text"},{"text":"GROK_API_KEY","type":"text","marks":[{"type":"code_inline"}]},{"text":"、","type":"text"},{"text":"GROK_MODEL","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"如果 Grok 配置缺失,自动降级为 Exa + Tavily 双源","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3: 合并","type":"text"}]},{"type":"paragraph","content":[{"text":"将 Brave 结果与 search.py 输出合并。按 canonical URL 去重,标记来源。","type":"text"}]},{"type":"paragraph","content":[{"text":"如果 search.py 返回了 ","type":"text"},{"text":"score","type":"text","marks":[{"type":"code_inline"}]},{"text":" 字段,用它排序;Brave 结果没有 score 的,用同样的意图权重公式补算。","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 3.5: 引用追踪(Thread Pulling)","type":"text"}]},{"type":"paragraph","content":[{"text":"当搜索结果中包含 GitHub issue/PR 链接,且意图为 Status 或 Exploratory 时,自动触发引用追踪。","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"自动触发条件","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"意图为 ","type":"text"},{"text":"status","type":"text","marks":[{"type":"code_inline"}]},{"text":" 或 ","type":"text"},{"text":"exploratory","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"搜索结果中包含 ","type":"text"},{"text":"github.com/.../issues/","type":"text","marks":[{"type":"code_inline"}]},{"text":" 或 ","type":"text"},{"text":"github.com/.../pull/","type":"text","marks":[{"type":"code_inline"}]},{"text":" URL","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"方式 1: search.py --extract-refs(批量)","type":"text"}]},{"type":"paragraph","content":[{"text":"在搜索结果上直接提取引用图,无需额外调用:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 search.py \"OpenClaw config validation bug\" --mode deep --intent status --extract-refs","type":"text"}]},{"type":"paragraph","content":[{"text":"输出中会多一个 ","type":"text"},{"text":"refs","type":"text","marks":[{"type":"code_inline"}]},{"text":" 字段,包含每个结果 URL 的引用列表。","type":"text"}]},{"type":"paragraph","content":[{"text":"也可以跳过搜索,直接对已知 URL 提取引用:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 search.py --extract-refs-urls \"https://github.com/owner/repo/issues/123\" \"https://github.com/owner/repo/issues/456\"","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"方式 2: fetch-thread(单 URL 深度抓取)","type":"text"}]},{"type":"paragraph","content":[{"text":"对单个 URL 拉取完整讨论流 + 结构化引用:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"python3 fetch_thread.py \"https://github.com/owner/repo/issues/123\" --format json\npython3 fetch_thread.py \"https://github.com/owner/repo/issues/123\" --format markdown\npython3 fetch_thread.py \"https://github.com/owner/repo/issues/123\" --extract-refs-only","type":"text"}]},{"type":"paragraph","content":[{"text":"GitHub 场景(issue/PR):通过 API 拉取正文 + 全部 comments + timeline 事件(cross-references、commits),提取:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Issue/PR 引用(#123、owner/repo#123)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Duplicate 标记","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Commit 引用","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"关联 PR/issue(timeline cross-references)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"外部 URL","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"通用 web 场景:web fetch + 正则提取引用链接。","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Agent 执行流程","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"Step 1: search-layer 搜索 → 获取初始结果\nStep 2: search.py --extract-refs 或 fetch-thread → 提取线索图\nStep 3: Agent 筛选高价值线索(LLM 判断哪些值得追踪)\nStep 4: fetch-thread 深度抓取每个高价值线索\nStep 5: 重复 Step 2-4,直到信息闭环或达到深度限制(建议 max_depth=3)","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 4: 结果排序","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"评分公式","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"score = w_keyword × keyword_match + w_freshness × freshness_score + w_authority × authority_score","type":"text"}]},{"type":"paragraph","content":[{"text":"权重由意图决定(见 Phase 1 表格)。各分项:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"keyword_match","type":"text","marks":[{"type":"strong"}]},{"text":" (0-1):查询词在标题+摘要中的覆盖率","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"freshness_score","type":"text","marks":[{"type":"strong"}]},{"text":" (0-1):基于发布日期,越新越高(无日期=0.5)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"authority_score","type":"text","marks":[{"type":"strong"}]},{"text":" (0-1):基于域名权威等级","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tier 1 (1.0): github.com, stackoverflow.com, 官方文档站","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tier 2 (0.8): HN, dev.to, 知名技术博客","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tier 3 (0.6): Medium, 掘金, InfoQ","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tier 4 (0.4): 其他","type":"text"}]}]}]}]}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"完整域名评分表见 ","type":"text"},{"text":"references/authority-domains.json","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Domain Boost","type":"text"}]},{"type":"paragraph","content":[{"text":"通过 ","type":"text"},{"text":"--domain-boost","type":"text","marks":[{"type":"code_inline"}]},{"text":" 参数手动指定需要加权的域名(匹配的结果权威分 +0.2):","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"search.py \"query\" --mode deep --intent tutorial --domain-boost dev.to,freecodecamp.org","type":"text"}]},{"type":"paragraph","content":[{"text":"推荐搭配:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tutorial → ","type":"text"},{"text":"dev.to, freecodecamp.org, realpython.com, baeldung.com","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Resource → ","type":"text"},{"text":"github.com","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"News → ","type":"text"},{"text":"techcrunch.com, arstechnica.com, theverge.com","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 5: 知识合成","type":"text"}]},{"type":"paragraph","content":[{"text":"根据结果数量选择合成策略:","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"小结果集(≤5 条)","type":"text"}]},{"type":"paragraph","content":[{"text":"逐条展示,每条带源标签和评分:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"1. [Title](url) — snippet... `[brave, exa]` ⭐0.85\n2. [Title](url) — snippet... `[tavily]` ⭐0.72","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"中结果集(5-15 条)","type":"text"}]},{"type":"paragraph","content":[{"text":"按主题聚类 + 每组摘要:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"**主题 A: [描述]**\n- [结果1] — 要点... `[source]`\n- [结果2] — 要点... `[source]`\n\n**主题 B: [描述]**\n- [结果3] — 要点... `[source]`","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"大结果集(15+ 条)","type":"text"}]},{"type":"paragraph","content":[{"text":"高层综述 + Top 5 + 深入提示:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"[一段综述,概括主要发现]\n\n**Top 5 最相关结果:**\n1. ...\n2. ...\n\n共找到 N 条结果,覆盖 [源列表]。需要深入哪个方面?","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"合成规则","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"先给答案,再列来源","type":"text","marks":[{"type":"strong"}]},{"text":"(不要先说\"我搜了什么\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"按主题聚合,不按来源聚合","type":"text","marks":[{"type":"strong"}]},{"text":"(不要\"Brave 结果:... Exa 结果:...\")","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"冲突信息显性标注","type":"text","marks":[{"type":"strong"}]},{"text":":不同源说法矛盾时明确指出","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"置信度表达","type":"text","marks":[{"type":"strong"}]},{"text":":","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"多源一致 + 新鲜 → 直接陈述","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"单源或较旧 → \"根据 [source],...\"","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"冲突或不确定 → \"存在不同说法:A 认为...,B 认为...\"","type":"text"}]}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"降级策略","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exa 429/5xx → 继续 Brave + Tavily + Grok","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tavily 429/5xx → 继续 Brave + Exa + Grok","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Grok 超时/错误 → 继续 Brave + Exa + Tavily","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"search.py 整体失败 → 仅用 Brave ","type":"text"},{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":"(始终可用)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"永远不要因为某个源失败而阻塞主流程","type":"text","marks":[{"type":"strong"}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"向后兼容","type":"text"}]},{"type":"paragraph","content":[{"text":"不带 ","type":"text"},{"text":"--intent","type":"text","marks":[{"type":"code_inline"}]},{"text":" 参数时,search.py 行为与 v1 完全一致(无评分,按原始顺序输出)。","type":"text"}]},{"type":"paragraph","content":[{"text":"现有调用方(如 github-explorer)无需修改。","type":"text"}]},{"type":"hr","attrs":{"markup":"---"}},{"type":"heading","attrs":{"level":2},"content":[{"text":"快速参考","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"场景","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"命令","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"快速事实","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"search.py --mode answer --intent factual","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"深度调研","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"search.py --mode deep --intent exploratory","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"最新动态","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"web_search(freshness=\"pw\")","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"search.py --mode deep --intent status --freshness pw","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"对比分析","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":" × 3 queries + ","type":"text"},{"text":"search.py --queries \"A vs B\" \"A pros\" \"B pros\" --intent comparison","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"找资源","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"web_search","type":"text","marks":[{"type":"code_inline"}]},{"text":" + ","type":"text"},{"text":"search.py --mode fast --intent resource","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"search-layer","author":"@skillopedia","source":{"stars":65,"repo_name":"claude-code-skills","origin_url":"https://github.com/aaaaqwq/claude-code-skills/blob/HEAD/skills/search-layer/SKILL.md","repo_owner":"aaaaqwq","body_sha256":"45c07765a48512f70f3fe0706fdd73fbfa1a5cb1436155648e2e66d51a55b916","cluster_key":"655a92c121bbe6456e8dca8064c45164dcf75a3e5b6c8ef057b9aa0b296a9511","clean_bundle":{"format":"clean-skill-bundle-v1","source":"aaaaqwq/claude-code-skills/skills/search-layer/SKILL.md","attachments":[{"id":"9d358285-1669-53e4-836f-1597a89f4626","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/9d358285-1669-53e4-836f-1597a89f4626/attachment.json","path":"references/authority-domains.json","size":2681,"sha256":"d95fb14d3244d10894479f59a734904c9de7b760102a99d24597cf952cb1f517","contentType":"application/json; charset=utf-8"},{"id":"767bb20b-166e-5215-9f59-a85f4fc1c39f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/767bb20b-166e-5215-9f59-a85f4fc1c39f/attachment.md","path":"references/intent-guide.md","size":4905,"sha256":"066b3fd5e1767d06c99d54440e64494a391ac76cb0119f76493c294020ac682b","contentType":"text/markdown; charset=utf-8"},{"id":"d7427113-2b6c-540c-93bc-b38ae5fafa5f","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d7427113-2b6c-540c-93bc-b38ae5fafa5f/attachment.py","path":"scripts/chain_tracker.py","size":7140,"sha256":"3b69b731e46c1978bff3fab2f05d63928d0c910595352986fa3d2af85c40fb80","contentType":"text/x-python; charset=utf-8"},{"id":"d5c46fd4-edc6-5a0d-af3e-72705b2d040d","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/d5c46fd4-edc6-5a0d-af3e-72705b2d040d/attachment.py","path":"scripts/fetch_thread.py","size":35914,"sha256":"671bf79efd0450a43553d74fb8f6c90b8db34d12d540a77634ede27d727b9b3c","contentType":"text/x-python; charset=utf-8"},{"id":"93ff31c2-1014-5e89-97c1-b62c28998e65","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/93ff31c2-1014-5e89-97c1-b62c28998e65/attachment.py","path":"scripts/relevance_gate.py","size":8809,"sha256":"249a3aa8137646b478ca8936e51f1ad007320b6ff768b074ccd5474cec103434","contentType":"text/x-python; charset=utf-8"},{"id":"6d4d5bbf-fa2c-59d1-9adf-b0e58ddfd722","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/6d4d5bbf-fa2c-59d1-9adf-b0e58ddfd722/attachment.py","path":"scripts/search.py","size":32115,"sha256":"96da9e677d18e4f712d791ab8e5ccea29b4cd7b4a459d402d7aea71bd32b4ffd","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"067a24d6b5e015365e3ea6a5dd56087d947bc18f2bbb81fad0e226918e7748fb","attachment_count":6,"text_attachments":6,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"skills/search-layer/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"web-development","category_label":"Web"},"exact_dupes_collapsed_into_this":0},"version":"v1","category":"web-development","import_tag":"clean-skills-v1","description":"四源同级:Brave (`web_search`) + Exa + Tavily + Grok。按意图自动选策略、调权重、做合成。 DEFAULT search tool for ALL search/lookup needs. Multi-source search and deduplication layer with intent-aware scoring. Integrates Brave Search (web_search), Exa, Tavily, and Grok to provide high-coverage, high-quality results. Automatically classifies query intent and adjusts search strategy, scoring weights, and result synthesis. Use for ANY query that requires web search — factual lookups, research, news, comparisons, resource finding, \"what is X\", status checks, etc. Do NOT use raw web_search directly; always route through this skill."}},"renderedAt":1782979993274}

Search Layer v2.2 — 意图感知多源检索协议 四源同级:Brave ( ) + Exa + Tavily + Grok。按意图自动选策略、调权重、做合成。 执行流程 --- Phase 1: 意图分类 收到搜索请求后, 先判断意图类型 ,再决定搜索策略。不要问用户用哪种模式。 | 意图 | 识别信号 | Mode | Freshness | 权重偏向 | |------|---------|------|-----------|---------| | Factual | "什么是 X"、"X 的定义"、"What is X" | answer | — | 权威 0.5 | | Status | "X 最新进展"、"X 现状"、"latest X" | deep | pw/pm | 新鲜度 0.5 | | Comparison | "X vs Y"、"X 和 Y 区别" | deep | py | 关键词 0.4 + 权威 0.4 | | Tutorial | "怎么做 X"、"X 教程"、"how to X" | answer | py | 权威 0.5 | | Exploratory | "深入了解 X"、"X 生态"、"about X" | deep | — | 权威 0.5 | | News | "X 新闻"、"本周 X"、"X this week" |…