团队项目第一次作业

「随行条件」旅游攻略 Agent —— 团队展示 · 选题报告 · 需求分析

一二三队 | 软件工程课程设计 · 第一次作业
一句话:把几十篇长攻略,压成一份带着你的条件、走得动、下雨也有 Plan B、每句话都有出处的行程。


0. 作业信息

项目 内容
作业所属课程 https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS
作业要求 https://edu.cnblogs.com/campus/gdgy/Class78-Grade2024-CS/homework/16767
文档 https://docs.qq.com/doc/DZU5GWEF2eW1qcG5z?rtkey=116e055b96faa16756a6c9931tURx1&appletId=14b730a4-4f67-47fe-acaf-8431b93afab5
团队名称 一二三队
团队成员 3124004224 宋浩霖 | 3124004203 程源

我理解的作业目标

这次作业不是交一个能跑的软件,而是立项:把“为谁做、解决什么问题、凭什么由我们做、做成什么样算完成”讲清楚,并且经得起追问。

但“立项”不等于“画大饼”。作业里写了两条硬约束:最终所有应用要上线运行,供老师、助教和其他同学检查;最终验收会参考需求文档。所以我们给自己定的标准是:

  1. 选题要来自真实需求,不能是“我们觉得这个很酷”;
  2. 功能要能验收,每条需求都要有对应的验收方式;
  3. 技术方案要能落地,这一版就按“能上线”的形态来设计,而不是先画一个以后再说的饼。

1. 团队展示

1.1 队名

一二三队。

名字很朴素,我们的解释也很朴素:一次只推进一步,但每一步都算数。做这个项目的过程基本也是这样——先把攻略读明白,再把条件说清楚,最后才谈生成。

1.2 团队项目的具体规划与描述

「随行条件」旅游攻略 Agent 是一个面向多代同游场景的 Web 应用。它不生产攻略,而是把团队手动收集的 50–100 篇长篇攻略,预处理成带条件标签的结构化片段;用户用自然语言或多条件组合描述自己的出行约束,后端检索相关片段并调用 DeepSeek,生成:

  • 分时段可执行行程(几点去哪、走多久、在哪吃);
  • 雨天备选方案(下雨那天换哪套,而不是把行程删一半);
  • 每条建议的原文出处(点开就能看到是哪篇攻略的哪一段);
  • 条件标签(步行强度 / 母婴设施 / 无障碍情况)。

规划上分三步走:11 月把需求和 50 篇攻略的数据底座做完;12 月打通“检索 → 生成 → 前端”整条链路,内网可演示;1 月部署到公网,按验收脚本能复现。范围只覆盖杭州、苏州、成都三城,只做单 Agent,不做 UGC 社区、不做用户体系。

1.3 队员风采

学号 姓名 性格 擅长的技术 兴趣爱好 希望的软工角色
3124004224 宋浩霖 沉稳,乐观 需求分析、HTML/JS、SSE 前端渲染 写代码,学习 PM / 需求 · 前端
3124004203 程源 善于思考,急性子 Node.js、检索与 Prompt 设计、数据处理 唱歌,运动 后端 / 数据

1.4 团队的首次合照

image

1.5 团队项目的愿景(约 100 字)

我们希望「随行条件」成为家庭出游时那个“先问一句”的助手:不问你想去哪,而问你和谁去、走不走得动、下雨怎么办。让每一个带着条件出发的家庭,都能在十分钟内拿到一份走得动、有备选、说得清依据的行程;也让攻略里的每一句话,都能找到它的出处。


2. 选题报告

2.1 需求从哪来:三次“走不动”的出行

这个选题不是拍脑袋,是从身边三次很具体的出行里长出来的。

场景一:带 3 岁孩子。 推车能不能走?哪一层有母婴室?厕所在几楼?
攻略里写了景点和美食,却没写这段路有没有台阶。

场景二:带腿脚不便的老人。 这段有没有坡?走多久能坐下?
“风景很好”对老人不是信息,“全程缓坡、每 300 米有座椅”才是。

