ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Travel 项目总结:从旅行规划到可治理 AI Agent 的工程化实践

Travel 项目总结:从旅行规划到可治理 AI Agent 的工程化实践 Travel 项目总结从旅行规划到可治理 AI Agent 的工程化实践开场Travel 解决的不是“生成一份攻略”Travel 是一个面向旅行规划与执行协同的全栈项目。它覆盖了身份、账单、行程、地点、出行执行、协作、媒体、社区、知识库和管理后台等业务边界AI 则负责把自然语言需求逐步转化为可验证的规划候选。这个项目最值得总结的地方不是接入了哪个大模型而是它对 AI 的定位AI 是一个会提问、会检索、会给出多个方案的规划助手但不是可以越过权限、预算和业务规则直接改写正式行程的“超级管理员”。模型提出候选系统负责核对用户负责确认领域用例负责最终落库。整套设计因此更接近一个可恢复、可审计、可治理的 AI workflow system。一、项目定位与整体架构Travel 采用 Monorepo 组织代码核心运行拓扑可以概括为Vue 3 SPA - Caddy / HTTPS - FastAPI modular monolith - PostgreSQL权威业务事实 - RedisBroker、缓存、限流 - MinIO对象存储 - Milvus可重建向量索引 - Celery Worker / Scheduler后端是“模块化单体优先、进程隔离、契约驱动、可演进拆分”的形态。它没有一开始就把每个功能拆成独立微服务而是在一个 FastAPI 应用中用限界上下文和 Clean Architecture 划分职责entrypoints - bootstrap - presentation - application - domain | ^ ^ ---------- infrastructure --- ---------- platform adapters实际模块包括identity、billing、planning、trip、places、execution、collaboration、memory、knowledge、ai_orchestration和content_governance等。这样做的好处是业务规则仍然集中、事务边界清晰需要异步执行的 AI 和研究任务则通过 Celery Worker 独立运行避免阻塞 API 进程。前端采用 Vue 3 TypeScript Vite页面和功能遵循 Feature-Sliced Designapp - pages - widgets - features - entities - shared。Vue Router、Pinia、TanStack Vue Query、Axios、Element Plus、Leaflet、Zod、Vitest 和 Playwright 共同组成前端基础设施OpenAPI 还用于生成接口类型减少前后端契约漂移。二、AI 模块的核心思路先理解再确认最后生成1. Butler 不是聊天框而是意图路由器ai_orchestration模块中的 Butler 首先判断用户在做什么。当前实现覆盖五类意图companionship旅行搭子或陪伴型对话travel_consultation旅行咨询new_planning新建行程规划vague_adjustment表达了想调整但目标不清晰explicit_adjustment明确要求调整已有行程。P0 默认使用DeterministicIntentClassifier。它通过关键词和保守规则工作并设置可靠置信度阈值0.55。当输入模糊时系统宁愿发起澄清也不擅自猜测用户想改哪一天、换什么交通或删掉哪个景点。项目也提供ModelBackedIntentClassifier但模型只负责提出 intent字段缺失、约束冲突和中断决策仍由业务域处理。模型调用失败时回退到确定性分类器保证“模型不可用”不会直接变成“功能不可用”。2. 需求抽取坚持“用户没有说过的不要替他决定”需求抽取会识别目的地、日期、人数、预算及预算口径、节奏、主题、成员、出行目的、交通和住宿偏好以及健康、饮食和安全注意事项。实现上同时存在本地 deterministic extraction 和 model extraction。前者用正则覆盖中文日期、人数、预算、天数、儿童、老人等高频表达后者遵循REQUIREMENT_DELTA_SCHEMA输出结构化候选。两者合并时模型结果只是候选系统还会重新清洗、校验并把金额统一换算为人民币分。抽取提示明确要求只抽取用户原话或能够由日期、天数直接计算的字段未提及的字段必须是null或空数组禁止把“常见旅行偏好”当成事实。这一点很关键因为旅游场景里的默认假设往往会直接影响预算、节奏和安全边界。3. LangGraph 把对话变成可恢复的状态机澄清流程不是一轮 prompt而是一个可中断、可恢复的 LangGraph授权预检 - 意图分类 - 需求抽取 - 约束分析 - 澄清 / 权衡 / 需求确认中断 - 方向集合生成 - 用户选择方向 - 恢复执行并交给规划流程规划流程则大致是授权与配额预检 - 上下文组装 - 读取方向与 baseline - trusted seed 就绪检查 - approved knowledge retrieval - 动态地点/天气适配 - 生成候选 - JSON Schema 校验 - 确定性候选校验 - 风险与不确定性分析 - candidate handoff用户看到的clarifying、requirement_confirmation、tradeoff、direction、planning、candidate等阶段实际上是后端任务状态的安全投影。LangGraph checkpoint 用来恢复运行状态但 PostgreSQL 中的任务、配额和正式行程版本才是权威事实。这让“用户离开页面、网络断开、任务被取消后再继续”成为正常路径而不是异常补丁。继续命令还会检查 actor、版本和中断 token过期中断会返回AI.INTERRUPT_STALE并发命令只有一个能够成功。三、结构化输出与确定性校验模型只交候选不直接改行程AI artifact 采用版本化 schema当前明确区分clarification_and_directionfast_planninglocal_adjustmentdiagnostic_fake。快速规划候选包含标题、目的地、时区、天数、预算摘要、风险、验证缺口、证据引用和动态观察。每天的节点还要有编号、标题、起止时间、类型、预算、步行时间和理由并可附地点引用、交通方式、是否需要预约、是否需要再次核实以及 backup 方案。网关层会执行 JSON Schema strict structured output返回后还会进行 schema validation。随后validate_candidate_deterministic()做第二道、与模型无关的检查日期必须落在行程窗口内不能重复节点编号递增且唯一开始时间早于结束时间没有明确请求时不能无理由重复景点节点预算不能超过候选预算候选总预算不能超过确认预算不能违反用户已确认的 hard constraints。可以把它理解为模型负责“想一个可行方案”代码负责“逐项验收”。因此即使模型生成了格式正确但业务上不合理的内容也只能停在候选阶段不能偷偷覆盖current或history版本。四、快速规划与局部调整把 AI 接进真实业务边界fast_planning是 P0 主路径。它只从 PostgreSQL 读取 trusted seed 和已批准知识不调用 embedding、Milvus 或 Deep Agents。这样做牺牲了一部分召回广度却换来了更容易解释、复现和验证的结果。快速规划会先完成授权、配额、方向和 baseline 读取再检查种子资料是否就绪之后才进行知识召回、动态地点与天气适配、候选生成和风险分析。最终结果通过candidate handoff持久化为 trip candidate由 Trip/Planning 用例接手而不是由 AI runner 直接写正式行程。局部调整同样有边界先重新验证 baseline再计算影响范围生成若干调整选项要求用户确认影响的是单日还是跨日范围最后才交给候选交接。这个设计避免了“用户只说换一家餐厅系统却把后面三天全部重排”的失控体验。五、RAG混合召回和权威事实校验知识模块实现的是 Hybrid RAG而不是单纯的向量搜索PostgreSQL 负责 lexical retrieval 和正文、权限、治理事实BGE-M3 负责语义向量默认维度为 1024Milvus 作为可重建的 semantic indexlexical 与 semantic 结果通过 Reciprocal Rank FusionRRF合并semantic 命中回 PostgreSQL 重新检查权限、content_version、governance_revision、stale vector 和来源多样性。默认 reranker 是DeterministicReranker保持 RRF 顺序并限制单个 source 的结果数量避免某一来源把上下文占满。Milvus 故障时可以降级为postgres_only但 PostgreSQL 本身故障会 fail-closed而不是静默返回一份看似正常的旧结果。索引构建也有双重 revalidateembedding 前检查权威版本写入后再次检查。若内容在 embedding 期间发生变化旧向量会被阻止写入或立即清理。collection version 和 logical alias 只有同时通过 evaluation 与 reconciliation 才能激活。这套机制的重点不是“向量搜得多快”而是“召回结果能不能证明自己仍然可信”。AI 生成时拿到的每条知识都应能追溯到受治理的来源和版本。六、Deep Research联网研究被限制在证据生产区项目提供 Deep Research但默认deep_research_enabled False。启用它需要显式配置 AI、Ark 和 Firecrawl并且强制使用 HTTPS。研究模块采用 supervisor 加四类子 Agent 的结构safety-health-researcher安全与健康transport-logistics-researcher交通与物流destination-experience-researcher目的地体验evidence-validator证据核验。研究前前端ResearchWorkbenchPage.vue要求用户填写范围并确认联网边界。研究 Agent 读取网页原文把外部内容当作不可信数据只输出事实、来源、置信度、冲突和缺口不能直接改写正式行程、知识库、配额或消息。研究结果进入待审核区需要用户或后续治理流程决定是否保存到个人资料库。受限ResearchWorkspace只允许.json、.md、.txt并限制文件数、单文件大小和总空间。这样做是为了让联网能力有明确的“证据生产区”而不是给 Agent 一个可以任意写入系统的后门。七、Agent Harness给 Agent 加上运行时护栏platform/agent_harness是项目里很有工程含量的一层。它把 Agent 执行拆成可审计的运行时组件AgentRunContext携带 task、workflow、actor、request、deadline、lease、fencing token 和 trace 信息ContextPacket与ContextPolicy限制数据源、条目数、token 预算、敏感来源、memory kind 和最大年龄并剔除 raw、prompt、secret 等字段ToolRegistry统一注册工具 schema 与 handler调用前执行 payload、policy、budget、context 校验ExecutionBudget与PersistentBudgetLedger限制模型调用、工具调用、token、费用、研究深度、网页数和工作区空间StopController检测 no progress 和重复调用造成的 retry stormTrajectoryEvent以 append-only 方式记录安全轨迹支持 replay但默认 dry-run禁止重放时产生正式副作用。标准工具端口包括地点搜索、当前天气、路线规划、知识搜索、资料读取、Firecrawl 页面读取和调整建议。工具不是把函数直接暴露给模型而是必须经过注册表、策略和预算的共同检查。预算账本尤其重要预留、结算、释放都落到 PostgreSQL过期 reservation 可以恢复并发测试验证同一预算下只有一个 reservation 能成功。对于真正会产生费用的模型或网页研究这比在内存里维护一个计数器可靠得多。八、模型网关与故障处理AI 通过统一的ModelGateway接口接入当前有fake、ark和deepseek三种 providerArk 走 HTTPS/responses支持 JSON Schema strict output、安全流式输出和文本/图片输入DeepSeek 走 HTTPS/chat/completions使用json_object再用jsonschema.validate复核Fake gateway 支持 success、partial、timeout、rate limited、schema error、unavailable 等模式。429、5xx、认证失败、超大输出、非法 JSON 和 schema 错误都会映射为明确的AdapterFailure类型。前端能够区分真实模型结果和deterministic_fallback用户也能看到任务是继续生成、等待重试还是需要重新确认。项目默认 provider 是fakeAI、RAG 和 Deep Research feature flags 默认关闭。真实模型需要显式 smoke gate生产环境还禁止 real-model smoke。这些开关不是“功能没做完”而是把外部成本、凭据和不确定性放在可控的发布边界之后。九、异步任务、SSE 与可靠交互AI 请求不会在 HTTP 请求里同步跑完整流程。创建任务时AiTaskService会强制要求Idempotency-Key校验 payload 和资源引用在 PostgreSQL 写入 task record写入 transactional outbox主题为ai.task.dispatch_requested.v1返回202 TASK.ACCEPTED由 Celery Worker 消费并 claim task获得 lease 与 fencing token。Worker 每个节点都会回读数据库重新检查权限、配额、版本和取消状态写入任务事件和进度。前端通过 SSE 获取事件流支持Last-Event-IDreplay、心跳和 snapshot 补发。即使浏览器短暂断线重新连接后也能恢复任务视图而不是重新创建一次 AI 任务。前端butler-flow.ts把后端pending_interrupt投影成问题、冲突、权衡、方向和调整选项ButlerPage.vue则承载历史持久化、图片附件、quick/deep planning、停止/继续生成、候选交接和路线卡片。这种交互让复杂 AI 流程看起来像一段可理解的对话而不是一堆后台状态码。十、一条完整用户链路以“帮我安排长沙三天亲子游”为例系统大致这样工作Butler 判断这是new_planning而不是陪伴或模糊调整抽取目的地、日期窗口、人数和亲子主题未知字段保持为空如果预算、节奏或成员信息会影响结果LangGraph 发起 clarification 或 requirement confirmation interrupt用户确认约束后系统生成多个 planning directions让用户选择更紧凑、更舒适或更偏主题的方向任务进入 fast planning读取 trusted seed 和批准知识必要时调用受控的地点、天气和路线工具模型返回候选 JSON经过 schema validation、预算检查、时间检查和 hard constraint 检查系统给出风险、验证缺口和 backup 节点候选进入 trip candidate用户在规划工作区确认后才由正式 Planning/Trip 用例创建或更新行程版本。整个过程中AI 从来没有被允许直接把一句自然语言变成不可逆的业务写入。它更像一个会不断把问题拆小、把不确定性显式化的规划员。十一、治理、可观测性与安全边界AI release 有明确状态机draft - validating - evaluation_pending - approval_pending - approved - canary / active - suspended / retired / rolled_back数据库迁移记录了 validation policies、AI releases、release decisions、model execution records、usage cost records 和 structured output validation records并通过 immutable / append-only guard 保护关键审计数据。可观测性覆盖 model request、duration、usage、failure、schema validation、release resolution、route state、evaluation case 和 telemetry export failure。轨迹记录会过滤 token、secret、password、API key、Bearer 和手机号等敏感内容并限制摘要大小。安全层使用TrustLevel区分 system、user、internal、external 和 untrusted 内容检测“ignore previous instructions”“disable safety”“call tool”等常见 Prompt Injection 表达。外部网页只能作为 data envelope 进入上下文不能修改 policy。十二、测试体系说明了什么这个项目的测试重点不是只验证“接口返回 200”而是验证状态、边界和失败路径artifact schema 会拒绝缺字段、多字段和非法数据候选校验会拒绝越界日期、乱序节点、预算溢出和 hard constraint 违反Fake gateway 覆盖 timeout、rate limit、partial result 和 schema errorclarification workflow 覆盖澄清中断、需求确认、方向选择和最终planning_decision_snapshot重复投递不会重复创建 interrupt过期命令返回AI.INTERRUPT_STALEactor 被撤销后恢复任务会失败Agent budget 并发 reservation 只允许一个成功RAG 覆盖 RRF 排序、stale semantic hit 拒绝、Milvus 降级和 PostgreSQL fail-closedrelease state machine 只允许声明过的状态迁移。这些测试共同证明了一个事实Travel 把 AI 当成一个需要满足业务不变量的执行参与者而不是一个只要生成文本就算成功的黑盒。十三、工程取舍与后续演进Travel 当前选择了几个很明确的取舍先确定性再扩展模型能力。P0 的 intent、抽取、快速规划和 RAG 都保留 deterministic fallback先保证可重复、可测试再逐步引入真实模型。先候选交接再正式写入。AI 产物与正式行程版本分离方便用户确认、审计和回滚。先受控联网再深度研究。Deep Research 默认关闭开启后也只能生产证据候选不能越权修改核心业务事实。先可观测再谈规模化。任务事件、预算账本、release、轨迹和 retrieval audit 都留下了后续运营需要的证据。后续可以在现有边界上继续演进让真实模型逐步接管确定性流程中的候选生成在评估数据和治理策略成熟后启用更强的 reranker扩展动态适配器和更多城市的 trusted seed最后再考虑把已经稳定的限界上下文拆成独立服务。当前架构已经为这些变化保留了接口但没有提前支付微服务化的复杂度。结语Travel 的价值不在于“让 AI 帮你写一份旅游攻略”而在于把旅行规划拆成了一套可解释、可暂停、可恢复、可验证和可审计的系统流程。它把 LangGraph 的状态编排、JSON Schema 的 Structured Output、Hybrid RAG、Milvus、Deep Agents、Firecrawl、Agent Harness、Transactional Outbox、SSE、Idempotency、Fencing Token 和 Release Governance 放进同一条业务链路里。
返回列表