MediGuide 是一个用于作品展示的智慧就医辅助项目。它把预问诊、报告解读、医院匹配、知识检索、事实核验和记忆确认放进同一套可审计 Agent Runtime,而不是堆叠多个没有边界的自主 Agent。
项目的核心判断是:Agent 的价值不在于“会聊天”,而在于能否在每一个最小循环中明确观察、提出结构化候选、经过确定性约束和证据核验,再决定继续追问、给出有引用的结果,或转人工确认。
本仓库仅用于展示,不提供线上部署或医疗服务。所有输出均不构成医学诊断、处方或用药建议;出现危险信号或危急值时,界面会提示及时线下就医。
- 一个主 Agent Loop:模型只负责受约束的抽取、追问草稿和证据整理;状态推进、字段校验、安全规则、医院隔离和引用校验由代码负责。
- 类型优先:自然语言先转换为带来源、置信度和确认状态的领域事实,再进入后续节点;不让一段未经校验的字符串直接驱动科室推荐。
- 证据优先:所有医院候选必须来自当前医院范围内的有效知识片段,并保留
source_document_id、章节、页码/定位和检索分数。 - 安全降级:出现危险信号、危急值、缺失关键字段、证据冲突或检索不可用时,优先提示就医/补充信息/人工复核,而不是编造结论。
- 可回放:运行事件 append-only 写入,记录节点输入摘要、输出、工具调用、状态变更和原因,支持审计与失败复盘。
- 开发期协作工具不属于产品:仓库不包含用于多智能体开发的编排文件;生产运行时只保留一个受控 Runtime。
flowchart LR
U[用户输入] --> C[ContextAssembler]
C --> G[LangGraph 预问诊图]
G --> X[LangChain 结构化抽取]
X --> V[类型校验与 FactLedger]
V --> Q{安全/缺失字段}
Q -->|需要补充| U
Q -->|摘要已确认| R[医院硬过滤 + 混合 RAG]
R --> L[LangChain 证据草稿]
L --> F[独立事实核验]
F --> O[可审计结果/人工复核]
运行时的最小循环是:
Observe → Propose → Validate → Act → Record
Observe 读取当前会话状态、用户已确认事实、工作记忆和受范围约束的知识证据;Propose 通过 LangChain 结构化输出提出事实、问题或草稿;Validate 由 Pydantic、领域规则和事实核验器检查;Act 只允许有限动作;Record 把结果写入 Agent Run 事件流。
预问诊图按以下顺序推进:
load_context
→ safety_scan
→ extract_facts
→ validate_facts
→ reconcile_facts
→ choose_action
safety_scan先执行确定性的危险信号规则,不等待 LLM 判断急症。extract_facts使用 LangChain 结构化输出,只允许写入领域模型定义的字段。validate_facts校验类型、范围、枚举、单位和字段间约束,包含DurationValue、SeverityValue、Trend、PatientContextValue等值对象。FactLedger保存每条事实的source、原文证据、置信度、时间、确认状态和冲突信息;用户明确确认的事实不会被低置信度新消息静默覆盖。ContextAssembler只注入与当前节点相关的有界上下文,避免把整个会话原文无差别塞给模型。choose_action只能选择继续追问、确认摘要、进入医院匹配、提示线下就医或进入人工复核。
报告文本/PDF 先经过提取、危急值规则和用户修订,再与预问诊摘要合并。医院匹配阶段执行:
- 对当前医院范围做硬过滤,不允许跨医院知识泄漏。
- 召回有效科室、就诊指南、服务范围和排除条件。
- 由 LangChain 生成带证据引用的受限草稿。
- 事实核验器检查医院、科室、来源状态、有效期和引用覆盖。
- 证据不足、冲突或规则未通过时返回人工确认,而不是返回无引用推荐。
知识入库与运行时召回是两条明确的链路:
官方资料
→ 标题/段落/列表/表格结构化切分
→ Embedding + 词法索引
→ hospital_id / 状态 / 有效期硬过滤
→ dense top-40 + lexical top-40
→ RRF 融合 + parent_section 去重
→ 最多 10 条 Evidence Pack
→ LangChain 证据草稿
→ citation / 医院 / 科室 / 来源核验
切分规则:
- 默认目标长度约 450–600 字符,硬上限 700 字符,优先在标题、段落边界和列表边界切分。
- 列表项和表格行保持语义完整;表格行会携带表头,避免单独召回时失去字段含义。
- 每个 chunk 记录文档、医院、章节、页码/定位、版本、有效期、内容哈希、
parent_section等元数据。 - 当前召回先分别取 dense top-40 和 lexical top-40,再通过 Reciprocal Rank Fusion 合并、按父章节去重,最终最多保留 10 条证据进入 Evidence Pack。
- 向量服务不可用时降级到词法召回;没有有效证据时禁止生成看似确定的医院候选。
评估脚本是 backend/scripts/evaluate_rag.py,输出 Recall@5、Recall@10、nDCG@5、引用精确率和“无证据时是否安全降级”。仓库不会伪造“80 个审核案例”的结果;当前没有足量人工标注集,因此只提供可运行的评估入口和数据格式,待真实审核集导入后再生成指标。
记忆不是把所有聊天记录拼进 Prompt,而是分层、可撤回、可过期的事实存储:
| 类型 | 内容 | 进入上下文的条件 |
|---|---|---|
| 工作记忆 Working | 当前会话状态、待确认问题、最近一次检索和证据包 | 当前 Agent Run 按节点有界注入 |
| 情景记忆 Episodic | 某次预问诊、报告解读、用户确认和人工复核过程 | 同一用户/会话且满足权限、时间范围和相关性 |
| 语义记忆 Semantic | 用户明确确认且可复用的偏好、既往事实或长期约束 | 只读取已确认、未过期、与当前任务相关的条目 |
记忆候选先进入确认队列;只有用户显式确认后才写入长期记忆。每条记忆具备来源、置信度、创建时间、过期时间、撤回状态和访问审计,SQL 持久化层预留加密字段,不把敏感报告文件放进 Git。
Skill 是可复用的受限流程描述,不是一个可以任意执行 Python 的插件。每个 Skill 由 manifest 和 SKILL.md 组成,运行时通过 allowlist、版本、内容哈希和输入输出契约校验后加载。
当前产品 Skill:
pre_consultation:危险信号扫描、字段抽取、摘要确认和追问策略。report_interpretation:报告提取、危急值规则、用户修订和证据化解释。hospital_department_recommendation:医院硬过滤、混合召回、引用草稿和事实核验。
Skill 只能声明允许使用的工具、输入模型、输出模型、停止条件和安全降级路径;实际状态迁移仍由 Agent Runtime 和 LangGraph 控制。
MyAgents/
├── backend/
│ ├── app/
│ │ ├── agent/
│ │ │ ├── core/ # AgentState、Action、Observation、Reducer、运行事件
│ │ │ ├── runtime/ # 通用 AgentRuntime 与 LangGraph 适配
│ │ │ ├── context/ # 有界上下文组装与注入
│ │ │ ├── memory/ # working/episodic/semantic 记忆与确认
│ │ │ ├── preconsult/ # 预问诊事实、规则和 LangGraph 图
│ │ │ ├── decision/ # 报告/医院匹配决策运行时
│ │ │ └── skills/ # Skill manifest 加载器
│ │ ├── business/ # 业务服务、RAG、报告提取、事实核验
│ │ ├── api/v1/ # FastAPI 路由和 SSE 流式接口
│ │ ├── models/ # SQLAlchemy 数据模型
│ │ ├── migrations/ # Alembic 迁移
│ │ └── main.py # 应用工厂与健康检查
│ ├── skills/ # 产品 Skill 包:manifest.toml + SKILL.md
│ ├── scripts/ # RAG 评估、知识导入等运维脚本
│ ├── tests/ # 单元、集成和安全回归测试
│ ├── pyproject.toml
│ ├── .env.example
│ └── README.md
├── frontend/
│ ├── src/
│ │ ├── components/ # Agent 运行、证据、工具状态、记忆确认 UI
│ │ ├── views/ # 预问诊、报告和医院匹配页面
│ │ ├── stores/ # Pinia 状态
│ │ └── api/ # 类型化 API 客户端
│ ├── tests/
│ ├── package.json
│ └── vite.config.ts
├── docs/
│ ├── REFACTOR_PLAN.md # 完整重构计划与阶段验收
│ ├── ARCHITECTURE.md # 架构与状态流转
│ ├── API_CONTRACT.md # API 契约
│ ├── agent-loop.md # 最小 Agent Loop
│ ├── context-and-facts.md # 上下文与事实账本
│ ├── rag-pipeline.md # RAG 切分、召回、评估
│ └── DEVELOPMENT.md # 开发与质量规范
├── qa/
│ ├── RELEASE_ACCEPTANCE.md # 发布验收矩阵
│ └── rag_evaluation/ # 可复现 RAG 评估数据格式
├── PROJECT_PLAN.md
└── README.md
后端需要 Python 3.11+、MySQL 和 Redis;Qdrant/百炼等向量与模型服务可按环境变量配置。详细变量说明见 backend/README.md 和 backend/.env.example。
cd backend
python -m venv .venv
.\\.venv\\Scripts\\Activate.ps1
python -m pip install -e ".[dev]"
Copy-Item .env.example .env
# 编辑 .env,替换数据库、JWT、Profile 加密等密钥
python -m alembic upgrade head
python -m uvicorn app.main:create_app --factory --reload启动后可访问:
前端:
cd frontend
npm ci
npm run devVite 默认将 /api 代理到 http://127.0.0.1:8000,也可以通过 VITE_API_BASE_URL 配置后端地址。
POST /api/v1/pre-consultations/{id}/messages/stream:预问诊 SSE 流,发送accepted、token、done或error事件。- 预问诊摘要确认与医院科室决策运行。
- 报告上传/提取、用户修订和报告后续决策运行。
/api/v1/agent-runs/*:运行详情、事件时间线、证据和工具执行状态。/api/v1/memory/candidates*:记忆候选的查看、确认和撤回。- 医院、知识文档、报告和用户资料相关 API。
# backend/
python -m pytest -q
# frontend/
npm run test
npm run typecheck
npm run build当前验收结果:后端测试通过(1 个环境相关跳过项),前端 19 个测试文件、77 个测试通过,TypeScript 检查和生产构建通过。构建中的 Element Plus vendor chunk 体积提示属于非阻断 warning。
发布前还应使用真实的、已脱敏并经过人工审核的知识与问诊数据运行 RAG 评估,不使用虚构指标替代 Recall、引用精确率和安全降级结果。
- 不诊断、不处方、不替代医生;危险信号和危急值优先触发线下就医提示。
- 医院知识按
hospital_id做硬隔离,任何引用必须可追溯到有效来源。 - 用户确认事实、长期记忆和报告内容都要经过权限、过期和撤回检查。
- 上传文件、环境变量、密钥和运行时私有缓存不纳入版本控制。
- 数据库迁移、审计事件和 Agent 输出必须可回放;异常时采用安全失败。