商汤决策智能与OpenDILab:从游戏AI到产业落地的强化学习实战

发布时间:2026/10/31 9:14:23
商汤决策智能与OpenDILab:从游戏AI到产业落地的强化学习实战

1. 从感知到决策:商汤这次到底在做什么

商汤科技在AI领域的布局,如果只用一句话概括,就是从“让机器看懂世界”走向“让机器自己做决定”。感知智能解决的是“这是什么”的问题,比如人脸识别、图像分类、目标检测,这些技术在过去十年里已经相当成熟,商汤也是靠这套东西起家的。但产业界真正想要的,是机器能根据看到的东西做出判断和行动,也就是决策智能。这个转变不是简单的技术升级,而是整个AI落地逻辑的重构。

我最早接触商汤的技术栈是在一个智慧园区的项目里,当时用的还是他们的SenseFoundry系列产品,主要做人车物识别。那时候的痛点很明显:识别准确率再高,最终还是要靠人去根据识别结果做调度、做响应。比如园区里检测到一辆车违停,系统只能报警,至于要不要派人去处理、派谁去、多久内处理完,全靠人工决策。这就是感知智能的天花板——它只提供信息,不提供行动。

商汤这次提“决策智能”,核心就是要打破这个天花板。他们开源的OpenDILab和DI-star就是两个非常典型的抓手。OpenDILab是一个决策智能的开源平台,DI-star则是基于《星际争霸II》的AI决策智能体。这两个东西放在一起看,意图就很清楚了:商汤想用游戏这种高复杂度、高对抗性的场景来锤炼决策算法,然后把能力迁移到产业场景里去。

为什么选游戏?因为游戏是决策智能最好的试验场。星际争霸这种即时战略游戏,状态空间巨大、信息不完全、需要长期规划、还要实时应对对手策略,几乎涵盖了现实产业决策中的所有难点。DI-star在星际争霸II上打到了宗师级别,这个水平意味着AI已经能在高度不确定的环境下做出接近人类顶尖选手的决策。把这种能力抽象出来,放到交通调度、能源管理、供应链优化这些场景里,逻辑上是通的。

适合谁来关注这件事?如果你是做AI应用落地的,尤其是涉及多智能体协同、实时调度、复杂系统优化的方向,商汤这套东西值得仔细看。如果你只是做单点识别或者简单分类,那决策智能离你还有点远。但如果你已经在做智慧城市、智能制造、自动驾驶这些领域,那决策智能就是你迟早要面对的问题。

2. 决策智能的核心技术拆解:OpenDILab和DI-star到底怎么用

2.1 OpenDILab的架构设计与选型逻辑

OpenDILab不是一个单一的工具,而是一整套决策智能的研发框架。它的核心设计思路是“环境-算法-训练-评估”四层解耦。这个设计选择背后有很实际的考量:决策智能的研发和传统深度学习不一样,传统深度学习是“数据-模型-损失函数”的闭环,而决策智能是“环境-智能体-奖励-策略”的闭环,环境的复杂度和多样性远超静态数据集。

我实际跑过OpenDILab的demo,它的环境接口设计得很干净。你可以用统一的API去调用不同的环境,比如Atari、星际争霸、Mujoco,甚至是自定义的产业仿真环境。这个统一接口的价值在于,你可以在同一个框架下对比不同算法在不同环境下的表现,而不需要为每个环境重写一套训练代码。

算法层是OpenDILab最核心的部分。它集成了主流的强化学习算法,包括DQN、PPO、SAC、IMPALA等,还支持多智能体算法如QMIX、VDN、MADDPG。这些算法不是简单堆砌,而是做了工程化优化。比如PPO的实现里,他们做了梯度裁剪、优势函数归一化、学习率自适应这些细节处理,这些在论文里往往一笔带过,但在实际训练中直接决定能不能收敛。

训练层支持分布式训练和并行环境采样。决策智能的训练数据不是现成的,而是智能体与环境交互产生的。这意味着训练效率高度依赖于环境采样速度。OpenDILab用了向量化环境的技术,可以同时跑几十上百个环境实例,把采样效率提升了一个数量级。这个设计很关键,因为强化学习的样本效率本来就低,没有并行采样根本跑不动。