场景三:第二天下雨。 Plan B 在哪?临时改会不会白跑?
天气一变,前一天排好的路线基本作废,用户只能现场打开手机硬扛。

三次场景指向同一个结论:攻略不是没写,是写在了 8000 字的第 5 屏。 用户要的不是更多攻略,是被“按我的条件筛过”的答案。

2.2 现有产品差在哪

对比维度 攻略平台(马蜂窝 / 小红书) 通用 AI 助手 「随行条件」
按复合条件筛 ◐ 只能按“亲子/周边”这类标签筛 ◐ 能听懂,但会自由发挥 ● 人员 / 天气 / 步行上限 / 设施等 8 个条件组合后检索
雨天 / 闭馆备选 ○ 基本没有 ◐ 有时会给 ● 必备,且每条备选带出处
每条建议的出处 ○ 靠自己翻原文 ○ 无法核验 ● 每条建议后有 [n],点开是原文那一段
体力 / 设施标签 ○ 无 ○ 无 ● 步行强度 · 母婴设施 · 无障碍

不是要再做一个攻略平台,而是补上“决策”这一层。

2.3 一句话定位

面向多代同游的条件化攻略决策助手:输入是条件,输出是走得动、有备选、可溯源的行程。

2.4 杀手级功能

这是整个项目最想让老师记住的一个功能,所以用用户语言说,而不是用技术语言说:

用户说一句:“杭州 2 天,带 3 岁小孩和腿脚不便的老人,第二天可能下雨,步行别太多。”
系统从大量长攻略里抽出适合的景点、餐饮、交通和避坑点,给出——
① 分时段可执行行程;② 雨天备选方案;③ 每条建议的攻略出处;④ 步行强度 / 母婴 / 无障碍标签。

它的关键在于三件事同时成立:

  1. 有条件的:不是通用行程,是按“谁去、什么天气、能走多少”筛过的;
  2. 可执行的:落到几点、走多久、在哪吃,而不是罗列景点;
  3. 可核验的:每条建议都能点回原文,说不清出处的会标“出处待核对”,不编。

“预处理长文本”“RAG”“Prompt 组装”是支撑它的手段,不是它本身。这一点我们在选题时反复纠正过自己:老师问“杀手级功能”,想听的是用户得到了什么,而不是我们用了什么技术。

2.5 创新点

# 创新点 具体是什么 现有产品的空白
1 条件组合,而不是单标签 同行人员、天气、步行上限、母婴、无障碍、天数、城市同时生效,冲突时主动提示冲突 最多做到“亲子”一个标签
2 每条建议可回溯到原文 建议 → 片段 → 原文段落,三级可查;编号缺失就标“出处待核对” 通用 AI 无法核验,平台靠用户自己翻
3 备选方案是必选项 下雨、闭馆、孩子闹情绪都有对应 Plan B 这是现有产品最普遍的空白

单看每一条都不算石破天惊,但“可溯源 + 备选”这两条叠在一起,就要求整条数据链路(预处理字段、检索、生成、展示)都重做一遍。这也是我们认为它比“又一个 AI 行程生成器”更难被抄的原因。

2.6 适用范围与边界

  • 适用:多代同游、亲子出行、有无障碍需求的家庭;2–3 天的城市短途(杭州 / 苏州 / 成都)。
  • 暂不覆盖:出境长线、自驾、实时票务与价格。V1.0 只验证“条件 → 行程”这一条链路。
  • 明确不做:完整 UGC 社区、复杂用户系统与权限、移动端原生 App / 小程序、自动爬虫与大规模采集、多智能体协商。

