Commit 0482e98e authored by 单欣鑫's avatar 单欣鑫

feat(chat): 集成千帆AI大模型并优化对话功能

- 集成百度千帆AI大模型,替换原有文心一言接口
- 实现新的消息格式构建,支持历史消息上下文传递
- 更新API认证方式,使用新的访问令牌和模型配置
- 优化响应解析逻辑,适配新API返回的数据结构
- 添加详细的日志记录,便于调试和监控
- 修复Redis缓存中的空值检查问题
- 统一API返回格式,确保前后端数据一致性
- 优化代码结构,提升可维护性和扩展性
parent a2f158f6
......@@ -58,10 +58,10 @@ public class MallMemberUserController extends BaseController
// if (school != null && loginUser.getUserId() != 1) {
// mallMemberUser.setSchoolId(school.getSchoolId());
// }
System.out.println(loginUser.getUserId());
MallMemberUser sysUserId = mallMemberUserService.selectMallMemberUserBySysUserId(loginUser.getUserId());
if (sysUserId != null && loginUser.getUserId() != 1) {
mallMemberUser.setIndexUserId(sysUserId.getId());
mallMemberUser.setFindId(sysUserId.getId());
}
startPage();
......
......@@ -65,6 +65,7 @@ public class ApiChatController {
private final String CHAT_URI = "https://aip.baidubce.com/rpc/2.0/ai_custom/v2/wenxinworkshop/chat/completions";
private String apiKey = "hco0U4TGdVpA73F5mGBZliai";
// private String apiKey = "bce-v3/ALTAK-e4lAevfWLzhTYIIXIlSmj/27d290cd6a83173d0221ce37240e92fb9a95a6ea";
private String secretKey = "kBwPxP7PxRy5fTtIalW81GN7A3LFBrEN";
......@@ -113,7 +114,7 @@ public class ApiChatController {
*/
private String getQianFanAccessToken() {
String qianFanAccessToken = new String();
if(null == redisTemplate.boundValueOps("qianFanAccessToken").get()){
if(StringUtils.isBlank((String) redisTemplate.boundValueOps("qianFanAccessToken").get())){
MediaType mediaType = MediaType.parse("application/json");
// MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "");
......@@ -497,15 +498,6 @@ public class ApiChatController {
saveMessage.setVoiceUrl(params.get("voiceUrl").toString());
}
com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
jsonObject.put("query", question);
List<String> plugins = new ArrayList<>();
plugins.add("uuid-zhishiku");
//plugins.add("uuid-weatherforecast");
//jsonObject.put("plugins", plugins);
//jsonObject.put("verbose", false);
// 创建存储类
SaveChatRequestMessage saveChatRequestMessage = new SaveChatRequestMessage();
ArrayList<Message> historyList = new ArrayList<>();
......@@ -530,8 +522,30 @@ public class ApiChatController {
}
}
//将新的问题添加到消息上下文
//jsonObject.put("history", historyList);
// 构建请求参数,包含历史消息和当前问题
com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
List<Map<String, Object>> maps = new ArrayList<>();
// 添加历史消息到请求中
if (!historyList.isEmpty()) {
for (Message historyMsg : historyList) {
Map<String, Object> historyMap = new HashMap<>();
historyMap.put("role", historyMsg.getRole());
historyMap.put("content", historyMsg.getContent());
maps.add(historyMap);
}
}
// 添加当前用户问题
Map<String, Object> map = new HashMap<String, Object>();
map.put("role","user");
map.put("content",question);
maps.add(map);
jsonObject.put("messages", maps);
jsonObject.put("model","deepseek-v3.1-250821");
// 新信息添加保存
saveChatRequestMessage.addSaveMessage(saveMessage);
......@@ -539,60 +553,67 @@ public class ApiChatController {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, jsonStr);
Request request = new Request.Builder()
// .url("https://aip.baidubce.com/rpc/2.0/ai_custom/v2/wenxinworkshop/plugin/jfa2nhi1zap61qy7?access_token="+getQianFanAccessToken())
.url("https://qianfan.baidubce.com/v2/chat/completions")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "Bearer " + getQianFanAccessToken())
// .addHeader("Authorization", "Bearer " + getQianFanAccessToken())
.addHeader("Authorization", "Bearer bce-v3/ALTAK-e4lAevfWLzhTYIIXIlSmj/27d290cd6a83173d0221ce37240e92fb9a95a6ea")
.build();
try{
logger.info("千帆AccessToken:{}",getQianFanAccessToken());
logger.info("千帆AccessToken:bce-v3/ALTAK-e4lAevfWLzhTYIIXIlSmj/27d290cd6a83173d0221ce37240e92fb9a95a6ea");
logger.info("请求参数:{}",jsonStr);
Response response = client.newCall(request).execute();
String responseJsonStr = response.body().string();
logger.info("返回的响应结果为:{}",responseJsonStr);
// 解析新API格式的响应:从choices[0].message.content获取内容
com.alibaba.fastjson.JSONObject data = com.alibaba.fastjson.JSONObject.parseObject(responseJsonStr);
com.alibaba.fastjson.JSONArray choices = data.getJSONArray("choices");
if (choices != null && choices.size() > 0) {
com.alibaba.fastjson.JSONObject choice = choices.getJSONObject(0);
com.alibaba.fastjson.JSONObject messageObj = choice.getJSONObject("message");
String result = messageObj.getString("content");
if (StringUtils.isNotBlank(result)){
// 保留换行符,只去除多余的连续换行
String answer = result.replaceAll("\n", "");
logger.info("AI回复内容:{}",answer);
Message assistant = new Message("assistant", answer);
// 存储信息
SaveMessage saveAnswer = BeanUtil.copyProperties(assistant, SaveMessage.class);
saveAnswer.setHasVoice(hasVoice);
saveChatRequestMessage.addSaveMessage(saveAnswer);
//redis 存储
if(redisTemplate.hasKey("ChatWith" + memberUser.getId())){
Long expire = redisTemplate.getExpire("ChatWith" + memberUser.getId());
redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).set(JSONUtil.toJsonStr(saveChatRequestMessage), 30, TimeUnit.DAYS);
}else{
redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).set(JSONUtil.toJsonStr(saveChatRequestMessage), 30, TimeUnit.DAYS);
}
logger.info("存入redis:" +redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).get().toString());
List<SaveMessage> newChat = new ArrayList<>();
newChat.add(saveMessage);
newChat.add(saveAnswer);
com.alibaba.fastjson.JSONObject data = JSONUtil.toBean(responseJsonStr, com.alibaba.fastjson.JSONObject.class);
System.out.println("返回的响应结果为:"+responseJsonStr);
System.out.println("data:"+data);
System.out.println("result:"+data.getString("result"));
System.out.println("response:"+response);
String result = data.getString("result");
if (StringUtils.isNotBlank(result)){
String answer = result.replaceAll("\n", "");
//int i = answer.indexOf("\n");
Message assistant = new Message("assistant", answer);
//if (i> 0){
// assistant.setContent(answer.substring(0,i));
//}
// 存储信息
SaveMessage saveAnswer = BeanUtil.copyProperties(assistant, SaveMessage.class);
saveAnswer.setHasVoice(hasVoice);
saveChatRequestMessage.addSaveMessage(saveAnswer);
//redis 存储
if(redisTemplate.hasKey("ChatWith" + memberUser.getId())){
Long expire = redisTemplate.getExpire("ChatWith" + memberUser.getId());
redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).set(JSONUtil.toJsonStr(saveChatRequestMessage), 30, TimeUnit.DAYS);
return AjaxResult.success(newChat);
}else{
redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).set(JSONUtil.toJsonStr(saveChatRequestMessage), 30, TimeUnit.DAYS);
logger.error("对话返回结果内容为空");
return AjaxResult.error("对话失败:返回内容为空!");
}
logger.info("存入redis:" +redisTemplate.boundValueOps("ChatWith" + memberUser.getId()).get().toString());
List<SaveMessage> newChat = new ArrayList<>();
newChat.add(saveMessage);
newChat.add(saveAnswer);
return AjaxResult.success(newChat);
}else{
logger.error("对话返回结果为空");
return AjaxResult.error("对话失败!");
logger.error("对话返回choices为空");
return AjaxResult.error("对话失败:返回格式异常!");
}
}catch (Exception e){
logger.error("调用千帆API异常", e);
e.printStackTrace();
return AjaxResult.error("对话失败!");
return AjaxResult.error("对话失败:" + e.getMessage());
}
}
......
......@@ -99,14 +99,16 @@ public class ApiMemberController {
// String nickName = userInfoJson.getString("nickName");
// String avatarUrl = userInfoJson.getString("avatarUrl");
String nickName = map.get("nickName").toString();
String avatarUrl = map.get("avatarUrl").toString();
// String nickName = map.get("nickName").toString();
// String avatarUrl = map.get("avatarUrl").toString();
String avatarUrl = "https://image.xnszz.com/IMG_64_64@Fj0Nw2316X8QtYj9phrPwA4IJYHi.png";
if (memberUserDO == null) {
//2、对encryptedData加密数据进行AES解密
MallMemberUser memberUser = new MallMemberUser();
memberUser.setName(nickName);
memberUser.setName("艺智果" + IdUtils.buildNumberCode(6));
memberUser.setOpenid(openid);
memberUser.setAvatar(avatarUrl);
memberUser.setCreateNum(5);
......@@ -149,7 +151,7 @@ public class ApiMemberController {
}
}
return ApiResult.ok().put("data", memberUser);
return ApiResult.ok().put("data", memberUser).put("code",200);
}
}else{
// 绑定上级
......@@ -164,7 +166,7 @@ public class ApiMemberController {
}
}
}
return ApiResult.ok("登陆成功").put("data", memberUserDO);
return ApiResult.ok("登陆成功").put("data", memberUserDO).put("code",200);
} catch (Exception e) {
e.printStackTrace();
return ApiResult.error("授权失败");
......
......@@ -134,7 +134,7 @@ wx:
# 小程序码跳转页面
wxPath: pages/index/index?parentId=
# 小程序码跳转页面
schoolPath: pages/schoolDeail/schoolDetail?schoolId=
schoolPath: pages/index/index?schoolId=
# 七牛云
qiNiu:
......
......@@ -235,6 +235,8 @@ public class MallMemberUser extends BaseEntity
/** 小程序邀请价 */
private BigDecimal indexPrice;
private Long findId;
public BigDecimal getIndexPrice() {
return indexPrice;
}
......@@ -790,45 +792,83 @@ public class MallMemberUser extends BaseEntity
this.developDirection = developDirection;
}
public Long getFindId() {
return findId;
}
public void setFindId(Long findId) {
this.findId = findId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("avatar", getAvatar())
.append("name", getName())
.append("phone", getPhone())
.append("openid", getOpenid())
.append("wechat", getWechat())
.append("sex", getSex())
.append("password", getPassword())
.append("token", getToken())
.append("status", getStatus())
.append("introUser", getIntroUser())
.append("invitationCode", getInvitationCode())
.append("money", getMoney())
.append("allMoney", getAllMoney())
.append("qrCode", getQrCode())
.append("userLevel", getUserLevel())
.append("provinceId", getProvinceId())
.append("cityId", getCityId())
.append("areaId", getAreaId())
.append("provinceName", getProvinceName())
.append("cityName", getCityName())
.append("areaName", getAreaName())
.append("address", getAddress())
.append("subjectId", getSubjectId())
.append("subjectName", getSubjectName())
.append("isOpen", getIsOpen())
.append("openTypeId", getOpenTypeId())
.append("openTypeName", getOpenTypeName())
.append("openAt", getOpenAt())
.append("expireAt", getExpireAt())
.append("createAt", getCreateAt())
.append("updateAt", getUpdateAt())
.append("loginAt", getLoginAt())
.append("delFlag", getDelFlag())
.append("developDirection", getDevelopDirection())
.append("createNum", getCreateNum())
.toString();
return "MallMemberUser{" +
"id=" + id +
", avatar='" + avatar + '\'' +
", name='" + name + '\'' +
", phone='" + phone + '\'' +
", openid='" + openid + '\'' +
", wechat='" + wechat + '\'' +
", sex='" + sex + '\'' +
", password='" + password + '\'' +
", token='" + token + '\'' +
", status='" + status + '\'' +
", introUser=" + introUser +
", introUserName='" + introUserName + '\'' +
", childrenNum=" + childrenNum +
", invitationCode='" + invitationCode + '\'' +
", parentCode='" + parentCode + '\'' +
", money=" + money +
", allMoney=" + allMoney +
", qrCode='" + qrCode + '\'' +
", userLevel=" + userLevel +
", provinceId=" + provinceId +
", cityId=" + cityId +
", areaId=" + areaId +
", provinceName='" + provinceName + '\'' +
", cityName='" + cityName + '\'' +
", areaName='" + areaName + '\'' +
", address='" + address + '\'' +
", subjectId=" + subjectId +
", subjectName='" + subjectName + '\'' +
", isOpen='" + isOpen + '\'' +
", openTypeId=" + openTypeId +
", openTypeName='" + openTypeName + '\'' +
", openAt='" + openAt + '\'' +
", expireAt='" + expireAt + '\'' +
", createAt='" + createAt + '\'' +
", updateAt='" + updateAt + '\'' +
", loginAt='" + loginAt + '\'' +
", delFlag='" + delFlag + '\'' +
", developDirection='" + developDirection + '\'' +
", subjectType='" + subjectType + '\'' +
", grade='" + grade + '\'' +
", majorSchool='" + majorSchool + '\'' +
", cultureSchool='" + cultureSchool + '\'' +
", cultureScore=" + cultureScore +
", majorScore=" + majorScore +
", languageType=" + languageType +
", languageScore=" + languageScore +
", scoreModify='" + scoreModify + '\'' +
", createNum=" + createNum +
", sharePerson=" + sharePerson +
", useCode=" + useCode +
", codeId=" + codeId +
", vipCode='" + vipCode + '\'' +
", rateFlag=" + rateFlag +
", schoolId=" + schoolId +
", indexCode='" + indexCode + '\'' +
", indexName='" + indexName + '\'' +
", indexLogo='" + indexLogo + '\'' +
", indexUserId=" + indexUserId +
", sysUserId=" + sysUserId +
", sysUserName='" + sysUserName + '\'' +
", sysUserPassword='" + sysUserPassword + '\'' +
", sysUserStatus=" + sysUserStatus +
", isSysUser=" + isSysUser +
", schoolName='" + schoolName + '\'' +
", indexPrice=" + indexPrice +
", findId=" + findId +
'}';
}
}
......@@ -29,7 +29,7 @@ public interface MallMemberUserMapper
* 查询用户会员列表
*
* @param mallMemberUser 用户会员
* @return 用户会员集合
* @return 用户会员集合
*/
public List<MallMemberUser> selectMallMemberUserList(MallMemberUser mallMemberUser);
......
......@@ -633,6 +633,8 @@ public class MallCountMethodServiceImpl implements IMallCountMethodService
// 个人综合分
BigDecimal totalScore = this.getTotalScore(cultureScore, majorScore, acceptRuleId);
reference = Optional.ofNullable(reference).orElse(BigDecimal.ZERO);
acceptRate = totalScore.subtract(reference).add(new BigDecimal("80"));
if (acceptRate.compareTo(BigDecimal.valueOf(99)) >= 0){
......
......@@ -132,62 +132,62 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="selectMallMemberUserList" parameterType="MallMemberUser" resultType="MallMemberUser">
select tmu.id id,
tmu.school_id schoolId,
tmu.index_code indexCode,
tmu.index_name indexName,
tmu.index_logo indexLogo,
tmu.index_user_id indexUserId,
tmu.sys_user_id sysUserId,
tmu.sys_user_name sysUserName,
tmu.sys_user_password sysUserPassword,
tmu.sys_user_status sysUserStatus,
tmu.index_price indexPrice,
tmu.avatar avatar,
tmu.name name,
tmu.phone phone,
tmu.openid openid,
tmu.wechat wechat,
tmu.sex sex,
tmu.password password,
tmu.token token,
tmu.status status,
tmu.intro_user introUser,
tmu.invitation_code invitationCode,
tmu.money money,
tmu.all_money allMoney,
tmu.qr_code qrCode,
tmu.user_level userLevel,
tmu.province_id provinceId,
tmu.city_id cityId,
tmu.area_id areaId,
tmu.province_name provinceName,
tmu.city_name cityName,
tmu.area_name areaName,
tmu.address address,
tmu.subject_id subjectId,
tmu.subject_name subjectName,
tmu.is_open isOpen,
tmu.open_type_id openTypeId,
tmu.open_type_name openTypeName,
tmu.open_at openAt,
tmu.expire_at expireAt,
tmu.create_at createAt,
tmu.update_at updateAt,
tmu.login_at loginAt,
tmu.del_flag delFlag,
tmu.develop_direction developDirection,
tmu.subject_type subjectType,
tmu.grade grade,
tmu.major_school majorSchool,
tmu.culture_school cultureSchool,
tmu.culture_score cultureScore,
tmu.major_score majorScore,
tmu.language_type languageType,
tmu.language_score languageScore,
tmu.score_modify scoreModify,
tmu.create_num createNum,
tmu.share_person sharePerson,
pmu.name introUserName
tmu.school_id schoolId,
tmu.index_code indexCode,
tmu.index_name indexName,
tmu.index_logo indexLogo,
tmu.index_user_id indexUserId,
tmu.sys_user_id sysUserId,
tmu.sys_user_name sysUserName,
tmu.sys_user_password sysUserPassword,
tmu.sys_user_status sysUserStatus,
tmu.index_price indexPrice,
tmu.avatar avatar,
tmu.name name,
tmu.phone phone,
tmu.openid openid,
tmu.wechat wechat,
tmu.sex sex,
tmu.password password,
tmu.token token,
tmu.status status,
tmu.intro_user introUser,
tmu.invitation_code invitationCode,
tmu.money money,
tmu.all_money allMoney,
tmu.qr_code qrCode,
tmu.user_level userLevel,
tmu.province_id provinceId,
tmu.city_id cityId,
tmu.area_id areaId,
tmu.province_name provinceName,
tmu.city_name cityName,
tmu.area_name areaName,
tmu.address address,
tmu.subject_id subjectId,
tmu.subject_name subjectName,
tmu.is_open isOpen,
tmu.open_type_id openTypeId,
tmu.open_type_name openTypeName,
tmu.open_at openAt,
tmu.expire_at expireAt,
tmu.create_at createAt,
tmu.update_at updateAt,
tmu.login_at loginAt,
tmu.del_flag delFlag,
tmu.develop_direction developDirection,
tmu.subject_type subjectType,
tmu.grade grade,
tmu.major_school majorSchool,
tmu.culture_school cultureSchool,
tmu.culture_score cultureScore,
tmu.major_score majorScore,
tmu.language_type languageType,
tmu.language_score languageScore,
tmu.score_modify scoreModify,
tmu.create_num createNum,
tmu.share_person sharePerson,
pmu.name introUserName
from mall_member_user tmu
left join mall_member_user pmu on pmu.id = tmu.intro_user
<where>
......@@ -226,16 +226,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
<if test="params.endCreateAt != null and params.endCreateAt != ''"><!-- 结束时间检索 -->
and date_format(tmu.create_at,'%y%m%d') &lt;= date_format(#{params.endCreateAt},'%y%m%d')
</if> <if test="updateAt != null and updateAt != ''"> and tmu.update_at = #{updateAt}</if>
</if>
<if test="updateAt != null and updateAt != ''"> and tmu.update_at = #{updateAt}</if>
<if test="loginAt != null and loginAt != ''"> and tmu.login_at = #{loginAt}</if>
<if test="developDirection != null and developDirection != ''"> and tmu.develop_direction = #{developDirection}</if>
<if test="createNum != null "> and tmu.create_num = #{createNum}</if>
<if test="sharePerson != null "> and tmu.share_person = #{sharePerson}</if>
<if test="schoolId != null "> and tmu.school_id = #{schoolId}</if>
<if test="indexUserId != null "> and tmu.index_user_id = #{indexUserId}</if>
<if test="isSysUser != null and isSysUser != '' and isSysUser == 0 "> and tmu.sys_user_id = 0}</if>
<!-- 修正:移除多余的 } 符号 -->
<if test="isSysUser != null and isSysUser != '' and isSysUser == 0 "> and tmu.sys_user_id = 0</if>
<if test="isSysUser != null and isSysUser != '' and isSysUser == 1 "> and tmu.sys_user_id != 0</if>
<if test="sysUserName != null and sysUserName != ''"> and tmu.sys_user_name like concat('%', #{sysUserName}, '%')</if>
<!-- 核心修正:1. 移除多余的 and;2. 增加参数非空校验,避免生成 = null -->
<if test="findId != null">
and (tmu.intro_user = #{findId} or tmu.index_user_id = #{findId})
</if>
and tmu.del_flag = '0'
</where>
order by tmu.create_at desc
......
......@@ -185,9 +185,9 @@
<el-table-column label="到期时间" align="center" prop="expireAt" />
<el-table-column label="注册时间" align="center" prop="createAt" />
<el-table-column label="小程序首页名" align="center" prop="indexName" />
<el-table-column label="小程序二维码" align="center" prop="indexCode" width="100">
<el-table-column label="小程序二维码" align="center" prop="qrCode" width="100">
<template slot-scope="scope">
<image-preview :src="scope.row.indexCode" :width="50" :height="50"/>
<image-preview :src="scope.row.qrCode" :width="50" :height="50"/>
</template>
</el-table-column>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment