尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LLM辅助写作实战:从API调用到RAG与Agent工作流

LLM辅助写作实战:从API调用到RAG与Agent工作流 在使用大模型辅助写作之前我经历过一段比较低效的时期每天面对空白文档不知道从哪下笔素材散落在各个文件夹里初稿改到第五遍的时候已经失去表达欲。后来我系统性地把 LLM 接入到写作流程中从调用 API 生成初稿到搭建 RAG 素材库再到用 Agent 自动检索资料整套链路跑通之后写作效率提升非常明显。这篇文章就是这段实践过程的全记录适合想用 LLM 改善写作流程的开发者也适合想入门 LLM 应用开发但还没有完整项目经验的后端工程师。读完你会掌握 LLM 写作应用的最小调用方式、结构化输出思路、精度选型、RAG 素材库和简易 Agent 的代码实现也就能把自己手头的内容生产流程真正跑起来。1. 理解 LLM 写作它到底在做什么1.1 从“写作”到“LLM 写作”先给一个比较直白的定义。LLM 写作就是借助大语言模型来辅助或自动完成与文字生产相关的任务比如生成初稿、改写润色、提炼摘要、拟标题、生成大纲、整理会议纪要等。这里的 LLM 既可以是云端 API比如 OpenAI 兼容接口也可以是本地部署的开源模型。从技术原理上看LLM 做写作本质上是“根据前文预测下一个 Token”。模型内部并不会有一本写作教科书它只是在海量文本上学习过词语之间、句子之间、结构之间常见的共现关系。当用户给出一个 Prompt 时模型会顺着概率分布生成一段看起来合理的文本。理解这一点很重要因为它决定了使用方式LLM 不是“替你写完文章”的终端编辑器而是“和你共同完成写作”的协作者。你需要给它清晰的目标、背景素材和风格约束它才能输出接近你预期的内容。1.2 常见应用场景LLM 写作常见的落地场景包括博客和技术文档的初稿生成先让模型生成章节骨架再由你补充细节和代码。营销文案与自媒体内容批量生成选题、标题、摘要人工润色后发布。会议纪要与信息压缩长文档翻译、提取要点、按模板生成周报。代码注释与 README 归档生成变量说明、接口文档、项目说明。多语言内容改写把中文材料翻译并调整成英文博客再检查准确性。这些场景有一个共同点信息组织成本高、存在明显的格式规律、需要大量重复劳动。LLM 写作解决的问题不是“让机器替代人类思考”而是把“从 0 到 1 的初稿”成本降到最低让人把精力集中在事实核查、观点打磨和风格调整上。1.3 常见认知误区误区一LLM 写完就能直接发布。实际不是。模型非常容易一本正经地编造数据、引用和案例也就是“幻觉”。没有事实核查的 AI 内容在技术类文章中风险很高。误区二Prompt 越长越好。很多人以为把需求写满一屏模型就能理解更准确但真正影响输出质量的是结构是否清晰、约束是否明确、是否有边界信息。误区三写作只是“生成”。完整的 LLM 写作流程应该包含检索、生成、校验、润色多个环节RAG 和 Agent 的意义就在这里。2. 环境准备与版本选型2.1 本地推理与云端 API 怎么选要做 LLM 写作实验首先需要确定模型从哪里来。云端 API 的优势是不依赖本地显卡、部署简单、生态成熟。你只需要注册一个服务商账号拿到 API Key就可以通过 HTTP 调用。缺点是需要考虑网络连通性、费用和数据隐私。本地推理的优势是数据不出内网、可以反复调试、没有 Token 费用。缺点是需要一定硬件配置尤其是显存。如果你手头只有普通办公电脑可以先用 Ollama、LM Studio 这类工具跑小参数模型做功能验证再决定是否升级硬件。我的建议是初期先用云端 API 把业务流程跑通因为它的输出质量和稳定性更容易得到保证当数据结构敏感、需要离线写稿时再迁移到本地模型。2.2 技术栈说明本文示例以 Python 为主要语言代码主要依赖以下内容Python 3.10 及以上版本。openai Python SDK用于访问 OpenAI 兼容的 Chat Completions 接口。可选sentence-transformers 做文本向量化faiss-cpu 做向量检索。可选Ollama 或 LM Studio 运行本地模型用于离线写作验证。版本需要根据你的项目实际情况调整。本文示例以常见环境为例重点演示配置思路不会把版本号写死。如果你的 SDK 版本较新个别参数名可能会略有差异请以官方文档为准。3. 最小可用示例用代码跑通一次 LLM 写作3.1 创建项目结构先创建一个干净的项目目录避免依赖混乱。mkdir llm-writing-demo cd llm-writing-demo python -m venv venv source venv/bin/activate pip install openai python-dotenv在 Windows 下激活虚拟环境的命令是venv\Scripts\activate。.env文件用来保存密钥不要提交到 Git。touch .env在.env中写入LLM_API_KEYyour-api-key LLM_BASE_URLhttps://api.openai.com/v1 LLM_MODELgpt-4o-mini这里强调一点API Key 属于敏感信息生产环境中建议通过密钥管理服务注入环境变量而不是硬编码在代码里。3.2 最小调用代码下面这段代码会调用 Chat Completions 接口让模型根据系统提示词写出一个 200 字左右的介绍段落。# 文件llm-writing-demo/chat_demo.py import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) response client.chat.completions.create( modelos.getenv(LLM_MODEL), messages[ { role: system, content: 你是一名中文科技博主文风清晰、专业、有条理。, }, { role: user, content: 请用200字介绍大语言模型的基本原理适合零基础读者。, }, ], temperature0.7, ) print(response.choices[0].message.content)运行命令python chat_demo.py如果一切正常你会看到一段通顺的中文介绍。这是整个 LLM 写作链路中最高频的调用方式一个系统提示词负责设定角色和风格一个用户提示词负责提出具体需求。这段代码里的base_url需要注意。如果你使用的服务商兼容 OpenAI 协议可以直接替换为服务商提供的地址。如果你使用的是本地 Ollama地址通常是http://localhost:11434/v1模型名则要换成你在本地拉取的模型名称。3.3 流式输出普通调用要等模型生成完整个回复才会返回文章稍长时等待时间会比较久。流式输出可以在模型生成过程中逐字打印体验更接近“真的有人在打字”。# 文件llm-writing-demo/chat_stream.py import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) stream client.chat.completions.create( modelos.getenv(LLM_MODEL), messages[ { role: system, content: 你是一名资深技术博客作者。, }, { role: user, content: 请用200字介绍RAG的基本概念。, }, ], streamTrue, ) for chunk in stream: delta chunk.choices[0].delta if delta and delta.content: print(delta.content, end) print()对于技术写作流式输出还有一个好处你可以提前发现模型是否跑偏及时中断生成节省 Token 和时间。3.4 设置系统提示词控制写作风格同一段素材给用户的感受可能完全不同。LLM 写作中最基础、最有效的控制手段就是系统提示词。以技术博文为例system_prompt 你是一名资深的技术博主写作特点是 1. 用通俗的语言解释复杂概念。 2. 每个技术点至少配一个可运行的示例。 3. 在关键步骤后解释“为什么这么做”。 4. 段落清晰不使用过度营销的语气。 在这个系统提示词里我同时给出了角色、风格、内容要求和语气约束。你可以根据博客定位不断迭代这个 Prompt形成自己的“写作风格包”。4. 稳定输出的关键提示词结构与生成参数4.1 temperature、top_p 对写作的影响temperature控制生成文本的随机性。数值越低输出越保守、稳定适合教程、技术文档和事实类内容数值越高输出越有创造性但跑题风险也越大。top_p是另一种采样策略通常和temperature二选一调节即可。不同写作任务的参考值写作任务推荐 temperature原因技术说明、摘要0.2 - 0.4需要准确性初稿生成、大纲0.6 - 0.8需要适度发散创意文案、标题0.8 - 1.0需要多样性这里没有绝对正确的值建议你针对自己的写作类型做一组小实验固定其他变量、只调整temperature对比输出质量。4.2 使用 JSON 结构输出写作大纲在实际项目中我不建议让模型自由发挥输出纯文本然后靠人肉解析。更可靠的做法是让模型输出结构化 JSON方便程序后续处理。以下是生成博客大纲的示例。# 文件llm-writing-demo/json_demo.py import json import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) response client.chat.completions.create( modelos.getenv(LLM_MODEL), messages[ { role: system, content: 你是一名写作规划助手。请严格按照 JSON 格式输出不要输出 Markdown 代码块。, }, { role: user, content: json.dumps( { task: 生成一篇关于本地部署LLM的博客文章大纲, sections: 4, include: [背景, 环境准备, 代码示例, 常见问题], }, ensure_asciiFalse, ), }, ], response_format{type: json_object}, temperature0.3, ) data json.loads(response.choices[0].message.content) print(json.dumps(data, ensure_asciiFalse, indent2))需要说明的是response_format{type: json_object}并不是所有兼容接口都支持。如果你的服务商不支持可以在系统提示词里强调“只输出 JSON”再在代码里用异常处理兜底。结构化输出的核心价值是让下游程序可以稳定地读取标题列表、章节内容而不是从一大段文本中正则匹配。4.3 用模板约束写作流程对于固定栏目比如每周发布一篇技术周报我通常会做一个“写作模板”。模板里包含三部分固定指令、动态输入、输出约束。template 请根据以下选题和素材写一篇技术博客文章。 选题{topic} 目标读者{audience} 文章结构 1. 开篇说明本文解决的问题。 2. 正文包含至少两个代码示例每个示例都要解释作用。 3. 结尾给出最佳实践或排错思路。 素材 {context} 要求 - 中文表达段落控制在5行以内。 - 不编造数据、版本号和案例。 - 输出使用 Markdown 格式。 调用时只需要用template.format(topic..., audience..., context...)填充即可。这种模板化方式特别适合内容生产团队既能让模型输出风格统一也方便非技术人员更换素材。5. LLM 精度问题详解FP16、FP32 与 BF165.1 为什么模型精度影响写作在聊“LLM 写作”时很多人只关注 Prompt却忽略了底层推理精度。模型权重和数据在计算时使用浮点数表示不同的浮点数类型决定了数值精度和显存占用。对于写作任务精度的影响不像代码生成那么直接但在长文本、复杂指令和中文语义理解上过低的精度可能导致表达不稳定、逻辑跳跃、重复输出等问题。这里说的精度主要包括 FP32单精度、FP16半精度和 BF16脑浮点。它们之间的差异不是简单的“谁更好”而是“谁更适合当前硬件”。5.2 FP16、FP32、BF16 对比精度类型位宽数值范围适用场景FP3232 位精度高、范围广调试、数值敏感场景FP1616 位范围有限容易溢出大多数 GPU 推理加速BF1616 位范围与 FP32 接近精度略低大模型训练和推理更稳定在写作场景下优先推荐 BF16因为它保留了较大的数值范围在长文本生成中不容易因为梯度溢出或值域问题出现异常。如果你的 GPU 不支持 BF16再退回到 FP16。用 FP32 推理最稳定但显存和速度成本会明显上升。5.3 在代码中指定加载精度如果是使用 Hugging Face Transformers 加载模型可以通过torch_dtype控制权重精度。# 文件llm-writing-demo/inference_precision.py import torch from transformers import AutoModelForCausalLM, AutoTokenizer # 这里仅演示精度加载思路实际模型名需要替换为你自己的模型 model_name your-llm-model tokenizer AutoTokenizer.from_pretrained(model_name) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypetorch.bfloat16, # 支持 bf16 的硬件优先 device_mapauto, ) prompt 请用100字介绍FP16和BF16的区别。 inputs tokenizer(prompt, return_tensorspt).to(model.device) output model.generate(**inputs, max_new_tokens200) print(tokenizer.decode(output[0], skip_special_tokensTrue))使用该代码前请先确认你的 GPU 驱动和 PyTorch 版本支持 CUDA 或 MPS否则device_mapauto可能无法正常工作。如果你的环境是 Apple Silicon Mac不同的推理引擎对精度的支持策略也不同需要以实际使用的推理框架文档为准。5.4 精度选择建议写作场景中精度选择可以遵循几个原则优先使用云端 API云端 API 的精度由服务商内部处理你不需要干预。本地部署时优先 BF16既能控制显存又能避免 FP16 的数值溢出问题。对比验证本地模型上线前用同一批 Prompt 在 FP16 和 BF16 下各跑一遍观察输出差异。关注量化模型GGUF、GPTQ 等量化格式会进一步降低精度但它们对写作质量的影响并非线性需要逐一测试。6. 给 LLM 装一个记忆库RAG 写作素材库实战6.1 RAG 解决什么问题写技术文章时我们经常需要参考大量资料官方文档、历史博客、产品更新日志、内部技术方案。如果每次都把这些资料塞进 Prompt一方面可能超出上下文窗口另一方面 Token 成本也会很高。RAGRetrieval-Augmented Generation检索增强生成的做法是先把你积累的资料切分、向量化、存储到向量库写作时先检索出与当前主题最相关的若干片段再把这些片段作为上下文传递给 LLM。这样做的好处有三个一是减少模型幻觉让模型基于真实素材回答问题二是节省 Token不需要把所有资料都放进 Prompt三是方便更新新增资料只需要重新写入向量库不需要重新训练模型。6.2 文本向量化文本向量化需要用到 Embedding 模型。这里以开源的sentence-transformers为例。pip install sentence-transformers faiss-cpu# 文件llm-writing-demo/embedding_demo.py from sentence_transformers import SentenceTransformer # 加载中文向量模型模型名称会随官方版本更新 model SentenceTransformer(BAAI/bge-small-zh-v1.5) sentences [ RAG可以让大模型基于外部知识回答问题。, 写作前先检索相关素材可以减少幻觉。, 向量数据库常用于相似文本召回。, ] embeddings model.encode(sentences) print(embeddings.shape)BAAI/bge-small-zh-v1.5是常见的中文向量模型之一你也可以替换成其他模型。需要提醒的是向量模型的选型与 LLM 并没有硬性绑定只要两者表达语义一致即可。6.3 建立向量库并检索上面示例只做了向量化实际写作库还需要一个局部检索方案。这里用 FAISS 完成一个最小可运行的检索流程。# 文件llm-writing-demo/search_demo.py import numpy as np import faiss # 假设已经通过 SentenceTransformer 得到向量 embeddings np.random.rand(10, 512).astype(float32) # 构建索引 dimension embeddings.shape[1] index faiss.IndexFlatL2(dimension) index.add(embeddings) # 模拟查询向量 query_vector np.random.rand(1, 512).astype(float32) # 检索最相似的3条 distances, indices index.search(query_vector, k3) print(检索下标:, indices) print(距离:, distances)在生产项目中你需要把真实的文档切分结果存入向量库。文本切分的粒度需要调试太长则检索不够精准太短则上下文碎片化。一个比较常见的做法是按标题段落切分每段保留 200 到 500 字并携带标题信息一起向量化。6.4 把检索结果注入提示词拿到检索结果后关键一步是把“外部素材”组织成 Prompt 的一部分。以下是一个模板函数。# 文件llm-writing-demo/build_prompt.py def build_prompt_with_context(query, contexts): context_text \n\n.join( f[资料{i 1}]\n{c} for i, c in enumerate(contexts) ) return f 请基于以下资料回答提问或撰写段落。 [资料开始] {context_text} [资料结束] 提问{query} 要求 1. 只使用资料中明确提到的事实不要额外编造。 2. 如果资料不足请直接说明“资料中没有覆盖该信息”。 3. 引用具体观点时请在括号内标注资料编号。 这里的关键点在于“约束模型只使用资料”。没有这一句模型还是会凭借自己的记忆自由发挥RAG 的效果就会被削弱。7. 让写作流程自动化Agent 与上下文工具雏形7.1 LLM Agent 在写作中的表现LLM Agent 可以理解为“能调用工具的大模型”。它不再只是“你说一句、它回一段”而是能够根据任务目标自主决定先检索资料再写大纲然后调用润色工具最后输出成稿。在写作场景中Agent 的核心价值是串联多个步骤减少人工搬运。一个简单的写作 Agent 可以拆成三部分规划把写作任务拆解成检索、大纲、初稿、润色等子任务。调用工具根据子任务选择向量检索、搜索 API、翻译插件等工具。校验对模型输出做格式检查、关键词覆盖度检查。7.2 MCP Client 连接 LLM 的思路MCPModel Context Protocol模型上下文协议是近期比较热门的工具协作方式。你可以把 MCP 理解成一套统一的“上下文插槽”LLM 通过 MCP 客户端与外部工具建立标准连接比如抓取网页内容、查询数据库、读取文件。实现思路通常分几步模型发出工具调用请求客户端解析请求客户端访问外部资源结果回传给模型继续生成。需要提醒的是给 Agent 授予的工具权限必须收敛不要为了演示方便直接放通任意命令执行和数据库操作。在合法授权和测试环境中先用只读工具验证流程再逐步增加写操作。7.3 用 Python 串起简易写作 Agent为了不依赖特定平台的特殊 API我给出一个基于 OpenAI 工具调用的简化版本。你的服务商如果支持tools参数可以直接参考。# 文件llm-writing-demo/agent_demo.py import json import os from dotenv import load_dotenv from openai import OpenAI load_dotenv() client OpenAI( api_keyos.getenv(LLM_API_KEY), base_urlos.getenv(LLM_BASE_URL), ) # 定义工具列表 tools [ { type: function, function: { name: search_material, description: 检索写作素材库, parameters: { type: object, properties: { query: {type: string, description: 检索关键词} }, required: [query], }, }, } ] def search_material(query): # 在实际项目中这里会调用向量库或搜索接口 return f关于 {query} 的素材RAG 可以将外部知识注入到 Prompt 中从而降低幻觉。 def run_agent(user_message): messages [ { role: system, content: 你是写作助手。如果需要素材请调用 search_material 工具。, }, {role: user, content: user_message}, ] for _ in range(3): response client.chat.completions.create( modelos.getenv(LLM_MODEL), messagesmessages, toolstools, tool_choiceauto, ) choice response.choices[0] if choice.finish_reason tool_calls: messages.append(choice.message) for tool_call in choice.message.tool_calls: args json.loads(tool_call.function.arguments) result search_material(args[query]) messages.append( { role: tool, tool_call_id: tool_call.id, content: result, } ) continue return choice.message.content if __name__ __main__: result run_agent(请基于素材库写一段关于RAG的介绍。) print(result)这段代码演示了一个非常关键的循环模型要求调用工具程序执行工具工具结果以tool角色返回模型继续生成。如果服务商不支持tools参数你可以退回到“人工分离”的方式先用分类模型判断当前任务是否需要检索再手动调用search_material最后把素材拼进提示词。8. 常见问题与排查思路8.1 高频问题速查表问题现象常见原因解决思路调用 API 报 401API Key 错误或未正确加载检查环境变量确认服务商配置请求超时网络延迟或模型响应过长开启流式输出缩短 max_tokens生成内容出现明显错误模型幻觉、缺乏上下文加入 RAG 检索限定事实来源提示文本向量 API 未配置向量模型密钥或 endpoint 缺失在配置中心补充向量模型 API 信息上下文窗口超限输入文档太长按段落切分先做摘要再调用FP16 下长文输出不稳定精度选择不合适尝试 BF16 或 FP32对比输出Agent 循环调用不结束工具返回结果未正确回传检查 tool_call_id 和 messages 顺序8.2 几个排查思路第一任何 LLM 写作应用都要先做“最小验证”。只用一个 Prompt、一段固定文本确认 API 通、参数对再逐步叠加 RAG 和 Agent避免一开始就陷入复杂调用链的排查。第二把模型输入和输出都记录到日志中。写作类应用的问题往往不是代码报错而是“输出质量不符合预期”。有了输入输出日志你可以回放现场判断是 Prompt 问题、检索素材问题还是模型精度问题。第三对向量化环节单独测试。很多 RAG 项目最终效果不好并不是 LLM 能力不够而是资料检索不到。建议先打印检索结果人工评估召回的相关性再决定是否调整切分长度或者向量模型。9. 最佳实践与工程建议9.1 固化系统提示词并做版本管理写作风格很容易在使用过程中被“慢慢改乱”。我建议把每个写作场景的系统提示词当作代码一样管理放到 Git 仓库中记录每次改动的原因。这样既能保持输出风格稳定也能在效果回退时快速定位是哪次 Prompt 导致的。9.2 对结构化输出做 Schema 校验当模型输出用于下游流程时不要默认它会返回合法 JSON。程序里应加入异常捕获和字段校验。必要时可以再调用一次模型要求它对已有输出做“修正”但这种方式浪费 Token不如在系统提示词里写清楚约束。9.3 控制检索密度与素材质量RAG 不是塞的资料越多越好。检索出的片段如果超过 5 段模型很容易忽略关键信息。建议每次交给模型的核心素材控制在 2000 字以内并且优先选择标题清晰、事实密集的段落。素材在入库前需要做去重、去噪避免把导航文字、广告文本也向量化进去。9.4 安全边界与数据脱敏如果写作素材包含内部业务数据一定要在进入 API 前完成脱敏。日志中不要记录完整 Prompt尤其是涉及账号、密钥、员工信息的内容。Agent 工具权限遵循最小权限原则只读优先写操作必须经过人工确认数据库操作一律先备份并在测试环境验证。9.5 保留人工审阅关口LLM 写作应该定位为“提效工具”而不是“自动发布机器”。我的习惯是初稿由模型生成事实核查、案例验证、代码运行确认全部由人工完成。这样既保留了效率又守住了内容质量底线。10. 后续可以继续深入的方向如果你已经跑通了本文示例下一步可以从这几个方向继续深入。第一学习编排框架。你可能会意识到直接用 Python 代码维护多轮工具调用、上下文拼接会越来越复杂。这时可以关注 Spring AI、LangChain 等框架或借助 MCP 构建标准化工具接入层将检索、网页抓取、数据库查询统一管理。第二搭建自己的“LLM 学习 Wiki”。这个概念来自 Andrej Karpathy 提出的学习思路不要零散地刷大模型新闻而是围绕架构、训练、推理、应用四个维度建立个人知识库配合 Obsidian 等工具形成知识图谱。当你遇到新问题先检索自己的 Wiki再按需查论文或文档。第三做写作质量回归测试。把常用写作任务整理成一个固定测试集每次更换模型、修改 Prompt 或调整精度后都跑一遍对比输出是否变差。这种方法虽然简单但能有效避免“模型换了博客风格随之漂移”的问题。回到“LLM Writing and Me”这个主题我的感受是写作并不需要被大模型替代但它天然适合被大模型重构。从拿到选题到最终发布中间的检索、大纲、初稿、润色、排版都有大量重复劳动而这些恰恰是 LLM 最擅长补位的地方。如果你的写作场景也需要大量信息检索、结构生成或风格仿写建议从最小调用开始再逐步叠加 RAG 与 Agent 能力最终沉淀成一套属于自己的 LLM 写作工作流。
返回列表