【从 LLM Demo 到 Agent 后端】从 0 到 1 构建一个智能旅行 Agent 后端
摘要本文是《从 0 到 1 构建一个智能旅行 Agent 后端》系列开篇。记录了一个个人学习项目如何从简单的 LLM Demo 逐步演进为具备状态管理、HITL 人工确认、Session Fork 多方案对比、双存储持久化和 FastAPI 服务化能力的 Agent 后端。当前 Agent 使用规则 Mock 实现尚未接入真实 LLM重点探索 Agent 后端工程架构而非模型调优。副标题基于 LangGraph FastAPI SQLite 的 Agent 后端工程实践本文是《从 0 到 1 构建一个智能旅行 Agent 后端》系列开篇。本系列记录一个个人学习项目如何从简单的 LLM 应用思路逐步演进为具备状态管理、人工确认、分支执行和持久化能力的 Agent 后端。这是一个个人学习项目helloagents-trip-planner。当前 Agent 使用规则 Mock实现尚未接入真实 LLM。我刻意把「模型能力」和「工程架构」拆开练——本系列重点探索 Agent 后端该怎么搭而不是 Prompt 怎么调。如果你也做过「用户输入 → 调模型 → 输出一段文字」的 Demo大概会和我有同样的起点。但当我把场景从「演示一次生成」推到「用户会改主意、会对比方案、会隔天回来继续」时问题就不再是「怎么让模型写得更好」而是为什么一个旅行规划 Agent不能只是 User → LLM → Answer 这么简单1. 我为什么开始做这个 Agent我一开始的目标很朴素输入旅行需求 ↓ 生成旅行方案Mock 能稳定吐出结构化字段和几条示例路线后我以为离「能用的 Agent」不远了。直到真实交互一个个冒出来我才意识到产品形态远比「生成内容」复杂。用户会修改需求。不是每次换一句新 prompt 重开一局而是在同一次规划里反复 tweak——改天数、改预算、补目的地。没有结构化状态后端只能整段重跑或假装「模型记住了」。用户会比较不同路线。已有「悉尼 5 天」方案又说「换墨尔本试试」。这不是改几个字段而是产生新的探索方向在同一时间线上原地改写旧方案会被覆盖无法并排对比。用户希望保留历史方案。上周那条路线还想留着从它再 fork 一条新分支继续改——而不是只能编辑当前这一条。用户希望暂停后继续。需求还没确认完就关了页面或者服务重启了下次回来应该从确认门接着走而不是从头再来。我选旅行规划做练手也是因为它天然带这些张力先锁「要什么样的旅行」再锁「选哪条路线」还可能另开方案对比。换成「单次问答式攻略生成」很多层根本不会出现——但那就不是我在练的产品形态了。这些问题逐渐把核心从「生成一段攻略」推成了管理一个持续演进的状态。今天的后端骨架——可暂停、可分支、可持久化、可接 HTTP——不是第一天画完架构图就有的是被这些问题一步步逼出来的。如果一开始就宣称「架构设计完备」那是在骗自己真实路径是Mock 能跑 → 用户改需求 → 加确认门 → 用户要比方案 → 加 Fork → 要跨重启 → 加持久化 → 要接前端 → 加 HTTP 边界。2. 普通 LLM Demo 遇到的问题一个最简单的 Agent 长这样User ↓ Prompt ↓ LLM ↓ Answer在 Demo 里它能跑。放进稍真实的交互很快就会撞墙。问题 1模型不应该决定流程例如是否等待用户确认是否进入路线规划阶段用户点了「修改需求」后该回到哪一步这些都不是「让模型再想想」能解决的——它们是产品规则必须确定性执行。如果把流程控制权交给 LLM短期看起来像 Agent长期一定状态漂移同一句用户输入有时跳过确认有时多问一轮。问题 2用户行为不是线性的用户不会按你设计的脚本走。常见场景悉尼路线不错但我想看看墨尔本版本。这不是在同一份草稿上改几个字段而是另开一条探索线。如果后端只有「当前方案」一个槽位每次探索都会覆盖上一次的结果用户就没法并排比较「悉尼版」和「墨尔本版」。问题 3执行过程需要恢复用户关闭页面、容器重启、部署更新——内存里的执行位置会全丢。没有持久化Agent 只能当一次性玩具每次回来都是新会话之前的确认门、选中的路线、fork 出来的分支全部归零。这三类问题叠在一起Agent 的核心逐渐变成三件事状态、流程、恢复。生成内容只是其中一环而且往往还不是最难的一环。把它们拆成五个更具体的问题就是本系列后面几层架构的直接动机用户为什么需要确认旅行规划不是「模型觉得可以就定稿」。需求还不完整时比如缺天数不应该进入路线规划用户说「差不多就这样」和「我还要改预算」后端必须能区分。确认是控制流事件不是多调一次模型就能替代的。为什么修改需求不是重新调用一次模型用户在确认门上点 MODIFY期望的是保留会话上下文、回到需求草稿、重新生成后再停在同一确认门——而不是新开一个 HTTP 请求、丢失 stage、把之前选过的路线一并清掉。修改是状态迁移不是「再 prompt 一遍」。为什么多方案探索需要 Session Fork「悉尼版」和「墨尔本版」是两条并行的时间线用户可能来回切换对比。在同一 thread 上 update 几个字段旧方案会被覆盖Fork 让每条探索线有独立的执行上下文父方案只读保留。为什么 Agent 需要保存执行状态图跑在 interrupt 处暂停时内存里只有「停在哪、next 是谁、当前 TripState 是什么」这一整套执行快照。用户隔天回来、容器重建如果没有 LangGraph Checkpoint 业务元数据只能从头再来。为什么 HTTP 接入后需要重新设计边界一旦暴露 REST 端点Router 很容易直接调 Graph、直接写 Repository、绕过 confirmation_flow。短期能跑长期一定破坏「Agent 不改 Control、transition 不外泄到 HTTP」这些不变量。HTTP 层需要 Application Service 收口而不是把图当普通函数调。3. 我的 Agent 后端最终解决了什么问题回头看这个项目是一层层补出来的不是一次设计完备的简单 Agent | v LangGraph 工作流 | v HITL 人工确认 | v Session Fork 多方案 | v Persistence 持久化 | v FastAPI 服务化LangGraph 工作流——因为单次 pipeline 撑不住「需求解析 → 确认 → 路线规划 → 再确认」的多步编排。HITL 人工确认——因为用户必须在关键节点显式 CONFIRM / MODIFY / BACK而不是让模型「假装确认过了」。Session Fork——因为「换墨尔本试试」需要独立时间线不能在同一 thread 上覆盖旧方案。Persistence——因为进程重启后还要能从 interrupt 位置继续业务元数据和图执行态都得有地方存。FastAPI 服务化——因为 HTTP 接入后Router 若直接碰 Graph 和 Repository边界会失控不变量很难守住。每一层都对应上面某个「为什么」确认门回答「为什么要 HITL」条件路由回答「为什么 MODIFY 不能当 CONFIRM 处理」Fork 回答「为什么不能原地覆盖」双存储回答「为什么 MemorySaver 不够」Application Service 回答「为什么 HTTP 不能直接调 Graph」。这些能力不是开会画一张大图就齐了的。真实顺序里LangGraph 和 HITL 来得最早Fork 和持久化是产品形态清晰之后才补FastAPI 则在内部闭环跑通后才收口到 HTTP。博客系列按概念理解顺序组织和代码提交顺序不完全一致——先建立心智模型再讲踩坑细节读者更容易跟住因果链。4. 最终架构的核心思想这里只做概念介绍细节留给后续文章。Agent ↓ 负责领域生成 Transition ↓ 负责用户动作和控制 LangGraph ↓ 负责执行流程 CheckpointLangGraph Checkpointer 持久化的执行快照 ↓ 负责恢复状态 Repository ↓ 负责业务元数据分工可以概括成一句话Agent 负责「想什么」流程系统负责「下一步做什么」。Agent 读用户输入、产出结构化需求和路线候选——它只管「理解与生成的领域内容」。用户点了 CONFIRM 还是 MODIFY当前 stage 能不能进路线规划选中 id 是否合法这些由Transition和LangGraph的确定性控制来管。进程重启后从哪恢复LangGraph Checkpoint管执行态interrupt 停在哪、next 节点是谁Repository管业务元数据Session 列表、active 分支、用户可见的快照——两者各存各的不混写。我曾差点违反这条原则让 Mock Agent 顺便写stage、在 wait 节点里直接做 transition、Router 里直接Command(resumeTrue)——每一种都让短期 demo 更快但测试立刻变成「看实现细节心情」。最终收口的约束是Domain 归 AgentControl 归 transitionExecution 归 LangGraph持久化分双存储HTTP 归 Application Service。这条原则看起来简单落地时要和 interrupt、条件路由、fork 权限、HTTP 边界一一对齐。本系列后面五篇就是围绕这些对齐过程展开的——这里不展开 conditional edge 怎么写、fork 怎么不复制父 LangGraph Checkpoint、metadata first 怎么投影那些留给对应篇章。5. 这个系列会讲什么如果把五层能力写成一篇「架构大全」读者很难跟住「当时为什么加这一层」。我把演进过程拆成五篇独立文章每篇对应一类设计张力按概念理解顺序组织——不是 API 文档也不是 README而是第一人称工程实践先讲我遇到了什么再讲我改了什么以及我当时差点怎么走偏。第一篇为什么我没有直接写 Agent而是先设计状态机核心为什么 Agent 首先应该设计状态而不是 Prompt。Domain / Control / Execution 必须拆开。第二篇LangGraph 实战踩坑为什么 interrupt 后 resume 会跑错节点核心状态正确不代表流程正确。interrupt、transition、条件边各管什么不能混。第三篇为什么 Agent 需要 Session Fork从改几个字段到多方案时间线核心用户在探索新可能不是原地改方案。Branch 是时间线不是版本号。第四篇为什么 Agent 系统需要双存储Business DB 和 Checkpoint 各管什么核心重启以后怎么办。业务事实与执行事实分存禁止双写 TripState。第五篇FastAPI 接入 Agent 后端为什么 Router 不能直接调用 Graph核心HTTP 接入后边界如何收口。Router → Application Service → Graph。6. 当前项目边界保持真实这是一个用于学习 Agent 后端工程化的项目不是生产系统。已完成Mock Requirement Agent规则解析Mock Route PlannerLangGraph HITL双确认门、interrupt / resumeSession Fork独立 thread、多方案时间线FastAPI HTTP 层SQLite PersistenceBusiness DB SqliteSaver LangGraph CheckpointRestart Recovery容器销毁重建后可从 interrupt 继续未完成Vue3 前端联调真实 LLM 接入MCP 工具集成鉴权与多用户多 worker / 高并发部署测试覆盖了 HTTP、分支隔离、失败补偿和重启恢复等主链路但测试通过不等于生产就绪。当前 Agent 仍是规则 Mock——换真实模型之前架构边界必须先站住。Mock 不是偷懒而是把「模型会不会胡说」和「系统能不能管住流程」拆开验证前者等 LLM 接入再测后者现在就能用规则和测试固定行为。如果你也在做 Agent 后端建议先问自己你的产品是需要「一次出答案」还是「长期管状态」我的答案是后者所以这套骨架值得先搭好再换真实模型。7. 总结做完这一圈我留下三个观点第一Agent 应该先解决状态和流程问题而不是只关注 Prompt。模型写得再漂亮没有确认门、没有 stage 约束、没有恢复能力撑不住真实交互。第二复杂 Agent 的核心不是一次生成而是长期交互过程中的状态管理。用户会改、会比、会暂停、会回来——后端要管理的是一个持续演进的状态而不只是一段输出文本。第三工程化 Agent 需要明确哪些事情交给模型哪些事情必须由系统控制。理解与生成交给 Agent流程、权限、持久化、HTTP 边界交给确定性系统。混在一起短期像 Agent长期一定失控。下一篇《为什么我没有直接写 Agent而是先设计状态机》

