软工团队实践第二次作业

2026秋软工实践 蛋仔派队——项目原型设计+概要设计

项目 内容
作业所属课程 H202601 软件工程与软件工程实践
作业要求 2026秋软工实践团队作业-第二次(项目原型设计+概要设计)
作业的目标 在第一次需求分析的基础上,完成可点击原型、系统分层架构、UML 与数据库设计,说明领域智能体与业务功能的协作方式,并通过 GitHub 留下可追踪的任务、评审与交付记录
团队名称 蛋仔派队
团队成员学号-名字 张诗培-102402145、张家祥-102402144、郑仕廷-102402146、郑宇嘉-102402147、叶腾骏-102402142、周凯-102402148、周山翔-102402149、周子钦-102402150、朱铭浩-102402151、韩尔洋-102402154、崔佳静-102402155、王昊-102402156
项目来源仓库 https://github.com/zsp-c/medical-agent
原型地址(墨刀) https://modao.cc/proto/nCt2gfA6to4u6sNYrJRyP7/sharing?view_mode=read_only

一、原型设计

1.1 十屏与任务流

十屏按五个阶段排列,全部面向终端用户:

访客 ── P01 登录 / 注册
              │
问答 ── P02 工作台 ──┬── P03 检索中(流式)── P04 回答与证据 ── P07 图谱实体详情
                     └── P08 附件上传与解析
练习 ── P05 互动题卡 · 作答 ── P06 判题讲解
回顾 ── P10 练习中心 · 答题统计
配置 ── P09 设置(模型 / 记忆)

1.2 各屏说明

P01 登录 / 注册

image

P02 工作台 · 新会话

image

P03 问答 · 检索中(流式)

image

P04 问答 · 回答与证据

image

P05 互动题卡 · 作答

image

P06 互动题卡 · 判题讲解

image

P07 图谱 · 实体详情与子图

image

P08 附件 · 上传与解析

image

P09 设置 · 模型与记忆

image

P10 练习中心 · 答题统计

image

二、概要设计

2.1 系统分层结构

系统切成七层。

image

自上而下是接入层、接口层、服务层、领域层、数据访问层、存储层和外部依赖。接入层负责渲染、消费流式响应、在本地保管用户的 Key,不缓存业务数据。接口层是 FastAPI 的路由,管鉴权、参数校验、流式编码、统一错误码,不写查询语句也不含业务分支。服务层由七个服务组成,编排用例、划事务边界、把失败翻译成错误码,但不拼查询语句。领域层就是 ReActAgent、工具集、提示词模板和那几层硬约束,负责推理循环和上下文裁剪,不直接碰连接。数据访问层是唯一的数据读写出口,包括会话、消息、用户、附件、练习记录的仓储,图谱的 Cypher 模板,以及向量库的客户端,不含业务判断。再往下是 SQLite、Neo4j、两个向量集合,以及模型服务和嵌入服务两个外部依赖。。

2.2 模块划分

功能按业务内聚性拆成七个域、二十八个功能项,粒度定在可以独立指派给一个人并且能独立验收的程度。

image

域 功能项 约束
M1 身份与权限 注册、登录、令牌校验、角色与停用 令牌有效期 720 分钟,停用即拒绝
M2 对话与推理 会话管理、流式问答、工具调度、上下文裁剪 五类流式事件,迭代预算硬上限
M3 知识检索 实体检索、关系查询、子图展开、证据回填 深度不超过 2,单次不超过 50 条,超限标记截断
M4 练习闭环 出题、题卡下发、作答判定、讲解生成 答案不下发,一题一提交
M5 附件与记忆 上传解析、附件注入、记忆检索、记忆沉淀、记忆清除 单文件不超过 20 MB,检索超时 5 秒按未命中处理
M6 练习统计 作答聚合、学科正确率、薄弱知识点、练习记录 口径固定,只统计已提交作答
M7 数据准备 图谱导入、题库向量化、索引重建、参数调整 本地脚本执行,不做界面

2.3 用例图

image

参与者三类:访客、个人用户、医学生(个人用户的特化)。外部系统三个:模型服务、图数据库、向量库。三个主用例都写了完整的用例描述表,这里各说要点。

医疗问答的前置条件是已登录。主成功场景是提问、检索图谱一到三次、组织回答、回填证据实体。异常分支有三条:图谱不可达时返回 503 并提示知识库暂不可用;模型超时返回已生成的部分并标记截断;幂等键命中时直接返回首次结果,写入条数为零。

