跳到主要内容
SpringBoot 整合 Weka 机器学习框架实战 | 极客日志
Java AI java 算法
SpringBoot 整合 Weka 机器学习框架实战 综述由AI生成 在 SpringBoot 项目中整合 Weka 机器学习框架的实战方案。内容涵盖 Weka、Spark MLlib 及 EasyRec 三种技术选型对比,重点演示了基于本地 CSV 和数据库样本数据构建决策树模型(J48)实现货品上架推荐的具体步骤。此外,还探讨了结合 AI 大模型进行推荐的实现思路。案例包含数据准备、依赖导入、模型训练、预测评估及代码实现,适用于小型系统的推荐场景开发。
草莓泡芙 发布于 2026/3/27 更新于 2026/5/31 33 浏览一、前言
在微服务开发中,经常会遇到需要进行推荐的场景,比如在电商场景中,需要基于用户的过往购买历史,选品喜欢,轨迹等指标信息进行选品推荐,再比如在社交应用中,需要根据用户的操作历史、个人标签等推荐一些功能从而展示给用户。尽管这样的推荐操作可以结合一些大数据、机器学习等推荐算法来做,但是对一些小型的系统来说,考虑到对接成本、学习成本和维护成本等因素,本篇将详细介绍下在微服务应用中如何对接第三方的机器学习框架,从而实现特定场景下的业务推荐。
二、Java 对接使用的机器学习技术方案
接下来介绍几种适合 Java 开发语言模式下的机器学习框架技术方案。
2.1 Weka 介绍
Weka(Waikato Environment for Knowledge Analysis)是一款由新西兰怀卡托大学开发的开源机器学习与数据挖掘软件,以其易用性、丰富的算法库和可视化界面闻名。它支持从数据预处理到模型评估的全流程,适合教学、研究和快速原型开发。官网:https://ml.cms.waikato.ac.nz/weka/
Weka,是一款免费、非商业化、基于 Java 的开源的机器学习与数据挖掘软件,并提供了 maven 依赖,拥有丰富的 Java API。
Github 地址:Weka Wiki
2.1.1 Weka 主要特点
Weka 具备如下特点:
开源免费:基于 GNU 通用公共许可证,用户可自由使用、修改和分发。
跨平台支持:基于 Java 开发,可在 Windows、macOS、Linux 等系统运行。
图形用户界面(GUI):提供直观的可视化操作,无需编程即可完成数据挖掘任务。
命令行接口:支持通过脚本自动化处理大规模数据或批量任务。
丰富的算法库:集成数百种机器学习算法,涵盖分类、回归、聚类、关联规则挖掘等。
2.1.2 Weka 核心功能模块
Weka 通过不同界面模块实现数据挖掘流程:
Explorer:主界面,包含以下子面板:
Preprocess:数据清洗、特征选择、离散化、标准化等。
Classify:分类算法(如决策树、SVM、神经网络)训练与评估。
Cluster:聚类分析(如 K-Means、DBSCAN)。
Associate:关联规则挖掘(如 Apriori 算法)。
Select attributes:特征选择与降维。
Visualize:数据可视化(散点图、箱线图等)。
Experimenter:设计对比实验,评估不同算法性能。
Knowledge Flow:通过拖拽组件构建数据处理流程图,支持复杂工作流。
Simple CLI:命令行交互,适合快速测试或脚本调用。
2.1.3 Weka 支持的算法类型
Weka 支持如下算法类型
分类:决策树(J48/C4.5)、随机森林、朴素贝叶斯、SVM、逻辑回归、神经网络等。
回归:线性回归、M5 规则树、支持向量回归(SVR)。
聚类:K-Means、EM、DBSCAN、层次聚类。
关联规则:Apriori、FP-Growth。
特征选择:信息增益、卡方检验、ReliefF、主成分分析(PCA)。
2.1.4 Weka 应用场景
学术研究:算法验证、教学演示(如机器学习课程实验)。
快速原型开发:测试不同算法对数据的适应性。
小规模数据挖掘:适合处理 GB 级以下数据(大数据需结合 Hadoop/Spark 扩展)。
工业应用:客户分群、欺诈检测、文本分类等(需结合业务逻辑优化)。
2.2 Apache Spark MLlib 介绍 Apache Spark MLlib 是一个专为大规模数据处理设计的分布式机器学习库,作为 Apache Spark 生态系统的核心组件,它通过利用 Spark 的分布式计算框架,能够高效处理海量数据,并加速模型的训练和预测过程。官网:MLlib | Apache Spark
2.2.1 核心模块介绍 MLlib 的架构由多个核心模块组成,协同工作以简化大规模数据处理中的机器学习任务复杂性:
算法库:提供丰富的监督学习(如逻辑回归、决策树、随机森林)和无监督学习(如 K-Means 聚类、高斯混合模型)算法,支持分类、回归、聚类、降维等任务,并涵盖推荐系统(如基于交替最小二乘法的协同过滤)和特征工程功能。
管道机制(Pipelines):通过串联多个 Transformer(数据转换组件,如标准化、归一化)和 Estimator(可训练模型,如逻辑回归、决策树),构建模块化的机器学习工作流,简化任务流程并支持复用。
数据类型:基于 Spark 的核心数据结构 RDD(弹性分布式数据集,提供容错和并行计算能力)和 DataFrame(类似 SQL 表的高层次数据类型,支持模式化数据结构和 SQL 查询),其中 DataFrame 是当前主要支持的数据类型,能更好地与 Spark SQL 集成。
2.2.2 核心功能介绍
算法支持:
分类:支持二分类和多分类任务,如逻辑回归、决策树、随机森林、朴素贝叶斯等。
回归:支持线性回归、岭回归、Lasso 回归等,用于预测连续值。
聚类:如 K-Means、高斯混合模型等,用于发现数据中的模式和相似性。
推荐系统:如基于交替最小二乘法的协同过滤算法,用于为用户推荐商品或内容。
降维:如主成分分析(PCA)、奇异值分解(SVD)等,用于降低数据维度。
特征处理:提供多种特征提取和转换方法,如 TF-IDF、Word2Vec、PCA 等,将原始数据转换为机器学习算法可处理的特征表示。
模型评估:提供丰富的评估指标工具,支持不同类型模型的性能评估:
分类模型:精度、召回率、F1 值、ROC 曲线等。
回归模型:均方误差(MSE)、均方根误差(RMSE)、平均绝对误差(MAE)等。
聚类模型:轮廓系数、簇间距离等。
2.2.3 技术优势
分布式计算能力:基于 Spark 的分布式计算框架,充分利用集群资源进行并行计算,大幅提升计算效率,尤其适合大规模数据集。
简洁易用的 API:提供简洁的 API 接口,支持 Scala、Java、Python 和 R 等多种编程语言,降低用户使用门槛。
可扩展性:用户可根据需求自定义算法和模型,并通过 Spark 的扩展机制将其集成到 MLlib 中。
与 Spark 生态无缝集成:与 Spark SQL、Spark Streaming 等组件无缝协作,支持复杂的数据处理和分析流程。
2.2.4 适用场景
分类任务:如垃圾邮件检测、情感分析、图像识别等。
回归任务:如房价预测、股票价格预测等。
聚类任务:如客户分群、市场细分、图像分割等。
推荐系统:如电商平台的个性化商品推荐、音视频网站的内容推荐等。
特征工程:如特征选择、特征提取、数据标准化等
2.3 EasyRec 介绍 EasyRec 是阿里巴巴开源的推荐系统框架,基于 TensorFlow 和 PyTorch 构建,提供模块化设计、分布式训练和在线预测等功能,适用于电商、音乐等领域,旨在简化推荐系统开发并提升推荐效果。
2.3.1 技术亮点
模块化设计:EasyRec 将推荐系统拆分为数据处理、特征工程、模型训练和在线预测等多个独立模块,用户可根据业务需求自由组合,减少代码复用,提升开发效率。
兼容主流深度学习框架:支持 TensorFlow 和 PyTorch 两大主流深度学习框架,满足不同开发者的技术偏好,降低技术切换成本。
高性能分布式训练:通过 horovod、TF-Replicator 等工具,EasyRec 提供高性能的分布式训练能力,支持大规模数据集和复杂模型训练,加速模型收敛,降低实验周期。
在线预测服务:EasyRec 内置在线预测服务,能够无缝对接到生产环境,提供低延迟的实时推荐,平滑从模型研发到业务上线的流程。
2.3.2 技术核心模块架构
数据处理层:支持多种数据输入方式,包括 MaxCompute、HDFS、CSV 文件等,满足不同数据源的需求。
特征工程层:提供丰富的特征类型支持,包括 IdFeature、RawFeature、TagFeature、SequenceFeature 以及 ComboFeature 等,满足不同业务场景的特征需求。
模型训练层:集成 DeepFM、DIN、MultiTower 及 DSSM 等经典推荐排序和召回算法,支持多任务学习、图神经网络等高级功能,满足不同业务场景的模型需求。
在线预测层:提供高性能的在线预测服务,支持模型增量更新、特征埋点等功能,满足实时推荐的需求。
2.3.3 技术优势
易用性:通过简洁的 API 设计,让推荐系统的开发变得简单,降低推荐系统开发的门槛。
灵活性:支持 TensorFlow 和 PyTorch,可按需选择,且模块化设计方便定制,满足不同业务场景的需求。
高效性:提供分布式训练和在线预测服务,加快模型迭代速度,提升推荐系统的性能。
全面性:覆盖推荐系统的全生命周期,从数据预处理到模型部署,提供一站式的解决方案。
2.3.4 适用场景 EasyRec 可广泛应用于电商、音乐、视频、新闻等各类需要个性化推荐的场景,无论是商品推荐、内容推送还是广告定向,都能帮助提升用户体验和业务转化率。
EasyRec 已经在阿里巴巴集团内部多个业务场景中得到广泛应用,如淘宝、天猫、优酷等,取得了显著的业务效果。同时,EasyRec 也积极与社区合作,推动推荐系统技术的发展和应用。
三、基于 Weka 实现货品推荐上架操作案例 接下来将通过一个实际案例,适用 Weka 实现一个货品的推荐上架案例。
3.1 案例需求
仓库有大货架,中型货架,还有小货架,三种货架类型;
每种货架能够容纳的货品尺寸,体积,重量各不相同;
对于需要上架的货品根据其尺寸、重量完成上架推荐;
3.2 前置准备
3.2.1 数据准备 使用 Weka 框架最后进行推荐的使用,需要导入样本数据,构建决策树,配合上述的需求,在本地提前准备一个 CSV 文件,里面有如下样本数据:
length,width,height,weight,fragile,shelf_type 50 ,40 ,30 ,5 ,false ,small_shelf 120 ,80 ,150 ,120 ,false ,floor_stack 30 ,20 ,10 ,1 ,false ,small_shelf 200 ,60 ,40 ,80 ,true ,high_rack 10 ,10 ,5 ,0.5 ,false ,small_shelf 300 ,120 ,80 ,300 ,false ,floor_stack 80 ,60 ,180 ,50 ,false ,high_rack 25 ,20 ,15 ,2 ,true ,small_shelf 150 ,100 ,200 ,150 ,false ,floor_stack 60 ,40 ,160 ,40 ,false ,high_rack
3.2.2 导入核心依赖 创建一个 springboot 工程,导入如下核心依赖:
<properties >
<maven.compiler.source > 17</maven.compiler.source >
<maven.compiler.target > 17</maven.compiler.target >
<project.build.sourceEncoding > UTF-8</project.build.sourceEncoding >
<satoken.version > 1.37.0</satoken.version >
<spring-ai.version > 1.0.0-M6</spring-ai.version >
<spring-ai-alibaba.version > 1.0.0-M6.1</spring-ai-alibaba.version >
</properties >
<parent >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-parent</artifactId >
<version > 3.2.2</version >
<relativePath />
</parent >
<dependencies >
<dependency >
<groupId > org.apache.commons</groupId >
<artifactId > commons-csv</artifactId >
<version > 1.9.0</version >
</dependency >
<dependency >
<groupId > nz.ac.waikato.cms.weka</groupId >
<artifactId > weka-stable</artifactId >
<version > 3.8.6</version >
</dependency >
<dependency >
<groupId > com.alibaba</groupId >
<artifactId > fastjson</artifactId >
<version > 1.2.83</version >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-aop</artifactId >
</dependency >
<dependency >
<groupId > org.springframework.boot</groupId >
<artifactId > spring-boot-starter-web</artifactId >
</dependency >
<dependency >
<groupId > mysql</groupId >
<artifactId > mysql-connector-java</artifactId >
<version > 8.0.28</version >
</dependency >
<dependency >
<groupId > org.projectlombok</groupId >
<artifactId > lombok</artifactId >
</dependency >
<dependency >
<groupId > com.alibaba.cloud.ai</groupId >
<artifactId > spring-ai-alibaba-starter</artifactId >
<version > ${spring-ai-alibaba.version}</version >
</dependency >
</dependencies >
<dependencyManagement >
<dependencies >
<dependency >
<groupId > org.springframework.ai</groupId >
<artifactId > spring-ai-bom</artifactId >
<version > ${spring-ai.version}</version >
<type > pom</type >
<scope > import</scope >
</dependency >
</dependencies >
</dependencyManagement >
<repositories >
<repository >
<name > Central Portal Snapshots</name >
<id > central-portal-snapshots</id >
<url > https://central.sonatype.com/repository/maven-snapshots/</url >
<releases >
<enabled > false</enabled >
</releases >
<snapshots >
<enabled > true</enabled >
</snapshots >
</repository >
<repository >
<id > spring-milestones</id >
<name > Spring Milestones</name >
<url > https://repo.spring.io/milestone</url >
<snapshots >
<enabled > false</enabled >
</snapshots >
</repository >
<repository >
<id > spring-snapshots</id >
<name > Spring Snapshots</name >
<url > https://repo.spring.io/snapshot</url >
<releases >
<enabled > false</enabled >
</releases >
</repository >
</repositories >
3.3 基于本地样本数据实现方案 基于上述的本地样本数据,完成一个基于 Weka 机器学习框架的推荐上架的案例实现。
3.3.1 导入核心依赖 <dependency >
<groupId > org.apache.commons</groupId >
<artifactId > commons-csv</artifactId >
<version > 1.9.0</version >
</dependency >
<dependency >
<groupId > nz.ac.waikato.cms.weka</groupId >
<artifactId > weka-stable</artifactId >
<version > 3.8.6</version >
</dependency >
3.3.2 添加本地样本数据 在本地的 resources 目录下增加一个 csv 样本文件,样本的数据如下:
3.3.3 完整的实现代码 package com.congge.command.v3;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import weka.core.converters.ConverterUtils.DataSource;
public class ShelfRecommendationSystemV3 {
private J48 decisionTree;
private Instances dataStructure;
public void trainModel (String csvFilePath) throws Exception {
DataSource source = new DataSource (csvFilePath);
Instances data = source.getDataSet();
if (data.classIndex() == -1 ) {
data.setClassIndex(data.numAttributes() - 1 );
}
this .dataStructure = new Instances (data, 0 );
decisionTree = new J48 ();
decisionTree.buildClassifier(data);
System.out.println("模型训练完成!" );
}
public String predictShelfType (double length, double width, double height, double weight, boolean fragile) throws Exception {
if (decisionTree == null || dataStructure == null ) {
throw new IllegalStateException ("模型尚未训练,请先调用 trainModel 方法" );
}
weka.core.Instance instance = new weka .core.DenseInstance(6 );
instance.setDataset(dataStructure);
instance.setValue(0 , length);
instance.setValue(1 , width);
instance.setValue(2 , height);
instance.setValue(3 , weight);
instance.setValue(4 , fragile ? "true" : "false" );
double prediction = decisionTree.classifyInstance(instance);
return dataStructure.classAttribute().value((int ) prediction);
}
public void evaluateModel (String csvFilePath) throws Exception {
DataSource source = new DataSource (csvFilePath);
Instances data = source.getDataSet();
if (data.classIndex() == -1 ) {
data.setClassIndex(data.numAttributes() - 1 );
}
weka.classifiers.Evaluation eval = new weka .classifiers.Evaluation(data);
eval.evaluateModel(decisionTree, data);
System.out.println("\n模型评估结果:" );
System.out.println(eval.toSummaryString());
System.out.println(eval.toClassDetailsString());
System.out.println(eval.toMatrixString());
}
public static void main (String[] args) {
ShelfRecommendationSystemV3 system = new ShelfRecommendationSystemV3 ();
try {
String csvPath = "data/shelf_data.csv" ;
system.trainModel(csvPath);
system.evaluateModel(csvPath);
System.out.println("\n测试预测:" );
String recommendation1 = system.predictShelfType(30 , 20 , 10 , 1 , false );
System.out.printf("货物 (30x20x10cm, 1kg, 非易碎) 推荐货架:%s%n" , recommendation1);
String recommendation2 = system.predictShelfType(200 , 100 , 180 , 200 , false );
System.out.printf("货物 (200x100x180cm, 200kg, 非易碎) 推荐货架:%s%n" , recommendation2);
String recommendation3 = system.predictShelfType(60 , 40 , 30 , 5 , true );
System.out.printf("货物 (60x40x30cm, 5kg, 易碎) 推荐货架:%s%n" , recommendation3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
在控制台中,输出了完整的决策树结构;
同时结合样本数据,也给出了基于 3 组测试数据的推荐上架库位;
3.4 基于数据库的样本数据实现方案 仍然是基于 Weka 机器学习框架,假如我们的样本数据存储在数据库的表中,下面看具体的实现
3.4.1 添加一张测试样本表 CREATE TABLE product_shelf_mapping (
id INT AUTO_INCREMENT PRIMARY KEY ,
product_name VARCHAR (100 ),
length DOUBLE NOT NULL COMMENT '长度 (cm)' ,
width DOUBLE NOT NULL COMMENT '宽度 (cm)' ,
height DOUBLE NOT NULL COMMENT '高度 (cm)' ,
weight DOUBLE NOT NULL COMMENT '重量 (kg)' ,
shelf_type ENUM('small_shelf' , 'high_shelf' , 'floor_stack' ) NOT NULL COMMENT '货架类型' ,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE= InnoDB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8mb4;
TRUNCATE TABLE product_shelf_mapping;
INSERT INTO product_shelf_mapping (product_name, length, width, height, weight, shelf_type) VALUES
('小型电子元件' , 15 , 10 , 5 , 0.2 , 'small_shelf' ),
('办公文具套装' , 30 , 20 , 8 , 0.5 , 'small_shelf' ),
('手机配件盒' , 25 , 15 , 5 , 0.3 , 'small_shelf' ),
('化妆品样品' , 12 , 8 , 6 , 0.1 , 'small_shelf' ),
('LED 灯泡' , 10 , 10 , 15 , 0.15 , 'small_shelf' ),
('书籍礼盒' , 40 , 30 , 20 , 2.5 , 'high_shelf' ),
('厨房调料套装' , 35 , 25 , 15 , 1.8 , 'high_shelf' ),
('玩具模型箱' , 50 , 40 , 30 , 3.0 , 'high_shelf' ),
('家庭清洁用品' , 45 , 35 , 25 , 2.2 , 'high_shelf' ),
('宠物食品袋' , 55 , 40 , 20 , 4.0 , 'high_shelf' ),
('大型家具部件' , 200 , 80 , 30 , 25.0 , 'floor_stack' ),
('健身器材包装' , 180 , 60 , 40 , 30.0 , 'floor_stack' ),
('工业设备箱' , 150 , 100 , 50 , 50.0 , 'floor_stack' ),
('自行车包装箱' , 160 , 70 , 20 , 18.0 , 'floor_stack' ),
('长条形管材' , 300 , 10 , 10 , 12.0 , 'floor_stack' ),
('中型电器箱' , 60 , 50 , 40 , 8.0 , 'high_shelf' ),
('超重小物件' , 20 , 20 , 10 , 15.0 , 'floor_stack' ),
('细长物品' , 150 , 5 , 5 , 3.0 , 'floor_stack' ),
('扁平大件' , 120 , 90 , 2 , 5.0 , 'floor_stack' );
3.4.2 导入依赖 除了上面的 Weka 框架库,还需要引入 mysql 依赖
<dependency >
<groupId > mysql</groupId >
<artifactId > mysql-connector-java</artifactId >
<version > 8.0.28</version >
</dependency >
3.4.3 完整的实现代码 package com.congge.command.v2;
import lombok.Data;
import weka.classifiers.trees.J48;
import weka.core.*;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ShelfRecommendationSystem {
private static final String DB_URL = "jdbc:mysql://<host>:3306/<database>" ;
private static final String DB_USER = "<username>" ;
private static final String DB_PASSWORD = "<password>" ;
public static void main (String[] args) {
try {
List<Product> trainingData = loadTrainingDataFromMySQL();
Instances instances = createInstances(trainingData);
J48 tree = trainDecisionTree(instances);
testModel(tree, instances);
Product newProduct = new Product ();
newProduct.setLength(120 );
newProduct.setWidth(80 );
newProduct.setHeight(30 );
newProduct.setWeight(25 );
String recommendedShelf = recommendShelf(tree, newProduct);
System.out.println("\n推荐货架类型:" + recommendedShelf);
} catch (Exception e) {
e.printStackTrace();
}
}
private static List<Product> loadTrainingDataFromMySQL () throws SQLException {
List<Product> products = new ArrayList <>();
try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
String query = "SELECT length, width, height, weight, shelf_type FROM product_shelf_mapping" ;
try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
Product product = new Product ();
product.setLength(rs.getDouble("length" ));
product.setWidth(rs.getDouble("width" ));
product.setHeight(rs.getDouble("height" ));
product.setWeight(rs.getDouble("weight" ));
product.setShelfType(rs.getString("shelf_type" ));
products.add(product);
}
}
}
System.out.println("从 MySQL 加载了 " + products.size() + " 条训练数据" );
return products;
}
private static Instances createInstances (List<Product> products) {
ArrayList<Attribute> attributes = new ArrayList <>();
attributes.add(new Attribute ("length" ));
attributes.add(new Attribute ("width" ));
attributes.add(new Attribute ("height" ));
attributes.add(new Attribute ("weight" ));
ArrayList<String> shelfTypes = new ArrayList <>();
shelfTypes.add("small_shelf" );
shelfTypes.add("high_shelf" );
shelfTypes.add("floor_stack" );
attributes.add(new Attribute ("shelf_type" , shelfTypes));
Instances instances = new Instances ("ProductShelfRelation" , attributes, 0 );
instances.setClassIndex(instances.numAttributes() - 1 );
for (Product product : products) {
double [] values = new double [instances.numAttributes()];
values[0 ] = product.getLength();
values[1 ] = product.getWidth();
values[2 ] = product.getHeight();
values[3 ] = product.getWeight();
switch (product.getShelfType()) {
case "small_shelf" : values[4 ] = 0 ; break ;
case "high_shelf" : values[4 ] = 1 ; break ;
case "floor_stack" : values[4 ] = 2 ; break ;
default : values[4 ] = Utils.missingValue();
}
instances.add(new DenseInstance (1.0 , values));
}
return instances;
}
private static J48 trainDecisionTree (Instances instances) throws Exception {
String[] options = new String [1 ];
options[0 ] = "-U" ;
J48 tree = new J48 ();
tree.setOptions(options);
tree.buildClassifier(instances);
System.out.println("\n训练好的决策树模型:" );
System.out.println(tree);
return tree;
}
private static void testModel (J48 tree, Instances instances) throws Exception {
instances.randomize(new Random (0 ));
int trainSize = (int ) Math.round(instances.numInstances() * 0.7 );
int testSize = instances.numInstances() - trainSize;
Instances train = new Instances (instances, 0 , trainSize);
Instances test = new Instances (instances, trainSize, testSize);
tree.buildClassifier(train);
int correct = 0 ;
for (int i = 0 ; i < test.numInstances(); i++) {
Instance inst = test.instance(i);
double predicted = tree.classifyInstance(inst);
double actual = inst.classValue();
if (predicted == actual) {
correct++;
}
}
double accuracy = (double ) correct / test.numInstances() * 100 ;
System.out.printf("\n模型准确率:%.2f%% (%d/%d)\n" , accuracy, correct, test.numInstances());
}
public static String recommendShelf (J48 tree, Product product) throws Exception {
ArrayList<Attribute> attributes = new ArrayList <>();
attributes.add(new Attribute ("length" ));
attributes.add(new Attribute ("width" ));
attributes.add(new Attribute ("height" ));
attributes.add(new Attribute ("weight" ));
ArrayList<String> shelfTypes = new ArrayList <>();
shelfTypes.add("small_shelf" );
shelfTypes.add("high_shelf" );
shelfTypes.add("floor_stack" );
attributes.add(new Attribute ("shelf_type" , shelfTypes));
Instances instances = new Instances ("Temp" , attributes, 0 );
instances.setClassIndex(instances.numAttributes() - 1 );
double [] values = new double [instances.numAttributes()];
values[0 ] = product.getLength();
values[1 ] = product.getWidth();
values[2 ] = product.getHeight();
values[3 ] = product.getWeight();
values[4 ] = Utils.missingValue();
instances.add(new DenseInstance (1.0 , values));
double prediction = tree.classifyInstance(instances.instance(0 ));
return shelfTypes.get((int ) prediction);
}
}
@Data
class Product {
private double length;
private double width;
private double height;
private double weight;
private String shelfType;
}
3.5 基于 AI 大模型实现方案
定义系统提示词
提示词中,参考的货架类型,需要提前根据实际业务需求 + 经验判断拟定;
体积 + 重量一起判断;
体积 = 长宽 高
将用户的问题,代入到提示词中,让大模型给出推荐
3.5.1 添加配置信息 spring:
ai:
dashscope:
api-key: <your_api_key>
chat:
options:
model: qwen-max
3.5.2 添加测试接口 package com.congge.command.v5;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/client/ai")
public class ChatController {
private final ChatClient chatClient;
public ChatController (ChatClient.Builder chatClientBuilder) {
this .chatClient = chatClientBuilder.build();
}
@PostMapping("/chat")
public String chat (@RequestBody Product product) {
Prompt prompt = new Prompt (new UserMessage (buildPrompt(product)));
String content = chatClient.prompt(prompt).call().content();
return content;
}
private static String buildPrompt (Product product) {
return String.format("""
你是一名仓库管理专家,需要根据商品尺寸和重量推荐合适的货架类型。
货架类型定义:
1. small_shelf: 体积小于 5000cm³且重量小于 1kg 的商品
2. high_shelf: 体积 5000-60000cm³且重量 1-10kg 的商品
3. floor_stack: 体积大于 60000cm³或重量大于 10kg 或形状特殊的商品(如超长、超宽)
商品信息:
名称:%s
尺寸:%.1fcm x %.1fcm x %.1fcm
重量:%.2fkg
体积:%.1fcm³
密度:%.2fg/cm³
请根据以上信息,只返回推荐货架类型,格式为:推荐货架类型:[类型]
""" , product.getProductName(), product.getLength(), product.getWidth(), product.getHeight(), product.getWeight(), product.getVolume(), product.getDensity());
}
}
package com.congge.command.v5;
import lombok.Data;
@Data
public class Product {
private Long id;
private String productName;
private double length;
private double width;
private double height;
private double weight;
private String shelfType;
public double getVolume () {
return length * width * height;
}
public double getDensity () {
return weight / getVolume();
}
}
3.5.3 效果测试 启动工程后,调用下接口,这里随机给一组产品的长宽高进行测试,结果如下:
四、写在文末 本文通过较大的篇幅详细介绍了基于 Java 技术栈,整合机器学习算法框架 Weka 结合一个实际案例实现一个货品上架的功能。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
RSA密钥对生成器 生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online