
如果你正准备用 Grok Bot 搭一个可复用、能交活的自动化助手最该先准备的其实不是提示词而是一套 Bot 模板。这里的模板不只是把角色设定写进模板字符串而是把配置、请求、提示词、输出解析、日志和失败重试组织成一个可复现的代码骨架。市面上很多教程一上来就贴提示词看起来很有用但真正把项目从脚本升级成服务时缺少的反而是后面那套看不见的工程结构。这篇指南围绕 Grok Bot 模板场景讲清楚一个通用 Bot 模板可以怎么组织。适合两类人看一是刚拿到接口权限、想从零搭一个 Bot 的新手二是已经有脚本但在批量任务、日志和报错上反复踩坑的开发者。全文示例不是某个官方仓库的复刻而是把最常用的工程骨架拆开讲一遍。具体端点、模型名、鉴权方式要以你手上的服务文档为准这一点在落地时一定要确认。1. 先搞清楚你要的是提示词模板还是 Bot 工程模板1.1 提示词模板解决内容层Bot 模板解决系统层“Grok Bot 模板”这个名字容易被理解成一段漂亮的提示词。提示词模板当然重要但它只覆盖内容层系统提示怎么定义角色、用户输入怎么拼进上下文、输出要 JSON 还是 Markdown。真正让 Bot 长期可用的是外层那套代码骨架。我用一个例子说明。提示词模板里写了“你是一个客服助手只根据产品文档回答”这是内容层。但如果请求失败、超时、返回异常、批量任务跑到一半提示词并不能帮上忙。工程模板要处理的是统一配置 API Key、封装请求重试、解析模型返回、记录日志、控制并发、把结果按规则命名落到文件。所以第一件事是确认需求。如果你只是想快速试一句话对格式也不挑那不需要工程模板一段提示词就够了。但如果你要做连续对话、批量生成、定时任务、Webhook 通知或者多用户服务就必须把系统层搭起来。这篇指南主要讨论系统层模板因为它决定了项目能不能从“试验”走向“维护”。从标题里的“模板分享”也能看出这类内容通常有两层含义一是分享别人可以直接复制的一套提示词二是分享一套代码工程结构。我认为对大多数人更有价值的反而是第二层。提示词可以慢慢调代码骨架如果一开始就乱后面每加一个功能都要返工。1.2 一份合格模板的判定线我判断一个 Bot 模板能不能直接用不看界面漂不漂亮只看下面几条能不能通过一份配置文件切换模型、超时、温度等基础参数而不改业务代码。能不能在单条任务、批量任务、交互式服务三种运行方式下复用同一套请求封装。能不能把输入、输出、请求耗时、错误原因记录为结构化日志。能不能在失败时按规则重试而不是直接崩溃或产出乱文件。能不能在不修改提示词逻辑的情况下替换或扩展新的角色模板。这五条标准听起来基础但很多临时脚本都做不到。最常见的情况是代码里写死了一套提示词换成另一套角色就要复制整个文件或者批量任务没有重试逻辑跑到一半断了就要人工重来又或者输出文件永远只写一个 result.txt上一批结果直接被覆盖。模板的价值就在这里把“能跑”提升到“稳定、可维护地跑”。我见过不少项目第一条就卡在“能不能通过配置文件切换参数”。写代码的人可能觉得把超时时间写死在 requests.post 里没什么但真上线时服务端变慢、任务变多需要调参时才发现要改三四个文件。所以我对自己的模板第一条要求就是凡是明天可能变化的量都要在配置层暴露出来。2. 搭建前的环境与地基版本、接口、目录和配置2.1 我建议的运行条件先明确环境。如果你的 Bot 主要做单条对话和轻量批量任务一台普通开发机就够了。我通常按下面这套条件准备操作系统Windows 10/11、macOS、Linux 都可以。语言运行时Python 3.10 或 Node.js 18选你熟的。开发工具VSCode配合 Python 的 ruff/black或 Node 的 ESLint/Prettier。网络条件开发机能正常访问模型服务所在域名。依赖Python 侧用 requests、python-dotenvNode 侧对应 axios、dotenv。低配置机器也可以跑但要注意一点批量任务和并发不是只看 CPU还要看网络出口、服务端限流和单次请求耗时。如果机器内存很小批量前先估算单条日志和输出文件的大小别把几千条结果一次性堆在内存里。Python 下最简单的依赖安装命令是pip install requests python-dotenvNode 环境则根据你用的包管理器安装 dotenv 和 axios。这里不建议临时写一堆 curl 脚本试完就丢因为一旦接口数量变多你仍然需要一个统一的请求入口。2.2 接口访问信息从哪里拿在没有接口信息之前任何模板都只能空跑。一个正常的接口访问信息通常包含请求端点例如一个 HTTP URL指向模型服务或你的内部网关。认证方式常见的是请求头里的 Bearer Token 或自定义 Key。模型名称服务端支持的模型标识不是所有服务都叫同一个名字。请求格式有些服务兼容 OpenAI 格式有些有自己约定。这些信息要以服务文档为准。我的建议是先把文档里的最小请求样例跑通再开始设计模板。因为模板里的 client 层依赖实际请求格式格式没确认写好的封装全是猜。有一个很多人忽略的点接口文档里给的示例有时是 curl有时是 Python有时是网页调试器生成的代码。你需要手动确认字段名、大小写、是否带版本前缀。这里花十分钟确认能省掉后面一整天的排查。2.3 初始目录结构一个轻量但够用的模板我推荐下面这种目录结构grok-bot-template/ ├── .env.example ├── .gitignore ├── requirements.txt ├── config.py ├── client.py ├── prompt_loader.py ├── prompts/ │ ├── base_prompt.txt │ └── json_prompt.txt ├── data/ │ ├── input.jsonl │ └── output/ ├── run_single.py ├── run_batch.py └── logs/这个结构解决三个问题配置不散落在代码里提示词不混入业务逻辑输出和日志有固定目录。.env.example是好习惯它列出所有需要配置的变量名比一个空 .env 文件更清晰。真正的 .env 要加入 .gitignore避免把密钥提交进仓库。如果你用 Git 管理建议在第一次提交代码之前就把 .gitignore 写好。.env、logs/、data/output/这些目录都不应该进入版本库。模板文件要提交但执行产物和密钥不需要提交。注意模板工程里最重要的红线就是密钥不入库。哪怕只是内部仓库也建议用环境变量或密钥管理服务。3. 核心实现从配置到稳定回一个请求3.1 配置文件环境变量集中管理config.py 的作用是把散落在脚本里的接口地址、密钥、模型名、超时时间统一收口。示例import os from dotenv import load_dotenv load_dotenv() GROK_API_ENDPOINT os.getenv(GROK_API_ENDPOINT, https://your-model-service.example.com/v1/chat/completions) GROK_API_KEY os.getenv(GROK_API_KEY, ) GROK_MODEL os.getenv(GROK_MODEL, grok-model-placeholder) REQUEST_TIMEOUT int(os.getenv(REQUEST_TIMEOUT, 60)) MAX_RETRIES int(os.getenv(MAX_RETRIES, 3))这里把地址写成占位域名是因为实际端点差异很大。你拿到自己的端点后替换即可。理由也很直接如果代码里直接写死密钥以后换环境、换账号、换服务商都要全局搜索替换迟早出错。配置文件不一定要很复杂。做到两件事就够了一是所有可变量集中在一个文件里二是没有给值的变量要有默认值避免导入时报错。对于超时和重试这两个参数我建议一定要暴露出来因为它们跟服务端限流策略强相关线上调整时不需要改代码是最省心的。3.2 client.py统一请求封装client.py 是整个模板的心脏。它只负责一件事输入一条消息返回服务端结果并把可能出现的错误统一成我们认识的异常。import time import requests class GrokBotClient: def __init__(self, endpoint, api_key, model, timeout60, max_retries3): self.endpoint endpoint self.headers { Authorization: fBearer {api_key}, Content-Type: application/json, } self.model model self.timeout timeout self.max_retries max_retries def chat(self, messages, temperature0.7, max_tokens2048): payload { model: self.model, messages: messages, temperature: temperature, max_tokens: max_tokens, } last_error None for attempt in range(self.max_retries): try: resp requests.post( self.endpoint, headersself.headers, jsonpayload, timeoutself.timeout, ) if resp.status_code 400: raise RuntimeError(fHTTP {resp.status_code}: {resp.text[:500]}) return resp.json() except Exception as e: last_error e time.sleep(min(2 ** attempt, 10)) raise last_error这段代码刻意保持简单但已经有三个关键点认证头统一、超时统一、重试统一。重试时每次等待时间递增避免同一时间把所有请求打到服务端。这不是最优方案但适合作为模板起点。如果你的服务端提供的请求格式和字段名不一样只需要改 payload 这一段。有一点需要说明重试不是越多越好。如果错误是 401 或 403重试大概率还是失败因为密钥或权限根本没对。如果错误是超时或 5xx重试才有意义。所以在 client 里可以根据状态码决定要不要重试但这属于进阶设计新手先从统一重试开始更稳妥。3.3 prompt 管理模板字符串怎么分层prompts 目录用来保存提示词。不要把超长提示词写在 main 函数里。推荐的做法是把系统提示、用户输入模板、输出格式要求分开。base_prompt.txt 可以这样写你是一个自动化助手。 请根据用户输入给出明确、可执行的回答。json_prompt.txt 可以这样写用户输入{user_input} 约束 1. 只输出 JSON。 2. JSON 结构为 {answer: 你的回答, confidence: 0.0-1.0}在 prompt_loader.py 里提供加载和拼接函数from pathlib import Path def load_prompt(name: str) - str: return Path(prompts, name).read_text(encodingutf-8) def build_messages(user_input: str): system_prompt load_prompt(base_prompt.txt) user_prompt load_prompt(json_prompt.txt).format(user_inputuser_input) return [ {role: system, content: system_prompt}, {role: user, content: user_prompt}, ]这里的模板字符串就是最简单的模板语言。它让提示词可以被单独编辑、测试、版本管理不需要动代码。后续如果要换角色新增一个 prompt 文件即可。注意.format()只适合变量少的场景如果提示词里本身有大量花括号或其他需要转义的内容就要换更稳的方案比如用 Jinja2 或通过字符串替换。3.4 响应解析不要直接当字符串用模型返回体在不同服务里不一样但大多是嵌套 JSON。解析层要做的是从原始返回里提取“真正要写成文件的文本、状态信息和用法统计”。def extract_answer(raw): try: return raw[choices][0][message][content] except Exception: raise ValueError(f无法从响应中提取 answer原始响应: {str(raw)[:800]})这样写的意思是解析失败时把原始响应前 800 字符记录到日志而不是直接打印整个响应或者静默通过。很多时候输出为空不是模型没有回答而是返回结构里没有我们预期的字段。把所有解析逻辑集中在一个函数里后续换格式时只需要改一处。还可以加一个extract_usage函数把返回里的 token 数字统计出来写到 summary 文件里。这对判断成本很有用。3.5 日志设计单条任务也能回溯日志不是可有可无。至少要有时间、输入摘要、响应状态、耗时、错误信息。我用内置 logging 就够了import logging def get_logger(): logging.basicConfig( levellogging.INFO, format%(asctime)s | %(levelname)s | %(message)s, handlers[ logging.FileHandler(logs/bot.log, encodingutf-8), logging.StreamHandler(), ], ) logger logging.getLogger(__name__) return logger关键点日志文件用encodingutf-8否则中文容易乱码。写入日志时不要把完整密钥、完整用户敏感内容都打进去可以记录前 100 个字符作为摘要。这样排错时能看到是哪条输入出了问题又不会把整个会话内容暴露在日志文件里。4. 从单条到批量真正能复用的执行流程4.1 单条最小验证模板搭好后先不急着写批量。用 run_single.py 跑一条输入确认五件事接口通、认证过、提示词生效、返回解析成功、日志有记录。from config import ( GROK_API_ENDPOINT, GROK_API_KEY, GROK_MODEL, MAX_RETRIES, REQUEST_TIMEOUT, ) from client import GrokBotClient from prompt_loader import build_messages def main(): client GrokBotClient( endpointGROK_API_ENDPOINT, api_keyGROK_API_KEY, modelGROK_MODEL, timeoutREQUEST_TIMEOUT, max_retriesMAX_RETRIES, ) messages build_messages(请用一句话解释什么是模板字符串) raw client.chat(messages) answer raw[choices][0][message][content] print(answer) if __name__ __main__: main()单条跑通之后再把脚本交给批量。判断标准很简单如果单条在日志里能看到明确的状态码、耗时和 reply 片段说明链路通如果链路不通不要继续叠加批量逻辑否则你会分不清是网络错、解析错还是文件逻辑错。注意单条验证时不要跳过日志。很多人跑通后只看控制台输出结果在批量阶段遇到问题连“上一次成功时的请求耗时”都查不到。4.2 批量执行并发、限速、时间戳和重试批量任务不能简单理解成“循环调用单条”。要关心三件事输入从哪里来、输出写到哪、失败之后怎么办。输入我建议使用 JSONL一行一条记录每条带上 id 和 content。输出目录按批次命名output/20250101_batch01/ ├── result.jsonl ├── errors.jsonl └── summary.json批量脚本的核心逻辑可以这样拆读取输入文件逐行解析 JSON。对每一条执行 client.chat记录开始时间、结束时间。成功后把结果写入 result.jsonl。失败后把输入、错误类型、错误信息写入 errors.jsonl。最终统计成功数、失败数、总耗时、平均耗时写入 summary.json。并发不要一上来就拉满。建议先设 MAX_CONCURRENCY3观察单条耗时和服务端是否稳定再逐步提高。用 ThreadPoolExecutor 可以快速实现并发但注意写入文件时要加锁或者让每个线程各自负责一个 buffered writer 再统一合并。这里有一个容易踩的坑批量结果文件的命名如果只有时间戳第二次跑同一个批次容易产生歧义。最好把输入文件名、批次号、开始时间拼在一起避免覆盖。比如input_20250101_batch01_result.jsonl。命名规则越清晰后续复查越省事。4.3 从脚本到交互式 Bot 的改造点如果你的目标不是批量生成而是一个能对话的 Bot模板也要预留改造点。交互式 Bot 和批量脚本的最大区别在于需要维护上下文状态。我的建议是在 client 外层增加一个 Session 管理器。它负责保存这个会话的 messages 列表每次用户输入后追加一条 user 消息拿到回复后追加一条 assistant 消息。上下文长度要设上限通常按最近 10 到 20 轮内截断避免超出模型上下文窗口。交互式 Bot 还有两个小问题一是用户可能输入空内容要提前校验二是同一个用户同时发多条消息要按会话 ID 串行排队否则上下文会错乱。这些逻辑都可以放到模板里而不是在每次接入时重新实现。5. 参数怎么看、怎么调温度、超时、并发与结果判断5.1 常见参数及调整判断我把模板里最常用的参数整理成一张表方便对照。参数作用新手建议什么时候调整temperature控制输出随机性0.7需要更稳定时降到 0.2 到 0.4需要创意时升到 0.9max_tokens控制单次输出最大长度2048输出被截断时调大追求低延迟时调小timeout单次请求最大等待时间60 秒服务端慢或本地网络差时要调大max