如果你过去一年也在坚持写技术博客,或者至少要维护一份团队技术文档,你大概率会遇到同一个问题:真正耗时的不是“写”,而是把散落在代码、聊天记录、笔记软件里的信息重新拼起来,形成一段别人能看懂的上下文。
我在反复经历这个过程之后,对 LLM 写作这件事有了一个和最初认知完全不同的判断:
LLM 写作的核心价值,不在于“让 AI 替你写”,而在于让“素材检索、上下文整理、初稿生成、人工修订”这个链条变成一条可复用、可自动化的工作流。它改变的不是你对文字的控制力,而是你整理信息的方式。
这篇文章会用一套完整的实践路径,讲清楚我是怎么理解和使用这条工作流的。内容包括 LLM、RAG、向量数据库、嵌入模型、Agent 编排等关键概念,以及一套可以实际跑起来的最小实现。无论你是 CSDN 技术作者、团队文档维护者,还是刚接触 LLM 的新手,读完都能从中找到可以落地的部分。
1. 这篇文章真正要解决的问题
很多接触 LLM 的开发者,第一次尝试用 AI 写文章,做法往往是这样:把主题丢给 ChatGPT 或类似的对话大模型,让它生成一篇 3000 字文章,然后复制粘贴。
这种做法的问题在于:生成的文字很流畅,但信息密度极低。模型不了解你过去的实践,不知道你踩过哪些坑,也不认识你的项目背景。它只是在用通用的语言模式生成一篇“看起来合理”的文章。你不敢直接发布,最后还是得重新写一遍。
这里真正要解决的问题,是技术写作中的“上下文断层”。
一篇高质量技术博客,通常由三类材料构成:
- 你通过实验得到的结论和数据。
- 你在代码、日志、配置中遇到的问题与解决办法。
- 你长期积累的项目背景和个人经验。
这三类材料大多不是结构化的,它们散落在笔记软件、命令行记录、代码仓库甚至聊天记录里。传统写作流程中,你必须手动把这些素材捞出来,再按逻辑串联成文。这个过程极其消耗精力,而且往往在你最想写作的时候,素材找不齐,状态就断了。
LLM 写作工作流的思路是:先用向量检索把你积累的笔记和资料找出来,再把这些资料作为上下文交给大语言模型生成初稿。模型不认识你,但检索系统认识你的笔记,二者结合之后,输出质量会明显高于“空对空”生成。
所以这篇文章要解决的核心问题可以概括成一句话:如何用工程化的方式,把“个人素材”和“大模型生成能力”连接起来,形成一套完整的技术写作辅助系统。
如果你正准备开始接触 RAG,或者想搭建一个个人知识库助理,这篇文章同样适用。技术写作只是这套组合拳的一个常见场景。
2. 核心概念:LLM、RAG、向量库与编排框架
在进入代码之前,先厘清几个概念。因为 LLM 写作工作流里的每个模块,本质上都是在解决某一类信息处理问题。
2.1 大语言模型(LLM)
LLM 就是大语言模型。它的能力本质是“根据已有上下文预测下一个 token”。这里的 token 可以粗略理解为词或子词。它知道大量的通用知识,也擅长模仿各种文体,但它不知道你的私有资料,除非你把这些资料放进输入文本里。它也不是数据库,不应该被用来“凭记忆回答”你项目中的具体事实。
在写作工作流中,LLM 负责三个任务:提炼要点、组织段落、生成初稿。这三个任务对模型的要求并不高,真正影响质量的是上下文中是否包含充分的素材。
2.2 上下文窗口
上下文窗口指的是模型一次能接收的最大 token 数。你可以把它理解为模型的“工作台面”。台面越大,能摆出来的资料越多。但技术笔记和日志往往很长,无法全部塞进窗口,所以需要检索模块先从资料堆里挑出最相关的部分。
这也是为什么很多知识库工具都采用“检索 + 生成”的组合,而不会简单地把所有内容都丢给模型。
2.3 检索增强生成(RAG)
RAG 的全称是 Retrieval-Augmented Generation,检索增强生成。它的流程可以拆成三步:
- 把个人文档切分成片段,并转成向量,存入向量数据库。
- 用户提出问题时,先将问题转为向量,再从向量库中检索最相关的片段。
- 把检索到的片段和用户问题一起拼进 prompt,交给 LLM 生成回答。
RAG 解决的核心问题,是让模型“在回答前先查资料”。技术写作中,资料就是你的历史笔记和实验记录。引入 RAG 之后,模型的输出不再依赖它训练时记住的内容,而是基于你提供的素材。
2.4 向量化与向量数据库
要让计算机在大堆文档中做“语义相似度检索”,不能直接比较文本,需要先把文本转成向量。嵌入模型(Embedding Model)做的事,就是把文本映射到一个高维向量空间。语义相近的文本,向量距离也更近。
向量数据库负责存储这些向量,并提供高效的相似度检索。常见的开源方案包括 Chroma、FAISS、Qdrant、Milvus。个人写作场景中,Chroma 或 FAISS 足够用,不需要引入重型的分布式数据库。
2.5 编排框架
当你的工作流不再只是“一个 prompt 调一次模型”,而是需要串联检索、重写、分章节生成、人工审核等多步操作时,就需要编排框架。编排框架可以是简单的 Python 函数链,也可以是完整的 Agent 框架。
这里引入一个关键概念:Agent。Agent 可以理解为一个能自主调用工具的 LLM 程序。它不只会“生成文本”,还能根据任务决定调用检索、访问数据库、运行命令。在写作场景中,一个 Agent 可能先根据主题搜索笔记,再根据笔记列提纲,再逐节生成内容,最后调用某个格式检查工具。
另一个相关的协议是 MCP,即 Model Context Protocol。它像是一种“模型工具接口标准”,让 LLM Application 能够以一种统一的协议连接外部工具和数据源。如果你需要把内部知识库、数据库、甚至绘图工具都接入同一个 LLM Agent,MCP 是一个值得关注的趋势。
2.6 传统写作流程与 LLM 工作流对比
| 环节 | 传统手写流程 | LLM 写作工作流 |
|---|---|---|
| 素材收集 | 手动搜索笔记和聊天记录 | 向量检索自动召回 |
| 上下文整理 | 人工理解并拼接材料 | 系统拼装 prompt 上下文 |
| 初稿生成 | 从零开始组织语言 | 模型基于素材生成初稿 |
| 修订 | 边写边改,反复重写 | 人工聚焦结构和事实校验 |
| 可复用性 | 每篇文章重复劳动 | 同一知识库持续复用 |
真实项目里,这套工作流并不神秘,也不需要一开始就上 Agent 和 MCP。先用最小成本把“向量检索 + LLM 生成”跑通,再逐步扩展,是更稳妥的路线。
3. 环境准备与前置条件
下面进入实操部分。我会用 Python 实现一套最小可用的 LLM 写作工作流。为了避免把文章变成“指定版本说明书”,这里的版本信息只做参考,重点演示通用思路。
3.1 运行环境
我目前的示例基于 Python 3.10+。你需要确认本机已经安装了 Python 和 pip。如果你的系统同时存在 Python 2 和 Python 3,建议用python3和pip3命令区分。
还需要准备以下几种环境之一作为模型服务:
- 在线大模型 API,支持 OpenAI 兼容接口。
- 本地部署的模型服务,例如 Ollama、llama.cpp 等。
- 企业内部统一模型网关。
无论使用哪种,关键是拿到一个可以调用的接口地址和密钥。如果你想先跑通流程,推荐使用本地模型或测试环境的 API,成本低,速度也足够。
3.2 安装依赖
需要安装的 Python 包有三个类别:大模型调用、向量数据库、文本处理。下面命令可以一次性安装基础依赖:
pip install openai chromadbopenai官方 Python 库不仅支持 OpenAI 的服务,也兼容大部分提供 OpenAI 风格接口的模型服务,因此你可以通过修改base_url来连接本地模型或其他服务。chromadb是轻量向量数据库,适合个人知识库场景。
如果后续使用 FAISS,再单独安装:
pip install faiss-cpu3.3 模型与密钥配置
不要直接把 API 密钥写进代码文件。这是很多新手容易忽略的安全问题。推荐使用环境变量,或独立配置文件,并加入.gitignore。
在命令行临时设置环境变量:
export LLM_API_KEY="your-api-key" export LLM_BASE_URL="https://your-model-service.example.com/v1"如果使用 Windows PowerShell:
$env:LLM_API_KEY="your-api-key" $env:LLM_BASE_URL="https://your-model-service.example.com/v1"如果你不知道模型服务地址,本地运行 Ollama 后,默认地址一般是http://localhost:11434/v1,模型名以你拉取的模型为准。这些细节建议以你所用工具的官方文档为准。
4. 第一步:搭建一个能调用的 LLM 文本处理模块
这个模块是整个工作流的地基。它只负责一件事:把一段文本和你的指令一起发给模型,拿到生成的文本。后面所有的摘要、改写、初稿生成,都基于这个函数。
新建一个文件llm_text.py:
# 文件路径:llm_text.py import os from openai import OpenAI client = OpenAI( api_key=os.environ.get("LLM_API_KEY"), base_url=os.environ.get("LLM_BASE_URL"), ) def chat(system_prompt: str, user_prompt: str, temperature: float = 0.3) -> str: """ 通用 LLM 调用函数。 :param system_prompt: 系统提示词,用来设定角色和规则。 :param user_prompt: 用户输入内容,包含任务描述和素材。 :param temperature: 采样温度,越低越稳定。 :return: 模型生成的文本。 """ response = client.chat.completions.create( model=os.environ.get("LLM_MODEL", "your-model-name"), messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=temperature, ) return response.choices[0].message.content这里的关键逻辑很简单:
client在模块加载时创建,复用连接,避免重复初始化。system_prompt控制模型角色和输出风格。user_prompt是每次任务的核心输入。temperature设为 0.3,是为了让技术文书类输出更稳定,减少发散。
现在用一个真实的技术笔记片段测试这段代码。假设你在一个运维项目中记录了这样一段笔记:
今天把服务从单实例扩容到三实例,应用负载确实下降了。但是 Redis 缓存命中率从原来的 95% 掉到了 80% 左右。排查后发现,热点 key 分散到了不同实例的本地缓存中,导致每个实例命中率都变低。后来把缓存热点 key 统一放回 Redis,命中率才恢复。调用这个函数:
# 文件路径:test_llm_text.py from llm_text import chat note = """ 今天把服务从单实例扩容到三实例,应用负载确实下降了。 但是 Redis 缓存命中率从原来的 95% 掉到了 80% 左右。 排查后发现,热点 key 分散到了不同实例的本地缓存中, 导致每个实例命中率都变低。后来把缓存热点 key 统一放回 Redis,命中率才恢复。 """ system_prompt = "你是一名技术写作助手,擅长把零散的技术笔记整理成逻辑清晰的中文文字。" result = chat(system_prompt, f"请根据下面的笔记整理一段可供博客引用的技术总结:\n\n{note}") print(result)这一步跑通之后,你已经拥有了最核心的生成能力。但只靠这个模块,模型仍然不知道你过去写过的其他笔记。下一步就是建知识库。
5. 第二步:把个人笔记变成可检索的知识库
要让 LLM 生成的内容带有“你的上下文”,必须先把散落的笔记向量化并存储起来。这里使用 Chroma 的本地持久化模式。
新建一个文件knowledge_base.py:
# 文件路径:knowledge_base.py import chromadb CHROMA_PATH = "./writing_kb" COLLECTION_NAME = "tech_notes" # 默认使用 Chroma 内置的 embedding 函数, # 如果要替换为模型 API 的 embedding,可以在此传入自定义 embedding function。 client = chromadb.PersistentClient(path=CHROMA_PATH) collection = client.get_or_create_collection( name=COLLECTION_NAME, metadata={"hnsw:space": "cosine"}, ) def add_note(note_id: str, text: str, metadata: dict = None): """ 向知识库添加一条笔记。 :param note_id: 笔记的唯一 ID。 :param text: 笔记正文。 :param metadata: 附加元信息,例如标签、日期、来源。 """ collection.add( ids=[note_id], documents=[text], metadatas=metadata or {}, ) def search_notes(query: str, top_k: int = 3): """ 根据查询内容从知识库中检索最相关的笔记。 """ results = collection.query( query_texts=[query], n_results=top_k, ) return results这段代码有几点值得说明:
PersistentClient会把数据持久化到本地目录./writing_kb,重启后数据还在。- collection 类似数据库中的表,
hnsw:space: cosine表示用余弦距离衡量向量相似度。 add_note是写入接口,search_notes是检索接口。
写入一条笔记:
# 文件路径:test_kb.py from knowledge_base import add_note, search_notes add_note( note_id="redis-cache-hit-001", text="服务从单实例扩容到多实例后,本地缓存导致热点 key 分散,Redis 命中率下降。" "解决思路:热点 key 统一放回 Redis,或使用分布式缓存。", metadata={"tag": "redis", "date": "2025-01-10"}, ) results = search_notes("多实例部署后缓存命中率下降怎么办?", top_k=2) print(results["documents"][0])运行后,你会在终端看到检索到的笔记片段。如果检索结果和你的问题明显相关,说明知识库已经可用。
这里插入一个常见注意点:分块大小会影响检索效果。笔记如果太长,检索到的片段可能是一大段无用信息;如果太短,又会缺失上下文。个人写作场景中,按“语义小节”切分是一个比较稳妥的策略。可以先用整篇笔记入库,后续检索效果不佳,再调整分块策略。
6. 第三步:组装完整的 RAG 写作助手
现在把 LLM 模块和知识库模块组合起来,形成一个完整的 RAG 工作流。
新建文件writing_agent.py:
# 文件路径:writing_agent.py from llm_text import chat from knowledge_base import search_notes SYSTEM_PROMPT = """你是一名技术博客写作助手。你的任务基于用户提供的参考资料,撰写技术文章初稿。 要求: 1. 标题要具体,避免“从零开始”“深入浅出”这类空泛表达。 2. 正文包含背景、操作步骤、验证方式、注意事项四个部分。 3. 尽量保留参考资料中的技术细节,不要泛化。 4. 如果参考资料不足以支撑某个结论,直接写明“该部分需要补充资料”,不要编造。 """ def build_context(query: str, top_k: int = 3) -> str: """检索知识库,拼装上下文。""" results = search_notes(query, top_k=top_k) documents = results["documents"][0] return "\n---\n".join(documents) def write_draft(topic: str, top_k: int = 3) -> str: """根据主题生成技术文章初稿。""" context = build_context(topic, top_k=top_k) user_prompt = f"""请根据以下主题写一篇技术文章初稿。 写作主题:{topic} 参考资料: {context} """ return chat(SYSTEM_PROMPT, user_prompt, temperature=0.3) if __name__ == "__main__": topic = "多实例部署后 Redis 缓存命中率下降" draft = write_draft(topic) print(draft)整个流程的关键点在于:build_context先把相关笔记从向量库中捞出来,write_draft再把笔记拼进 prompt。模型没有直接“回答”,而是在给定的素材范围内组织语言。
运行命令:
python writing_agent.py预期输出是一篇结构完整的中文文章初稿。它不一定每个细节都准确,但至少包含了背景、步骤和问题分析,比直接让模型“凭记忆写”要靠谱得多。
如果你希望生成更长的文章,可以把write_draft拆成两个步骤:先让 LLM 列出大纲,再对每个章节分别执行一次“检索 + 生成”。这样每次生成的内容更聚焦,上下文窗口的压力也更小。
7. 运行结果与效果验证
技术文章不能写“运行即可”就结束,需要明确验证标准。这里给出三个维度的验证方法。
7.1 验证生成结果的信息覆盖度
一篇合格的技术初稿,至少要覆盖你笔记中的核心结论。在测试时,你可以在 prompt 中加入一个系统指令:
SYSTEM_PROMPT = """你是一名技术博客写作助手。生成结束后,必须列出“本次参考了哪些技术要点”。"""这样你可以快速检查模型是否真的使用了检索到的笔记,而不是自己在编。
7.2 验证检索质量
如果 LLM 输出内容和你的笔记完全不相关,问题很大可能不在生成,而在检索。你可以在search_notes后单独打印results["documents"],观察召回结果是否合理。
7.3 验证幻觉
最简单的幻觉验证方法,是让模型在输出中标注信息来源段落引用的原文关键句。在技术写作中,我通常要求模型使用“根据参考资料,……”这类句式,避免把推测写成既定结论。
下面是一个判断项目是否为“验证成功”的检查列表:
| 检查项 | 通过标准 |
|---|---|
| 检索结果相关 | 返回的笔记片段与主题语义相关 |
| 输出覆盖关键点 | 初稿包含背景、步骤、验证、注意点 |
| 不胡编细节 | 关键结论在参考资料中有对应表述 |
| 格式可复用 | 输出结构稳定,能直接进入人工修订环节 |
| 调用成本可接受 | 单次运行耗时和 token 消耗在可接受范围 |
如果失败,第一步不是改 prompt,而是查看检索结果。RAG 项目里大部分问题都出在“没检索到该检索的内容”,模型只是忠实地下游生成。
8. 进阶方案:编排框架、MCP 与 Agent
最小方案跑通之后,你会发现一个局限:上面的代码是“硬编码流程”。一旦你想加入更多环节,比如自动抓取网页、调用绘图工具、读取数据库,就需要不断改代码。这种场景下,编排框架和 Agent 概念就派上用场了。
8.1 为什么需要编排框架
编排框架要解决的是多步骤任务的组织问题。在写作场景中,典型的多步骤任务可能是:
- 根据主题抓取相关网页内容。
- 检索个人笔记库。
- 整理大纲。
- 逐节生成内容。
- 调用格式检查工具。
- 输出最终 Markdown。
如果用最原始的 Python 写,几段流程也能完成,但很难维护。每个环节都要处理异常、重试、上下文传递,代码很快会变得复杂。
编排框架做的事情,是把这些环节抽象成“节点”,并提供状态管理和节点间通信机制。你可以把“检索笔记”和“抓取网页”都注册成工具,然后让 Agent 根据任务动态调用。
8.2 MCP 与 Agent
MCP(Model Context Protocol)是一种连接模型和外部工具的标准协议。你可以把它理解成“USB 接口”之于电脑:设备厂商只需要按标准接口实现,就能被不同系统识别。
在 LLM 写作工作流里,MCP 的价值在于让不同来源的工具、数据库和企业系统,都能以统一协议接入 Agent。你不需要为每个工具单独写一套适配代码,而是通过 MCP 配置接入。
近期中文技术社区中,Spring AI 相关讨论也经常出现。Spring AI 是 Java 生态中相对成熟的 AI 应用框架,它把模型调用、向量存储、Agent 编排纳入统一的编程模型。如果你本身是 Java 技术栈,可以考虑用它替代 Python 手写方案。
不过,MCP 和 Spring AI 的这些能力仍处于快速演进期,API 变化频繁。我建议先用最小的 Python 示例理解 RAG 原理,再根据实际项目需要选择框架,不要一上来就引入重依赖。
8.3 一个更贴近 Agent 的流程示意
真实的 Agent 流程可以用下面的伪代码表达:
# 文件路径:agent_flow_demo.py def agent_writer(topic: str): notes = retrieve_notes(topic) # 1. 检索笔记 web_data = fetch_web_pages(topic) # 2. 抓取网页(可选) outline = generate_outline(topic, notes, web_data) # 3. 生成大纲 draft = "" for section in outline.sections: section_context = retrieve_section_material(topic, section.title) draft += generate_section(section.title, section_context) draft += "\n\n" return post_process(draft) # 4. 格式检查和修订 result = agent_writer("多实例部署后的缓存一致性") print(result)这段代码不是直接可运行的完整实现,但它展示了从“线性 RAG”到“Agent 编排”的思维差异:系统需要在不同阶段动态决定检索什么、生成什么、校验什么。
9. LLM 精度问题:fp16、fp32、bf16 对写作任务的影响
很多读者会在社区里看到关于 LLM 精度问题的讨论,比如 fp16、fp32、bf16 的区别。这里用写作场景做一个简单分析,帮助你在选型时不被测试指标带偏。
9.1 三种常见精度格式
| 格式 | 占用内存 | 表示范围 | 典型用途 |
|---|---|---|---|
| fp32 | 4 字节 | 大 | 训练早期稳定计算 |
| fp16 | 2 字节 | 较小,容易溢出 | 部分推理场景 |
| bf16 | 2 字节 | 大,精度低 | 大规模训练和推理 |
fp16 的问题在于表示范围小,可能出现溢出。bf16 牺牲了尾数精度但保留了和 fp32 相同的大动态范围,所以在很多现代大模型训练和推理中被广泛使用。
9.2 对写作任务的实际影响
写作任务本质上是对文本分布的采样,对数值精度并不敏感。模型不需要小数点后很多位的精确计算,它需要的是在语义空间中稳定地走出一条合理路径。因此,在个人写作工作流中,你完全可以优先使用量化版本或 bf16 版本模型,获得更低的显存占用和更快的推理速度,而不必执着于 fp16 或 fp32 精度。
需要注意的是,如果你的场景涉及数值计算、工具调用 JSON 输出、或者模型需要精确地对齐结构化数据,精度和量化对结果的影响会明显增大。写作场景下,影响输出质量的首要因素往往是提示词、检索资料和上下文长度,而不是“最后几位精度”。
如果你打算在本地部署模型,建议参考模型发布方的推荐精度和量化方案,以官方文档为准,不盲目追求高精度。
10. 常见问题与排查思路
在搭建 LLM 写作工作流时,最容易遇到的几个问题如下:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 检索结果不相关 | 笔记分块过大或过小 | 打印检索到的文档片段 | 调整分块策略,或换更合适的 embedding 模型 |
| 模型输出出现编造内容 | 参考资料不足,或 prompt 未约束 | 在 prompt 中要求“来源不完全则明确说明” | 补充知识库笔记,降低 temperature |
| 日志中提示模型不存在 | 模型名配置错误 | 查看模型服务列表 | 确认实际模型 ID,填入环境变量 |
| 首次运行 chromadb 时下载模型失败 | 网络受限或默认模型不可用 | 查看报错日志 | 换用 API 嵌入模型,或配置代理方式访问 |
| 调用 API 超时 | 上下文过长或服务不稳定 | 查看服务端监控和错误日志 | 缩短 prompt 长度,增加重试机制 |
| 向量库数据一直增加,越来越慢 | collection 中数据冗余 | 检查 collection.count() | 删除过期数据,或按日期建多个 collection |
| 生成内容风格不像你 | 缺少个人风格样本 | 在知识库中存入自己过去的文章 | 增加“参考我的历史文章风格”示例 |
在这些问题中,最值得强调的还是第一条:检索质量是 RAG 的生死线。模型生成能力再强,如果检索系统没有把正确的资料放进上下文,产出效果也必然打折。遇到输出异常时,先从链路前端开始排查,而不是一味调整生成 prompt。
11. 最佳实践与工程建议
经过一段时间使用,我总结出几条比较稳定的工程建议。它们适合个人写作场景,也适合小团队的知识管理。
11.1 分块策略要“按语义切,而不是按行数切”
技术笔记中,一段完整的调试记录往往包含背景、操作、结论。按固定字符数量切块,容易把结论切丢。更推荐的做法是:
- 整理笔记时,用空行或标题划分语义块。
- 入库时按语义块插入。
- 为每个块添加元数据,例如项目名、日期、标签。
11.2 知识库的“写入质量”比“检索算法”更重要
很多人在优化 RAG 时,第一反应是换更复杂的检索算法。但个人知识库场景下,第一步应该做的是清洗数据。如果你存入的笔记本身有空话、结论不清,任何检索算法都无能为力。
建议在写入前加一个简单的质量检查流程:
def is_useful_note(text: str) -> bool: """简单过滤空泛笔记。""" if len(text) < 50: return False if "待补充" in text or "TODO" in text: return False return True11.3 使用环境变量管理密钥和模型配置
不要在代码库中提交真实密钥。生产或长期使用场景,建议使用.env文件加配置文件进行管理,并把敏感文件加入.gitignore。
示例.env文件:
LLM_API_KEY=your-api-key LLM_BASE_URL=https://your-model-service.example.com/v1 LLM_MODEL=your-model-name11.4 人工修订是不可或缺的环节
LLM 生成的初稿只适合作为“第二稿素材”,不能直接发布。至少要检查三个点:
- 技术结论是否正确,尤其是数据和命令。
- 参考资料引用是否真实。
- 文章结构是否符合你的博客习惯。
为了让人工修订更高效,可以在生成 prompt 中要求模型输出“初步校验问题清单”,让模型先把不确定的地方列出来。
11.5 控制上下文长度,避免 token 浪费
写作场景不需要把所有笔记都塞进上下文中。通过top_k控制召回数量,用max_tokens限制生成长度,可以显著降低成本。如果你的服务支持缓存历史对话,注意区分“可复用上下文”和“一次性任务上下文”。
11.6 给生成结果做版本管理
当你反复调 prompt 时,建议记录每个版本的 prompt 和输出结果。最简单的做法是按日期保存 prompt 模板:
# 文件路径:prompt_templates/20250110_writer_system.txt 你是一名技术博客写作助手。你的任务基于用户提供的参考资料,撰写技术文章初稿。 ...这样,当某次输出效果特别好时,你能回溯到当时的完整配置。
12. 总结与后续学习方向
LLM 写作工作流的核心,不是“让模型替你创造”,而是“把你已有的素材和模型的表达能力连接起来”。文章开头提到的那句话值得再强调一次:它改变的是信息整理方式,不是文字控制力。
从实际操作看,你不需要一次性搭建完整的 Agent 系统。先把最小 RAG 跑通,至少应该完成:
- 一个能稳定调用的 LLM 模块。
- 一个能存储个人笔记的向量知识库。
- 一个能把检索结果拼进 prompt 的写作助手。
- 一套确定的验证标准,用于判断输出是否可用。
后续值得深入的方向包括:更合理的分块策略、针对不同文章类型的提示词模板、多路召回、MCP 工具接入,以及把工作流打包成内部团队服务。
最后提醒一句:在把内部技术资料提交给任何外部模型服务前,先确认数据合规边界和最小权限原则。敏感代码、客户信息、内部架构图,不要在没有授权的情况下发送给外部 API。安全边界永远是第一位。
如果你准备开始实践,可以先从自己的旧笔记中挑 10 条有代表性的素材,按步骤跑通最小工作流。这套系统不会替你完成全部写作,但它能帮你把“找素材、搭框架、写初稿”这个最耗精力的阶段,压缩到几分钟之内。