出题练习与问答的区别在于它会改变对话形态。模型调用展示型工具下发题卡,然后停止展开讲解、等待用户作答。这条"暂停"的语义必须同时写进提示词和状态机,否则模型会在发题卡的同时把答案讲出来。

证据追溯从回答的证据标签进入实体详情,再展开一跳子图,它包含图谱检索用例,因为详情页的关系分组和子图走的是同一套查询模板。

上传附件和配置 Key 被明确标为可选用例。它们在主流程之外,不配置也能正常问答,这样可以避免把边缘功能画成必经步骤。

2.4 活动图

image

问答主流程的活动图重点不在主干,主干就是提问、检索、回答三步,重点在四个判断上。一是令牌是否有效,二是会话是否属于当前用户,两条都走拒绝分支,分别返回 401 与 403。三是是否需要调用工具,不需要就直接组织回答,省掉一轮空转。四是本轮轮次是否小于八、与已执行过的查询是否重复,任一条不满足就强制基于已有信息作答,并在回答里标注证据不足。

第二点值得展开。ReAct 循环必须有硬约束,一个是迭代次数上限八轮,一个是单轮图谱查询上限八次,还有一个是同轮重复查询拦截,参数完全相同的查询直接返回"请勿重复查询"。在这三条之外还有一层软约束,提示词里写明一般四次工具调用就够,引导模型尽早收敛。缺任何一层,模型都可能在一个模糊问题上反复查同一张图,单请求成本从几分钱涨到几块钱。约束不是限制能力,是让成本可预测。

image

题卡闭环单独画一张,因为它的状态比问答复杂:出题、下发(不含答案)、等待作答(模型挂起)、收到选择、检索答案、判定、锁定题卡、逐项解析、记录作答。这里有两个容易混淆的分支,「换一题」丢弃本题且不写作答记录,「再来一题」会写入上一题的结果。这条规则不画出来,实现时两边一定不一致,统计页的数据就废了。

2.5 类图

image

类图只画有行为的类,纯数据模型用注释带过,否则图会被二三十个数据结构淹没。结构上几个决定是这样的。

智能体服务是 ReActAgent 的唯一持有者,实例池按用户和模型两个维度缓存。智能体不放在请求作用域里,因为一次推理要跨多个工具调用,重复初始化会把工具注册的开销乘以调用次数。响应对象由智能体服务组装,不由接口层拼装,因为流式和非流式两条路径必须返回同一个结构,拼装逻辑只能有一处。图谱服务依赖仓储层的查询模板而不依赖驱动,驱动只在装配文件里出现一次,换驱动不改业务。

记忆服务的接口里没有"由智能体决定记什么"这样的方法。记忆的读是同步的,超过五秒按未命中处理,不再等待;写是异步的,回答完成后才沉淀。这个不对称是刻意的:读在关键路径上必须有时限,写不在关键路径上,慢一点没关系,但不能阻塞用户看到答案。

2.6 时序图

image

从浏览器发出流式请求到连接关闭,一共十一步消息。有三点值得单独说。

流式事件的顺序是契约,不是实现细节。工具调用、工具结果循环若干次,然后正文增量若干次,最后结束。前端的状态机完全建立在这个顺序上:收到工具调用就把步骤条推到检索图谱,收到第一个正文增量就推到组织回答。如果把工具结果提前或者合并,前端就会出现已经在输出正文、步骤条却还停在检索的错乱。

结束事件携带完整响应,包括证据实体列表和元信息。证据没有在正文增量里带,是因为要等所有工具调用结束才能确定,边流边发会让证据列表反复变化,用户看到标签闪烁。

消息落库只在结束之后写一次。流式中途断开时,已经发给用户的文字会以截断标记落库,保证用户看到的和库里存的一致。如果边流边写,断线就会留下一堆半截消息。

image

长期记忆单独画一张,因为它是唯一一条跨请求的链路:本次回答结束后异步沉淀,下次提问时同步检索注入。图里用分隔线把第 N 轮和第 N+1 轮切开。隔离键是用户和场景两层,用户层保证 A 的记忆不会被 B 检索到,场景层让同一用户在不同课程或不同会话组下有独立的记忆空间。检索超过五秒按未命中处理,不阻塞回答,因为记忆是增强不是前提。

2.7 协作图

image

协作图和时序图信息等价但视角不同,时序图看时间,协作图看耦合。这张图能直接读出三件事。

