Просмотр исходного кода

客户管理详情ai标签工具类优化
客户管理详情客户画像

lk 1 месяц назад
Родитель
Сommit
8074933520

+ 5 - 2
fs-admin/src/main/java/com/fs/task/CrmCustomerAiProcessingTask.java

@@ -1,5 +1,6 @@
 package com.fs.task;
 
+import com.fs.crm.service.ICrmCustomerAnalyzeService;
 import com.google.common.collect.Lists;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -20,6 +21,7 @@ public class CrmCustomerAiProcessingTask {
     private final RedisTemplate redisTemplate;
 
     private static final String CRM_AI_REDIS_KEY = "crm:AI:data:processing";
+    private final ICrmCustomerAnalyzeService crmCustomerAnalyzeService;
 
     // 自定义线程池
     private final ExecutorService executorService = new ThreadPoolExecutor(
@@ -100,8 +102,9 @@ public class CrmCustomerAiProcessingTask {
                 // 获取数据
                 String customerId = data.get("customerId");
                 String dataJson = data.get("data");
-                //todo 业务!!!!!!1.ai沟通总结2.流失风险等级3.沟通摘要4.客户画像8.客户关注点9.客户意向度
-
+                String logId = data.get("logId");
+                //todo 业务!!!!!!1.ai沟通总结2.流失风险等级3.沟通摘要4.客户画像8.客户关注点9.客户意向度 //都要异步处理
+                crmCustomerAnalyzeService.aiGeneratedCustomerPortrait(customerId,dataJson,logId);
 
 
                 // 模拟业务处理

+ 12 - 7
fs-service/src/main/java/com/fs/crm/mapper/CrmCustomerAnalyzeMapper.java

@@ -3,17 +3,18 @@ package com.fs.crm.mapper;
 import java.util.List;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.fs.crm.domain.CrmCustomerAnalyze;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * 客户聊天记录分析Mapper接口
- * 
+ *
  * @author fs
  * @date 2026-03-24
  */
 public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>{
     /**
      * 查询客户聊天记录分析
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 客户聊天记录分析
      */
@@ -21,7 +22,7 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     /**
      * 查询客户聊天记录分析列表
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 客户聊天记录分析集合
      */
@@ -29,7 +30,7 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     /**
      * 新增客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -37,7 +38,7 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     /**
      * 修改客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -45,7 +46,7 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     /**
      * 删除客户聊天记录分析
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 结果
      */
@@ -53,9 +54,13 @@ public interface CrmCustomerAnalyzeMapper extends BaseMapper<CrmCustomerAnalyze>
 
     /**
      * 批量删除客户聊天记录分析
-     * 
+     *
      * @param ids 需要删除的数据主键集合
      * @return 结果
      */
     int deleteCrmCustomerAnalyzeByIds(Long[] ids);
+
+    CrmCustomerAnalyze selectLatestOne(@Param("customerId") Long customerId);
+
+    int updateCustomerPortrait(@Param("customerId") Long customerId,@Param("customerPortrait") String customerPortrait);
 }

+ 9 - 7
fs-service/src/main/java/com/fs/crm/service/ICrmCustomerAnalyzeService.java

@@ -6,14 +6,14 @@ import com.fs.crm.domain.CrmCustomerAnalyze;
 
 /**
  * 客户聊天记录分析Service接口
- * 
+ *
  * @author fs
  * @date 2026-03-24
  */
 public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>{
     /**
      * 查询客户聊天记录分析
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 客户聊天记录分析
      */
@@ -21,7 +21,7 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
 
     /**
      * 查询客户聊天记录分析列表
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 客户聊天记录分析集合
      */
@@ -29,7 +29,7 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
 
     /**
      * 新增客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -37,7 +37,7 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
 
     /**
      * 修改客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -45,7 +45,7 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
 
     /**
      * 批量删除客户聊天记录分析
-     * 
+     *
      * @param ids 需要删除的客户聊天记录分析主键集合
      * @return 结果
      */
@@ -53,9 +53,11 @@ public interface ICrmCustomerAnalyzeService extends IService<CrmCustomerAnalyze>
 
     /**
      * 删除客户聊天记录分析信息
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 结果
      */
     int deleteCrmCustomerAnalyzeById(Long id);
+
+    void aiGeneratedCustomerPortrait(String customerId, String dataJson,String logId);
 }

+ 125 - 11
fs-service/src/main/java/com/fs/crm/service/impl/CrmCustomerAnalyzeServiceImpl.java

@@ -1,25 +1,45 @@
 package com.fs.crm.service.impl;
 
-import java.util.List;
-import com.fs.common.utils.DateUtils;
+import cn.hutool.core.lang.TypeReference;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import org.springframework.stereotype.Service;
-import com.fs.crm.mapper.CrmCustomerAnalyzeMapper;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fs.common.core.domain.R;
+import com.fs.common.core.domain.entity.SysDictData;
+import com.fs.common.utils.DateUtils;
 import com.fs.crm.domain.CrmCustomerAnalyze;
+import com.fs.crm.mapper.CrmCustomerAnalyzeMapper;
 import com.fs.crm.service.ICrmCustomerAnalyzeService;
+import com.fs.crm.utils.CrmCustomerAiTagUtil;
+import com.fs.system.mapper.SysDictDataMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * 客户聊天记录分析Service业务层处理
- * 
+ *
  * @author fs
  * @date 2026-03-24
  */
 @Service
 public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyzeMapper, CrmCustomerAnalyze> implements ICrmCustomerAnalyzeService {
 
+    @Autowired
+    private SysDictDataMapper sysDictDataMapper;
     /**
      * 查询客户聊天记录分析
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 客户聊天记录分析
      */
@@ -31,7 +51,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 
     /**
      * 查询客户聊天记录分析列表
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 客户聊天记录分析
      */
@@ -43,7 +63,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 
     /**
      * 新增客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -56,7 +76,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 
     /**
      * 修改客户聊天记录分析
-     * 
+     *
      * @param crmCustomerAnalyze 客户聊天记录分析
      * @return 结果
      */
@@ -68,7 +88,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 
     /**
      * 批量删除客户聊天记录分析
-     * 
+     *
      * @param ids 需要删除的客户聊天记录分析主键
      * @return 结果
      */
@@ -80,7 +100,7 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
 
     /**
      * 删除客户聊天记录分析信息
-     * 
+     *
      * @param id 客户聊天记录分析主键
      * @return 结果
      */
@@ -89,4 +109,98 @@ public class CrmCustomerAnalyzeServiceImpl extends ServiceImpl<CrmCustomerAnalyz
     {
         return baseMapper.deleteCrmCustomerAnalyzeById(id);
     }
+    private static final String AI_PORTRAIT = "crm_ai_portrait";
+    private static final ObjectMapper mapper = new ObjectMapper();
+    //ai获取客户画像
+    @Override
+    @Async
+    public void aiGeneratedCustomerPortrait(String customerId, String dataJson,String logId) {
+        Map<String, Object> stringObjectMap = buildRequestParam(Long.valueOf(customerId), dataJson);
+        R aiResponse = CrmCustomerAiTagUtil.callAiService(stringObjectMap, Long.valueOf(logId));
+
+        JSONObject root = JSON.parseObject(JSONUtil.toJsonStr(aiResponse));
+
+// 获取 data.responseData
+        JSONArray responseData = root.getJSONObject("data").getJSONArray("responseData");
+
+        JSONObject userInfo = null;
+
+// 遍历 responseData
+        for (int i = 0; i < responseData.size(); i++) {
+            JSONObject node = responseData.getJSONObject(i);
+            JSONArray historyPreview = node.getJSONArray("historyPreview");
+
+            if (historyPreview != null) {
+                for (int j = 0; j < historyPreview.size(); j++) {
+                    JSONObject historyItem = historyPreview.getJSONObject(j);
+
+                    // 找到 obj 为 "AI" 的项
+                    if ("AI".equals(historyItem.getString("obj"))) {
+                        String valueStr = historyItem.getString("value");
+                        JSONObject valueObj = JSON.parseObject(valueStr);
+                        userInfo = valueObj.getJSONObject("userInfo");
+                        break;
+                    }
+                }
+            }
+            if (userInfo != null) break;
+        }
+
+        if (userInfo != null) {
+            baseMapper.updateCustomerPortrait(Long.valueOf(customerId),userInfo.toString());
+        }
+    }
+    private Map<String, Object> buildRequestParam(Long customerId,
+                                                         String communication) {
+        Map<String, Object> requestParam = new HashMap<>();
+
+        // 获取各类数据
+        HashMap<String, Object> history = new HashMap<>();
+        history.put("history", communication);
+        Map<String, Object> userInfo = getUserInfo(customerId);
+        String likeRatio ="";
+        if (!userInfo.isEmpty()){
+            likeRatio = (String) userInfo.remove("likeRatio");
+        }
+        // 合并数据
+        requestParam.putAll(history);
+        requestParam.putAll(userInfo);
+
+        // 设置其他参数
+        requestParam.put("tagInfos", Collections.emptyList());
+        requestParam.put("isRepository", "");
+        requestParam.put("userContent", "");
+        requestParam.put("aiContent", "");
+        requestParam.put("likeRatio", likeRatio);
+        requestParam.put("modelType","客户画像");
+
+        return requestParam;
+    }
+    private Map<String, Object> getUserInfo(Long customerId) {
+        CrmCustomerAnalyze crmCustomerAnalyze = baseMapper.selectLatestOne(customerId);
+        if (ObjectUtil.isEmpty(crmCustomerAnalyze))throw new RuntimeException("客户信息不存在");
+        HashMap<String, String> userInfo = new HashMap<String, String>();
+//        userInfo.put("name", crmCustomerAnalyze.getCustomerName()==null?"" : crmCustomerAnalyze.getCustomerName());
+        List<SysDictData> portraits = sysDictDataMapper.selectDictDataByType(AI_PORTRAIT);
+        List<String> dictValue = portraits.stream().map(SysDictData::getDictValue).collect(Collectors.toList());
+        Map<String, String> portraitMap = portraits.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
+
+        if (crmCustomerAnalyze.getCustomerPortraitJson() != null){
+            Map<String, String> portraitList = JSON.parseObject(
+                    crmCustomerAnalyze.getCustomerPortraitJson(),
+                    new TypeReference<Map<String, String>>() {}
+            );
+            portraitList.forEach((k, v)->{
+                if(ObjectUtil.isNotEmpty(portraitMap.get(k)))userInfo.put(portraitMap.get(k),v);
+            });
+
+        }else {
+            dictValue.forEach(o->{
+                userInfo.put(o, "");
+            });
+        }
+        HashMap<String, Object> result = new HashMap<>();
+        result.put("userInfo", userInfo);
+        return result;
+    }
 }

+ 8 - 8
fs-service/src/main/java/com/fs/crm/utils/CrmCustomerAiTagUtil.java

@@ -76,17 +76,18 @@ public class CrmCustomerAiTagUtil {
         // 4. 解析响应并保存
         List<CrmCustomerAiTagVo> results = parseAiResponse(aiResponse, customerId);
 
-        // 5. 异步保存到Redis,后续调用ai分析其他数据
-        saveToRedisAsync(customerId, aiResponse);
+        // 5. 异步保存到Redis,后续调用ai分析其他数据 //暂时只传聊天记录
+        saveToRedisAsync(customerId, (String) requestParam.get("history"),logId);
         return results;
     }
-    private static void saveToRedisAsync(Long customerId, R aiResponse) {
+    private static void saveToRedisAsync(Long customerId, String aiResponse, Long logId) {
         // 使用线程池异步保存,避免影响主流程
         CompletableFuture.runAsync(() -> {
             try {
                 Map<String, Object> dataMap = new HashMap<>();
                 dataMap.put("customerId", customerId);
                 dataMap.put("data", aiResponse);
+                dataMap.put("logId", logId);
                 dataMap.put("timestamp", System.currentTimeMillis());
 
                 RedisTemplate<String, Object> redisTemplate = SpringUtils.getBean(RedisTemplate.class);
@@ -121,7 +122,7 @@ public class CrmCustomerAiTagUtil {
                 .map(tag -> buildTagVo(tag, customerId))
                 .collect(Collectors.toList());
     }
-    private static R callAiService(Map<String, Object> requestParam, Long logId) {
+    public static R callAiService(Map<String, Object> requestParam, Long logId) {
         try {
             String requestJson = mapper.writeValueAsString(requestParam);
 
@@ -172,6 +173,7 @@ public class CrmCustomerAiTagUtil {
         requestParam.put("userContent", "");
         requestParam.put("aiContent", "");
         requestParam.put("likeRatio", likeRatio);
+        requestParam.put("modelType","ai标签");
 
         return requestParam;
     }
@@ -342,8 +344,8 @@ public class CrmCustomerAiTagUtil {
             customerMapper.insertCrmCustomerInfo(crmCustomerInfo);
         }
         HashMap<String, String> userInfo = new HashMap<String, String>();
-        userInfo.put("name", crmCustomerInfo.getName());
-        userInfo.put("sex", crmCustomerInfo.getSex());
+        userInfo.put("name", crmCustomerInfo.getName()==null?"" : crmCustomerInfo.getName());
+        userInfo.put("sex", crmCustomerInfo.getSex()==null?"" : crmCustomerInfo.getSex().toString());
         userInfo.put("age", "");
         userInfo.put("city", "");
         userInfo.put("habits", "");
@@ -369,8 +371,6 @@ public class CrmCustomerAiTagUtil {
         result.put("history", history);
         ArrayList<Map> maps = new ArrayList<>();
         //存入crm_customer_info
-        HashMap<String, Object> time = new HashMap<>();
-        maps.add(time);
         communication.forEach(o->{
             String role = (String) o.get("role");
             String content = (String) o.get("content");

+ 19 - 6
fs-service/src/main/resources/mapper/crm/CrmCustomerAnalyzeMapper.xml

@@ -3,7 +3,7 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.fs.crm.mapper.CrmCustomerAnalyzeMapper">
-    
+
     <resultMap type="CrmCustomerAnalyze" id="CrmCustomerAnalyzeResult">
         <result property="id"    column="id"    />
         <result property="customerId"    column="customer_id"    />
@@ -28,7 +28,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectCrmCustomerAnalyzeList" parameterType="CrmCustomerAnalyze" resultMap="CrmCustomerAnalyzeResult">
         <include refid="selectCrmCustomerAnalyzeVo"/>
-        <where>  
+        <where>
             <if test="customerId != null "> and customer_id = #{customerId}</if>
             <if test="customerName != null  and customerName != ''"> and customer_name like concat('%', #{customerName}, '%')</if>
             <if test="customerPortraitJson != null  and customerPortraitJson != ''"> and customer_portrait_json = #{customerPortraitJson}</if>
@@ -43,12 +43,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="reserveStr != null  and reserveStr != ''"> and reserve_str = #{reserveStr}</if>
         </where>
     </select>
-    
+
     <select id="selectCrmCustomerAnalyzeById" parameterType="Long" resultMap="CrmCustomerAnalyzeResult">
         <include refid="selectCrmCustomerAnalyzeVo"/>
         where id = #{id}
     </select>
-        
+    <select id="selectLatestOne" resultType="com.fs.crm.domain.CrmCustomerAnalyze">
+        <include refid="selectCrmCustomerAnalyzeVo"/>
+        where
+        customer_id = #{customerId}
+        order by create_time desc limit 1
+    </select>
+
     <insert id="insertCrmCustomerAnalyze" parameterType="CrmCustomerAnalyze" useGeneratedKeys="true" keyProperty="id">
         insert into crm_customer_analyze
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -105,15 +111,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         </trim>
         where id = #{id}
     </update>
+    <update id="updateCustomerPortrait">
+        update crm_customer_analyze
+        set customer_portrait_json = #{customerPortrait}
+        where customer_id = #{customerId}
+        ORDER BY create_time DESC
+        LIMIT 1
+    </update>
 
     <delete id="deleteCrmCustomerAnalyzeById" parameterType="Long">
         delete from crm_customer_analyze where id = #{id}
     </delete>
 
     <delete id="deleteCrmCustomerAnalyzeByIds" parameterType="String">
-        delete from crm_customer_analyze where id in 
+        delete from crm_customer_analyze where id in
         <foreach item="id" collection="array" open="(" separator="," close=")">
             #{id}
         </foreach>
     </delete>
-</mapper>
+</mapper>