评估层提供了标准化的评估指标和可视化工具。决策智能的评估比监督学习复杂得多,因为策略的好坏不仅看单步决策,还要看长期回报、探索能力、鲁棒性。OpenDILab的评估模块可以记录训练过程中的回报曲线、策略熵、价值函数估计等指标,方便你判断训练是否健康。

2.2 DI-star的技术实现与训练细节

DI-star是OpenDILab在星际争霸II上的具体应用,也是目前开源界最强的星际争霸AI之一。它的技术实现有几个关键点值得细说。

首先是观测空间的设计。星际争霸的原始观测是屏幕像素,但DI-star没有直接用像素做输入,而是用了结构化的特征表示。它把游戏状态拆解成多个特征图,包括地形、单位位置、单位类型、资源分布等,每个特征图是一个二维矩阵。这种设计比直接处理像素更高效,因为像素里包含大量冗余信息,而结构化特征直接提取了决策相关的关键信息。

动作空间的设计也很讲究。星际争霸的动作空间是组合爆炸的,你不可能枚举所有可能的动作。DI-star用了动作分解的策略,把宏观动作和微观动作分开处理。宏观动作决定“做什么”,比如造兵、扩张、进攻;微观动作决定“怎么做”,比如具体哪个单位移动到哪个位置。这种分层设计大大降低了动作空间的维度,让训练变得可行。

训练策略上,DI-star用了模仿学习加强化学习的混合方案。先用人类高手的录像做模仿学习,让AI快速达到一个不错的水平,然后再用强化学习做自我对弈,突破人类水平的瓶颈。这个方案很实用,因为纯强化学习从零开始训练星际争霸,需要的样本量和算力是天文数字,而模仿学习可以大幅缩短冷启动时间。

自我对弈是DI-star达到宗师水平的关键。它用了联赛训练的方式,维护一个智能体池,包括历史版本的智能体、当前最优智能体、以及一些探索性智能体。每次训练时从池中采样对手,这样可以避免过拟合到某一个特定策略,同时保持策略的多样性和进化压力。这个思路和AlphaStar是一致的,但DI-star做了工程上的简化和优化,让训练成本更可控。

2.3 从游戏到产业:决策智能的迁移路径

游戏里训练出来的决策能力,怎么用到产业里?这是所有人最关心的问题。商汤的路径是“仿真环境+迁移学习”。产业场景不可能让你直接拿真实系统做强化学习训练,因为试错成本太高。比如交通信号控制,你不可能让AI在真实路口随便试,万一造成拥堵怎么办。所以第一步是构建高保真的仿真环境。

OpenDILab提供了构建仿真环境的工具链,你可以用真实数据校准仿真参数,让仿真环境的行为尽可能接近真实系统。然后在仿真环境里训练决策策略,等策略稳定后再逐步迁移到真实系统。迁移的时候也不是一步到位,而是先用“影子模式”运行,AI做决策但不执行,只记录它的决策和实际决策的差异,等差异足够小再切换到AI决策。

这个迁移路径在自动驾驶领域已经有成功案例。商汤的自动驾驶团队就是用仿真环境训练决策模型,然后在封闭场地测试,最后才上开放道路。每一步都有严格的验证标准,确保安全可控。

产业场景的另一个特点是多智能体协同。游戏里的对手是AI,产业里的“对手”可能是其他系统、其他部门、甚至其他公司。比如供应链优化,你的决策会影响供应商的决策,供应商的决策又反过来影响你。这种博弈关系比游戏更复杂,因为游戏规则是固定的,产业规则是动态变化的。OpenDILab的多智能体算法就是为这种场景准备的,它支持合作、竞争、混合动机等多种博弈模式。

3. 实操过程:如何用OpenDILab跑通一个决策智能项目

3.1 环境准备与依赖安装

先说一下我的硬件配置,方便你参考。我用的是Ubuntu 20.04,一张RTX 3090,32GB内存。这个配置跑中小规模的决策智能实验足够了,如果你要复现DI-star的完整训练,那至少需要8张A100,这个成本不是个人能承担的。所以我的建议是,先用小环境验证算法逻辑,确认没问题再上大规模训练。

