人工智能
阿里云AI实训营电商专题「电商人爆款打造攻略」课程上新!第二期课程由设计领域头部AI博主「来真的」教你在阿里云百炼上用Wan2.5-Preview生成电商服饰设计图,零基础也能玩转AI服饰设计,点击链接立即学习!还有tokens超值优惠包,最低20元可抵千万tokens! 立即点击链接,观看课程: https://click.aliyun.com/m/1000408193/
用户画像系统扩展实战:AI原生架构下的水平扩容策略设计与落地
一、引言:当用户画像遇到“扩容焦虑症”
凌晨3点,某电商公司的运维群炸了——大促预热期间,用户画像系统突然宕机,推荐引擎无法获取用户偏好,首页推荐直接变成“猜你喜欢”的默认列表。工程师紧急排查后发现:
实时特征计算的Flink作业并行度不足,延迟从500ms飙升到8s;模型服务的Tomcat实例扛不住10倍流量,CPU利用率100%;画像存储的MongoDB分片键设计失误,热点数据集中在一个分片,读写超时。这不是个例。随着AI技术在用户运营中的深度渗透,用户画像系统的“扩容能力”早已成为企业的核心竞争力:
数据量爆炸:日均处理10TB用户行为数据、1亿+用户的实时特征更新;模型复杂度提升:从简单的标签统计到LLM驱动的用户意图识别,模型推理算力需求增长10倍;实时性要求:从“T+1”离线画像到“毫秒级”实时画像,用户点击后1秒内要更新推荐策略。传统用户画像系统的“垂直扩容”(加CPU/内存)早已走到尽头——不仅成本高,还无法解决分布式场景下的性能瓶颈。AI原生架构下的水平扩容,成为破局的关键。
本文将带你从0到1理解:
AI原生用户画像系统的核心特征;特征、模型、存储、计算四层的水平扩容策略;实战落地中的坑点与保障机制;某电商公司的真实扩容案例。无论你是用户画像工程师、AI运维还是架构师,读完本文都能掌握一套可落地的扩容方法论。
二、基础认知:AI原生架构vs传统用户画像系统
在讲扩容策略前,我们需要先明确AI原生架构的用户画像系统到底是什么——它不是“云原生+AI”的简单拼接,而是从设计之初就融合了“AI工程化”与“分布式扩展”的特性。
2.1 传统用户画像系统的“扩容痛点”传统用户画像系统通常采用“分层架构”:
数据层:离线数据存在Hive,实时数据存在Kafka;特征层:离线特征用MapReduce计算,实时特征用Storm;模型层:单体模型服务(如TensorFlow Serving)部署在物理机;画像层:用MySQL/MongoDB存储用户标签。这种架构的扩容痛点非常明显:
特征计算瓶颈:实时特征计算的Storm作业无法动态调整并行度,流量高峰时延迟暴增;模型服务单点故障:单体模型服务挂了会导致整个推荐系统瘫痪,扩容需要手动部署实例;存储热点问题:MongoDB按user_id分片,但头部用户(如大V)的访问量是普通用户的100倍,导致分片过载;资源利用率低:离线计算集群在非高峰时闲置,实时计算集群高峰时资源不足。2.2 AI原生架构的定义与核心特性AI原生架构的用户画像系统,是以“AI任务”为核心,结合云原生弹性、分布式计算、模型工程化的新一代架构,其核心特性包括:
特性
说明
数据与计算分离
特征存储(如Feast)与计算引擎(Flink/Spark)解耦,计算资源按需调度
模型即服务(MaaS)
模型容器化部署(Docker),用K8s管理,支持动态扩缩容
实时优先
实时特征计算(Flink)与离线特征(Spark)协同,毫秒级更新用户画像
弹性资源调度
用K8s/YARN动态分配计算资源,离线/实时作业共享集群,提高资源利用率
全链路可观测
用Prometheus+Grafana监控特征延迟、模型QPS、存储读写性能,实现闭环优化
在阅读后续内容前,建议你具备以下基础:
用户画像基础:理解标签(如“25-30岁女性”)、特征(如“最近7天浏览美妆次数”)、画像库的概念;云原生基础:熟悉K8s的Deployment、HPA(水平 Pod 自动扩缩)、容器化;AI工程化基础:了解模型部署(TensorFlow Serving/TorchServe)、特征存储(Feast);分布式计算:熟悉Flink的并行度、Spark的集群模式。三、AI原生架构下的水平扩容核心策略
水平扩容(Scale Out)的本质是将单一节点的负载分散到多个节点,但在AI原生架构中,扩容不是“加机器”那么简单——需要针对特征、模型、存储、计算四层分别设计策略,实现“分层扩展、协同优化”。
3.1 特征系统:从集中式到分布式的实时/离线协同扩容特征是用户画像的“原子单元”(比如“最近30天购买金额”“点击商品的类目偏好”),特征系统的扩容直接决定了画像的实时性与准确性。
3.1.1 离线特征存储:按“时间+分片”解决大文件查询瓶颈离线特征通常是T+1计算的批量数据(如用户月度消费总结),传统存储方式是Hive按日期分区,但当数据量达到PB级时,单个分区的文件数会超过10万,查询延迟高达分钟级。
解决策略:日期分区+哈希分片
将离线特征表按“日期(dt)+ 用户ID哈希分片(shard)”双层分区,例如:
代码示例:Hive离线特征表建表
CREATE TABLE user_features_offline ( user_id STRING COMMENT '用户ID', monthly_spend DOUBLE COMMENT '月度消费金额', category_preference MAP<STRING, DOUBLE> COMMENT '类目偏好' ) PARTITIONED BY (dt STRING COMMENT '日期', shard INT COMMENT '用户ID哈希分片') STORED AS PARQUET -- 列式存储,提高查询效率 TBLPROPERTIES ( 'parquet.compression'='SNAPPY', -- 压缩减少存储空间 'partition.autodiscovery'='true' -- 自动发现分区 );1.2.3.4.5.6.7.8.9.10.11.
查询示例:快速获取用户特征
要查询user_id=123在20240520的特征,只需定位到dt=20240520和shard=MOD(HASH('123'), 100)的分区:
SELECT * FROM user_features_offline WHERE dt='20240520' AND shard=MOD(HASH('123'), 100) AND user_id='123';1.2.3.4.
效果:查询延迟从30秒降到1秒内,支持每秒10万+次查询。
3.1.2 实时特征计算:Flink并行度与KeyGroup优化实时特征(如“最近5分钟点击次数”)需要毫秒级计算,Flink是目前最主流的实时计算引擎,但默认配置下,Flink作业的并行度无法动态调整,导致流量高峰时延迟飙升。
解决策略:动态调整并行度+KeyGroup优化
动态调整并行度:用Flink的rescale API或K8s的HPA,根据作业的“输入吞吐量”自动调整并行度。KeyGroup优化:Flink将数据按KeyBy分组后分配到不同的KeyGroup,每个KeyGroup对应一个TaskManager。通过调整KeyGroup的数量,可以平衡不同TaskManager的负载。代码示例:Flink实时特征计算的并行度配置
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // 设置初始并行度为10 env.setParallelism(10); // 从Kafka读取用户行为数据 DataStream<UserBehavior> behaviorStream = env.addSource(kafkaConsumer); // 按user_id分组,计算最近5分钟点击次数 DataStream<UserRealTimeFeature> realTimeFeatureStream = behaviorStream .keyBy(UserBehavior::getUserId) // 按用户ID分组 .window(SlidingEventTimeWindows.of(Time.minutes(5), Time.seconds(10))) // 滑动窗口:5分钟窗口,10秒滑动 .aggregate(new ClickCountAggregateFunction()); // 自定义聚合函数 // 输出到Redis Cluster realTimeFeatureStream.addSink(redisSink); // 启用动态并行度调整(Flink 1.17+支持) env.enableDynamicParallelism(); env.setMaxParallelism(100); // 最大并行度1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.
效果:当Kafka输入吞吐量从1万条/秒增长到10万条/秒时,Flink会自动将并行度从10调整到50,延迟保持在200ms以内。
3.1.3 特征存储的热点问题:缓存+二次分片即使做了分片,仍可能出现热点问题——比如某明星的粉丝用户在短时间内集中访问,导致对应的分片过载。
解决策略:
本地缓存:在特征服务层(如Feast)增加本地缓存(如Caffeine),缓存热点用户的特征,减少对存储的查询压力;二次分片:将热点分片按“user_id+时间”再次拆分,比如将shard=1的用户按user_id % 10拆分成10个子分片;动态迁移:用Redis Cluster的MOVED指令,将热点分片迁移到资源更充足的节点。代码示例:Feast特征服务的本地缓存配置
# Feast特征服务配置文件 kind: FeatureService metadata: name: user_real_time_features spec: features: - user_features:click_count_last_5min - user_features:category_preference serving_config: online_store: type: redis redis_config: host: redis-cluster:6379 cluster: true # 本地缓存配置 local_cache: type: caffeine caffeine_config: maximum_size: 100000 # 缓存10万条特征 expire_after_write: 60s # 写入后60秒过期1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.3.2 模型服务:弹性伸缩的AI推理引擎
模型服务是用户画像的“大脑”(比如用LLM预测用户意图),其扩容需要解决模型加载时间长、冷启动延迟高、资源利用率低的问题。
3.2.1 模型的容器化部署与多实例并行传统模型服务通常部署在物理机上,扩容需要手动安装依赖、加载模型,耗时数小时。容器化部署是解决这个问题的关键——将模型打包成Docker镜像,用K8s管理实例。
步骤1:打包模型为Docker镜像
以TorchServe为例,将PyTorch模型打包成镜像:
FROM pytorch/torchserve:latest COPY user_intent_model.mar /home/model-server/model-store/ COPY config.properties /home/model-server/config/ EXPOSE 8080 8081 8082 CMD ["torchserve", "--start", "--model-store", "/home/model-server/model-store", "--ts-config", "/home/model-server/config/config.properties"]1.2.3.4.5.
步骤2:用K8s部署模型服务
编写deployment.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: user-intent-model-deployment spec: replicas: 2 # 初始2个实例 selector: matchLabels: app: user-intent-model template: metadata: labels: app: user-intent-model spec: containers: - name: user-intent-model image: my-registry/user-intent-model:v1.0 ports: - containerPort: 8080 # 推理端口 resources: requests: cpu: "1" memory: "2Gi" limits: cpu: "2" memory: "4Gi"1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.3.2.2 基于流量的动态扩缩容:HPA与自定义指标
K8s的**HPA(水平Pod自动扩缩)**可以根据CPU/内存利用率或自定义指标(如QPS)自动调整Pod数量。对于模型服务,QPS是更精准的扩缩指标——当QPS超过阈值时增加实例,反之减少。
步骤1:配置自定义指标采集
用Prometheus采集模型服务的QPS指标,需要在模型服务中暴露 metrics 接口(TorchServe默认支持)。
步骤2:编写HPA配置
apiVersion: autoscaling/v2beta2 kind: HorizontalPodAutoscaler metadata: name: user-intent-model-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: user-intent-model-deployment minReplicas: 2 # 最小实例数 maxReplicas: 10 # 最大实例数 metrics: - type: Pods pods: metric: name: http_requests_per_second # 自定义QPS指标 target: type: AverageValue averageValue: 100m # 每个Pod每秒处理100个请求1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.3.2.3 模型冷启动优化:预热+模型缓存
模型服务的冷启动问题——新Pod启动时需要加载模型(耗时数十秒),导致初始请求延迟高。解决策略包括:
模型预热:在Pod启动后,自动发送测试请求,提前加载模型到内存。例如在TorchServe的config.properties中配置:inference_address=http://0.0.0.0:8080 management_address=http://0.0.0.0:8081 metrics_address=http://0.0.0.0:8082 model_store=/home/model-server/model-store load_models=user_intent_model:1.0 # 预热配置:启动后发送10个测试请求 warmup_requests=10 warmup_delay=500ms1.2.3.4.5.6.7.8.模型缓存:用K8s的PersistentVolumeClaim(PVC)缓存模型文件,避免每次启动都从镜像拉取模型(镜像中的模型文件可能很大,拉取耗时)。3.3 画像存储:分布式数据库的水平扩展实践
画像存储是用户画像的“最终载体”(比如存储用户的“综合画像”:年龄、性别、偏好类目、最近购买行为),其扩容需要解决数据一致性、读写性能、无缝迁移的问题。
3.3.1 分片键的设计原则:唯一性、均匀性、查询友好分片键(Shard Key)是分布式数据库水平扩展的核心——它决定了数据如何分布到不同的分片。设计分片键需遵循三个原则:
唯一性:分片键应能唯一标识数据(如user_id);均匀性:数据应均匀分布到所有分片,避免热点;查询友好:查询条件应包含分片键,避免全分片扫描。反例:用create_time作为分片键——新数据会集中在最近的分片,导致热点;
正例:用user_id作为分片键——数据均匀分布,查询时只需指定user_id。
Cassandra是一款高可用、分布式的NoSQL数据库,非常适合存储用户画像(支持高写入、低延迟查询)。其核心扩展策略包括:
多数据中心(Multi-DC):将数据复制到多个数据中心,提高容灾能力;一致性级别调整:根据业务需求调整一致性级别(如写入时用QUORUM,查询时用ONE);自动分片(Auto-Sharding):Cassandra会自动将数据按分片键分布到不同的节点,扩容时只需添加新节点,数据会自动重新分布。代码示例:Cassandra画像表建表
CREATE KEYSPACE user_profile WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 3, -- 数据中心1保留3个副本 'dc2': 2 -- 数据中心2保留2个副本 }; CREATE TABLE user_profile.user_portrait ( user_id UUID PRIMARY KEY, -- 分片键:user_id age INT, gender TEXT, category_preference MAP<TEXT, DOUBLE>, last_purchase_time TIMESTAMP ) WITH comment = '用户综合画像表';1.2.3.4.5.6.7.8.9.10.11.12.13.3.3.3 存储扩容的无缝迁移:滚动升级+数据重分片
当存储容量不足时,需要添加新节点并迁移数据,但不能影响线上服务。Cassandra的滚动升级策略可以实现无缝扩容:
添加新节点:在Cassandra集群中添加新节点,配置相同的cluster_name和seeds;自动数据迁移:Cassandra会自动将部分数据从旧节点迁移到新节点,过程中服务保持可用;验证数据一致性:用nodetool status查看节点状态,用nodetool repair修复不一致的数据。3.4 计算引擎:离线与实时的弹性资源调度计算引擎是用户画像的“动力源”(离线计算用Spark,实时计算用Flink),其扩容需要解决资源闲置、作业冲突的问题。
3.4.1 Spark集群的水平扩容:YARN/K8s的资源动态分配传统Spark集群采用“静态资源分配”——作业提交时申请固定资源,作业结束后释放。这种方式会导致资源闲置(如夜间离线作业少,集群资源利用率低)。
解决策略:动态资源分配(Dynamic Resource Allocation)
Spark会根据作业的负载自动申请/释放资源。例如,当作业需要更多Executor时,Spark会向YARN/K8s申请;当Executor空闲超过一定时间,Spark会释放资源。
代码示例:Spark动态资源分配配置
在spark-submit中添加以下参数:
spark-submit \ --class com.example.UserFeatureComputation \ --master yarn \ --deploy-mode cluster \ --conf spark.dynamicAllocation.enabled=true \ --conf spark.dynamicAllocation.minExecutors=2 \ --conf spark.dynamicAllocation.maxExecutors=100 \ --conf spark.dynamicAllocation.executorIdleTimeout=60s \ user-feature-computation.jar1.2.3.4.5.6.7.8.9.3.4.2 Flink作业的并行度调整:Savepoint与作业重启
Flink作业的并行度调整需要Savepoint(保存作业的状态)——先停止作业并生成Savepoint,然后用新的并行度重启作业。
步骤1:生成Savepoint
bin/flink savepoint <job-id> hdfs:///savepoints/1.
步骤2:重启作业并调整并行度
bin/flink run \ --class com.example.RealTimeFeatureComputation \ --fromSavepoint hdfs:///savepoints/savepoint-xxxx \ --parallelism 50 \ real-time-feature-computation.jar1.2.3.4.5.3.4.3 资源混部:K8s的QoS级别优化
K8s的**QoS(服务质量)**级别可以实现离线/实时作业的资源混部——将实时作业(如Flink)设置为Guaranteed(保证资源),离线作业(如Spark)设置为Burstable(弹性资源),这样离线作业会在实时作业空闲时使用资源,提高利用率。
代码示例:Flink作业的QoS配置
apiVersion: batch/v1 kind: Job metadata: name: flink-real-time-job spec: template: spec: containers: - name: flink-taskmanager image: flink:1.18 resources: requests: cpu: "2" memory: "4Gi" limits: cpu: "2" memory: "4Gi" # 请求等于限制,QoS级别为Guaranteed restartPolicy: Never1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.
四、扩容的保障机制:监控、熔断与灰度
水平扩容不是“一扩了之”——需要建立全链路保障机制,确保扩容后的系统稳定运行。
4.1 全链路监控体系:Prometheus+Grafana监控是扩容的“眼睛”,需要监控特征、模型、存储、计算四层的关键指标:
层级
关键指标
特征层
实时特征延迟(p50/p95)、离线特征查询QPS、特征存储缓存命中率
模型层
模型推理延迟、QPS、错误率、Pod资源利用率(CPU/内存)
存储层
画像存储读写延迟、分片使用率、副本一致性
计算层
Flink作业并行度、Spark Executor数量、K8s集群资源利用率
示例:Grafana仪表盘
用Prometheus采集指标后,在Grafana中创建仪表盘:
当系统负载超过阈值时,需要熔断(停止对某些服务的请求)或降级(返回默认结果),避免雪崩。
示例:模型服务的降级策略
用Sentinel(阿里开源的流量控制框架)配置模型服务的降级规则:
代码示例:Sentinel配置
// 初始化Sentinel EnvUtils.setEnv(EnvUtils.Env.PROD); Sentinel.init(); // 配置降级规则 DegradeRule rule = new DegradeRule(); rule.setResource("user-intent-model-inference"); rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // 按延迟降级 rule.setCount(500); // 延迟阈值:500ms rule.setTimeWindow(10); // 降级时间窗口:10秒 DegradeRuleManager.loadRules(Collections.singletonList(rule)); // 模型推理逻辑 public String infer(UserPortrait portrait) { try (Entry entry = SphU.entry("user-intent-model-inference")) { // 正常推理逻辑 return model.infer(portrait); } catch (BlockException e) { // 降级处理:返回默认结果 return "unknown"; } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.4.3 灰度发布:Istio的流量切分
扩容后的新节点需要验证稳定性,不能直接全量上线。灰度发布(Canary Release)是解决这个问题的关键——用Istio(服务网格)将部分流量导向新节点,验证没问题后再全量。
步骤1:部署新老版本的模型服务
老版本:deployment/user-intent-model-v1;新版本:deployment/user-intent-model-v2。步骤2:配置Istio的流量切分规则
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: user-intent-model-vs spec: hosts: - user-intent-model http: - route: - destination: host: user-intent-model subset: v1 weight: 90 # 90%流量到老版本 - destination: host: user-intent-model subset: v2 weight: 10 # 10%流量到新版本1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.
步骤3:验证与全量
监控新版本的延迟、错误率;若稳定,逐步调整权重到100%;下线老版本。五、实战案例:某电商用户画像系统的AI原生扩容
5.1 背景与问题某电商公司的用户画像系统在2023年双11期间遇到以下问题:
实时特征延迟从500ms飙升到8s,导致推荐系统无法实时调整策略;模型服务的Tomcat实例扛不住10倍流量,CPU利用率100%,宕机3次;画像存储的MongoDB按user_id分片,但头部用户(如大V)的访问量是普通用户的100倍,导致分片过载,读写超时。5.2 解决方案设计针对问题,该公司采用AI原生架构进行改造,核心方案如下:
层级
改造前
改造后
特征层
实时特征用Storm,离线用Hive
实时特征用Flink(动态并行度),离线用Hive(dt+shard分片)
模型层
单体Tomcat部署TensorFlow Serving
TorchServe容器化部署,K8s HPA按QPS扩缩
存储层
MongoDB按user_id分片
Cassandra按user_id分片,多数据中心副本
计算层
静态Spark/YARN集群
动态资源分配,K8s混部离线/实时作业
改造后,实时特征存储用Redis Cluster按user_id分片,但某明星代言的商品导致该明星的粉丝用户访问量暴增,出现热点分片。
解决:将分片键改成user_id+dt,把同一用户的不同日期的特征分到不同分片。坑点2:模型冷启动延迟
模型服务扩容时,新Pod启动需要加载模型(耗时30秒),导致初始请求延迟高。
解决:在TorchServe中配置预热,启动后发送10个测试请求,提前加载模型到内存。坑点3:监控指标遗漏
初期监控没有覆盖Cassandra的分片使用率,导致某分片使用率达到90%才发现。
解决:添加Cassandra的nodetool status指标到Prometheus,监控每个分片的使用率。5.4 结果与反思
改造后,双11期间的系统表现:
实时特征延迟从8s降到200ms;模型推理延迟从2s降到300ms;画像存储读写延迟从1.5s降到200ms;资源利用率从30%提高到75%;大促期间0宕机,推荐转化率提升12%。反思:
扩容前需做容量规划(比如预测双11的流量是日常的10倍,提前调整最大并行度);需建立故障演练(比如模拟分片宕机,验证系统的容灾能力);需持续优化成本(比如用Spot Instance降低K8s集群成本)。六、结论与未来展望
6.1 核心要点总结AI原生架构下的水平扩容,本质是**“分层扩展+协同优化”**:
特征层:离线特征用“日期+分片”,实时特征用Flink动态并行度,解决查询延迟与热点问题;模型层:容器化部署+K8s HPA+模型预热,解决冷启动与资源利用率问题;存储层:分布式数据库(Cassandra)+ 合理分片键,解决一致性与读写性能问题;计算层:动态资源分配+K8s混部,解决资源闲置问题;保障机制:全链路监控+熔断降级+灰度发布,确保扩容后的稳定性。6.2 行动号召现在就可以开始你的AI原生扩容实践:
选择一个小模块(比如实时特征计算),用Flink的动态并行度改造;将模型服务容器化,用K8s部署并配置HPA;用Prometheus+Grafana搭建监控体系;在评论区分享你的实践经验或问题,我们一起讨论!6.3 未来方向AI原生架构的水平扩容还有很大的探索空间:
AI自动扩容:用LLM预测流量,提前调整并行度与Pod数量;Serverless AI:用AWS Lambda或阿里云函数计算,实现模型服务的“按需扩容”;边缘画像系统:将部分特征计算与模型推理部署在边缘节点(如CDN),降低延迟。七、附加部分
7.1 参考文献《云原生AI架构实践》——阿里云智能;《Flink 1.18官方文档》——Apache Flink;《Cassandra权威指南》——O’Reilly;《Sentinel流量控制框架》——阿里巴巴。7.2 致谢感谢某电商公司的架构师团队提供的真实案例,感谢Apache Flink、Cassandra、K8s社区的开源贡献。
阿里云AI实训营电商专题「电商人爆款打造攻略」课程上新!第二期课程由设计领域头部AI博主「来真的」教你在阿里云百炼上用Wan2.5-Preview生成电商服饰设计图,零基础也能玩转AI服饰设计,点击链接立即学习!还有tokens超值优惠包,最低20元可抵千万tokens! 立即点击链接,观看课程: https://click.aliyun.com/m/1000408193/
网址:人工智能 https://m.mxgxt.com/news/view/1887452
相关内容
“智能制造=人工智能+制造业” 未来,工业产品拼“智商”人工智能小ai
人工智能 明星
人工智能概念
人工智能简史 01:达特茅斯会议—人工智能的缘起
人工智能改变时尚圈,年轻人的人工智能生活
人工智能偶像来袭:Snh48推出全球首款明星人工智能
设计人工智能系统
软件测试 / 人工智能丨为什么人工智能 = 大数据 + 机器学习
工业互联网 + 人工智能,谁能笑到最后?