2.7 技术可行性:为什么做得出来

  • 数据可控:50–100 篇手动收集,来源公开可引用,规模小但每一篇都能被预处理成结构化字段,演示够用。
  • 模型够用:DeepSeek API 兼容 OpenAI SDK,stream: true 支持流式输出,接进 Web 后端是最短路径。
  • 链路清晰:预处理与检索是我们自己写的确定性代码,模型只负责“组织”,不负责“发现”,所以可测、可降级。
  • 风险已知:长链路任何一环超时都会影响演示,所以从设计之初就写了降级策略(检索为空不调用生成、超时返回片段摘要)。

3. 需求分析

本节只写骨架和关键判断;完整的功能字段、接口报文、数据字典和逐条验收对照表见需求规格说明书。

3.1 迭代记录

版本 日期 修改人 修改内容 评审
V0.1 2026-11-01 宋浩霖 初稿:项目范围、用户角色、功能结构 全组
V0.2 2026-11-03 程源 补充预处理字段、检索与 Prompt 方案 宋浩霖
V0.3 2026-11-05 宋浩霖 补充前端页面、SSE 事件与交互状态 全组
V1.0 2026-11-07 全组 补齐接口、类图、验收对照表,定稿 全组

3.2 项目标志

  • 项目编号:TC-Agent-2026
  • 标识元素:一条蜿蜒的路线 + 一枚定位点,代表“按条件走出来的路”;配色取西湖的墨绿与米白,点缀陶土橙。
  • 文档封面与 PPT 使用同一套文字标识,不做复杂图形,保证在不同设备上都清晰。

3.3 功能结构(思维导图)

「随行条件」旅游攻略 Agent
├── 1 攻略数据管理(3)
│   ├── 1.1 攻略长文本导入
│   ├── 1.2 原文存储与来源标识
│   └── 1.3 攻略列表查看
├── 2 预处理与结构化(5)
│   ├── 2.1 长文本分块
│   ├── 2.2 结构化字段抽取
│   ├── 2.3 条件标签标注(步行/母婴/无障碍/雨天备选)
│   ├── 2.4 抽取结果查看与人工修正
│   └── 2.5 结构化片段入库
├── 3 条件查询(3)
│   ├── 3.1 自然语言条件输入
│   ├── 3.2 多条件组合选择
│   └── 3.3 条件解析与检索参数生成
├── 4 Agent 生成(6)
│   ├── 4.1 攻略片段检索
│   ├── 4.2 Prompt 组装与上下文构造
│   ├── 4.3 DeepSeek API 调用(流式)
│   ├── 4.4 分时段行程生成
│   ├── 4.5 雨天备选方案生成
│   └── 4.6 出处溯源与条件标签附着
├── 5 结果展示(4)
│   ├── 5.1 行程流式展示
│   ├── 5.2 备选方案展示
│   ├── 5.3 出处引用展示
│   └── 5.4 条件标签展示
└── 6 异常与降级(4)
    ├── 6.1 Agent 超时提示
    ├── 6.2 检索为空处理
    ├── 6.3 接口异常提示与重试
    └── 6.4 调用日志记录

6 大模块、25 项子功能。前三个模块解决“数据从哪来、怎么读懂”,4 和 5 是核心链路,6 是兜底——它不是附属功能,而是这个产品敢不敢让人用的前提。

3.4 核心类图

系统共 8 个类,其中 7 个是核心领域类,1 个是降级日志:

classDiagram class GuideText { +String textId +String title +String source +String city +String rawContent +importText() +getRaw() } class GuideChunk { +String chunkId +String textId +String location +String walkingLevel +String babyFacility +String accessibility +String rainyBackup +String sourceRef +extract() +validate() } class Query { +String queryId +String rawInput +String[] companions +String[] weather +String walkingLimit +String[] facilityNeeds +parse() +toSearchParams() } class RetrievalResult { +String resultId +String queryId +String[] chunkIds +Float score +rank() +filter() } class AgentRequest { +String requestId +String queryId +String prompt +String[] contextChunks +String model +Boolean stream +buildPrompt() +send() } class AgentResponse { +String responseId +String requestId +String content +String status +Int latency +streamOut() +save() } class Citation { +String citationId +String responseId +String chunkId +String textId +String sourceRef +String excerpt +attach() +render() } class FallbackLog { +String logId +String requestId +String errorType +String message +record() } GuideText "1" --> "N" GuideChunk : 预处理产生 Query "1" --> "N" RetrievalResult : 检索 Query "1" --> "1" AgentRequest : 构造 RetrievalResult "N" --> "N" GuideChunk : 引用 AgentRequest "1" --> "1" AgentResponse : 调用 AgentResponse "1" --> "N" Citation : 标注出处 Citation "N" --> "1" GuideChunk : 回溯 FallbackLog "N" --> "1" AgentRequest : 异常关联