问答服务的扇出是六,分别连向智能体、图谱、题库、记忆、会话、附件六个服务,它必然是一个薄编排层,一旦它开始有业务判断,就说明职责漏到上层了。会话仓储是唯一被多方引用的仓储,问答、附件、统计都会碰消息,所以它的接口必须最稳定。记忆服务和练习服务之间没有连线,这是有意的:练习记录和长期记忆是两套数据,不能因为都跟用户有关就混在一起,否则清空记忆会顺手删掉练习统计。

三、数据库设计

完整内容见《蛋仔派队_数据库设计说明书》,这里说清几条主线。

3.1 四类存储各管一段

这个系统没有"一个数据库解决所有问题"的条件。四类数据形态不同,硬塞进一种存储必然有一类是残废的。

存储 承载 为什么用它
SQLite 用户、会话、消息、附件元数据、练习记录 单机部署、事务简单、免安装,读多写少且数据量可控
Neo4j 60,689 个实体、354,752 条关系 多跳可达性查询,关系型数据库要写递归查询,图库一句话
Chroma 两个集合 题库向量(39,307 条、346 学科)、记忆向量 语义检索是近似最近邻问题,字符串匹配解决不了同义表达
对象卷 附件原文 大文本不进数据库,避免备份体积失控

3.2 ER 图与关系模型

image

核心五张表是用户、会话、消息、附件和练习记录,关系以一对多为主。用户到会话是一对多,删用户级联删会话。会话到消息是一对多,会话是消息的聚合根。用户到附件是一对多,附件仅本人可见,跨用户访问返回 403。用户到练习记录是一对多,练习记录独立于消息。

3.3ORM 映射

用 SQLAlchemy 2.0 的声明式映射,类型注解配 mapped_column,关系用双向显式声明。

class Message(Base):
    __tablename__ = "messages"
    id: Mapped[int] = mapped_column(primary_key=True)
    session_id: Mapped[str] = mapped_column(
        ForeignKey("sessions.id", ondelete="CASCADE"), index=True)
    role: Mapped[str] = mapped_column(String(16))        # user | assistant
    content: Mapped[str] = mapped_column(Text)
    request_id: Mapped[str | None] = mapped_column(String(64), unique=True)
    truncated: Mapped[bool] = mapped_column(default=False)
    created_at: Mapped[datetime] = mapped_column(server_default=func.now())
    session: Mapped["Session"] = relationship(back_populates="messages")

图谱和向量不走 ORM。Cypher 和向量库的查询语义与关系模型不同构,硬套 ORM 只会得到一层无意义的包装。这两处用参数化的查询模板和向量库客户端,都只暴露领域语义的方法,比如找实体、搜题目。

四、团队协作记录

4.1 开发计划

计划从 2026 年 11 月 9 日开始,九周做到可演示。每一周的验收标准是「当周结束时仓库里有一个能跑的版本」,不做无法验证的并行铺开。

周次 日期 阶段 主要工作 产出
W1 11.09–11.15 起步 仓库结构、依赖与配置、SQLite 建表、十屏静态页 作业二提交,骨架能启动
W2 11.16–11.22 数据层 图谱分批导入与校验,题库向量化,四个仓储与单测 图谱与题库查得通
W3 11.23–11.29 对话主链路 推理循环、白名单工具、三层硬约束、五类流式事件 流式问答跑通
W4 11.30–12.06 练习闭环 题卡出题、作答判题、逐项讲解、练习记录落库 出题到统计闭环
W5 12.07–12.13 记忆与附件 记忆召回与沉淀、清空、附件解析与按需注入 两个增强特性可用
W6 12.14–12.20 前端联调 十屏按原型还原、统计页接真实数据、错误态补齐 功能冻结
W7 12.21–12.27 测试 单测、端到端走查、异常路径(拔图库、停嵌入服务)、修缺陷 主流程无阻断缺陷
W8 12.28–01.03 文档与部署 部署说明、用户手册、演示录屏、答辩材料 可交付版本
W9 01.04–01.10 收尾 答辩、按反馈修缺陷、补测试 最终提交

五、附页

通过网盘分享的文件:蛋仔派队_数据库设计说明书.pdf

链接: https://pan.baidu.com/s/16j4_mPG8yniDU9WWxjV4Cw?pwd=jzq4 提取码: jzq4

通过网盘分享的文件:蛋仔派队_系统设计说明书.pdf

链接: https://pan.baidu.com/s/1Ihyz4TXNNZ2DQOD-tpEQQw?pwd=za68 提取码: za68

posted @ 2026-11-08 20:34  zsp-  阅读(4)  评论(0)    收藏  举报