Browse Source

ai识别优化

cangku
wangfukang 2 years ago
parent
commit
053179a365
  1. 1
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java
  2. 110
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java
  3. 4
      hiver-modules/hiver-mall/src/main/resources/mapper/PurchaseOcrPictureMapper.xml

1
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/purchaseocr/service/impl/PurchaseOcrPictureServiceImpl.java

@ -107,6 +107,7 @@ public class PurchaseOcrPictureServiceImpl implements PurchaseOcrPictureService
addPurchaseOcrPicture.setOrderId(purchaseOciPictureAddVo.getOrderId());
addPurchaseOcrPicture.setOcrStatus(PurchaseConstant.OCR_STATUS[0]);
addPurchaseOcrPicture.setCount(purchaseOcrPicture.getCount());
addPurchaseOcrPicture.setOcrPictureOrder(purchaseOcrPicture.getOcrPictureOrder());
addPurchaseOcrPicture.setParentPicturePath(purchaseOcrPicture.getParentPicturePath());
purchaseOcrPictureAddList.add(addPurchaseOcrPicture);
}

110
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/AliOcrUtil.java

@ -61,11 +61,20 @@ public class AliOcrUtil {
public static JSONObject multiRoundConversationCall(PurchaseOcrPicture purchaseOcrPicture, PurchaseOcrExample purchaseOcrExample, ProductService productService, PurchaseDetailService purchaseDetailService) throws ApiException, NoApiKeyException, UploadFileException {
final JSONObject jsonObject = new JSONObject();
final String picturePath = purchaseOcrPicture.getOcrPicture();
final String parentPicturePath = purchaseOcrPicture.getParentPicturePath();
final Integer count = purchaseOcrPicture.getCount();
final String orderId = purchaseOcrPicture.getOrderId();
final String shopId = purchaseOcrPicture.getShopId();
// 下角标,第一张那个主图和子图用 前台传的 货号和名称,后边的主图子图那个JSON示例的货号和名称 (先判断前台传值了没) 后边递加1、2、3......
final String ocrPictureOrder = purchaseOcrPicture.getOcrPictureOrder();
// 拼接的示例结果
String productSnExample = purchaseOcrExample.getProductSn();
String productNameExample = purchaseOcrExample.getProductName();
if(StringUtils.isNotEmpty(ocrPictureOrder)){
final String[] strings = ocrPictureOrder.split("-");
final String indexStr = strings[0];
productSnExample += indexStr;
productNameExample += indexStr;
}
final StopWatch stopWatch = new StopWatch("Ai回答计时");
Constants.apiKey = "sk-bcfa4865b89548acb8225f910f13d682";
final CopyOnWriteArrayList<MultiModalConversationResult> multiModalConversationResults = new CopyOnWriteArrayList<>();
@ -76,7 +85,7 @@ public class AliOcrUtil {
final MultiModalMessageItemImage userImage = new MultiModalMessageItemImage(picturePath);
final String firstQuestionMsg = "请把图片中的内容按照商品的不同规格拆分,返回" + count + "条JSON数据。\n" +
" JSON示例:[{ \"productSn\": \"" + purchaseOcrExample.getProductSn() + "\", \"productName\":\"" + purchaseOcrExample.getProductName() + "\", \"price\": \"" + purchaseOcrExample.getPrice() + "\", \"productCount\": \"" + purchaseOcrExample.getProductCount() + "\", \"attributeList\": \"{'color':'" + purchaseOcrExample.getColor() + "','size':'" + purchaseOcrExample.getSize() + "'}\" }]。" +
" JSON示例:[{ \"productSn\": \"" + productSnExample + "\", \"productName\":\"" + productNameExample + "\", \"price\": \"" + purchaseOcrExample.getPrice() + "\", \"productCount\": \"" + purchaseOcrExample.getProductCount() + "\", \"attributeList\": \"{'color':'" + purchaseOcrExample.getColor() + "','size':'" + purchaseOcrExample.getSize() + "'}\" }]。" +
"以下是几点要求: " +
"1.JSON中“productSn”字段可能由字母或数字或特殊符号组成,“color”字段如果图片中没有内容,则赋值“均色”,“size”字段如果图片中没有内容,则赋值“均码”。" +
"2.严格按照JSON示例的格式和字段名返回! " +
@ -85,6 +94,7 @@ public class AliOcrUtil {
"5.如果图中内容没有productSn和productName信息,则使用JSON示例中的值填充。 " +
"6.请注意返回JSON符号解析格式正确 ,确保java程序能够正确解析。" +
"7.严格返回" + count + "条JSON数据,如果数量有偏差按照实际条数返回,不能自动省略!";
log.info("AI提问内容:"+firstQuestionMsg);
MultiModalMessageItemText userText = new MultiModalMessageItemText(firstQuestionMsg);
final MultiModalConversationMessage userMessage =
MultiModalConversationMessage.builder().role(Role.USER.getValue())
@ -118,9 +128,9 @@ public class AliOcrUtil {
String jsonStr = '[' + text.substring(startIndex, endIndex + 1) + ']';
// 有时候返回的是productCounts,改为productCount
jsonStr = fixProductCounts(jsonStr);
JSONArray json = new JSONArray();
JSONArray endJson = new JSONArray();
try{
json = JSON.parseArray(jsonStr);
endJson = JSON.parseArray(jsonStr);
}catch (Exception e){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,我把错误信息输出出来:"+e.getMessage(), e);
// 如果格式化报错,特殊处理下,再次进行转义。
@ -134,7 +144,7 @@ public class AliOcrUtil {
// 如果是attributeList出现问题,那么尝试修复。
jsonStr = fixAttributeList(jsonStr);
try{
json = JSON.parseArray(jsonStr);
endJson = JSON.parseArray(jsonStr);
}catch (Exception replaceOneException){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,attributeList替换了也没好使!");
needAgain = true;
@ -143,13 +153,13 @@ public class AliOcrUtil {
}
// 识别多了个“}”
if(message.contains("not close json text")){
if(message.contains("not close endJson text")){
needAgain = false;
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!");
//
jsonStr = jsonStr.substring(0, jsonStr.length()-1);
try{
json = JSON.parseArray(jsonStr);
endJson = JSON.parseArray(jsonStr);
}catch (Exception replaceOneException){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,没关系,可能是多了“}”,去掉了也没好使!");
needAgain = true;
@ -186,7 +196,7 @@ public class AliOcrUtil {
try{
//
json = JSON.parseArray(errorJsonJsonStr);
endJson = JSON.parseArray(errorJsonJsonStr);
}catch (Exception errorJsonException){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,没关系,我把错误信息输出出来:"+errorJsonException.getMessage(), errorJsonException);
// 如果格式化报错,特殊处理下,再次进行转义。
@ -198,7 +208,7 @@ public class AliOcrUtil {
// 如果是attributeList出现问题,那么尝试修复。
errorJsonJsonStr = fixAttributeList(errorJsonJsonStr);
try{
json = JSON.parseArray(errorJsonJsonStr);
endJson = JSON.parseArray(errorJsonJsonStr);
}catch (Exception errorJsonJsonException){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,attributeList替换了也没好使!");
firstCheckResult = true;
@ -206,13 +216,13 @@ public class AliOcrUtil {
}
// 识别多了个“}”
if(errorJsonExceptionMessage.contains("not close json text")){
if(errorJsonExceptionMessage.contains("not close endJson text")){
firstCheckResult = false;
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!");
//
errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length()-1);
try{
json = JSON.parseArray(errorJsonJsonStr);
endJson = JSON.parseArray(errorJsonJsonStr);
}catch (Exception replaceOneException){
log.error(Thread.currentThread().getName()+"-一轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!");
firstCheckResult = true;
@ -227,7 +237,7 @@ public class AliOcrUtil {
}
}
final int fristResultCount = json.size();
final int fristResultCount = endJson.size();
// 我会在这里对结果进行解析,然后,判断要不要走第二次回话
final int missingCount = count - fristResultCount;
if (missingCount > 0) {
@ -259,7 +269,12 @@ public class AliOcrUtil {
// 有时候返回的是productCounts,改为productCount
secondJsonStr = fixProductCounts(secondJsonStr);
try{
json = JSON.parseArray(secondJsonStr);
final JSONArray secondJson = JSON.parseArray(secondJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception e){
boolean needAgain = true;
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,我把错误信息输出出来:"+e.getMessage(),e);
@ -271,20 +286,32 @@ public class AliOcrUtil {
// 如果是attributeList出现问题,那么尝试修复。
secondJsonStr = fixAttributeList(secondJsonStr);
try{
json = JSON.parseArray(secondJsonStr);
// endJson = JSON.parseArray(secondJsonStr);
final JSONArray secondJson = JSON.parseArray(secondJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception exception){
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,attributeList替换了也没好使!");
needAgain = true;
}
}
// 识别多了个“}”
if(message.contains("not close json text")){
if(message.contains("not close endJson text")){
needAgain = false;
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,没关系,可能是多了“}”,我来去掉试一下一下!");
//
secondJsonStr = secondJsonStr.substring(0, secondJsonStr.length()-1);
try{
json = JSON.parseArray(secondJsonStr);
// endJson = JSON.parseArray(secondJsonStr);
final JSONArray secondJson = JSON.parseArray(secondJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception replaceOneException){
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,可能是多了“}”,去掉了也没好使!");
needAgain = true;
@ -320,7 +347,13 @@ public class AliOcrUtil {
errorJsonJsonStr = fixProductCounts(errorJsonJsonStr);
try{
//
json = JSON.parseArray(errorJsonJsonStr);
// endJson = JSON.parseArray(errorJsonJsonStr);
final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception errorJsonException){
boolean secondCheckResult = true;
final String errorJsonExceptionMessage = errorJsonException.getMessage();
@ -329,21 +362,33 @@ public class AliOcrUtil {
secondCheckResult = false;
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,没关系,,attributeList格式有问题,我来替换一下!");
// 如果是attributeList出现问题,那么尝试修复。
secondJsonStr = fixAttributeList(secondJsonStr);
errorJsonJsonStr = fixAttributeList(errorJsonJsonStr);
try{
json = JSON.parseArray(secondJsonStr);
// endJson = JSON.parseArray(errorJsonJsonStr);
final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception secondCheckException){
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,attributeList替换了也没好使!");
secondCheckResult = true;
}
}
if(errorJsonExceptionMessage.contains("not close json text")){
if(errorJsonExceptionMessage.contains("not close endJson text")){
secondCheckResult = false;
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,重新识别又报错了,没关系,可能是多了“}”,我来去掉试一下一下!");
// 如果是attributeList出现问题,那么尝试修复。
secondJsonStr = secondJsonStr.substring(0, secondJsonStr.length()-1);
errorJsonJsonStr = errorJsonJsonStr.substring(0, errorJsonJsonStr.length()-1);
try{
json = JSON.parseArray(secondJsonStr);
// endJson = JSON.parseArray(errorJsonJsonStr);
final JSONArray secondJson = JSON.parseArray(errorJsonJsonStr);
final int secondResultCount = secondJson.size();
// 20240515 跟第一次的数据对比,哪个数量多,用哪个。
if(secondResultCount > fristResultCount){
endJson = secondJson;
}
}catch (Exception secondCheckException){
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,重新识别又报错了,可能是多了“}”,去掉了也没好使!");
secondCheckResult = true;
@ -351,22 +396,21 @@ public class AliOcrUtil {
}
if(secondCheckResult){
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接毁灭吧!");
throw errorJsonException;
log.error(Thread.currentThread().getName()+"-二轮对话--->json识别报错喽,,重新识别又报错了,不识别了,直接用第一次识别的结果吧!");
}
}
}
}
}
}
log.info(JSON.toJSONString(json));
log.info(JSON.toJSONString(endJson));
stopWatch.start("解析结果==");
// 解析结果
// 入库的时候子图直接存放主图的路径
/*if (StringUtils.isNotEmpty(parentPicturePath)) {
picturePath = parentPicturePath;
}*/
getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, json);
getPurchaseDetailMap(purchaseDetailService, productService, orderId, shopId, picturePath, endJson);
stopWatch.stop();
// 将map 转为list 进行落库操作
/*stopWatch.start("批量插入==");
@ -375,11 +419,11 @@ public class AliOcrUtil {
stopWatch.stop();*/
log.info(stopWatch.prettyPrint());
jsonObject.put("resultContent", json);
jsonObject.put("resultContent", endJson);
jsonObject.put("tokenCount", result.getUsage());
jsonObject.put("requestId", result.getRequestId());
jsonObject.put("cod", 200);
jsonObject.put("ocrCount", json.size());
jsonObject.put("ocrCount", endJson.size());
return jsonObject;
}
@ -636,12 +680,12 @@ public class AliOcrUtil {
productSnMap.put(product.getProductSn(), product);
});
// 根据商品名称获取商品信息
final CopyOnWriteArrayList<Product> productByProductNameList = productService.getProductByProductNameList(productNameList, shopId);
/*final CopyOnWriteArrayList<Product> productByProductNameList = productService.getProductByProductNameList(productNameList, shopId);
final Map<String, Product> productNameMap = new ConcurrentHashMap<>();
// 将商品信息封装到Map 中,商品名称作为key,商品作为value
productByProductNameList.forEach(product -> {
productNameMap.put(product.getProductName(), product);
});
});*/
// 得到数据之后,开始跟该店铺的商品进行对比。
// orderId
final Map<String, PurchaseDetail> purchaseDetailMap = new ConcurrentHashMap<>();
@ -652,13 +696,13 @@ public class AliOcrUtil {
// 根据商品的货号或者
Product product = productSnMap.get(productSn);
// 如果货号存在,就以货号为准查询库存商品能查到就是有,没有查到就是没有,如果有货号,不再根据名称查询
if (product == null && StringUtils.isEmpty(productSn)) {
/*if (product == null && StringUtils.isEmpty(productSn)) {
product = productNameMap.get(productName);
if (product != null) {
// 如果根据名称获取到商品信息,则需要重新赋值货号,保持统一
productSn = product.getProductSn();
}
}
}*/
// 先将规格信息拼接好,后边肯定会插入这个值
final CopyOnWriteArrayList<PurchaseOcrDetailVo> attributeList = purchaseOcrVo.getAttributeList();
final StringBuilder attributeStr = new StringBuilder();

4
hiver-modules/hiver-mall/src/main/resources/mapper/PurchaseOcrPictureMapper.xml

@ -11,7 +11,7 @@
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="order_id" jdbcType="VARCHAR" property="orderId" />
<result column="ocr_picture" jdbcType="VARCHAR" property="ocrPicture" />
<result column="ocr_picture_order" jdbcType="INTEGER" property="ocrPictureOrder" />
<result column="ocr_picture_order" jdbcType="VARCHAR" property="ocrPictureOrder" />
<result column="ocr_status" jdbcType="INTEGER" property="ocrStatus" />
<result column="ocr_msg" jdbcType="VARCHAR" property="ocrMsg" />
<result column="shop_id" jdbcType="VARCHAR" property="shopId" />
@ -94,7 +94,7 @@ ocr_picture_order, ocr_status, ocr_msg, shop_id, shop_name,count,ocr_count,paren
#{purchaseOcrPicture.createByName,jdbcType=VARCHAR},#{purchaseOcrPicture.createTime,jdbcType=TIMESTAMP},
#{purchaseOcrPicture.delFlag,jdbcType=INTEGER},#{purchaseOcrPicture.updateBy,jdbcType=VARCHAR},
#{purchaseOcrPicture.updateTime,jdbcType=TIMESTAMP},#{purchaseOcrPicture.orderId,jdbcType=VARCHAR},
#{purchaseOcrPicture.ocrPicture,jdbcType=VARCHAR},#{purchaseOcrPicture.ocrPictureOrder,jdbcType=INTEGER},
#{purchaseOcrPicture.ocrPicture,jdbcType=VARCHAR},#{purchaseOcrPicture.ocrPictureOrder,jdbcType=VARCHAR},
#{purchaseOcrPicture.ocrStatus,jdbcType=INTEGER},#{purchaseOcrPicture.ocrMsg,jdbcType=VARCHAR},
#{purchaseOcrPicture.shopId,jdbcType=VARCHAR},#{purchaseOcrPicture.shopName,jdbcType=VARCHAR},
#{purchaseOcrPicture.count,jdbcType=INTEGER},#{purchaseOcrPicture.ocrCount,jdbcType=INTEGER},#{purchaseOcrPicture.parentPicturePath,jdbcType=VARCHAR})

Loading…
Cancel
Save