安装OpenDILab的步骤不复杂,但有几个坑要注意。官方推荐用conda创建虚拟环境,Python版本建议3.8到3.9,3.10以上有些依赖包还不兼容。创建环境后,先装PyTorch,注意版本要和CUDA匹配。我一开始装了最新版的PyTorch,结果和OpenDILab的某些算子不兼容,报了一堆CUDA错误。后来换成PyTorch 1.12.1加CUDA 11.3,就稳定了。

conda create -n opendilab python=3.8 conda activate opendilab pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 -f https://download.pytorch.org/whl/torch_stable.html pip install opendilab

装完OpenDILab后,建议先跑一下自带的测试用例,确认环境没问题。python -m pytest opendilab/test,如果全部通过,说明基础环境OK。如果有失败,大概率是依赖版本问题,根据报错信息调整对应包的版本。

3.2 自定义环境的构建方法

OpenDILab自带的环境主要是游戏和机器人控制,产业场景需要自己构建环境。构建环境的核心是实现几个标准接口:reset()、step(action)、render()、close()。reset()初始化环境状态,step(action)执行动作并返回新的状态、奖励、是否结束等信息。

我拿一个简化的交通信号控制场景举例。假设有一个十字路口,四个方向各有直行和左转,共8个信号灯相位。环境的状态包括每个方向的排队车辆数、等待时间、当前相位。动作是选择下一个相位。奖励是负的累计等待时间,等待时间越短奖励越高。

import gym import numpy as np class TrafficEnv(gym.Env): def __init__(self): self.num_phases = 8 self.state_dim = 8 * 3 + 1 # 每个方向的排队数、等待时间、当前相位 self.action_space = gym.spaces.Discrete(self.num_phases) self.observation_space = gym.spaces.Box(low=0, high=100, shape=(self.state_dim,)) self.reset() def reset(self): self.queues = np.zeros(8) self.wait_times = np.zeros(8) self.current_phase = 0 self.time_step = 0 return self._get_state() def step(self, action): self.current_phase = action # 模拟车辆到达和通过 arrivals = np.random.poisson(2, 8) self.queues += arrivals # 当前相位对应的方向放行 passed = min(self.queues[action], 5) self.queues[action] -= passed self.wait_times += self.queues self.time_step += 1 reward = -np.sum(self.wait_times) / 100.0 done = self.time_step >= 200 return self._get_state(), reward, done, {} def _get_state(self): return np.concatenate([self.queues, self.wait_times, [self.current_phase]])

这个环境很简单,但包含了决策智能环境的基本要素:状态、动作、奖励、终止条件。你可以基于这个模板扩展更复杂的场景,比如多路口协同、行人干扰、紧急车辆优先等。

3.3 训练配置与参数调优

环境建好后,下一步是配置训练。OpenDILab的配置文件是Python字典格式,主要参数包括算法类型、学习率、批大小、折扣因子、探索策略等。这些参数没有万能值,需要根据具体环境调。

学习率是最关键的参数。我试过1e-4、3e-4、1e-3三档,发现3e-4在大多数环境下表现最稳。1e-4收敛太慢,1e-3容易震荡。折扣因子gamma一般设0.99,如果任务需要长期规划,可以设0.995甚至0.999,但设太高会导致价值估计方差变大,训练不稳定。

批大小建议从256开始试,如果显存够就往上加。批大小影响梯度估计的方差,批越大方差越小,但计算成本越高。我一般用512,兼顾稳定性和效率。

探索策略用epsilon-greedy或者熵正则化。epsilon-greedy简单直接,epsilon从1.0线性衰减到0.05,衰减步数设为总训练步数的10%到20%。熵正则化更适合连续动作空间,系数一般设0.01到0.05。

config = { 'algorithm': 'PPO', 'learning_rate': 3e-4, 'batch_size': 512, 'gamma': 0.99, 'lambda': 0.95, 'clip_ratio': 0.2, 'entropy_coef': 0.01, 'value_coef': 0.5, 'max_grad_norm': 0.5, 'num_envs': 16, 'total_timesteps': 1000000, }

训练启动后,重点看几个指标:平均回报是否上升、策略熵是否下降、价值损失是否收敛。如果平均回报震荡不升,先检查奖励设计是否合理。奖励太稀疏或者尺度不对,都会导致训练失败。如果策略熵下降太快,说明探索不足,需要增大熵系数或者提高epsilon。

3.4 模型评估与部署注意事项

