Atmosis这个名字是我从 atmosphere 和 osmosis 两个词里拼出来的想法也很直白让环境数据像渗透一样自然融进每个人的日常健康决策。做了大半年从最初一个只会读传感器数据的脚本慢慢长成了一套能输出健康建议的AI环境智能系统。市面上查空气质量、查花粉指数的App很多但大多数止步于告诉你环境怎么样而Atmosis想多走一步——告诉你在这种情况下你该怎么做。这篇文章就把整个项目的设计思路、系统架构、核心算法和踩坑记录完整拆开给同样想做环境智能或健康顾问方向的朋友一些可以直接参考的经验。1. 为什么看得见环境数据和知道该怎么做之间隔着最后一公里1.1 环境数据平台普遍只到状态层没有到行动层我一开始也觉得奇怪环境数据已经这么丰富了怎么大家还是不满足后来想明白一个关键问题绝大多数产品提供的是状态不是行动。状态是当前PM2.5为75微克每立方米空气质量指数105行动是你有过敏性鼻炎今天风小湿度高出门建议佩戴N95口罩并且避开早高峰路段。前者只是把传感器和气象站的数字搬到了手机屏幕上后者才真正影响人的行为决策。而这个翻译过程恰恰是最费劲、最需要结合多维度数据的。天气App不会知道你家里有哮喘的老人不会知道你今天的通勤路线要路过一片正处在盛花期的行道树也不会关心你昨晚没睡好、今天心肺负担本来就偏重。传统环境监测产品的信息架构就没有为个人化行动建议留出位置。Atmosis想补上的正是这个从环境状态到个人行动的推理层。1.2 同样的空气对不同的人是完全不同的风险同样一个空气质量指数为120的早晨对一个心肺功能正常的年轻人来说可能只是出门有点不舒服但对一个尘螨和花粉双重过敏的患者来说这可能意味着接下来一整天的鼻塞、结膜充血甚至诱发哮喘发作。再叠加湿度和风速——湿度高会让花粉颗粒吸水膨胀、更容易破裂释放过敏原风速低则让污染物和花粉在地面附近堆积。这些因素单看都不起眼组合起来风险等级完全不一样。所以环境健康顾问必须做两件事第一把多维环境信号压缩成暴露风险等级第二把风险等级结合个体画像翻译成具体动作。只做第一件事那就还是环境监测不是健康顾问。这两步合在一起才是Atmosis被称为Intelligence Health Advisory而不是Air Quality Monitor的原因。1.3 目标用户与适用场景界定项目早期我犯过一个典型错误——想把所有人群、所有环境一网打尽。后来痛定思痛把目标用户收敛成了四类过敏体质人群花粉、尘螨、霉菌过敏、有呼吸系统慢病的人群哮喘、慢阻肺、需要精细化环境管理的家庭有婴幼儿或高龄老人以及注重运动表现的户外运动爱好者。适用场景也做了裁剪通勤出行规划、室内通风换气决策、户外运动时段选择、家庭环境异常预警。这四个场景有一个共同点——环境变量对人的影响在短时间内就能显现用户能直观感受到建议是否有效这为后续的产品迭代和信任建立带来很大便利。如果一开始就去做环境与肿瘤长期发病率关联这类超长周期的判断既缺少数据也缺少用户反馈闭环。2. 系统骨架四层单向流动的架构2.1 感知层室内传感器与外部数据源的分工Atmosis的数据感知层有两类来源分工非常明确。室内部分靠自建的物联网传感器节点采集温度、相对湿度、PM2.5、PM10、二氧化碳浓度、TVOC总挥发性有机物。这些节点体积不大每个房间放一个通过Wi-Fi上报数据。室外部分则对接开放数据接口拉取气象预报、空气质量指数、花粉浓度、紫外线强度。两类数据的语义完全不同室内数据回答你现在所处的微观环境怎么样室外数据回答你即将进入的宏观环境怎么样。为什么室内要自建传感器而不是直接买现成的因为健康建议对数据完整性要求很高。现成智能家居设备通常只上报温湿度和PM2.5缺少二氧化碳和TVOC。而二氧化碳浓度是判断室内通风质量的黄金指标——当浓度升到1000ppm以上时人会出现嗜睡、注意力下降这对居家办公和儿童学习的场景非常关键。没有CO2数据通风建议就只能靠猜。这一层我的建议是传感器可以不用买贵的但一定要保证覆盖关键指标宁可精度差一点不能缺维度。2.2 处理层清洗、校准与时间对齐感知层的数据是原始的、充满噪声的直接喂给模型会出事。处理层做三件事清洗、校准、对齐。清洗主要过滤明显异常值——传感器信号跳变、离线补传导致的重复数据、户外接口偶尔返回的空值。经验是不要用全局均值填充缺失值而要用前后时间窗的线性插值。比如温度传感器五分钟没上报用前后两个有效值的线性插值补上比用全天平均值填充要合理得多。校准针对的是低成本传感器的长期漂移。便宜的电化学PM2.5传感器用半年之后零点漂移可能让数据整体偏高20%以上。解决思路是周期性零点校准同时与附近固定监测站的公开数据做交叉验证。我曾做了一版自动校准脚本每周自动拉取距离最近的几个参考站点的数据对自家传感器读数做线性回归修正。这么做之后室内PM2.5数据和参考站的偏差从平均每立方米15微克降到了5微克以内。时间对齐是处理层最琐碎但又最重要的一环。不同数据源的时间戳语义不一样有些接口返回的当前小时花粉指数其实滞后了一小时。统一做法是所有数据在进入特征层之前一律先转换成标准UTC时间戳存储并且记录每个数据源的数据时间和到达时间两个字段。任何算法只认数据时间不认到达时间这个问题在后面真正跑线上时让我吃过大亏第5节会详细讲。2.3 特征层与画像层把原始值变成风险画像处理完之后的数据还不能直接用。特征层的主要工作是把时间序列转成有物理含义的统计特征。举例来说原始数据是过去24小时每小时一个PM2.5浓度值特征层会计算当前值、3小时滑动平均、24小时滑动平均、变化率现在比3小时前高还是低、以及当前浓度超过同季度历史80分位这类相对排名指标。同样的处理也应用到温度、湿度、风速、花粉指数上最终拼成一个几百维的特征向量。之所以用滑动窗口而不是只看瞬时值是因为人体对环境刺激的反应有滞后性哮喘发作往往不是被某个瞬时峰值触发而是被持续几小时的高浓度暴露触发。只看瞬时值会漏掉这种累积效应。画像层单独存放用户的静态和半静态信息年龄、是否有过敏史花粉/尘螨/霉菌、是否患有哮喘或慢阻肺、日常通勤时段、常用出行方式、是否佩戴运动手环等。画像层不与传感器数据混在一起存储而是独立成表只有在生成建议时才会被特征层调用。这样设计的好处是用户更换设备、更换传感器品牌、甚至搬家迁移部署环境时健康画像不会丢。2.4 推荐层建议输出与展示策略推荐层拿到风险等级和个人画像之后输出的是结构化的建议对象包含四个字段动作建议、可选方案、置信度、时间窗口。动作建议是主推的行动比如关闭朝南窗户并开启新风系统可选方案给用户选择空间比如如果必须外出请佩戴N95口罩并缩短停留时间置信度表示模型对自己判断的把握程度时间窗口告诉用户这条建议什么时候到期。展示策略上踩过不少坑。最初我让建议一生成就弹到用户手机屏幕上结果一个月后通知关闭率达到七成。后来改成静默待命关键节点推送轻度风险时只更新App内页面中度以上风险才推送通知极高风险直接用强提醒。置信度低于0.6的建议一律不主动推送而是让用户手动查询时展示。这套策略上线之后通知关闭率降到了两成以内。低置信度内容不打扰用户是高可信度建议的保障。2.5 为什么流程必须是单向的整个架构我强制规定数据只能从感知层往推荐层流动禁止反向调用。也就是说推荐层不能反过来要求感知层现在立刻把传感器精度调高一点。原因很简单健康决策系统最怕的就是反馈回路失控。如果推荐层能反向影响数据采集理论上一旦建议规则写了一行Bug可能导致采集层数据被篡改而后续建议又基于被篡改的数据继续生成最后整个系统都不可信。单向流动虽然牺牲了一些灵活性但最大程度保证了每一步的输入输出都是可审计、可复现的。3. 从监测到建议两阶段推理模型的设计思路3.1 为什么不用端到端深度学习做空气到建议做AI环境健康顾问最直觉的方案是收集大量环境数据用户行为健康反馈的配对样本训练一个端到端的深度学习模型输入环境序列直接输出建议。我评估过这个方案最终否掉了原因有三点。第一健康标签太稀疏。用户不会每天记录今天鼻炎发作了几次更不会把每次发作都归因到环境因素。拿不到稠密、准确的标签监督学习就无从谈起。第二可解释性需求极强。健康建议不同于商品推荐用户会追问为什么让我今天别晨跑。端到端模型给不出病历级解释而规则引擎可以把推理链路一条条列出来。第三冷启动问题。新用户没有历史反馈数据端到端模型只能随机猜测而规则引擎至少能覆盖大众健康阈值这类基线知识。所以最终方案是两阶段推理先用一个机器学习模型把多维环境特征压缩成暴露风险等级再用一个规则引擎根据风险等级和用户画像选择具体建议。机器学习和规则各管一段各发挥各的优势。3.2 阶段一环境暴露风险分级模型第一阶段的核心任务是4分类——把当前环境判成低、中、高、极高四个暴露风险等级。模型输入是特征层生成的几百维特征向量输出是四个等级的概率分布。我尝试过多种模型实践下来梯度提升树家族的效果和工程性价比最高。一方面它对特征尺度不敏感不需要做复杂的归一化另一方面它对缺失值天然有容忍度某个传感器故障时结果不会立刻崩溃。树模型另外的好处是能输出特征重要度这对我做可解释性非常有帮助。训练数据从哪里来公开的环境监测历史数据可以当作环境侧的数据集但风险等级标签怎么打这里用了一个关键技巧把医学指南和临床文献里的暴露阈值转化为标签规则。比如世界卫生组织的PM2.5日均指导值、各国过敏学会的花粉等级对应症状概率表把它们组装成如果PM2.5高于X且湿度高于Y则判定为高风险这类先验规则。然后用这些规则给历史环境数据自动打标签再让树模型去拟合。这本质上是一种弱监督方案——规则不完美但能提供足够的信号让模型学到跨维度的非线性组合。线上推理时模型返回四个等级的概率但不会直接硬取最高等级。我加了一个保守偏置如果高和极高的概率都超过0.2就向上取一级。环境健康领域误报的危害小于漏报宁可建议更谨慎一些不能漏掉真正的高风险时刻。3.3 阶段二基于规则模板的建议匹配引擎第二阶段接收风险等级和用户画像输出具体建议。这一层用的是白盒规则引擎逻辑如下先根据画像过滤出适用于该用户的建议模板池再根据风险等级和当前环境特征在模板池里做条件匹配。模板长这样场景通勤出行条件风险等级为高 且 用户有花粉过敏史 且 当前风速低于3米每秒动作建议改乘公共交通或地下通勤路线若骑行佩戴密闭性更好的口罩并把出发时间后延到风起之后备选若用户选择必须按原计划出行则建议缩短户外停留时间并回屋后立即清洗面部和更换衣物规则模板的来源分两类一类是循证医学指南的改写比如花粉过敏人群在高浓度时段应减少户外活动、关闭门窗另一类是环境工程常识的结构化比如室内外温差大时长时间开窗会导致湿度倒灌、霉菌滋生。两类知识都用条件-动作的统一格式存放方便维护和审计。这里有一个设计细节规则引擎永远不会直接对用户说你可能要得哮喘了这类诊断性语言。Atmosis的边界是环境顾问不是医生所有输出都是行动建议和预防性提示不做疾病预测。边界一旦划清规则设计就简单了产品的法律和伦理风险也小了很多。3.4 置信度与安静模式的权衡模型概率和规则匹配两者都会输出一个0到1的分数置信度取两者的几何平均。比如风险分级模型给出高风险的概率是0.85规则匹配的满足度是0.8最终置信度大概是0.82。置信度低于0.6的结论只记录不进推送0.6到0.8之间展示但不打扰高于0.8才触发通知提醒。这套分级在实践中有个意想不到的好处——它变相解决了狼来了问题。如果每条建议都推用户很快会麻木。安静的展示策略让用户形成只有真正重要时才会弹出提醒的预期反而提高了紧急建议的响应率。我经常跟人讲健康顾问产品的核心指标不是建议生成量而是每百次建议中被用户采纳的次数。4. 完整跑通一个真实案例花粉季早晨通勤4.1 场景与输入拿一个实际跑通的案例来演示整个链路。某位花粉过敏的用户我们叫A同学工作日在某城市骑车通勤出发时间是早上7点40分。四月底正处在柏树花粉的盛花期前一天晚上他的手机收到了一条预告——建议明天关注花粉和风速变化。到了早晨7点后台的定时任务开始拉取各项数据。输入数据大致是室外气温16℃相对湿度72%东北风2米每秒花粉指数等级4满分5PM2.5浓度58微克每立方米。室内节点数据显示卧室夜间CO2峰值到了1100ppm开窗通风后降到600ppm。画像库里查到的A同学信息是有明确的柏树花粉过敏史鼻炎症状每年春季规律发作通勤方式是普通自行车戴一次性外科口罩没有其他基础疾病。4.2 处理与特征工程这些原始输入先进入处理层。外部接口数据统一转成标准时间戳花粉指数保留等级和浓度两列风速取过去一小时的均值而不是瞬时值。特征层随后计算当前PM2.5的3小时趋势呈缓降湿度处于过去五天的高位比同期均值高12个百分点花粉等级连续三天维持4级风速低于3米每秒的静风条件污染物扩散条件较差。组件拼成的特征向量显示这是一个典型的高花粉浓度高湿度弱风三要素叠加的早晨。单拎出任何一个指标都不到极端水平PM2.5的58只是轻度污染花粉4级不是最高级风速2米每秒只是有点静风。但这个组合对花粉过敏人群来说属于症状大概率会被明显诱发的配置。4.3 模型输出与建议生成风险分级模型给出的结果是高风险概率0.76中等风险概率0.19剩下0.05分散在低和极高。经过保守偏置后等级定为高。这个结果和我自己翻文献的感受一致——高湿度会让花粉颗粒吸水膨胀、裂解释放出更多致敏蛋白静风又让它们在近地面持续堆积这比单纯的花粉高等级更需要警惕。规则引擎接着开始匹配。A同学的画像命中了花粉过敏通勤出行模板池当前环境满足风险等级高湿度大于65%风速小于3米每秒三个条件因此输出主建议更换通勤方式优先选择地铁或公交把户外暴露时间压缩到10分钟以内备选一如果坚持骑车改为佩戴N95级别的口罩并选择绿化带离道路较远的路线备选二把出发时间推迟到9点以后通常这个时段风会起来、露水也会蒸发湿度下降后风险随之降低附加提醒到达公司后先清洗面部和鼻腔并更换进门前穿的衣物置信度最终为0.78触发了通知推送。消息在7点10分送达正好在A同学出门前半小时。4.4 验证与复盘这条建议到底准不准我做了两层验证。第一层是事后的数据复盘当天上午9点后风速果然升到4米每秒湿度从72%降到58%花粉浓度也略有回落9点后出门的环境确实比早高峰时段温和。第二层是用户反馈A同学当天按建议推迟了出门时间并选了地铁傍晚反馈说上午基本没有明显打喷嚏比前两天好太多。单个案例当然不能说明模型处处准确但它提供了一个重要的信号——规则推理出的行动建议与用户的主观体感吻合。为了积累更系统的证据我建了一个小规模反馈表单每推一条建议都记录用户后来是否采纳、症状是否加重再用累积数据反哺下一版规则阈值。项目跑到现在积累了两百多条带反馈标签的有效样本建议采纳率大概在65%上下比第一版盲推不到30%的采纳率好了不少。5. 上线半年踩过的坑数据质量、校准与建议可信度5.1 CO2传感器漂移导致的误触发Atmosis上线的第三个月家里那台CO2传感器开始发作。明明开着一整夜新风系统早上系统却提示室内CO2浓度偏高建议开窗通风。我以为是新风系统坏了手动测试发现新风正常开窗后传感器读数也从1100ppm跌到500ppm。问题出在传感器自身CO2传感器每隔一段时间需要做零点校准而我的节点固件里没有这个机制读数慢慢偏移最终整体偏高了三四百ppm。修法分两层。硬件层换成支持自动基线校准的红外传感器并要求固件至少每24小时做一次零点校准。软件层增加了一条交叉校验规则——当室内CO2读数持续两小时高于室外参考值500ppm以上且新风系统正常开启时判定为传感器可疑标记数据不参与建议生成。这两个改动之后CO2误报基本消失。现在回头看这个坑迟早会踩早踩反而逼着我提前把数据质量监控机制做了。5.2 外部数据源的时间戳对齐问题这是最隐蔽的一个坑。接入室外数据时我最初没有仔细读文档想当然地认为当前小时的花粉指数就是本小时刚测出来的。后来对比发现每天凌晨0点左右总会莫名其妙地弹出一条极高风险预警白天却没有。排查了大半天才意识到那个接口返回的实际上是上一小时的累计数据凌晨0点返回的是前一天半夜的数据累积起来跨越了日期边界导致日级统计特征被严重污染。修复方案是在采集层加了一个强制约束凡进入处理层的每条记录都必须自带数据时间字段该字段由数据源显式给出不由服务器到达时间推断。同时对所有外部数据做滞后对齐比如花粉指数统一视为滞后1小时数据。这一改之后凌晨的误报消失了特征层的日级统计也恢复了正常。现在项目里所有时间敏感的数据流都遵循一个原则宁可慢不可错。5.3 建议措辞的尺度不可制造恐慌最初版本的模板里我犯过过度渲染的错。为了强调PM2.5的严重性我写过相当于你今天被动吸了10根烟之类的类比。用户在问卷里反馈看到这句话之后特别焦虑甚至不太敢看App了。这个反馈点醒了我——健康顾问建议的目标是降低用户风险不是制造焦虑。如果建议让用户产生无力感和恐慌用户就会关闭通知反而在真正高风险时刻失去保护。后来我把所有类比类表述全部删除改用两类安全措辞一类是相对变化比如比昨天同一时段升高40%处于本月较高水平另一类是具体行动比如关闭朝东窗户可减少约30%的室外颗粒物进入。让用户感觉我还能做点什么而不是完蛋了。这个措辞尺度的转变影响的不只是用户满意度更是整个产品的可信度。5.4 用户画像隐私的云端与本地之争项目早期为了攒数据集优化模型我把用户画像和原始环境数据都传到了后端服务器。后来朋友提醒我健康画像属于非常敏感的个人信息一旦服务器被拖库后果很严重。我评估之后决定回滚架构改为画像只存本地设备云端只接收匿名化的聚合特征比如35到45岁、花粉过敏人群的平均采纳率不涉及具体个体。这个改动牺牲了一部分模型迭代便利性——我自己拿到手里的数据不再包含个体的完整信息。但安全合规的红线不能碰。现在的做法是个性化推理尽可能在端侧完成云端只做群体层面的统计分析。这条路走起来慢一些但每一步都踏实。涉及健康数据的项目隐私保护不是加分项是准入门槛。6. 隐私边界、可解释性与下一步的扩展方向6.1 端侧推理与完全离线模式基于5.4那条回滚的经验我把推理链路做了进一步的本土化。风险分级模型用工具转换成端侧可运行的格式四个风险等级的接口在手机或边缘网关本地就能完成预测。建议匹配的规则引擎本来就是离线可跑的所以整套Atmosis的推理不依赖云端网络。只有在拉取室外数据时才需要联网访问公开数据接口。由此我还做了一个完全离线模式——用户家里局域网断开、彻底不访问外部API时系统退回室内传感器检测加通用健康基线规则。这个模式不适合室外场景但至少在断网环境下还能给出室内通风建议。做这个模式不是技术难点而是给用户一个选择你可以完全不用任何云端服务数据全部留在家里。6.2 从瞬时浓度升级到累计暴露剂量目前的Atmosis核心用的是瞬时或短时窗平均浓度这是有局限的。环境健康学里更看重的是累计暴露剂量——不是你某分钟吸入了多少而是你这一天、这一周累计吸入了多少。两个用户同样面对PM2.5浓度60的环境一个在户外待了20分钟一个待了6小时健康影响完全不同。下一步计划引入剂量模型结合用户的位置轨迹和停留时长估算每天累计暴露剂量再与本周累计值联动。比如本周累计细颗粒物暴露剂量已经超过你的个人周均水平尽量把明天的户外跑步换成室内力量训练。这会是个更有说服力的健康顾问行为。6.3 融合可穿戴设备与自然语言交互再往后走我想把手环数据接进来。心率、血氧、睡眠时长这些生理指标能大幅降低健康建议的不确定性。比如用户睡眠不足时环境刺激对免疫系统的负担会被放大同样浓度下风险比休息充足时更高。这些信号目前是缺失的只能靠画像里的静态信息兜底。交互层也在尝试自然语言问答。与其让用户面对一堆卡片式建议不如支持我今天适合跑步吗家里能开窗吗这类自由提问。后端先把问题解析成环境查询加上画像查询跑一遍推理链路拿到结构化建议后再用语言模板组装成自然回复。整个过程仍然可解释——用户可以一键查看这条建议的依据。6.4 对社区开放的一点点期待整个Atmosis项目走到现在我最深的体会是环境健康智能这个方向单靠某个人或者某个小团队的力量远远不够。环境数据的采集标准、个人健康画像的隐私保护模式、建议输出的评估规范每一块都需要更大范围的协作。我现在把内部使用的建议模板格式和匿名化数据结构整理了出来准备逐步开源期待更多做传感器、做算法、做医学信息学的朋友一起来把这套框架打磨得更扎实。健康建议这件事多一分严谨就多一分安心。