ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Gemini CLI google_web_search 工具深度解析:实时网络检索、Grounding 摘要与引用标注机制

Gemini CLI google_web_search 工具深度解析:实时网络检索、Grounding 摘要与引用标注机制 Gemini CLI google_web_search 工具深度解析实时网络检索、Grounding 摘要与引用标注机制【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cliGemini CLI 的google_web_search工具让 Agent 能够越过训练数据的知识截止时间通过 Google Search 获取实时新闻、最新版本文档和最新漏洞信息。本文基于 工具参考文档 展开并结合仓库中该工具的完整实现源码 web-search.ts、工具声明 default-legacy.ts、注册入口 config.ts 以及配套测试完整拆解该工具「检索—摘要—引用标注」三层工作机理以及它在实际会话中的启用方式与行为边界。读完本文你将能够准确判断 Agent 何时会调用该工具、如何解读其带引用的返回结果并理解其空结果、取消与失败路径的源码级处理。工具定位何时触发google_web_search参考文档对该工具的定位非常明确当用户请求需要当前事件current events或模型训练数据中不存在的在线文档时Agent 会调用它。其返回内容有三个特征这也是理解整个实现的关键线索Grounding事实接地返回的不是原始搜索结果列表而是基于搜索结果生成的摘要Citations引用标注附带来源 URI 与标题用于事实溯源Processing服务端处理搜索与合成由 Gemini API 侧完成工具本身只是「发起查询 解析 grounding 元数据」的薄封装。这一设计意味着该工具解决的是「模型知识过期」问题典型使用场景包括调研某个软件库或 API 的最新版本查找近期软件缺陷或安全漏洞的解决方案获取在模型知识截止之后更新过的新闻与文档。工具名、显示名与注册位置工具的实际注册名与终端显示名在 tool-names.ts 中集中定义注册名为google_web_search常量WEB_SEARCH_TOOL_NAME定义于 base-declarations.ts面向用户的显示名为GoogleSearchWEB_SEARCH_DISPLAY_NAME。工具在核心配置初始化阶段被有条件注册config.ts 中的调用链为maybeRegister(WebSearchTool, () registry.registerTool(new WebSearchTool(this, this.messageBus)), );maybeRegister表明该工具是否真正进入工具注册表取决于用户配置例如设置中的tools.core工具列表这一点在集成测试中有直接验证见文末「验证与测试」一节。工具类别为Kind.Search且isOutputMarkdown标记为true——即其输出会被渲染层按 Markdown 处理这与它返回带引用列表的 Markdown 文本格式相呼应见 web-search.ts 的构造函数参数。参数定义唯一的必填参数query参考文档声明该工具仅有一个必填参数querystring。仓库中的 JSON Schema 与之完全一致位于 default-legacy.tsgoogle_web_search: { name: WEB_SEARCH_TOOL_NAME, description: Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query., parametersJsonSchema: { type: object, properties: { [WEB_SEARCH_PARAM_QUERY]: { type: string, description: The search query to find information on the web., }, }, required: [WEB_SEARCH_PARAM_QUERY], }, },需要注意两点实现细节声明按模型族切换。WebSearchTool.getSchema(modelId)并非直接返回上面的 legacy 声明而是通过 resolveToolDeclaration 在DEFAULT_LEGACY_SET与各模型族集合如 gemini-3.ts之间按当前模型解析从而允许不同模型家族使用定制化的工具描述文本。参数校验前置。除了 Schema 层的required约束运行时还有一道显式校验web-search.ts 中的validateToolParamValues会拒绝空字符串或纯空格的query返回错误信息The query parameter cannot be empty.。核心执行流程以web-search伪模型号委托给 Gemini API理解该工具最关键的一点是它并不直接调用 Google Search API而是把搜索请求封装为一次特殊的 Gemini API 生成调用。WebSearchToolInvocation.execute 的核心逻辑const response await geminiClient.generateContent( { model: web-search }, [{ role: user, parts: [{ text: this.params.query }] }], signal, LlmRole.UTILITY_TOOL, );从源码结构看这里有三处值得注意的设计model: web-search这不是一个真实模型名而是 Gemini API 的 Grounding 能力入口——客户端以此「模型号」发起请求API 侧执行 Google Search 并将搜索结果合成进响应。搜索、抽取与摘要全部在服务端完成这正是参考文档所说「The Gemini API processes the search results before returning a synthesized response」的实现载体。LlmRole.UTILITY_TOOL调用被标记为工具用途utility role从遥测维度上把它与主对话链路的模型调用区分开便于统计与配额管理。signalAbortSignal透传用户的取消操作会直接中断这次生成请求后续在 catch 分支中被识别为中止并优雅返回。执行后的结果解析分为两步先取响应文本与 grounding 元数据再对空结果、引用插入与来源列表做后处理。Grounding 元数据的结构工具结果类型WebSearchToolResult在标准ToolResult基础上扩展了sources字段web-search.ts其内容取自 API 响应的candidates[0].groundingMetadata。源码中本地定义了三个与 API 元数据对应的接口GroundingChunkWeb{ uri?: string; title?: string }即单个来源网页的 URI 与标题GroundingSupportSegment{ startIndex: number; endIndex: number; text?: string }标记摘要文本中某一段内容所对应的字节区间GroundingSupportItem{ segment?: GroundingSupportSegment; groundingChunkIndices?: number[]; confidenceScores?: number[] }把「摘要中的某一段」与「支撑它的来源 chunk 下标」关联起来并可携带置信度。这套结构完整地支撑了参考文档中「Citations: Includes source URIs and titles for factual grounding」这一行为groundingChunks提供引用清单groundingSupports提供内联标注的位置依据。内联引用标注按 UTF-8 字节位置插入[n]标记实现中最精巧的部分在于内联引用的插入算法web-search.ts。它遍历每条groundingSupports根据segment.endIndex与groundingChunkIndices生成形如[2][5]的引用标记然后执行以下操作// Sort insertions by index in descending order to avoid shifting subsequent indices insertions.sort((a, b) b.index - a.index); // Use TextEncoder/TextDecoder since segment indices are UTF-8 byte positions const encoder new TextEncoder(); const responseBytes encoder.encode(modifiedResponseText);这里有两个必须理解的技术决策倒序插入先按插入位置从大到小排序自后向前在字节数组中「切片—拼接」避免前面插入导致后续位置整体偏移而标错位置以字节而非字符定位API 返回的segment下标是UTF-8 字节位置因此源码使用TextEncoder/TextDecoder在字节层面操作再解码回字符串。对于包含中文、日文等多字节字符的查询结果若按 JS 字符串下标插入会导致引用标记错位——这一点在单元测试 web-search.test.ts 中专门用「multibyte query」用例做了覆盖。插入完成后来源列表以 Markdown 形式追加到响应末尾web-search.tssourceListFormatted.push([${index 1}] ${title} (${uri})); // ... modifiedResponseText \n\nSources:\n sourceListFormatted.join(\n);即每条来源渲染为[1] 标题 (URI)的编号列表缺失的标题回退为Untitled、缺失的 URI 回退为No URI。最终返回给 Agent 的llmContent形如Web search results for query: 带内联 [n] 标记的合成摘要 Sources: [1] title (uri) [2] title (uri)returnDisplay展示给终端用户的简短状态则为Search results for query returned.与注入模型上下文的完整内容分离保证终端输出简洁。边界路径空结果、用户取消与检索失败参考文档只描述了正常路径源码则给出了三条完整的异常/边界处理分支web-search.ts这决定了工具在真实网络环境下的行为边界场景触发条件返回行为无搜索结果响应文本为空llmContent提示No search results or information found for query: queryreturnDisplay为No information found.不视为错误用户取消捕获到 AbortError返回Web search was cancelled./Search cancelled.静默结束检索失败其他异常llmContent携带Error: Error during web search for query query: message并附带结构化错误{ type: ToolErrorType.WEB_SEARCH_FAILED }同时经debugLogger.warn记录完整堆栈值得注意的是错误处理策略失败不会抛出中断 Agent 循环而是以带错误类型的ToolResult返回让模型自行决定是重试、换查询词还是放弃搜索——这与 Agent 系统的容错设计一致。实战使用检索、抓取与知识落地的工作流Web tools 教程 给出了该工具在真实会话中的四类典型用法可与上文实现一一对应调研新技术触发google_web_searchSearch for the Bun 1.0 release notes and summarize the key changes.Agent 检索相关页面后合成答案这一「grounding」过程确保 Agent 不会编造不存在的特性。查找 API 文档Find the documentation for the React Router v7 loader API.错误排查Im getting Error: hydration mismatch in Next.js. Search for recent solutions.Agent 会搜索 GitHub issues、StackOverflow 与论坛等来源找到超出其基础训练集的新鲜修复方案。检索 落地组合工作流先 Search「How do I implement auth with Supabase?」再用web_fetch抓取具体文档 URL最后让 Agent 基于检索到的模式生成auth.ts文件——搜索给摘要web_fetch给原文细节两者互补。与web_fetch工具的分工参考文档「Next steps」中提到的 web_fetch 工具参考 值得对照理解google_web_search面向「不知道答案在哪个页面」的开放式查询返回合成摘要 引用web_fetch面向「已知具体 URL」的深度抓取把页面正文去除广告与导航直接喂入上下文。两者在注册表中是并列的两个Kind.Search类工具可按需分别启用。验证与测试从单元测试到端到端集成测试仓库为该工具提供了两层测试验证了「声明—校验—执行」链路的正确性单元测试web-search.test.ts 覆盖参数校验query为或纯空白 时均返回「query 不能为空」错误正常路径与无结果路径分别验证Web search results for ...与No search results ...的llmContent文本grounding 引用对含groundingChunks/groundingSupports的模拟响应验证引用插入包括多字节字符场景错误路径验证ToolErrorType.WEB_SEARCH_FAILED的返回结构。端到端集成测试google_web_search.test.ts 则验证真实会话中的自动调用。其配置与流程await rig.setup(should be able to search the web, { settings: { tools: { core: [WEB_SEARCH_TOOL_NAME] } }, }); result await rig.run({ args: what is the weather in London }); const foundToolCall await rig.waitForToolCall(WEB_SEARCH_TOOL_NAME);测试要点通过tools.core白名单显式启用google_web_search后输入时效性问题伦敦天气断言 Agent确实发起了该工具的调用且最终输出包含weather、london相关内容。同时测试对 CI 环境的网络抖动做了容错捕获 network/timeout 错误时跳过而非失败。这也印证了前文「注册受配置控制」的推断工具白名单是控制 Agent 联网能力的关键开关。小结一次工具调用背后的完整链路将参考文档的三句行为描述映射回源码google_web_search的完整链路可以概括为声明与注册default-legacy.ts 定义query参数的 JSON Schemaconfig.ts 按配置注册到工具注册表参数校验Schemarequired约束 validateToolParamValues 双重把关服务端检索以model: web-search委托 Gemini API 完成 Google Search 与摘要合成execute引用标注基于groundingMetadata的groundingSupports按 UTF-8 字节位置倒序插入[n]内联标记并追加Sources:编号来源列表优雅降级空结果、取消、失败分别有独立的非中断式返回失败时携带ToolErrorType.WEB_SEARCH_FAILED供上层决策。这套机制让 Gemini CLI 在终端 Agent 场景下具备了可信的实时信息获取能力答案来自合成摘要但每一处关键论断都可通过内联标记回溯到具体来源兼顾了检索效率与事实可验证性。【免费下载链接】gemini-cliAn open-source AI agent that brings the power of Gemini directly into your terminal.项目地址: https://gitcode.com/GitHub_Trending/gemi/gemini-cli创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进