为 Grok 模型定制 SurfSense 主 Agent 系统提示词:provider_hints 的设计逻辑与多模型适配实践
【免费下载链接】SurfSenseOpen-source NotebookLM alternative. Research the open web with live data(Reddit, YT, IG, TikTok, Indeed, Google Search, Maps etc) through one platform, API or MCP server. Join our Discord: https://discord.gg/ejRNvftDp9项目地址: https://gitcode.com/GitHub_Trending/su/SurfSense
导读
Grok 是 xAI 发布的对话式大模型,在工具调用与推理场景中有着与 Anthropic、OpenAI 不同的输出习惯。SurfSense(开源 NotebookLM 替代方案,通过一个平台、API 与 MCP Server 研究 Reddit、YouTube、Instagram、TikTok、Indeed、Google Search、Maps 等实时网络数据)在为其主 Agent 构建系统提示词时,采用了"通用骨架 + 按模型定制"的分层架构:通用行为约束由core_behavior.md、routing.md等公共片段保证,而每个具体模型则通过一份provider_hints提示片段注入专属风格与纪律。本文以grok.md为主线,讲解该机制的设计原理、Grok 提示词片段的逐条语义,以及 SurfSense 如何让同一套多 Agent 编排在不同模型上保持一致的输出质量。
一、背景:为什么主 Agent 的系统提示词需要按模型拆分
1.1 多模型接入带来的一致性问题
SurfSense 的主 Agent 是一个多 Agent 编排体系:用户提问后,主 Agent 需要决定调用哪个研究子 Agent(specialist)、使用哪些工具、如何引用来源,最终生成回答。这个"决策大脑"可以运行在多种模型上。仓库中surfsense_backend/app/agents/chat/multi_agent_chat/main_agent/system_prompt/prompts/providers/目录下并列存放了 9 份提示词片段:
anthropic.md、google.md、grok.md、kimi.md、deepseek.md(各家专有模型)openai_classic.md、openai_codex.md、openai_reasoning.md(OpenAI 三种形态)default.md(空文件,作为无特定适配时的回退)
不同模型的"性格"差异是客观存在的:有的模型偏向一次性并行发起多个工具调用,有的模型擅长先规划再行动,有的模型对引用格式的敏感度不同。如果对所有模型下发同一套提示词,输出质量与工具调用效率都会参差不齐。因此 SurfSense 将提示词分成两层:
- 公共层:
core_behavior.md、kb_first.md、routing.md、output_format.md、refusal_and_limits.md、reminder.md等,对所有模型一致; - 模型专属层:
providers/*.md中的<provider_hints>片段,针对具体模型的特性给出补充纪律。
1.2 组装流程:compose.py 中的固定顺序
主 Agent 系统提示词由 builder/compose.py 中的build_main_agent_system_prompt()函数按固定顺序拼装。其文档注释明确给出了默认顺序:
<agent_identity> [user's custom_system_instructions, if any] <core_behavior> # default body <knowledge_base_first> # default body <dynamic_context> # always <routing> # default body <specialists> # always (dynamic roster) <tools> # always (vertical-slice) <memory_protocol> # default body <citations> # always <output_format> # always <refusal_and_limits> # always <reminder> # always函数签名build_main_agent_system_prompt(..., model_name: str | None = None)预留了model_name参数——从源码结构可以推断,这正是系统提示词按运行模型动态选择 provider 片段的接入点。所有提示片段通过 builder/load_md.py 的read_prompt_md(filename)从app.agents.chat.multi_agent_chat.main_agent.system_prompt.prompts包内读取(使用importlib.resources定位资源文件,文件不存在时返回空字符串,保证片段缺失不会导致组装失败)。
需要强调两点设计细节:
custom_system_instructions是"加法"而非"替换":用户自定义指令被插入 identity 与默认正文之间,平台级的安全网(KB-first、routing、citations、输出格式、拒绝规则)永远生效;use_default_system_instructions=False会跳过 4 个"default body"片段,但 always-on 的平台片段(dynamic_context、specialists、tools、citations、output_format、refusal_and_limits、reminder)依然保留。
二、Grok 提示词片段逐条解析
grok.md全文如下(位于 prompts/providers/grok.md):
<provider_hints> You are running on an xAI Grok model (SurfSense **main agent**). Maximum terseness: - Fewer than 4 lines unless detail is requested; skip preamble/postamble. Tool discipline: - Typically one investigative tool per turn unless several independent read-only queries are clearly needed; don't repeat identical calls. Attribution: - When citations are **enabled** (see citation block above) and you answer from labelled passages, cite with the bare `[n]` label exactly as specified there. - When citations are **disabled**, never emit `[n]` or `[citation:…]` — plain prose and links per tool guidance. Style: - No emojis unless asked; flat lists for short answers.整份片段由 4 个部分组成,每个部分对应一个维度的纪律约束。
2.1 身份声明:让模型知道自己是谁
首行You are running on an xAI Grok model (SurfSense **main agent**).是一个身份锚定。它同时完成两件事:
- 告诉模型它的底层实现是 xAI Grok,暗示其已知的工具调用与输出习惯;
- 强调它是 SurfSense 的main agent,即整个多 Agent 体系中的决策中枢,而非某个专项子 Agent——这与
routing.md(路由规则)和specialists动态名册的职责划分相呼应。
类似的模式可见于kimi.md("You are running on a Moonshot Kimi model (Kimi-K1.5 / Kimi-K2 / Kimi-K2.5+)")、google.md("You are running on a Google Gemini model"),说明身份声明是 provider 片段的通用约定。
2.2 Maximum terseness:极限简洁策略
Grok 的提示词将"简洁"推到极致:
- 少于 4 行:除非用户明确要求详细回答,否则默认输出不超过 4 行文本;
- 跳过开场白与收尾语:不要 "Sure!"、"Here's the answer!" 这类客套话。
这与公共层core_behavior.md中的要求("Be concise and direct. No preamble"、"Don't narrate intent — just act")方向一致,但把量化阈值(4 行)写死,属于对 Grok 模型的强约束。对比之下:
google.md要求"少于约 3 行散文"、使用 GitHub 风格 Markdown;kimi.md强调"行为偏向"——默认用工具行动而非用文字描述方案;- Grok 的定位则是最少字数 + 最少铺垫,把篇幅让给工具调用与结果本身。
2.3 Tool discipline:单轮单工具为主
Grok 的工具纪律是:
- 每轮通常只调用一个调查类工具,除非确实需要多个相互独立的只读查询;
- 不重复发起相同调用,避免浪费上下文窗口。
这是一个与 Kimi 形成鲜明对比的设计决策:kimi.md明确鼓励"在单次响应中输出多个互不干扰的工具调用——并行是这个模型最大的效率优势",而 Grok 走的是"稳扎稳打、逐轮推进"路线。两种策略没有对错之分,本质是模型能力画像不同:
| 维度 | Grok(grok.md) | Kimi(kimi.md) |
|---|---|---|
| 工具调用节奏 | 每轮通常 1 个调查工具 | 单响应并行发起多个不冲突的调用 |
| 重复调用 | 明确禁止重复相同调用 | 未显式禁止,但要求不啰嗦 |
| 叙事风格 | 跳过前言后记,直入主题 | 不预演、不道歉,用状态行合并进度 |
| 行动偏好 | 简洁优先 | 默认行动优先(action bias) |
从源码结构看,这种按模型差异化的纪律来自同一套build_tools_section()工具清单(由enabled_tool_names/disabled_tool_names控制可见工具),但"怎么用工具"的软约束则由 provider 片段差异化注入。
2.4 Attribution:引用开关下的双态行为
引用纪律是 provider 片段中最精细的部分,它要求模型感知当前会话的引用开关状态并做出不同反应:
- 引用开启时(citations enabled):如果回答基于带标签的段落,必须使用
[n]裸标签原样引用,即"exactly as specified there"; - 引用关闭时(citations disabled):绝不输出
[n]或[citation:…],改用纯散文 + 工具指引中的链接。
这一"双态"设计正好对应 prompts/citations/on.md 中定义的引用协议。该协议要求:[n]标签紧跟其所支撑的论断之后;多个来源叠加为[1][2];标签必须原样复制、不得重编号;只写裸[n],不写[citation:...]、不加 Markdown 链接、不建 "References" 章节;没有标签支撑的论断一律不引用、绝不虚构。
值得注意的是,引用是否开启由组装期的build_citations_section(citations_enabled=...)决定(见 builder/sections/citations.py),而 Grok 提示词主动将"两种状态各自该怎么写"写入模型约束,防止模型在引用关闭时仍然习惯性输出 citation 标记——这在实际部署中是一个高频踩坑点,因为许多模型一旦在系统提示词中见过[n]格式,就会在关闭状态下"惯性输出"。
2.5 Style:无 emoji + 扁平列表
最后一条风格约束:
- 不用 emoji,除非用户明确要求;
- 简短回答用扁平列表(flat lists)。
emoji 禁令与 SurfSense 面向专业研究场景的定位一致:研究型 Agent 的输出应当被直接复制进文档、报告或引用系统,表情符号会污染纯文本管线。扁平列表则降低了短回答的解析成本,方便后续被引用解析器或 UI 渲染。
三、横向对比:Grok 与其他 provider 片段的差异
将grok.md与同目录其他片段对比,可以清晰地看出 SurfSense 的"一模型一纪律"思路:
| 片段 | 核心主题 | 代表约束 |
|---|---|---|
grok.md | 极限简洁 + 单工具纪律 | 少于 4 行;每轮 1 个调查工具;引用双态 |
google.md | 工作流四步法 | Understand → Plan → Act → Verify;不越权声明工具 |
kimi.md | 行动偏向 + 强并行 | 默认行动而非描述;单响应并行多调用;事实核查 |
anthropic.md | Claude 行为适配 | 仓库中存在,具体条款以 文件 为准 |
deepseek.md | 深度求索模型适配 | 同上,见 文件 |
openai_classic.md/openai_codex.md/openai_reasoning.md | OpenAI 三种形态 | 经典 / Codex / 推理模型各自的行为画像 |
default.md | 空回退 | 无额外约束 |
此外,从 model_list_fallback.json 与tests/unit/services/test_auto_model_pin_service.py中都能看到 grok 相关模型名的存在,说明 Grok 系列是 SurfSense 模型清单中的正式成员,该片段服务于真实的模型接入链路(可结合 auto model pinning 等模型选择机制使用)。
四、实战启示:如何为自家 Agent 编写 provider_hints
读完grok.md,可以提炼出一套可复用的 provider 提示词编写方法论:
4.1 识别模型的能力画像
写 provider 片段前先回答三个问题:
- 该模型擅长并行工具调用还是串行深挖?(Grok 取串行、Kimi 取并行)
- 该模型的输出默认冗长还是简洁?(Grok 需要硬性行数上限)
- 该模型对引用格式的"惯性"有多强?(引用关闭时是否容易误输出 citation 标记)
4.2 用量化约束代替形容词
"要简洁"是无效约束,"少于 4 行"才是可执行约束。grok.md的 4 行、google.md的 3 行散文上限、kimi.md的"单响应并行"都是可被模型直接遵循的量化指令。
4.3 覆盖"开/关"双态行为
任何与平台开关(引用、工具启用、自定义指令)联动的纪律,都要显式写出两种状态各自的行为,避免模型在状态切换时沿用默认习惯。
4.4 与公共层正交
provider 片段只补充模型特性相关的差异,公共行为(知识库优先、路由、拒绝规则、输出格式)交给core_behavior.md等公共片段,保证切换模型不会破坏平台安全网。
五、总结
grok.md是 SurfSense 多模型适配体系中的一个小而关键的模块:它以<provider_hints>片段的形式,为 xAI Grok 模型注入"极限简洁、单工具纪律、引用双态、无 emoji"四项专属约束,与公共提示词层、组装器compose.py、引用协议citations/on.md协同工作。从源码结构可以推断,build_main_agent_system_prompt()的model_name参数即为 provider 片段的选择入口,实际部署时只需在系统提示词组装阶段传入当前运行模型的名称,即可让同一套多 Agent 编排在不同模型上输出风格一致、纪律统一的结果。对于任何希望将多 Agent 产品接入多模型服务商的研究型应用,这套"通用骨架 + 模型专属 hints"的模式都值得直接借鉴。
【免费下载链接】SurfSenseOpen-source NotebookLM alternative. Research the open web with live data(Reddit, YT, IG, TikTok, Indeed, Google Search, Maps etc) through one platform, API or MCP server. Join our Discord: https://discord.gg/ejRNvftDp9项目地址: https://gitcode.com/GitHub_Trending/su/SurfSense
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考