【三个月 AI Agent 实战学习】Day 20:综合实战 —— 全自动日报生成器

📅 发布时间:2026/9/28 11:40:39
【三个月 AI Agent 实战学习】Day 20:综合实战 —— 全自动日报生成器
Day 20综合实战 —— 全自动日报生成器欢迎来到第一阶段的收官之战今天我们将综合运用过去 19 天所学的核心技能完成一个完整的实战项目全自动日报生成器。这个项目将串联起 API 调用、结构化输出、提示词设计、重试机制、文件操作等关键技术同时体验 LangChain 框架在工程化中的便利。完成后你将拥有一个能根据零散的工作记录自动生成规范日报的工具这也标志着你已经具备了开发实际 LLM 应用的基本能力。一、今日学习目标综合运用前期知识结构化输出Day 6、系统提示词设计Day 13、LangChain 核心组件Day 15、输出解析器Day 16。实现一个命令行工具用户输入流水账式的记录程序自动生成结构化日报并保存为 Markdown 文件。学会使用 LangChain 的PydanticOutputParser定义日报数据结构并自动解析模型输出。掌握基本的文件操作和 Markdown 渲染技巧。完成第一阶段的全部学习内容为进入 Agent 核心阶段做好准备。二、详细实现步骤步骤 1需求分析与设计用户希望快速生成工作日报但每天只记得一些零散的事件。程序需要接收用户输入的多行流水账例如“上午开了项目会讨论了新功能下午写了代码修复了登录 bug晚上学了一小时英语”。调用大模型将零散信息整理成结构化日报包含日期、核心摘要、完成的任务列表、会议记录、问题与风险、明日计划等。将结构化数据渲染成 Markdown 格式的日报文本。自动保存到本地文件文件名包含日期如日报_2025-03-20.md。我们利用 LangChain 的PydanticOutputParser来定义日报的数据模型使模型输出严格的 JSON并自动解析为 Python 对象。步骤 2环境准备确保已安装langchain、langchain-openai、pydantic。如果尚未安装执行pipinstalllangchain langchain-openai pydantic步骤 3定义日报数据模型使用 Pydantic 定义一个DailyReport类包含我们希望从模型中提取的字段。字段说明要清晰因为解析器会将这些描述嵌入到格式说明中指导模型输出。新建daily_report_generator.pyfrompydanticimportBaseModel,FieldfromtypingimportList,OptionalclassDailyReport(BaseModel):date:strField(description日报日期格式 YYYY-MM-DD如果用户未提及则使用今天)summary:strField(description今日工作核心概述一句话)tasks:List[str]Field(description今日完成的任务列表每条任务简短清晰)meetings:Optional[List[str]]Field(defaultNone,description今日参与的会议及简要结论)issues:Optional[List[str]]Field(defaultNone,description遇到的问题或风险)tomorrow_plan:Optional[List[str]]Field(defaultNone,description明日计划事项)步骤 4构建 LLM 和解析器初始化 DeepSeek 模型通过 LangChain 的ChatOpenAI并创建PydanticOutputParser。importosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_core.output_parsersimportPydanticOutputParser load_dotenv()llmChatOpenAI(modeldeepseek-chat,api_keyos.getenv(DEEPSEEK_API_KEY),base_urlhttps://api.deepseek.com,temperature0.2# 日报需要准确、专业低温度减少随机性)parserPydanticOutputParser(pydantic_objectDailyReport)步骤 5编写提示词模板设计系统提示词明确任务、输出格式并注入解析器提供的格式说明。同时加入 Few-shot 示例帮助模型理解如何从流水账中提取结构化信息。fromlangchain_core.promptsimportChatPromptTemplate system_template 你是一个专业的工作日报助手。用户会提供一些零散的工作记录可能包含会议、任务、问题等你需要将其整理成结构化的日报。 {format_instructions} 请严格遵循格式要求只输出 JSON 对象不要包含任何额外文字。 示例 用户输入上午开了项目会讨论了新功能下午写了代码修复了登录 bug晚上学了一小时英语。 输出 {{ date: 2025-03-20, summary: 今日完成了项目会议、代码修复和个人学习。, tasks: [参加项目会议, 修复登录 bug, 学习英语 1 小时], meetings: [项目会议讨论了新功能], issues: [], tomorrow_plan: [] }} promptChatPromptTemplate.from_messages([(system,system_template),(user,{input})])步骤 6构建处理链并实现重试逻辑我们将提示词、模型、解析器连接成链。如果模型偶尔输出格式错误导致解析失败我们可以用简单的重试循环来处理。fromlangchain_core.output_parsersimportOutputParserExceptionimporttimedefgenerate_report(raw_text:str,max_retries:int2)-DailyReport:# 构建链chainprompt|llm|parserforattemptinrange(max_retries1):try:# 注入格式说明resultchain.invoke({input:raw_text,format_instructions:parser.get_format_instructions()})returnresultexceptOutputParserExceptionase:print(f解析失败第{attempt1}次{e})ifattemptmax_retries:time.sleep(1)else:raise步骤 7将结构化数据渲染为 Markdown使用 Python 字符串格式化将DailyReport对象转换为美观的 Markdown 文本。defrender_markdown(report:DailyReport)-str:mdf# 工作日报{report.date}\n\nmdf## 今日概述\n{report.summary}\n\nmd## 完成任务\nfortaskinreport.tasks:mdf-{task}\nmd\nifreport.meetings:md## 会议记录\nformeetinginreport.meetings:mdf-{meeting}\nmd\nifreport.issues:md## 问题与风险\nforissueinreport.issues:mdf-{issue}\nmd\nifreport.tomorrow_plan:md## 明日计划\nforplaninreport.tomorrow_plan:mdf-{plan}\nreturnmd步骤 8保存 Markdown 文件生成文件名使用当前日期或报告中的日期。fromdatetimeimportdatetimedefsave_report(md_text:str,date_str:strNone):ifnotdate_str:date_strdatetime.now().strftime(%Y-%m-%d)filenamef日报_{date_str}.mdwithopen(filename,w,encodingutf-8)asf:f.write(md_text)print(f日报已保存至{filename})步骤 9整合主流程编写主函数接收多行用户输入调用生成函数渲染并保存。defmain():print(欢迎使用全自动日报生成器)print(请输入您今天的工作记录可多行输入 END 结束)lines[]whileTrue:lineinput()ifline.strip().upper()END:breaklines.append(line)raw_text\n.join(lines).strip()ifnotraw_text:print(输入为空退出。)returnprint(\n正在生成日报...)try:reportgenerate_report(raw_text)print(\n生成的日报结构)print(report.json(indent2,ensure_asciiFalse))mdrender_markdown(report)print(\nMarkdown 预览)print(md)save_report(md,report.date)exceptExceptionase:print(f生成失败{e})if__name____main__:main()步骤 10运行与测试运行程序输入示例流水账观察输出和生成的 Markdown 文件。可以多次测试不同风格的输入检验解析的稳定性。三、常见问题与调试Q1模型输出的 JSON 字段缺失或类型错误导致解析失败。→ 解析器会抛出OutputParserException我们已经加入了重试机制。如果连续失败可以考虑增强提示词中的示例或在代码中对缺失字段设置默认值但 Pydantic 要求必填字段存在可以改为可选字段并在后续处理。Q2生成的日报内容不准确遗漏了某些重要信息。→ 可以在提示词中要求模型“提取所有关键信息不要遗漏”并提供更详细的示例。另外可以尝试降低温度至 0提高确定性。Q3如何适应不同的日期格式→ 我们要求模型返回YYYY-MM-DD如果用户输入包含其他格式模型通常会转换。如果未提及日期模型可能使用今天通过 API 上下文可能不知道具体日期我们可以在提示词中动态插入今天的日期作为参考。Q4文件保存失败例如权限问题。→ 检查当前目录写入权限或指定其他路径。可以在save_report中添加异常处理提示用户。Q5能否将日报直接发送到邮箱或企业微信→ 这涉及外部 API 集成不在本项目的范围内。但通过将生成逻辑封装成函数可以轻松扩展为定时任务或 Web 服务。四、今日总结与作业今天你完成了✅ 综合运用 LangChain 的ChatOpenAI、ChatPromptTemplate、PydanticOutputParser构建了一个完整的日报生成应用。✅ 实现了从非结构化文本到结构化数据的自动化流程。✅ 掌握了 Markdown 渲染和文件保存的基本操作。✅ 通过重试机制提高了系统的健壮性。✅ 完成了第一阶段基础期的所有核心知识点为进入 Agent 核心阶段第二阶段做好了准备。今日作业必做为日报生成器添加一个date参数用户可以在启动时用命令行参数指定日期如python daily_report_generator.py 2025-03-21如果未指定则使用当前日期。尝试使用不同的temperature值0、0.3、0.7运行同一份流水账对比生成的日报风格和准确性选择一个你认为最适合的默认值。将你的日报生成器代码提交到 GitHub 仓库如果还没有创建一个并在 README 中简要说明功能和使用方法。这是你学习旅程的一个重要里程碑明日预告明天是休息与查漏补缺日建议你回顾第一阶段的全部内容整理笔记和代码为第二阶段ReAct 与 Agent 框架养精蓄锐。有任何疑问都可以在明天向我提出。恭喜你坚持到了第 20 天你已经超越了大多数初学者继续加油