基于LangChain与Ollama构建AI技术写作Agent:从提示工程到自动化内容生成
在实际技术写作和内容创作领域,从“读者”到“作者”的转变,核心挑战往往不是写作本身,而是如何将零散的灵感系统化、工程化地转化为结构完整、逻辑清晰、可执行的技术文章。这个过程如果仅依赖手动整理,效率低下且容易遗漏关键细节。本文旨在为有志于成为技术作者(尤其是技术博客作者)的开发者,提供一个从“灵感火花”到“Agent全自动码字”的完整实践框架。我们将构建一个能够理解技术主题、自动生成大纲、填充内容、并遵循特定平台风格(如CSDN技术博客)的自动化写作助手原型。通过这个项目,你将掌握如何利用现代AI工具链和工程化思维,将创作流程从手动劳动升级为可配置、可迭代的自动化流水线。
本文适合有一定编程基础(建议熟悉Python),对AI应用开发、自然语言处理以及技术写作流程优化感兴趣的开发者。我们将从零开始,搭建一个基于本地或云模型、具备结构化输出能力的写作Agent,并深入探讨其核心模块、配置细节和常见陷阱。
1. 理解“写作Agent”的核心工作机制
一个有效的技术写作Agent,其目标不是替代人类的创造性思考,而是将人类从重复性、格式化的劳动中解放出来,专注于核心的技术判断和深度分析。它本质上是一个具备特定领域知识(技术写作规范)和任务分解能力的工作流自动化系统。
1.1 从灵感到成文的典型瓶颈
手动写作技术博客时,通常会遇到以下几个效率瓶颈:
- 灵感碎片化:想法停留在便签或脑子里,缺乏结构化整理。
- 大纲构建耗时:需要反复构思章节逻辑,确保技术深度和可读性。
- 内容填充重复:撰写环境准备、命令示例、代码块等格式化内容占用大量时间。
- 风格不一致:不同文章在结构、语气、详略程度上可能差异很大。
- 排查与优化遗漏:容易忘记加入“常见问题排查”、“最佳实践”等增值部分。
1.2 Agent的自动化解决思路
我们的写作Agent将模拟资深技术作者的思考和工作流程,将其分解为可编程的步骤:
- 主题理解与需求澄清:解析用户输入的模糊需求(如“写一篇关于Spring Security登录流程的文章”),提炼核心要素。
- 结构化大纲生成:根据技术文章类型(教程、原理、排错、集成),生成符合逻辑的章节结构(H2, H3)。
- 内容分块生成与填充:针对每个章节,调用AI模型生成符合技术细节要求的内容,并自动插入代码块、配置示例、命令和表格。
- 风格与规范校验:确保生成的内容符合目标平台(如CSDN技术博客)的写作风格,过滤禁止用语,检查技术准确性。
- 内容组装与输出:将各章节内容组装成一篇完整的Markdown文档。
1.3 技术栈选型
我们将使用Python作为实现语言,因其在AI应用开发和快速原型构建方面生态丰富。核心组件包括:
- 语言模型:作为Agent的“大脑”。可以选择OpenAI GPT系列API、国内大模型API(如DeepSeek、通义千问)或本地部署的Ollama(运行Llama 3、Qwen等开源模型)。本文示例将采用Ollama + Qwen2.5本地方案,兼顾可控性和成本。
- 应用框架:使用LangChain或LlamaIndex来构建链式工作流和上下文管理。本文使用LangChain进行演示,因其在任务编排方面更为直观。
- 提示工程:这是Agent的“灵魂”,通过精心设计的系统提示词(System Prompt)来约束模型行为,确保输出质量。
2. 环境准备与依赖配置
在开始构建之前,需要准备好开发和运行环境。以下步骤在Ubuntu 22.04或macOS上进行过验证,Windows用户建议使用WSL2。
2.1 基础环境与Ollama安装
首先,确保系统已安装Python 3.9+和pip。然后安装Ollama,用于在本地运行大语言模型。
# 在macOS或Linux上安装Ollama curl -fsSL https://ollama.com/install.sh | sh # 安装完成后,拉取一个适合技术写作的中英文模型,例如Qwen2.5 ollama pull qwen2.5:7b # 7B参数版本,对大多数机器友好 # 启动Ollama服务(通常安装后自动运行) ollama serve运行ollama list可以查看已下载的模型。
2.2 创建Python虚拟环境与安装依赖
为项目创建一个独立的Python环境,避免包冲突。
# 创建项目目录并进入 mkdir tech-writing-agent && cd tech-writing-agent python3 -m venv venv # 激活虚拟环境 # Linux/macOS source venv/bin/activate # Windows (cmd) # venv\Scripts\activate.bat # 安装核心依赖 pip install langchain langchain-community langchain-core pip install pydantic # 用于数据验证和设置 pip install requests # 用于可能的API调用(如果后续切换为云端模型)2.3 项目结构初始化
一个清晰的项目结构有助于后续维护和扩展。
tech-writing-agent/ ├── config/ │ └── prompts.py # 存放所有系统提示词模板 ├── core/ │ ├── agent.py # Agent核心逻辑和工作流 │ └── models.py # 数据模型定义(如文章大纲、章节) ├── outputs/ # 生成的文章输出目录 ├── utils/ │ └── formatter.py # 内容格式化工具(如Markdown表格生成) ├── main.py # 程序主入口 ├── requirements.txt # 项目依赖列表 └── README.md使用以下命令快速创建目录和文件:
mkdir -p config core utils outputs touch config/prompts.py core/agent.py core/models.py utils/formatter.py main.py requirements.txt将当前安装的依赖导出到requirements.txt:
pip freeze > requirements.txt3. 构建写作Agent的核心模块
Agent的核心是定义清晰的数据流和任务链。我们首先定义文章的结构化表示,然后构建生成每个部分的链。
3.1 定义数据模型(Pydantic)
在core/models.py中,我们使用Pydantic定义文章大纲和章节的数据结构,这有助于AI输出结构化的JSON,方便我们解析。
# core/models.py from typing import List, Optional from pydantic import BaseModel, Field class SubSection(BaseModel): """文章子章节(H3级别)""" title: str = Field(description="子章节的标题,例如‘3.1 环境准备与依赖配置’") content: str = Field(description="该子章节的详细内容,应包含必要的解释、步骤、代码示例等") code_blocks: Optional[List[str]] = Field(default_factory=list, description="本节中出现的代码块列表,用于后续格式化") class Section(BaseModel): """文章主章节(H2级别)""" title: str = Field(description="主章节的标题,例如‘2. 理解核心工作机制’") description: str = Field(description="本章节的简要目标和内容概述") sub_sections: List[SubSection] = Field(description="本章节下的子章节列表") class ArticleOutline(BaseModel): """文章大纲""" title: str = Field(description="文章主标题") introduction: str = Field(description="文章开头段落,约200-300字,引出主题和读者收益") target_audience: str = Field(description="本文的目标读者描述") sections: List[Section] = Field(description="文章的主要章节列表") conclusion: str = Field(description="文章结尾段落,总结与展望") keywords: List[str] = Field(description="文章关键词列表")3.2 设计系统提示词(Prompt Engineering)
提示词是指导AI行为的关键。在config/prompts.py中,我们定义几个核心提示词模板。
# config/prompts.py # 大纲生成提示词 OUTLINE_PROMPT_TEMPLATE = """ 你是一位拥有十多年一线经验的资深技术博主和工程实践作者,擅长撰写CSDN、博客园、掘金等平台风格的高质量技术长文。 请根据用户提供的【写作主题】和【补充信息】,生成一篇技术博客的详细结构化大纲。 大纲必须符合以下要求: 1. 文章必须具备强烈的“教程感”,读者能按顺序理解概念、准备环境、完成操作、验证结果。 2. 技术颗粒度要足,大纲中需指明哪些章节需要包含配置、参数、代码、命令、数据结构、错误现象等具体内容。 3. 大纲结构需清晰,包含:引言、目标读者、至少4个H2主章节(每个主章节下至少2个H3子章节)、结尾。 4. 文章风格需专业、直接,避免“大家好”、“总之”、“本文将对…进行介绍”等套话。以解决问题为导向。 【写作主题】: {theme} 【补充信息(可选)】: {additional_info} 请严格按照以下JSON格式输出,不要有任何额外的解释: {{ “title”: “文章主标题”, “introduction”: “文章开头段落”, “target_audience”: “目标读者描述”, “sections”: [ {{ “title”: “1. 第一个主章节标题”, “description”: “本章节目标描述”, “sub_sections”: [ {{ “title”: “1.1 第一个子章节标题”, “content”: “该子章节计划撰写的内容要点描述(非完整内容)”, “code_blocks”: [“这里计划插入的代码类型,如‘Python安装命令’、‘YAML配置示例’”] }} ] }} ], “conclusion”: “文章结尾段落”, “keywords”: [“关键词1”, “关键词2”] }} """ # 章节内容生成提示词 SECTION_PROMPT_TEMPLATE = """ 你正在撰写一篇技术博客的以下章节: 文章标题:《{article_title}》 当前章节:{section_title} - {section_description} 当前子章节:{sub_section_title} 请根据以上上下文,撰写该子章节的完整内容。 要求: 1. 内容需详细、具体,达到可操作、可复现的程度。如果是操作步骤,请写出具体命令、代码、配置和参数。 2. 必须解释“为什么”,而不仅仅是“怎么做”。说明设计原理、参数含义、常见坑及原因。 3. 在需要的地方,用‘```语言’和‘```’标记出代码块、命令块或配置块。 4. 语言风格:专业、清晰、直接,像经验丰富的开发者在分享。避免任何营销口吻和平台引流话术。 5. 字数要求:此子章节内容应不少于500字。 请开始撰写: """3.3 实现Agent工作流(LangChain)
在core/agent.py中,我们使用LangChain连接Ollama模型,并构建两个主要的链:大纲生成链和内容填充链。
# core/agent.py import json from typing import Dict, Any from langchain_community.llms import Ollama from langchain.prompts import PromptTemplate from langchain.output_parsers import PydanticOutputParser from langchain.schema import StrOutputParser from core.models import ArticleOutline from config.prompts import OUTLINE_PROMPT_TEMPLATE, SECTION_PROMPT_TEMPLATE class WritingAgent: def __init__(self, model_name: str = “qwen2.5:7b”, base_url: str = “http://localhost:11434”): """ 初始化写作Agent。 :param model_name: Ollama中已拉取的模型名称 :param base_url: Ollama服务地址 """ self.llm = Ollama(model=model_name, base_url=base_url, temperature=0.7) # temperature稍高于0,让创作有一定灵活性,但不宜过高以保证技术准确性。 def generate_outline(self, theme: str, additional_info: str = “”) -> ArticleOutline: """生成文章结构化大纲""" # 创建提示词 prompt = PromptTemplate.from_template(OUTLINE_PROMPT_TEMPLATE) chain = prompt | self.llm | StrOutputParser() # 执行链 raw_output = chain.invoke({“theme”: theme, “additional_info”: additional_info}) # 解析JSON输出为Pydantic模型 try: outline_dict = json.loads(raw_output.strip()) return ArticleOutline(**outline_dict) except json.JSONDecodeError as e: print(f“大纲生成输出不是有效JSON: {e}”) print(“原始输出:”, raw_output) # 简易修复:尝试提取JSON部分(某些模型会在JSON外加说明) import re json_match = re.search(r‘\{.*\}’, raw_output, re.DOTALL) if json_match: outline_dict = json.loads(json_match.group()) return ArticleOutline(**outline_dict) else: raise ValueError(“无法从模型输出中解析出有效的大纲结构。”) def write_sub_section(self, article_title: str, section_info: Dict[str, Any], sub_section_info: Dict[str, Any]) -> str: """撰写单个子章节的完整内容""" prompt = PromptTemplate.from_template(SECTION_PROMPT_TEMPLATE) chain = prompt | self.llm | StrOutputParser() content = chain.invoke({ “article_title”: article_title, “section_title”: section_info[“title”], “section_description”: section_info[“description”], “sub_section_title”: sub_section_info[“title”] }) return content def write_article(self, outline: ArticleOutline) -> str: """根据大纲,撰写整篇文章""" article_parts = [] # 1. 添加标题和引言 article_parts.append(f“# {outline.title}\n\n”) article_parts.append(f“{outline.introduction}\n\n”) article_parts.append(f“**目标读者**:{outline.target_audience}\n\n”) # 2. 遍历所有章节和子章节,生成内容 for section in outline.sections: article_parts.append(f“## {section.title}\n\n”) article_parts.append(f“{section.description}\n\n”) for sub_section in section.sub_sections: article_parts.append(f“### {sub_section.title}\n\n”) # 调用模型生成该子章节内容 section_info = {“title”: section.title, “description”: section.description} sub_section_info = {“title”: sub_section.title} content = self.write_sub_section(outline.title, section_info, sub_section_info) article_parts.append(f“{content}\n\n”) # 3. 添加结尾和关键词 article_parts.append(f“## 总结与后续方向\n\n”) article_parts.append(f“{outline.conclusion}\n\n”) article_parts.append(f“**关键词**:{‘, ’.join(outline.keywords)}\n”) return “”.join(article_parts)4. 运行验证与结果分析
现在,我们将上述模块组合起来,创建一个主程序来验证整个工作流。
4.1 编写主程序入口
在main.py中,我们提供一个简单的命令行交互。
# main.py import sys from pathlib import Path from core.agent import WritingAgent from core.models import ArticleOutline def main(): print(“=== 技术写作Agent启动 ===“) print(“请提供你想要撰写的技术文章主题。”) print(“示例:‘如何使用Docker部署Spring Boot应用’”) theme = input(“请输入文章主题: “).strip() if not theme: print(“主题不能为空!”) sys.exit(1) additional_info = input(“请输入补充信息(如特定技术栈、重点难点,可选): “).strip() # 初始化Agent agent = WritingAgent() print(“\n[步骤1/3] 正在生成文章大纲...”) try: outline = agent.generate_outline(theme, additional_info) print(f“大纲生成成功!文章标题:《{outline.title}》”) print(f“共规划 {len(outline.sections)} 个主章节。”) except Exception as e: print(f“大纲生成失败:{e}”) sys.exit(1) # 预览大纲(可选) preview = input(“\n是否预览大纲?(y/n): “).strip().lower() if preview == ‘y’: print(“\n--- 大纲预览 ---“) print(f“标题:{outline.title}”) for i, section in enumerate(outline.sections, 1): print(f“{section.title}”) for j, sub in enumerate(section.sub_sections, 1): print(f“ {sub.title}”) print(“--- 预览结束 ---\n”) confirm = input(“是否基于此大纲开始撰写完整文章?(y/n): “).strip().lower() if confirm != ‘y’: print(“已取消。”) sys.exit(0) print(“\n[步骤2/3] 正在撰写文章内容(可能需要几分钟)...”) try: article_content = agent.write_article(outline) except Exception as e: print(f“文章撰写失败:{e}”) sys.exit(1) print(“\n[步骤3/3] 保存文章...”) # 清理标题中的非法文件名字符 safe_title = “”.join(c for c in outline.title if c.isalnum() or c in (‘ ‘, ‘-’, ‘_’)).rstrip() output_filename = f“outputs/{safe_title}.md” Path(“outputs”).mkdir(exist_ok=True) with open(output_filename, ‘w’, encoding=‘utf-8’) as f: f.write(article_content) print(f“文章已成功保存至:{output_filename}”) print(“\n=== 完成 ===") if __name__ == “__main__”: main()4.2 执行与输出示例
确保Ollama服务正在运行(ollama serve),然后在项目根目录下激活虚拟环境并运行:
python main.py按照提示输入主题,例如:“从零搭建一个基于Prometheus和Grafana的微服务监控系统”。
程序将首先调用模型生成大纲,然后依次为每个子章节生成内容。最终,在outputs/目录下会生成一个Markdown文件。以下是一个生成内容的片段示例:
# 从零搭建一个基于Prometheus和Grafana的微服务监控系统 在实际的微服务架构中,服务的数量会快速增长,手动登录服务器查看日志和指标的方式变得不可行。一个集中、可视化的监控系统对于保障系统稳定性和快速定位问题至关重要。本文将带你从零开始,搭建一套基于Prometheus(指标采集与存储)和Grafana(数据可视化)的完整监控体系,并集成到Spring Boot微服务中。通过本文,你将掌握监控系统的核心组件部署、Spring Boot应用指标暴露、Grafana仪表盘配置以及告警规则设置的全流程。 **目标读者**:拥有Spring Boot基础,了解微服务概念,希望为项目引入系统化监控的Java后端开发者。 ## 1. 理解监控系统的基本组成与工作流程 在动手部署之前,需要先理解Prometheus和Grafana各自扮演的角色以及它们如何协同工作。 ### 1.1 为什么是Prometheus + Grafana? Prometheus是一个开源的系统监控和警报工具包,它通过主动拉取(Pull)模式从配置好的目标(Targets)收集指标(Metrics)。其核心特点包括: * **多维数据模型**:通过指标名称和键值对标签(Labels)来标识时间序列数据。 * **强大的查询语言PromQL**:允许你对收集的指标进行灵活查询和聚合。 * **不依赖分布式存储**:单个节点即可工作,服务自治。 * **拉取模型为主**:更适合于服务发现和动态环境。 然而,Prometheus自带的Web UI主要用于数据查询和简单图表,在数据可视化方面功能较弱。这时就需要Grafana。 Grafana是一个开源的度量分析和可视化平台。它可以从多种数据源(如Prometheus, MySQL, InfluxDB等)加载数据,并提供强大的、可配置的仪表盘(Dashboard)来展示图表、图形和警报。 **工作流程**: 1. 各微服务应用(如Spring Boot服务)通过Actuator或Micrometer暴露符合Prometheus格式的指标端点(例如 `/actuator/prometheus`)。 2. Prometheus Server根据配置(`prometheus.yml`)定期(如每15秒)向这些端点发起HTTP请求,拉取指标数据并存储在本地时间序列数据库中。 3. Grafana配置Prometheus作为数据源。 4. 用户在Grafana中创建仪表盘,通过编写PromQL查询语句从Prometheus获取数据,并以丰富的图表形式展示。 这种组合实现了**数据采集、存储、查询、可视化**的完整闭环。可以看到,生成的内容已经具备了技术博客的基本要素:清晰的背景介绍、目标读者、技术原理解释和工作流程图解。
5. 常见问题排查与优化
在实际运行Agent的过程中,你可能会遇到以下问题。这里提供排查思路和解决方案。
5.1 模型相关问题
| 问题现象 | 可能原因 | 检查与解决方案 |
|---|---|---|
启动时报ConnectionError | 1. Ollama服务未启动。 2. 端口被占用或地址错误。 | 1. 运行ollama serve并确保无报错。2. 检查 base_url参数是否正确(默认http://localhost:11434)。3. 运行 curl http://localhost:11434/api/tags测试API连通性。 |
| 生成内容质量差,胡言乱语 | 1. 模型本身能力不足。 2. temperature参数过高。3. 提示词不够清晰。 | 1. 尝试更换更大参数或更擅长中文的模型,如qwen2.5:14b或llama3.2:3b。2. 在 WritingAgent初始化时调低temperature(如0.3-0.5)。3. 仔细优化 config/prompts.py中的提示词,约束更具体。 |
| 输出格式不符合JSON要求 | 模型未严格遵循指令输出纯JSON。 | 1. 在提示词中更加强调“严格按照以下JSON格式输出”。 2. 使用LangChain的 PydanticOutputParser进行更严格的输出解析(需调整链的构建方式)。3. 在 generate_outline方法中添加后处理,清洗非JSON字符。 |
5.2 内容生成相关问题
| 问题现象 | 可能原因 | 检查与解决方案 |
|---|---|---|
| 生成的内容过于笼统,缺乏代码和配置细节。 | 提示词中未强调“技术颗粒度足”和“必须包含配置、参数、代码、命令”。 | 强化SECTION_PROMPT_TEMPLATE中的要求,例如:“必须在操作步骤中给出具体的命令行示例、YAML/Properties配置代码块、关键Java/Python代码片段。避免使用‘配置一下’、‘写一段代码’等模糊描述。” |
| 文章结构松散,章节之间逻辑不强。 | 大纲生成阶段规划不合理。 | 优化OUTLINE_PROMPT_TEMPLATE,要求大纲必须遵循“概念->环境->实现->验证->排错->优化”的逻辑流。可以给出更具体的结构示例。 |
| 生成速度慢。 | 1. 本地模型推理速度受硬件限制。 2. 文章过长,子章节太多。 | 1. 考虑使用更小的模型(如3B参数),或使用云端API(需处理网络和成本)。 2. 对于长文,可以考虑异步生成各章节,或先生成核心章节。 |
5.3 工程化优化建议
- 加入缓存:对于相同主题和大纲,可以缓存生成的内容,避免重复调用模型,节省时间和成本。
- 实现异步生成:使用
asyncio或langchain的异步支持,并行生成多个子章节,大幅提升长文生成速度。 - 引入内容校验:编写规则检查生成的Markdown是否包含代码块、表格等必要元素,对不合格的章节触发重写。
- 连接知识库:使用
LlamaIndex将你的个人技术笔记、项目文档构建成本地知识库,让Agent在生成内容时能参考这些具体资料,提高准确性和个性化。 - 支持多模型降级:配置多个模型(如一个主力模型,一个轻量模型),当主力模型不可用时自动降级。
6. 最佳实践与扩展方向
6.1 提示词工程最佳实践
- 角色定义要具体:如“资深技术博主”比“一个AI助手”效果更好。
- 指令要清晰且结构化:使用编号列表、明确的要求(必须/不要)。
- 提供高质量示例:在提示词中给出你期望的输出格式的简短示例(Few-shot Learning),能极大提升模型输出质量。
- 迭代优化:将生成的提示词和输出结果进行对比分析,不断调整提示词,这是一个持续的过程。
6.2 生产环境部署考量
当前原型适合个人或小团队使用。若要投入生产环境(如作为团队内部写作工具),需考虑:
- 稳定性:增加重试机制、熔断机制,应对模型API的不稳定。
- 安全性:对用户输入进行过滤,防止提示词注入攻击。
- 成本控制:如果使用付费API,需监控Token使用量,设置预算和告警。
- 版本管理:对提示词模板、模型版本进行管理,便于回滚和A/B测试。
- 人工审核环节:自动化生成的文章必须有人工审核和修正环节,确保技术准确性。
6.3 扩展方向
- 多平台适配:在提示词库中预置CSDN、博客园、掘金、知乎等不同平台的风格模板,一键切换。
- 垂直领域深化:训练或微调模型,使其更擅长某个特定技术领域(如前端、算法、运维),生成内容更专业。
- 交互式写作:将Agent升级为可交互模式,作者可以实时提出修改意见(如“这个例子换成Go语言”、“把这段排错内容加个表格”),Agent据此调整后续内容。
- 多媒体内容生成:结合图像生成模型,自动为文章生成架构图、流程图或示意图。
通过以上步骤,你已经成功构建了一个能够将“灵感火花”转化为结构化技术文章的自动化写作Agent原型。这个系统的价值不在于完全替代人类作者,而在于成为一个强大的“副驾驶”,处理繁琐的格式化工作和基础内容填充,让你能更专注于技术深度、架构设计和创造性思考。从今天开始,让你的技术创作流程进入“Agent辅助”的新阶段。
关键词:AI写作助手, LangChain, Ollama, 提示工程, 技术博客自动化, 内容生成, 大语言模型应用