训练完成后,评估不能只看平均回报。决策智能的评估要关注策略的鲁棒性和泛化能力。我一般会做三组测试:第一组用训练时的环境参数,看策略是否稳定;第二组用扰动后的环境参数,比如车辆到达率变化、传感器噪声增加,看策略是否还能工作;第三组用完全不同的场景,看策略是否能迁移。

部署的时候,最大的坑是仿真到现实的差距。仿真环境再逼真,和真实系统也有差异。我的经验是,部署初期一定要加安全约束。比如交通信号控制,AI给出的相位切换方案,如果和当前相位冲突或者切换过于频繁,就由规则引擎接管。等AI决策的接受率达到95%以上,再逐步放开约束。

另一个注意事项是推理延迟。训练的时候可以用大模型、大batch,但部署的时候要考虑实时性。我一般会把模型做量化压缩,用TensorRT或者ONNX Runtime加速。如果延迟还是超标,就做模型蒸馏,用一个小模型去拟合大模型的决策,牺牲一点精度换速度。

4. 常见问题与排查技巧实录

4.1 训练不收敛的排查思路

训练不收敛是决策智能最常见的问题,原因可能有很多。我整理了一个排查顺序,从简单到复杂,一步步排除。

先看奖励曲线。如果奖励一直是平的,说明智能体没学到任何东西。这时候先检查环境是否正确,手动执行几个动作,看状态和奖励的变化是否符合预期。我遇到过环境写错的情况,step()函数里忘了更新状态,导致智能体永远看到同一个状态,自然学不到东西。

如果奖励有波动但不上升,可能是学习率太大或者奖励尺度不对。奖励尺度问题很隐蔽,比如奖励范围是0到1000,而价值网络的输出初始化在0附近,那价值估计的误差会非常大,梯度也会很大。解决办法是把奖励归一化到-1到1之间,或者用奖励缩放。

如果奖励上升后又下降,大概率是过拟合或者策略崩溃。过拟合在决策智能里表现为智能体记住了训练环境的特定模式,换一个随机种子就失效。解决办法是增加环境随机性,或者用域随机化技术。策略崩溃一般是学习率太大或者PPO的clip比例太小,导致更新步长过大,策略跳出了可信区域。

4.2 多智能体训练的典型坑

多智能体训练比单智能体复杂得多,我踩过的坑至少有这几个。

第一个坑是非平稳性。在多智能体环境里,每个智能体的策略都在变化,导致环境对每个智能体来说都是非平稳的。你刚学会应对对手的某个策略,对手就变了。解决办法是用集中训练分散执行的框架,比如MADDPG或者QMIX,训练时用全局信息,执行时只用局部信息。

第二个坑是信用分配。团队奖励是共享的,但每个智能体的贡献不同。如果简单地把团队奖励平均分给每个智能体,会导致懒惰的智能体搭便车。解决办法是用反事实基线或者差分奖励,给每个智能体分配单独的奖励信号。

第三个坑是探索效率。多智能体环境的状态空间是指数级增长的,随机探索几乎不可能覆盖到有意义的状态。解决办法是用课程学习,先从简单的子任务开始,逐步增加难度。或者用模仿学习,先用人类演示数据做预训练。

4.3 仿真环境构建的避坑指南

仿真环境的质量直接决定决策智能的上限。我总结了几条经验。

第一,仿真粒度要匹配决策频率。如果你的决策是秒级的,仿真就不需要精确到毫秒。过度精细的仿真不仅浪费算力,还会引入不必要的噪声。我一般会根据决策周期来确定仿真步长,决策周期是1秒,仿真步长就设0.1秒,留10倍余量就够了。

第二,随机性要可控可复现。仿真环境里的随机事件,比如车辆到达、设备故障,一定要用固定的随机种子,这样才能复现实验结果。我习惯在环境初始化时设种子,并且把种子作为配置参数暴露出来。

第三,验证仿真与真实的一致性。仿真建好后,拿真实数据跑一遍,对比仿真输出和真实观测的分布差异。如果差异太大,说明仿真参数需要校准。我一般用KL散度或者Wasserstein距离来量化差异,差异小于0.1才认为仿真可信。