相关新闻

CAN总线协议深度解析:从核心原理到实战调试指南

CAN总线协议深度解析:从核心原理到实战调试指南

1. 项目概述:从“汽车神经”到工业脉络如果你接触过汽车电子或者工业控制,那么“CAN总线”这个词大概率已经在你耳边磨出了茧子。它不像TCP/IP那样家喻户晓,也不像I2C、SPI那样简单直观,但在它自己的领域里,CAN总线是当…

2026/10/12 13:44:25 阅读更多 →
Altium Designer 9 原理图绘制入门:从核心概念到实战电机驱动模块设计

Altium Designer 9 原理图绘制入门:从核心概念到实战电机驱动模块设计

1. 项目概述:从零开始,用AD9绘制你的第一张原理图如果你刚刚踏入电子设计的大门,面对琳琅满目的EDA软件感到无从下手,那么从Altium Designer 9(简称AD9)开始学习原理图绘制,是一个非常经典且实用…

2026/10/10 8:21:59 阅读更多 →
LangChain:模块化AI应用开发框架解析与实践

LangChain:模块化AI应用开发框架解析与实践

1. 为什么说LangChain是AI应用的"乐高积木"?第一次接触LangChain时,我正为一个客户项目头疼——需要将大模型能力整合进现有业务系统。传统做法要么直接调用API(功能单一),要么从零开发(成本过高…

2026/10/9 22:17:43 阅读更多 →

最新新闻

豆瓣影评情感分析:朴素贝叶斯文本分类实战

豆瓣影评情感分析:朴素贝叶斯文本分类实战

简介:面向人工智能与自然语言处理初学者的情感分析实践项目,聚焦豆瓣Top250影评数据,基于朴素贝叶斯分类器完成正负面情感判别。资料涵盖Scrapy爬虫采集的约5万条影评语料,好评差评比例均衡,并按照4:1划分训练集与测试…

2026/10/12 13:43:55 阅读更多 →
操作系统T1考题解析:进程状态迁移与上下文切换双线推演

操作系统T1考题解析:进程状态迁移与上下文切换双线推演

1. 项目概述:这是一份面向操作系统的教学实操型考题解析,不是试卷搬运工“第2单元进程的描述与控制考试T1”——光看标题,你可能以为这只是某高校《操作系统原理》课程的一道普通期中题。但作为带过十几届系统课实验的从业者,我得…

2026/10/12 13:43:55 阅读更多 →
Java中extends与implements的区别:从语法到设计选型

Java中extends与implements的区别:从语法到设计选型

1. 为什么这两个关键字总让人犯迷糊刚入行那会儿,我在一个后台管理系统里写代码,需要定义一个订单服务类。当时脑子里想的是“订单服务是一种服务,那就用 extends 继承一个基础服务类吧”,结果写着写着发现基础服务类里有一堆跟订…

2026/10/12 13:43:55 阅读更多 →
C语言浮点数精度陷阱与避坑指南:从IEEE 754到工程实践

C语言浮点数精度陷阱与避坑指南:从IEEE 754到工程实践

1. 从"整数思维"到"浮点思维"的认知切换很多人学C语言学到浮点数这一块,都会有一种"好像懂了但又好像没懂"的感觉。声明一个float变量、打印用%f、做做加减乘除,看起来和整数没什么区别。但一旦程序跑出0.1 0.2 ! 0.3这种…

2026/10/12 13:43:55 阅读更多 →
运动估计实验从零到一:块匹配原理、实现与调参避坑指南

运动估计实验从零到一:块匹配原理、实现与调参避坑指南

1. 运动估计到底在解决一个什么问题很多人第一次接触运动估计,脑子里冒出来的画面是摄像头追踪一个跑来跑去的人。这个理解不算错,但只看到了冰山一角。运动估计真正要回答的核心问题其实非常朴素:同一场景在相邻两帧画面里,像素点…

2026/10/12 13:43:55 阅读更多 →
【yyds】大模型开发新风向:上下文工程接管AI编程,RAG真的凉了吗?用TaoToken统一Key实测进阶指南

【yyds】大模型开发新风向:上下文工程接管AI编程,RAG真的凉了吗?用TaoToken统一Key实测进阶指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 13:42:54 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →