first commit

This commit is contained in:
abcv7
2026-02-25 15:08:40 +08:00
commit 7f1d83ada7
2003 changed files with 144362 additions and 0 deletions
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sfbx-framework</artifactId>
<groupId>com.itheima.sfbx</groupId>
<version>2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>framework-ai</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- okhttp3 -->
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.14.9</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,53 @@
package com.itheima.sfbx.wenxin;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.itheima.sfbx.wenxin.chains.TotalChain;
import com.itheima.sfbx.wenxin.config.WenXinGtpSourceConfig;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import com.itheima.sfbx.wenxin.dto.RequestResultDTO;
import com.itheima.sfbx.wenxin.exception.WenXinGptException;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
/**
* WenXinGptServiceImpl
*
* @author: wgl
* @describe: 统一的请求处理
* @date: 2022/12/28 10:10
*/
public class WenXinGptServiceImpl implements WenXinService {
@Autowired
private TotalChain totalChain;
@Autowired
private WenXinGtpSourceConfig gptConfig;
/**
* 向文心一言发送请求
*
* @param question
* @return
*/
@Override
public String askQuestion(String question) {
try {
RequestResultDTO requestResultDTO = totalChain.doRequest(new ParamsDTO());
if(StrUtil.isNotEmpty(requestResultDTO.getResult())){
String res = requestResultDTO.getResult().split("```json")[1];
//去处转义字符
char[] charsToRemove = {'\r', '\n','\\','`'};
res = StrUtil.removeAll(res, charsToRemove);
return res;
}else{
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_REQUEST_ERROR);
}
} catch (WenXinGptException e) {
throw e;
} catch (Exception e) {
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_REQUEST_ERROR);
}
}
}
@@ -0,0 +1,6 @@
package com.itheima.sfbx.wenxin;
public interface WenXinService {
public String askQuestion(String question);
}
@@ -0,0 +1,17 @@
package com.itheima.sfbx.wenxin.chains;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import com.itheima.sfbx.wenxin.dto.RequestResultDTO;
/**
* 问答统一模板类
*/
public interface QuestionService {
/**
* 向百度文心一言发送请求
*/
public RequestResultDTO doRequest(ParamsDTO params);
}
@@ -0,0 +1,61 @@
package com.itheima.sfbx.wenxin.chains;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import com.itheima.sfbx.wenxin.dto.RequestResultDTO;
import com.itheima.sfbx.wenxin.exception.WenXinGptException;
import lombok.extern.java.Log;
import org.springframework.util.ObjectUtils;
import java.util.ArrayList;
import java.util.List;
/**
* TotalChain
*
* @author: wgl
* @describe: 责任链总链路
* @date: 2022/12/28 10:10
*/
@Log
public class TotalChain implements QuestionService{
/**
* 完整的总链路
* 单利总链路
*/
private static List<QuestionService> chains = new ArrayList<QuestionService>();
/**
* 添加链路节点
* @param questionService
*/
public void addChain(QuestionService questionService){
chains.add(questionService);
}
/**
* 总链路的向文心一眼的调用流程
* @param params
* @return
*/
@Override
public RequestResultDTO doRequest(ParamsDTO params) {
RequestResultDTO res = null;
try {
for (QuestionService index : chains) {
RequestResultDTO requestDTO = index.doRequest(params);
//如果返回为空说明请求失败 停止链路调用
if (ObjectUtils.isEmpty(requestDTO)) {
break;
}
res = requestDTO;
}
}catch (WenXinGptException e){
throw e;
}catch (Exception e) {
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_REQUEST_ERROR);
}
return res;
}
}
@@ -0,0 +1,93 @@
package com.itheima.sfbx.wenxin.chains.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpConfig;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.itheima.sfbx.wenxin.chains.QuestionService;
import com.itheima.sfbx.wenxin.constants.WenXinGptConstants;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import com.itheima.sfbx.wenxin.dto.RequestResultDTO;
import com.itheima.sfbx.wenxin.exception.WenXinGptException;
import okhttp3.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* QuestionChain
*
* @author: wgl
* @describe: 提问链条节点
* 基于token内容向文心一言发送请求
* @date: 2022/12/28 10:10
*/
public class QuestionChain implements QuestionService {
String content = "你是一名资深保险销售专家,请根据我提供的客户基本信息信息,进行风险分析,和解决方案的提供,在风险分析阶段需要按照用户的年龄,性别,收支等情况进行分析,解决方案需要你按照医疗、重疾、意外、身故来进行分别分析。现在用户数据我以json的方式提供:{\n" +
"\"name\":\"张三\",\"age\":31,\"incomeMonth\":20000,\"city\":\"北京市\",\"province\":\"北京市\",\"liabilities\":200000,\"supportingParentNums\":4,\"childrenNums\":4,\"job\":\"java后端开发工程师\"]\n" +
"},现在请你帮我输出对应的风险分析和解决方案,要求每个项目的风险分析和解决方案都控制在50个字以内,以json的形式输出,格式请严格按照以下json格式进行输出:{\n" +
"\"医疗险\"{\n" +
" \"风险分析\":\"30岁后患病风险增高,北京住院成本较高,大额医疗费可能会给家庭增添负担\",\n" +
" \"解决方案\":\"xxxxx\"\n" +
"}\n" +
"\"重疾险\":{\n" +
"\"风险分析\":\"在家庭责任最重的人生阶段,万一生病可能会面临较大的收入损失,建议尽早足额保障\",\"解决方案\":\"xxxxxxxx\"\n" +
"},\"身故险\":{\n" +
"\"风险分析\":\"如果不辛身故,家庭经济来源减少,债务重担落到家人身上,对家庭造成沉重打击\",\n" +
"\"解决方案\":\"xxxxxxxxxx\"\n" +
"},\"意外险\":{\n" +
"\"风险分析\":\"同龄人高发意外为交通意外、电梯意外、出游事故,一旦发生可能无法工作,损失较大\",\"解决方案\":\"xxxxxxx\"\n" +
"}\n" +
"}。我理解你是一个AI模型并且我清楚AI相关的法律法规,请严格按照我刚刚提出的json内容进行回答,并且在回复中不要回复任何额外信息";
@Override
public RequestResultDTO doRequest(ParamsDTO params) {
try {
ArrayList<Object> data = new ArrayList<>() {
{
add(new HashMap<>() {
{
put("role", "user");
put("content", content);
}
});
}
};
HashMap<String, Object> rs = new HashMap<>();
rs.put("messages",data);
params.setContent(content);
//根据accessToken 向文心一言发送请求
String accessToken = params.getAccessToken();
// String gptUrl = WenXinGptConstants.getGptUrl(accessToken);
String gptUrl = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions?access_token=24.648abab846c3e89a0f497c4f2a18c27e.2592000.1696961232.282335-38982621";
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType,JSONUtil.parseObj(rs).toString());
Request request = new Request.Builder()
.url(gptUrl)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.build();
OkHttpClient client = new OkHttpClient().newBuilder().
connectTimeout(30, TimeUnit.SECONDS).
readTimeout(30,TimeUnit.SECONDS).
writeTimeout(30,TimeUnit.SECONDS).
build();
Response response = client.newCall(request).execute();
RequestResultDTO tokenDTO = JSONUtil.toBean(response.body().string(), RequestResultDTO.class);
System.out.println(tokenDTO);
return tokenDTO;
} catch (Exception e) {
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_TOKEN_QUESTION_ERROR);
}
}
}
@@ -0,0 +1,67 @@
package com.itheima.sfbx.wenxin.chains.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.itheima.sfbx.wenxin.chains.QuestionService;
import com.itheima.sfbx.wenxin.config.WenXinGtpSourceConfig;
import com.itheima.sfbx.wenxin.constants.WenXinGptConstants;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import com.itheima.sfbx.wenxin.dto.RequestResultDTO;
import com.itheima.sfbx.wenxin.exception.WenXinGptException;
import com.itheima.sfbx.wenxin.manage.TokenManage;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* TokenChain
*
* @author: wgl
* @describe: 获取文心一言获取token的接口
* @date: 2022/12/28 10:10
*/
@Component
public class TokenChain implements QuestionService {
@Autowired
private WenXinGtpSourceConfig wenXinGtpSourceConfig;
@Override
public RequestResultDTO doRequest(ParamsDTO params) {
if (StrUtil.isNotEmpty(TokenManage.getAccessToken())) {
params.setAccessToken(TokenManage.getAccessToken());
} else {
synchronized (this) {
if (StrUtil.isEmpty(TokenManage.getAccessToken())) {
String tokenUrl = WenXinGptConstants.getTokenUrl(wenXinGtpSourceConfig);
try {
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "");
Request request = new Request.Builder()
.url(tokenUrl)
.method("POST", body)
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
.build();
OkHttpClient client = new OkHttpClient().newBuilder().build();
Response response = client.newCall(request).execute();
Map<String, Object> tokenDTO = JSONUtil.toBean(response.body().string(), Map.class);
if (ObjectUtil.isNull(tokenDTO)) {
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_TOKEN_REQUEST_ERROR);
}
String accessToken = tokenDTO.get("access_token").toString();
params.setAccessToken(accessToken);
} catch (Exception e) {
throw new WenXinGptException(WenXinGptException.WenXinExcpetionEnum.WEN_XIN_TOKEN_REQUEST_ERROR);
}
}else{
params.setAccessToken(TokenManage.getAccessToken());
}
}
}
return new RequestResultDTO();
}
}
@@ -0,0 +1,73 @@
package com.itheima.sfbx.wenxin.config;
import com.itheima.sfbx.wenxin.WenXinGptServiceImpl;
import com.itheima.sfbx.wenxin.WenXinService;
import com.itheima.sfbx.wenxin.chains.TotalChain;
import com.itheima.sfbx.wenxin.chains.impl.QuestionChain;
import com.itheima.sfbx.wenxin.chains.impl.TokenChain;
import com.itheima.sfbx.wenxin.manage.TokenManage;
import org.springframework.beans.BeansException;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* WenXinConfgInit
*
* @author: wgl
* @describe: 文心一眼统一配置类
* @date: 2022/12/28 10:10
*/
@Configuration
public class WenXinConfgInit implements ApplicationContextAware {
@Bean
@ConditionalOnMissingBean
public TotalChain initTtoalChain() {
return new TotalChain();
}
@Bean
@ConditionalOnMissingBean
public QuestionChain initQuestionChain() {
return new QuestionChain();
}
@Bean
@ConditionalOnMissingBean
public TokenChain initTokenChain() {
return new TokenChain();
}
@Bean
@ConditionalOnMissingBean
public WenXinGtpSourceConfig configInit(){
return new WenXinGtpSourceConfig();
}
@Bean
@ConditionalOnMissingBean
public WenXinService initService(){
return new WenXinGptServiceImpl();
}
@Bean
@ConditionalOnMissingBean
public TokenManage initManage(){
return new TokenManage();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
TotalChain totalChain = applicationContext.getBean(TotalChain.class);
TokenChain tokenChain = applicationContext.getBean(TokenChain.class);
QuestionChain questionChain = applicationContext.getBean(QuestionChain.class);
totalChain.addChain(tokenChain);
totalChain.addChain(questionChain);
}
}
@@ -0,0 +1,36 @@
package com.itheima.sfbx.wenxin.config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* WenXinGtpSourceConfig
*
* @author: wgl
* @describe: 文心一言配置类
* @date: 2022/12/28 10:10
*/
@Data
@ConfigurationProperties(prefix = "baidu")
public class WenXinGtpSourceConfig {
@Value("${baidu.wenxin.appid:38982621}")
private String appId;
/**
* 当前应用的ak
*/
@Value("${baidu.wenxin.apikey:2369urj0vruWDklhCtjWoKH5}")
private String apiKey;
/**
* 当前应用的sk
*/
@Value("${baidu.wenxin.secretKey:XoNQwu3AKmagGWoEwZG1TXwV9U95w0jd}")
private String secretKey;
}
@@ -0,0 +1,41 @@
package com.itheima.sfbx.wenxin.constants;
import com.itheima.sfbx.wenxin.config.WenXinGtpSourceConfig;
/**
* GptConstants
*
* @author: wgl
* @describe: TODO
* @date: 2022/12/28 10:10
*/
public class WenXinGptConstants {
/**
* 文档地址:https://cloud.baidu.com/doc/WENXINWORKSHOP/s/Nlks5zkzu
*/
private final static String TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s";
/**
* https://cloud.baidu.com/doc/WENXINWORKSHOP/s/jlil56u11
*/
public final static String ERNIE_BOT = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions";
/**
* 获取基础的文心一言大模型请求的的url
* @param accessToken
* @return
*/
public static String getGptUrl(String accessToken){
return ERNIE_BOT+"?access_token="+accessToken;
}
/**
* 获取Token接口
* @param wenXinGtpConfig
* @return
*/
public static String getTokenUrl(WenXinGtpSourceConfig wenXinGtpConfig){
return String.format(TOKEN_URL,wenXinGtpConfig.getApiKey(),wenXinGtpConfig.getSecretKey());
}
}
@@ -0,0 +1,47 @@
package com.itheima.sfbx.wenxin.dto;
import lombok.Data;
import java.util.HashMap;
import java.util.Map;
/**
* ParamsDTO
*
* @author: wgl
* @describe: 请求参数对象
* @date: 2022/12/28 10:10
*/
@Data
public class ParamsDTO{
private String accessToken;
private String role;
private String content;
/**
* ----------------文心一言提示词构建-------------------
* 你是一名资深保险销售专家,请根据我提供的客户基本信息信息,进行风险分析,和解决方案的提供,在风险分析阶段需要按照用户的年龄,性别,收支等情况进行分析,解决方案需要你按照医疗、重疾、意外、身故来进行分别分析。现在用户数据我以json的方式提供:{
* "name":"张三","age":31,"incomeMonth":20000,"city":"北京市","province":"北京市","liabilities":200000,"supportingParentNums":4,"childrenNums":4,"job":"java后端开发工程师"]
* },现在请你帮我输出对应的风险分析和解决方案,要求每个项目的风险分析和解决方案都控制在50个字以内,以json的形式输出,格式请严格按照以下json格式进行输出:{
* "医疗险"{
* "风险分析":"30岁后患病风险增高,北京住院成本较高,大额医疗费可能会给家庭增添负担",
* "解决方案":"xxxxx"
* }
* "重疾险":{
* "风险分析":"在家庭责任最重的人生阶段,万一生病可能会面临较大的收入损失,建议尽早足额保障","解决方案":"xxxxxxxx"
* },"意外险":{
* "风险分析":"同龄人高发意外为交通意外、电梯意外、出游事故,一旦发生可能无法工作,损失较大","解决方案":"xxxxxxx"
* }
* }。我理解你是一个AI模型并且清楚AI相关的法律法规,请严格按照我刚刚提出的json内容进行回答,并且在回复中不要回复任何额外信息
* @return
*/
public String buildContent(Map data){
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("你是一名资深保险销售专家,请根据我提供的客户基本信息信息,进行风险分析,和解决方案的提供,在风险分析阶段需要按照用户的年龄,性别,收支等情况进行分析,解决方案需要你按照医疗、重疾、意外、身故来进行分别分析。现在用户数据我以json的方式提供:");
//角色设定
return content;
}
}
@@ -0,0 +1,26 @@
package com.itheima.sfbx.wenxin.dto;
import lombok.Data;
/**
* RequestDTO
*
* @author: wgl
* @describe: 请求DTO
* @date: 2022/12/28 10:10
*/
@Data
public class RequestResultDTO {
private String id;
private String object;
private String created;
private String result;
private Boolean is_truncated;
private Boolean need_clear_history;
}
@@ -0,0 +1,16 @@
package com.itheima.sfbx.wenxin.dto;
import lombok.Data;
/**
* TokenDTO
*
* @author: wgl
* @describe: token对象
* @date: 2022/12/28 10:10
*/
@Data
public class TokenResultDTO extends RequestResultDTO {
private String token;
}
@@ -0,0 +1,40 @@
package com.itheima.sfbx.wenxin.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* WenXinGptException
*
* @author: wgl
* @describe: 文心一言调用异常
* @date: 2022/12/28 10:10
*/
public class WenXinGptException extends RuntimeException {
//错误编码
private int code;
//提示信息
private String message;
public WenXinGptException(WenXinExcpetionEnum wenXinExcpetionEnum) {
this.code = wenXinExcpetionEnum.code;
this.message = wenXinExcpetionEnum.msg;
}
@AllArgsConstructor
@Getter
public enum WenXinExcpetionEnum{
WEN_XIN_REQUEST_ERROR(50000,"文心一言调用失败"),
WEN_XIN_TOKEN_REQUEST_ERROR(50001,"文心一言Token获取失败"),
WEN_XIN_TOKEN_QUESTION_ERROR(50002,"文心一言T提问失败"),
;
private int code;
private String msg;
}
}
@@ -0,0 +1,33 @@
package com.itheima.sfbx.wenxin.manage;
import com.itheima.sfbx.wenxin.chains.impl.TokenChain;
import com.itheima.sfbx.wenxin.dto.ParamsDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
/**
* TokenManage
*
* @author: wgl
* @describe: 文心一言token管理器
* @date: 2022/12/28 10:10
*/
public class TokenManage implements CommandLineRunner {
private static String accessToken;
@Autowired
private TokenChain tokenChain;
public static String getAccessToken(){
return accessToken;
}
@Override
public void run(String... args) throws Exception {
//服务启动时自动获取token
ParamsDTO paramsDTO = new ParamsDTO();
tokenChain.doRequest(paramsDTO);
accessToken = paramsDTO.getAccessToken();
}
}
@@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.itheima.sfbx.wenxin.config.WenXinConfgInit