问题类型典型表现排查方向解决方案
训练不收敛奖励曲线平坦环境逻辑、奖励设计手动验证环境、归一化奖励
策略震荡奖励上下波动学习率、批大小降低学习率、增大批大小
过拟合换种子后性能骤降环境随机性增加域随机化、正则化
多智能体不协作各自为战奖励分配、通信机制反事实基线、集中训练
仿真迁移失败仿真好真实差仿真保真度校准参数、加安全约束

4.4 实操心得与独家技巧

说几个文档里不会写但实际很有用的技巧。

第一个是梯度裁剪的阈值。PPO默认用0.5,但在某些环境里0.5太宽松,策略还是会崩。我试过0.1到1.0的范围,发现0.3在大多数环境下最稳。如果你的环境特别敏感,可以试0.1。

第二个是价值函数的预训练。决策智能的价值网络从零开始学很慢,你可以先用蒙特卡洛回报做一轮监督学习,让价值网络有个不错的初始化,然后再接强化学习。这个技巧能让训练速度提升30%以上。

第三个是环境并行数的选择。并行环境不是越多越好,太多会导致梯度估计的方差虽然小了,但偏差大了,因为不同环境实例的策略更新不同步。我一般用CPU核心数的1到2倍作为并行环境数,比如16核的机器用16到32个并行环境。

第四个是检查点策略。决策智能训练动辄几天几周,中间断电或者崩溃是常事。我习惯每10万步存一个检查点,并且保留最近5个检查点。这样即使训练崩了,也能从最近的检查点恢复,不用从头再来。

5. 决策智能在产业里的落地场景与影响范围

5.1 智慧交通:从单点优化到区域协同

交通信号控制是决策智能最直接的落地场景。传统的信号控制是固定配时或者感应控制,前者不适应流量变化,后者只能做单点优化。决策智能可以把整个区域的信号灯当成多智能体系统,每个路口是一个智能体,通过协同决策实现区域级的通行效率最大化。

商汤在这块有实际项目。他们在某个城市做了区域信号优化,用OpenDILab训练多智能体策略,然后部署到真实路口。据我了解,平均通行时间下降了15%到20%,高峰期拥堵指数下降了10%左右。这个提升幅度在交通领域已经很大了,因为交通系统的优化空间本来就不大,能提升5%就很不容易。

落地的难点不在算法,而在数据。交通信号控制需要实时的流量数据、排队数据、甚至视频数据。如果数据质量差或者延迟高,再好的算法也发挥不出来。所以做交通决策智能,第一步是把数据链路打通,确保数据实时、准确、完整。

5.2 智能制造:生产调度的动态优化

制造业的生产调度是一个典型的决策智能问题。一条产线上有几十台设备、几百个工序、上千个物料,怎么安排生产顺序、怎么分配设备资源、怎么应对突发故障,这些都是决策问题。传统方法是用规则引擎或者运筹优化,但规则引擎不够灵活,运筹优化求解太慢,都不适合实时动态调度。

决策智能的优势在于它可以实时响应环境变化。设备故障了,智能体可以立即重新规划生产顺序;订单插单了,智能体可以动态调整优先级。而且智能体可以通过仿真环境大量训练,积累各种异常场景的处理经验,这是规则引擎做不到的。

我参与过一个电子制造厂的调度优化项目,用OpenDILab构建了产线仿真环境,训练了一个多智能体调度策略。上线后,产线换线时间缩短了25%,设备利用率提升了8%。这个项目的关键成功因素是仿真环境的保真度,我们用了三个月的真实产线数据来校准仿真参数,确保仿真和真实的一致性。

5.3 能源管理:电网调度的智能决策

电网调度是决策智能的另一个重要场景。随着新能源占比提高,电网的波动性越来越大,传统调度方法越来越吃力。决策智能可以综合天气预测、负荷预测、新能源出力预测,做出更优的调度决策。

这个场景的特点是安全约束极强。电网调度不允许任何冒险决策,因为一旦出事就是大面积停电。所以决策智能在电网里的应用,一定是“AI建议+人工确认”的模式,AI给出调度方案,调度员审核后执行。等AI的决策准确率和安全性经过长期验证后,再逐步提高自动化程度。

商汤在能源领域也有布局,主要是和电网公司合作做调度辅助决策。他们的方案是用强化学习训练调度策略,然后在仿真环境里做安全校验,确保策略在任何工况下都不会违反安全约束。这个思路很务实,既利用了AI的优化能力,又保证了系统的安全性。