这张图里最重要的不是字段,是从 AgentResponse 到 Citation 再到 GuideChunk 这条回路:它保证了“每条建议都能回到原文”,也让“可溯源”从一句口号变成了一个可以被检查的数据结构。

3.5 功能描述(挑三条讲透)

完整的功能表在需求文档第 6 章,这里挑三条最能说明问题的。

FR-PRE-02 结构化字段抽取

项 内容
使用角色 系统(由团队成员触发)
优先级 高
前置条件 攻略原文已完成分块
输入 一个 GuideChunk 文本片段
处理逻辑 按数据字典抽取:地点、适合人群、步行强度、母婴设施、无障碍情况、雨天备选、建议时长、交通方式、注意事项、来源位置 → 写入片段
输出 带条件标签的结构化片段
异常与边界 抽不到就填“未知”,不留空;低置信度片段标“待人工复核”;不得编造原文不存在的信息
关联 INT-01;GuideChunk;附录 A 数据字典

这一条是整条链路的“地基”。如果字段定义不清,后面的检索和生成全是黑盒,验收时也没法判断做没做对。

FR-AGENT-01 条件化行程生成与出处溯源

项 内容
使用角色 普通用户
优先级 高
输入 用户条件 + 检索到的片段(已按相关度编号)
处理逻辑 后端组装 system prompt(角色、输出结构、引用规则)与 user 内容(条件 + 带编号片段)→ 调用 DeepSeek 流式接口 → 按“分时段行程 / 雨天备选 / 每条建议附编号与标签”输出 → 后端把编号映射成 Citation → SSE 推送
输出 行程 + 备选 + 出处 + 标签
异常与边界 首字超过 5 秒提示“生成较慢”;60 秒未完成返回已生成部分;模型漏标编号时标“出处待核对”;不得输出检索片段之外的地点作为主推荐
关联 API-02、INT-03;AgentRequest / AgentResponse / Citation

FR-FALLBACK-01 Agent 调用降级

项 内容
触发 超时、限流、5xx 或网络错误
处理 网络错误 / 5xx 重试 1 次(4xx 不重试)→ 仍失败写 FallbackLog → 返回标准化错误码 → 前端展示“智能生成暂不可用”+ 检索片段摘要
边界 不向前端泄露 Key、内部地址、原始堆栈;降级内容必须明确标注“非智能生成”,不能伪装成模型输出

3.6 前端与后端

前端只要三个页面,够用就行:条件输入页、结果展示页、出处详情浮层。真正的难点不在页面,而在流式渲染的状态管理:收到 meta 显示加载、收到 chunk 增量渲染、收到 citation 插入出处标记、收到 done 关闭连接、收到 error 给出重试入口,中间断流要保留已展示内容。

后端是“代理 + 编排”:接收条件 → 解析成检索参数 → 检索片段 → 组装 Prompt → 调 DeepSeek → 转发 SSE → 记录日志。前后端只认 5 个接口:

编号 方法 路径 用途
API-01 POST /api/query 创建查询,返回 queryId 与片段数
API-02 GET /api/query/{id}/stream SSE 流式获取生成结果
API-03 GET /api/query/{id}/result 非流式兜底,取完整结果
API-04 GET /api/citation/{id} 出处:原文摘录、标题、来源、位置
API-09 GET /api/health 服务与 DeepSeek 连通状态