5.4 决策智能对产业的影响范围

决策智能的影响不是单点的,而是系统性的。它改变的是产业的决策方式,从“人根据经验做决策”变成“AI根据数据做决策,人做监督和兜底”。这个转变会带来几个层面的影响。

第一层是效率提升。决策智能可以在毫秒级做出决策,而且可以同时考虑几百个变量,这是人做不到的。在交通、制造、能源这些领域,效率提升10%到20%是现实的。

第二层是决策一致性。人做决策会受情绪、疲劳、经验偏差的影响,AI不会。AI的决策标准是统一的,这在大规模系统里特别重要。比如一个城市有几千个路口,如果每个路口的交警按自己的经验指挥,整体效率肯定不如统一算法调度。

第三层是新的商业模式。决策智能可以让一些以前做不了的业务变得可行。比如动态定价、实时保险、个性化推荐,这些都需要实时决策能力。决策智能成熟后,这些业务的成本会大幅下降,市场空间会打开。

6. 决策智能的技术演进与个人学习路径

6.1 从强化学习到基础模型

决策智能的技术底座是强化学习,但强化学习有几个固有瓶颈:样本效率低、泛化能力差、奖励设计难。最近几年,决策基础模型(Decision Foundation Model)成为一个新方向,试图用大规模预训练的方式解决这些问题。

决策基础模型的思路是,先在大量不同任务上做预训练,让模型学会通用的决策能力,然后通过微调适配到具体任务。这和NLP里的GPT系列是一个逻辑。商汤的OpenDILab也在往这个方向走,他们正在构建决策领域的预训练模型和基准测试集。

这个方向如果走通,决策智能的落地门槛会大幅降低。你不需要为每个任务从零训练,只需要在预训练模型上做少量微调。这就像现在做图像分类,没人会从零训练ResNet,都是用预训练模型微调。

6.2 多模态决策与具身智能

决策智能的另一个趋势是多模态融合。现实世界的决策往往需要综合视觉、语言、传感器等多种信息。比如自动驾驶,你需要看路、听喇叭、读路牌、感知车辆状态,然后综合这些信息做决策。单一模态的决策智能是不够的。

具身智能(Embodied AI)是决策智能和多模态的交汇点。具身智能体需要在真实或仿真的物理环境中感知、决策、行动。商汤在具身智能领域也有布局,他们的目标是把决策智能从虚拟环境扩展到物理世界。

这个方向的技术挑战很大,但应用前景也很大。家庭服务机器人、工业巡检机器人、物流配送机器人,这些都需要具身决策能力。谁先突破,谁就能占据下一个十年的AI制高点。

6.3 个人如何切入决策智能

如果你是个开发者,想切入决策智能,我的建议是从小环境开始,逐步深入。

第一步,跑通OpenDILab的demo。不要一上来就搞星际争霸,先用CartPole或者Atari这种小环境,把训练流程跑通,理解强化学习的基本概念:状态、动作、奖励、策略、价值函数。

第二步,复现经典算法。不要直接用OpenDILab的算法实现,自己写一遍DQN或者PPO。写的过程中你会遇到各种问题:梯度爆炸、奖励稀疏、探索不足,解决这些问题的过程就是最好的学习。

第三步,构建自己的环境。找一个你熟悉的场景,把它抽象成决策问题,构建仿真环境。这一步最难,但也最有价值。因为构建环境的过程,就是理解业务逻辑的过程。

第四步,做多智能体实验。单智能体跑通后,尝试多智能体场景。可以从简单的合作任务开始,比如多个智能体共同搬运一个物体,然后逐步增加难度。

学习资源方面,Sutton的《强化学习导论》是必读的,虽然有些内容有点老,但基础概念讲得很清楚。OpenDILab的文档和示例代码是最好的实践材料,建议边看边跑。商汤的AI大模型基础理论课程也值得一看,他们对决策智能的讲解很系统。

我在实际项目里最大的体会是,决策智能的难点不在算法,而在问题建模。把现实问题抽象成马尔可夫决策过程,定义好状态、动作、奖励,这步做对了,后面的算法选择反而简单。这步做错了,再先进的算法也救不回来。所以我的建议是,花70%的时间在问题建模和环境构建上,30%的时间在算法调优上。这个比例和很多人直觉相反,但实际做下来就是这样。