SSE 有 5 类事件:meta / chunk / citation / done / error,连接超时 60 秒。

3.7 智能体如何嵌入(这块是重点)

作业要求“智能体要能嵌入到你开发的软件系统中”,我们的做法是后端代理 + 流式返回:

sequenceDiagram participant U as 用户 participant F as 前端 participant B as 后端代理 participant R as 检索模块 participant D as DeepSeek U->>F: 填写条件并提交 F->>B: POST /api/query B->>R: INT-02 检索结构化片段 R-->>B: 18 条候选片段(带出处编号) B->>B: INT-03 组装 system + user prompt B->>D: POST /chat/completions(stream: true) D-->>B: 增量 token B-->>F: SSE meta / chunk / citation B-->>F: SSE done F->>B: GET /api/citation/{id} B-->>F: 原文摘录 + 来源 + 位置

三个关键点:

  1. Key 只在后端:DEEPSEEK_API_KEY 放在后端环境变量,前端代码、网络面板、日志、版本库里都不出现;
  2. 上下文我们说了算:检索片段按相关度排序、编号、按 token 上限截断,模型只看到我们给的材料;
  3. 失败有退路:超时/5xx 降级为片段摘要,检索为空直接不调用模型。

接口层面:POST https://api.deepseek.com/chat/completions,模型 deepseek-chat,stream: true,连接超时 10s、首字期望 ≤5s、整体 60s。

3.8 验收标准

需求写了多少,就要能验多少。我们的验收方式是可复现的七步演示脚本:

步骤 操作 预期结果
1 导入 1 篇杭州长攻略 返回 textId,原文完整保存
2 触发预处理 生成多个片段,字段含位置与条件标签
3 输入“杭州 / 2 天 / 3 岁小孩 / 老人腿脚不便 / 第二天雨” 返回 queryId 与检索片段数
4 观察流式生成 5 秒内出现首字,内容逐步出现,不白屏
5 检查结果 分时段行程 + 雨天备选 + 每条建议带 [n] 与标签
6 点开 2 条出处 浮层展示原文摘录、标题、来源、片段位置
7 断网 / 模拟超时,再查“北京” 降级提示 + 片段摘要;未覆盖城市返回空结果,不编造

三条硬指标:首字 ≤5s、整体 ≤60s、抽查 10 条建议出处 100% 可映射。

3.9 非功能指标

维度 指标
性能 普通接口 P95 ≤ 2s;Agent 首字 ≤5s、整体 ≤60s
可用性 Agent 失败时页面不白屏,必须有降级提示与重试入口
安全 Key 仅后端持有;用户输入转义防 XSS;日志不含 Key 与隐私文本
兼容 Chrome / Edge / Firefox 最新两个主要版本,支持 SSE
可维护 抽取字段、Prompt 模板、模型名全部配置化

4. 上线计划

老师明确要求“最终需要上线运行”,所以这一块不是可选项:

阶段 时间 交付
数据与需求 2026.11 需求定稿;50 篇攻略入库;预处理跑通,抽检 10 条
链路打通 2026.12 检索 + Agent + 前端联调;SSE 与降级可用;内网演示
公网部署 2027.01 前端 Vercel / 后端 Render(或校园服务器);HTTPS 域名可访问;按验收脚本复现

上线形态:一个公网可访问的 https 地址 + 一套只含杭州的演示数据,其余城市同理。


5. 分工与下一步

成员 主要负责 本轮产出
宋浩霖 需求、前端、答辩 需求文档、条件表单与 SSE 渲染、PPT 与验收脚本
程源 后端、数据 预处理、检索、Prompt、接口

下一步:先把 50 篇攻略的字段抽检做完(这是效果的天花板),再调 Prompt 的输出结构稳定性,最后做流式与降级的前端联调。

posted @ 2026-11-08 16:40  JJ123456789  阅读(22)  评论(0)    收藏  举报