新增腾讯混元大模型的支持

This commit is contained in:
lisang 2024-11-28 23:49:15 +08:00
parent db0402e32e
commit 3a1a025c63
28 changed files with 1024 additions and 9 deletions

4
.gitignore vendored
View File

@ -31,3 +31,7 @@ build/
### VS Code ###
.vscode/
info.text
conf

View File

@ -1,8 +1,16 @@
# AiCoder
Ai模型
Ai模型
- 通义千问-MAX
- ollama
**在线大模型**
使用建议将AiExecutor中的ApiKey改为你在阿里云上申请的token
_apiKey需要在对应的平台进行申请_
- 阿里云
- 通义千问大模型qwen-max、qwen-long
- 腾讯云
- 混元大模型hunyuan-lite
**本地大模型**
- ollama大模型llama3

58
pom.xml
View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.shockkid</groupId>
<artifactId>AiCoder</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>AiCoder</name>
@ -45,6 +45,62 @@
<artifactId>commonmark</artifactId>
<version>0.19.0</version>
</dependency>
<!--引入Knife4j的官方start包,该指南选择Spring Boot版本<3.0,开发者需要注意-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.9.1</version>
<!-- <scope>runtime</scope>-->
</dependency>
<!-- 数据库导出文档 -->
<!-- https://mvnrepository.com/artifact/cn.smallbun.screw/screw-core -->
<dependency>
<groupId>cn.smallbun.screw</groupId>
<artifactId>screw-core</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>com.pig4cloud.screw</groupId>
<artifactId>screw-extension</artifactId>
<version>0.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--循环重试-->
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.3.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openjdk.jol/jol-core -->
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.16</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -3,6 +3,9 @@ package com.shockkid.aicoder;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// @ComponentScan(value = "com.shockkid.aicoder",
// excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION,
// value = {Controller.class, RestController.class})})
@SpringBootApplication
public class AiCoderApplication {

View File

@ -0,0 +1,19 @@
package com.shockkid.aicoder.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @Author lisang
* @Date 2022/4/10 23:53
* @Description 方法记录
* @Version 1.0
*/
//注解用在方法上
@Target(ElementType.METHOD)
//注解保留多久RUNTIME运行时
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodExporter {
}

View File

@ -0,0 +1,40 @@
package com.shockkid.aicoder.aspect;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.time.Instant;
/**
* @Author lisang
* @Date 2022/4/10 23:55
* @Description
* @Version 1.0
*/
@Aspect
@Component
@Slf4j
public class MethodExporterAspect {
@Around("@annotation(com.shockkid.aicoder.annotation.MethodExporter)")
public Object methodExporter(ProceedingJoinPoint joinPoint) throws Throwable {
long st = Instant.now().toEpochMilli();
Object proceed = joinPoint.proceed();
long et = Instant.now().toEpochMilli();
ObjectMapper mapper = new ObjectMapper();
String jsonParam = mapper.writeValueAsString(joinPoint.getArgs());
String jsonResult = null;
jsonResult = proceed != null ? mapper.writeValueAsString(proceed) : "null";
log.info("正在上报服务调用过程:\ntarget{}.{}\nexecution:{}ms,\nparameter:{}\nresult:{}"
, joinPoint.getTarget().getClass().getSimpleName()
, joinPoint.getSignature().getName()
, (et - st)
, jsonParam
, jsonResult);
return proceed;
}
}

View File

@ -0,0 +1,44 @@
package com.shockkid.aicoder.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @Author lisang
* @Date 2024/11/28 18:18
* @Description:
* @Version 1.0
**/
@Configuration
@ConfigurationProperties(prefix = "shockkid.ai.hunyuan")
public class HunYuanProperties {
private String url;
private String apiKey;
private String model;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getApiKey() {
return apiKey;
}
public void setApiKey(String apiKey) {
this.apiKey = apiKey;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}

View File

@ -0,0 +1,31 @@
package com.shockkid.aicoder.config;
/**
* @auther lisang
* @date 2024/8/6 13:19
**/
// @Configuration
// @EnableSwagger2WebMvc
public class Knife4jConfiguration {
// @Bean(value = "dockerBean")
// public Docket dockerBean() {
// //指定使用Swagger2规范
// Docket docket=new Docket(DocumentationType.SWAGGER_2)
// .apiInfo(new ApiInfoBuilder()
// //描述字段支持Markdown语法
// .description("# Knife4j RESTful APIs")
// .termsOfServiceUrl("https://mlisan.com/")
// .contact("lisang_chn@163.com")
// .version("1.0")
// .build())
// //分组名称
// .groupName("AI服务")
// .select()
// //这里指定Controller扫描包路径
// .apis(RequestHandlerSelectors.basePackage("com.shockkid.aicoder.controller"))
// .paths(PathSelectors.any())
// .build();
// return docket;
// }
}

View File

@ -0,0 +1,43 @@
package com.shockkid.aicoder.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @Author lisang
* @Date 2024/11/28 22:03
* @Description: AI 配置类
* @Version 1.0
**/
@Configuration
@ConfigurationProperties(prefix = "shockkid.ai")
@Data
public class ShockKidAiProperties {
private AliyunTongYiPropertis tongyi;
private TencentHunYuanPropertis hunyuan;
private OllmaPropertis ollma;
@Data
public static class AliyunTongYiPropertis {
private boolean enable;
private String url;
private String apiKey;
private String model;
}
@Data
public static class TencentHunYuanPropertis {
private boolean enable;
private String url;
private String apiKey;
private String model;
}
@Data
public static class OllmaPropertis {
private boolean enable;
private String url;
private String model;
}
}

View File

@ -15,4 +15,5 @@ public class ModelConstant {
public static final String ASSISTANT_ROLE = "assistant";
public static final String MESSAGE = "message";
public static final String CONTENT = "content";
public static final String HUNYUAN_LITE = "hunyuan-lite";
}

View File

@ -1,7 +1,13 @@
package com.shockkid.aicoder.controller;
import com.shockkid.aicoder.executor.AiExecutor;
import com.shockkid.aicoder.factory.AiExecutorFactory;
import com.shockkid.aicoder.storage.MessageHistoryStorage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@ -9,16 +15,25 @@ import org.springframework.web.bind.annotation.RestController;
* @auther lisang
* @date 2024/5/22 23:43
**/
@Api(tags = "AI模块")
@RestController
public class AiController {
@Autowired@Qualifier("aiHunYuanExecutor")
private AiExecutorFactory aiExecutor;
@ApiImplicitParam(name = "text", value = "请求文本", required = true)
@ApiOperation(value = "AI反馈结果")
@PostMapping("/aiChat")
public String aiChat(String text) {
AiExecutor aiExecutor = new AiExecutor();
String result = aiExecutor.getChatMessageByTongYi(text);
/*AiExecutor aiExecutor = new AiExecutor();
String result = aiExecutor.getChatMessageByTongYi(text);*/
String result = aiExecutor.getChatMessage(text);
return result;
}
@ApiImplicitParam(name = "text", value = "请求文本含历史记录", required = true)
@ApiOperation(value = "AI反馈结果")
@PostMapping("/aiChatHistory")
public String aiChatHistory(String text) {
AiExecutor aiExecutor = new AiExecutor();

View File

@ -0,0 +1,55 @@
package com.shockkid.aicoder.example.pay;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @auther lisang
* @date 2024/6/25 10:49
**/
public class AsyncPaymentService {
// 创建线程池
private final ExecutorService single = Executors.newSingleThreadExecutor();
// 阻塞队列 -> 可以替换成分布式队列
ArrayBlockingQueue<PaymentRequest> taskQueue = new ArrayBlockingQueue(10);
// 标识
private volatile boolean isRunning = true;
{
init();
}
// 异步处理
public void init() {
single.execute(()->{
while (isRunning) {
try {
PaymentRequest paymentRequest = taskQueue.take();// 阻塞方式拿到支付任务
doPay(paymentRequest);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
public String submitPay(PaymentRequest paymentRequest) {
System.out.println("开始校验请求参数:" + paymentRequest);
taskQueue.add(paymentRequest); // 添加到队列
return "processing"; // 返回支付处理成功 -> 可能变成失败
}
public String doPay(PaymentRequest paymentRequest) {
try {
System.out.println("开始处理支付请求:" + paymentRequest);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("支付处理结束:" + paymentRequest);
return "success";
}
}

View File

@ -0,0 +1,44 @@
package com.shockkid.aicoder.example.pay;
/**
* @auther lisang
* @date 2024/6/25 10:41
**/
public class PaymentRequest {
public int payMethod;
public int totalFee;
public String returnUrl;
public int getPayMethod() {
return payMethod;
}
public void setPayMethod(int payMethod) {
this.payMethod = payMethod;
}
public int getTotalFee() {
return totalFee;
}
public void setTotalFee(int totalFee) {
this.totalFee = totalFee;
}
public String getReturnUrl() {
return returnUrl;
}
public void setReturnUrl(String returnUrl) {
this.returnUrl = returnUrl;
}
@Override
public String toString() {
return "PaymentRequest{" +
"payMethod=" + payMethod +
", totalFee=" + totalFee +
", returnUrl='" + returnUrl + '\'' +
'}';
}
}

View File

@ -0,0 +1,23 @@
package com.shockkid.aicoder.example.pay;
/**
* @auther lisang
* @date 2024/6/25 10:41
**/
public class PaymentService {
public String submitPay(PaymentRequest paymentRequest) {
System.out.println("开始校验请求参数:" + paymentRequest);
return doPay(paymentRequest);
}
public String doPay(PaymentRequest paymentRequest) {
try {
System.out.println("开始处理支付请求:" + paymentRequest);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("支付处理结束:" + paymentRequest);
return "success";
}
}

View File

@ -0,0 +1,21 @@
package com.shockkid.aicoder.example.pay;
import java.io.IOException;
/**
* @auther lisang
* @date 2024/6/25 10:41
**/
public class PaymentTestMain {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
PaymentRequest request = new PaymentRequest();
request.setPayMethod(1);
request.setTotalFee(100);
request.setReturnUrl("http://www.baidu.com");
String result = new AsyncPaymentService().submitPay(request);
long end = System.currentTimeMillis() - start;
System.out.println("支付处理结果:"+result+"->总处理时间:"+end);
//System.in.read();
}
}

View File

@ -23,7 +23,7 @@ import static com.shockkid.aicoder.constant.ModelConstant.*;
public class AiExecutor {
private String generateUrl = "http://127.0.0.1:11434/api/generate";
private String chatUrl = "http://127.0.0.1:11434/api/chat";
private String ApiKey = "Bearer 你的TOKEN";
private String ApiKey = "Bearer 通义千问TOKEN";
/**
* 通义大模型模型链接
*/

View File

@ -0,0 +1,92 @@
package com.shockkid.aicoder.executor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shockkid.aicoder.config.HunYuanProperties;
import com.shockkid.aicoder.config.OkHttpClientSingleton;
import com.shockkid.aicoder.factory.AiExecutorFactory;
import com.shockkid.aicoder.model.InputModel;
import com.shockkid.aicoder.model.OpenAiModel;
import com.shockkid.aicoder.model.RoleContentModel;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.shockkid.aicoder.constant.ModelConstant.HUNYUAN_LITE;
import static com.shockkid.aicoder.constant.ModelConstant.USER_ROLE;
/**
* @Author lisang
* @Date 2024/11/28 18:25
* @Description: 腾讯混元大模型
* @Version 1.0
**/
@Service
public class AiHunYuanExecutor implements AiExecutorFactory {
private static final Logger log = LoggerFactory.getLogger(AiHunYuanExecutor.class);
@Autowired
private HunYuanProperties hunYuanConfig;
/**
* 基于腾讯混元大模型API获取返回结果
*
* @param prompt
* @return
*/
public String getChatMessage(String prompt) {
OkHttpClient client = OkHttpClientSingleton.getInstance();
// 构建入参
OpenAiModel model = new OpenAiModel();
model.setModel(HUNYUAN_LITE);
InputModel inputModel = new InputModel();
List<RoleContentModel> messages = new ArrayList<>();
RoleContentModel roleContentModel = new RoleContentModel();
roleContentModel.setRole(USER_ROLE);
roleContentModel.setContent(prompt);
messages.add(roleContentModel);
model.setMessages(messages);
// 发起请求
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(model));
log.info("" + JSON.toJSONString(model));
Request request = new Request.Builder()
.header("Authorization", "Bearer " + hunYuanConfig.getApiKey())
.url(hunYuanConfig.getUrl())
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
// 处理响应
if (response.isSuccessful()) {
// 请求成功
ResponseBody responseBody = response.body();
String string = responseBody.string();
JSONObject jsonObject = JSON.parseObject(string);
// 处理响应体
List choices = jsonObject.getObject("choices", List.class);
if (choices.size() > 0) {
JSONObject jsonObject2 = JSON.parseObject(jsonObject.getObject("choices", List.class).get(0).toString());
return jsonObject2.getJSONObject("message").getString("content");
}
return "模型未给出相关回答";
} else {
// 请求失败
return "请求失败,响应码: " + response.code();
}
} catch (IOException e) {
// 发生异常
e.printStackTrace();
}
return "请求失败";
}
@Override
public String getChatHistory(String prompt) {
return null;
}
}

View File

@ -0,0 +1,108 @@
package com.shockkid.aicoder.executor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shockkid.aicoder.config.OkHttpClientSingleton;
import com.shockkid.aicoder.config.ShockKidAiProperties;
import com.shockkid.aicoder.factory.AiExecutorFactory;
import com.shockkid.aicoder.model.ChatModel;
import com.shockkid.aicoder.model.ChatRoleModel;
import com.shockkid.aicoder.storage.MessageHistoryStorage;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import static com.shockkid.aicoder.constant.ModelConstant.*;
/**
* @Author lisang
* @Date 2024/11/28 18:25
* @Description: ollma大模型
* @Version 1.0
**/
@Service
public class AiOllmaExecutor implements AiExecutorFactory {
private static final Logger log = LoggerFactory.getLogger(AiOllmaExecutor.class);
@Autowired
private ShockKidAiProperties aiConf;
/**
* 基于ollma大模型API获取返回结果
*
* @param prompt
* @return
*/
public String getChatMessage(String prompt) {
if (!aiConf.getOllma().isEnable()){
return "llama接口尚未接入";
}
OkHttpClient client = OkHttpClientSingleton.getInstance();
ChatModel chatModel = new ChatModel();
chatModel.setModel(aiConf.getOllma().getModel());
chatModel.setPrompt(prompt);
chatModel.setStream(false);
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(chatModel));
Request request = new Request.Builder()
.url(aiConf.getOllma().getUrl())
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
// 处理响应
if (response.isSuccessful()) {
// 请求成功
ResponseBody responseBody = response.body();
String string = responseBody.string();
JSONObject jsonObject = JSON.parseObject(string);
// 处理响应体
return jsonObject.getString(RESPONSE);
} else {
// 请求失败
return "请求失败,响应码: " + response.code();
}
} catch (IOException e) {
// 发生异常
e.printStackTrace();
}
return "请求失败";
}
@Override
public String getChatHistory(String prompt) {
if (!aiConf.getOllma().isEnable()){
return "llama尚未开启";
}
OkHttpClient client = OkHttpClientSingleton.getInstance();
ChatRoleModel chatRoleModel = new ChatRoleModel();
chatRoleModel.setModel(aiConf.getOllma().getModel());
chatRoleModel.setStream(false);
chatRoleModel.setMessages(MessageHistoryStorage.buildRoleContentModel(prompt));
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(chatRoleModel));
Request request = new Request.Builder()
.url(aiConf.getOllma().getUrl())
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
// 处理响应
if (response.isSuccessful()) {
ResponseBody responseBody = response.body();
String string = responseBody.string();
JSONObject jsonObject = JSON.parseObject(string);
JSONObject messageJson = jsonObject.getJSONObject(MESSAGE);
return messageJson.getString(CONTENT);
} else {
// 请求失败
System.out.println("请求失败,响应码: " + response.code());
return "请求失败,响应码: " + response.code();
}
} catch (IOException e) {
// 发生异常
e.printStackTrace();
}
return "请求失败";
}
}

View File

@ -0,0 +1,124 @@
package com.shockkid.aicoder.executor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.shockkid.aicoder.config.OkHttpClientSingleton;
import com.shockkid.aicoder.config.ShockKidAiProperties;
import com.shockkid.aicoder.factory.AiExecutorFactory;
import com.shockkid.aicoder.model.InputModel;
import com.shockkid.aicoder.model.RoleContentModel;
import com.shockkid.aicoder.model.TongYiModel;
import com.shockkid.aicoder.storage.MessageHistoryStorage;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import static com.shockkid.aicoder.constant.ModelConstant.*;
/**
* @Author lisang
* @Date 2024/11/28 18:25
* @Description: 阿里通义千问大模型
* @Version 1.0
**/
@Service
public class AiTongYiExecutor implements AiExecutorFactory {
private static final Logger log = LoggerFactory.getLogger(AiTongYiExecutor.class);
@Autowired
private ShockKidAiProperties aiConf;
/**
* 基于阿里通义千问大模型API获取返回结果
*
* @param prompt
* @return
*/
public String getChatMessage(String prompt) {
if (!aiConf.getTongyi().isEnable()){
return "通义千问接口尚未接入";
}
OkHttpClient client = OkHttpClientSingleton.getInstance();
// 构建入参
TongYiModel model = new TongYiModel();
model.setModel(aiConf.getTongyi().getModel());
InputModel inputModel = new InputModel();
List<RoleContentModel> messages = new ArrayList<>();
RoleContentModel roleContentModel = new RoleContentModel();
roleContentModel.setRole(USER_ROLE);
roleContentModel.setContent(prompt);
messages.add(roleContentModel);
inputModel.setMessages(messages);
model.setInput(inputModel);
// 发起请求
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(model));
Request request = new Request.Builder()
.header("Authorization","Bearer "+ aiConf.getTongyi().getApiKey())
.url(aiConf.getTongyi().getUrl())
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
// 处理响应
if (response.isSuccessful()) {
// 请求成功
ResponseBody responseBody = response.body();
String string = responseBody.string();
JSONObject jsonObject = JSON.parseObject(string);
// 处理响应体
JSONObject outputJson = jsonObject.getJSONObject(OUTPUT);
return outputJson.getString(TEXT);
} else {
// 请求失败
return "请求失败,响应码: " + response.code();
}
} catch (IOException e) {
// 发生异常
e.printStackTrace();
}
return "请求失败";
}
@Override
public String getChatHistory(String prompt) {
OkHttpClient client = OkHttpClientSingleton.getInstance();
// 构建入参
TongYiModel model = new TongYiModel();
model.setModel(aiConf.getTongyi().getModel());
InputModel inputModel = new InputModel();
// 构建上下文入参
inputModel.setMessages(MessageHistoryStorage.buildRoleContentModel(prompt));
model.setInput(inputModel);
// 发起请求
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), JSON.toJSONString(model));
Request request = new Request.Builder()
.header("Authorization","Bearer "+ aiConf.getTongyi().getApiKey())
.url(aiConf.getTongyi().getUrl())
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
// 处理响应
if (response.isSuccessful()) {
// 请求成功
ResponseBody responseBody = response.body();
String string = responseBody.string();
JSONObject jsonObject = JSON.parseObject(string);
// 处理响应体
JSONObject outputJson = jsonObject.getJSONObject(OUTPUT);
return outputJson.getString(TEXT);
} else {
// 请求失败
return "请求失败,响应码: " + response.code();
}
} catch (IOException e) {
// 发生异常
e.printStackTrace();
}
return "请求失败";
}
}

View File

@ -0,0 +1,13 @@
package com.shockkid.aicoder.factory;
/**
* @Author lisang
* @Date 2024/11/28 20:05
* @Description:
* @Version 1.0
**/
public interface AiExecutorFactory {
public String getChatMessage(String prompt);
public String getChatHistory(String prompt);
}

View File

@ -0,0 +1,17 @@
package com.shockkid.aicoder.model;
import lombok.Data;
import java.util.List;
/**
* @Author lisang
* @Date 2024/11/28 18:41
* @Description: OpenAi通用模型参数
* @Version 1.0
**/
@Data
public class OpenAiModel {
private String model;
private List<RoleContentModel> messages;
}

View File

@ -0,0 +1,26 @@
package com.shockkid.aicoder.util;
import java.util.Random;
/**
* 批量生成工具
*
* @auther lisang
* @date 2024/11/7 0:44
**/
public class BatchUtils {
public String autoBuildAcount() {
long t = System.currentTimeMillis();
Random random = new Random();
int i = random.nextInt(900000) + 100000;
int checksum = (int) ((t + i) % 10);
return String.format("%d%d%d", t, i, checksum);
}
public static void main(String[] args) {
BatchUtils batchUtils = new BatchUtils();
for (int i = 0; i < 10; i++) {
System.out.println(batchUtils.autoBuildAcount());
}
}
}

View File

@ -0,0 +1,95 @@
package com.shockkid.aicoder.util;
import cn.smallbun.screw.core.Configuration;
import cn.smallbun.screw.core.engine.EngineConfig;
import cn.smallbun.screw.core.engine.EngineFileType;
import cn.smallbun.screw.core.engine.EngineTemplateType;
import cn.smallbun.screw.core.execute.DocumentationExecute;
import cn.smallbun.screw.core.process.ProcessConfig;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import java.time.Instant;
import java.util.ArrayList;
/**
* @Author lisang
* @Date 2022/4/11 9:04
* @Description 数据库结构文档导出工具
* @Version 1.0
*/
public class DataExportUtil {
String FILE_OUT_PUT_DIR = "E:\\test";
/**
* 文档生成
*/
public void documentGeneration() {
//数据源
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariConfig.setJdbcUrl("jdbc:mysql://49.232.23.130:13306/onlinegit");
hikariConfig.setUsername("root");
hikariConfig.setPassword("sz@ongit123");
//设置可以获取tables remarks信息
hikariConfig.addDataSourceProperty("useInformationSchema", "true");
hikariConfig.setMinimumIdle(2);
hikariConfig.setMaximumPoolSize(5);
DataSource dataSource = new HikariDataSource(hikariConfig);
//生成配置
EngineConfig engineConfig = EngineConfig.builder()
//生成文件路径
.fileOutputDir(FILE_OUT_PUT_DIR)
//打开目录
.openOutputDir(true)
//文件类型
.fileType(EngineFileType.HTML)
//生成模板实现
.produceType(EngineTemplateType.freemarker)
//自定义文件名称
.fileName("onlinegit").build();
//忽略表
ArrayList<String> ignoreTableName = new ArrayList<>();
ignoreTableName.add("test_user");
ignoreTableName.add("test_group");
//忽略表前缀
ArrayList<String> ignorePrefix = new ArrayList<>();
ignorePrefix.add("test_");
//忽略表后缀
ArrayList<String> ignoreSuffix = new ArrayList<>();
ignoreSuffix.add("_test");
ProcessConfig processConfig = ProcessConfig.builder()
//指定生成逻辑当存在指定表指定表前缀指定表后缀时将生成指定表其余表不生成并跳过忽略表配置
//根据名称指定表生成
.designatedTableName(new ArrayList<>())
//根据表前缀生成
.designatedTablePrefix(new ArrayList<>())
//根据表后缀生成
.designatedTableSuffix(new ArrayList<>())
//忽略表名
.ignoreTableName(ignoreTableName)
//忽略表前缀
.ignoreTablePrefix(ignorePrefix)
//忽略表后缀
.ignoreTableSuffix(ignoreSuffix).build();
//配置
Configuration config = Configuration.builder()
.title("在线课堂设计文档")
//版本
.version("1.0.0")
//描述
.description("在线课堂数据库设计文档\n时间" + Instant.now())
//数据源
.dataSource(dataSource)
//生成配置
.engineConfig(engineConfig)
//生成配置
.produceConfig(processConfig)
.build();
//执行生成
new DocumentationExecute(config).execute();
}
}

View File

@ -0,0 +1,66 @@
package com.shockkid.aicoder.util;
import cn.smallbun.screw.core.process.ProcessConfig;
import cn.smallbun.screw.extension.pojo.PojoConfiguration;
import cn.smallbun.screw.extension.pojo.execute.PojoExecute;
import cn.smallbun.screw.extension.pojo.strategy.HumpNameStrategy;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import java.util.ArrayList;
/**
* @Author lisang
* @Date 2022/4/11 12:07
* @Description 生成实体类
* @Version 1.0
*/
public class MakePojoUtil {
final String POJOFILE_PATH = "E:\\wk\\idea\\AiCoder\\src\\main\\java\\com\\shockkid\\aicoder\\pojo";
final String PACKAGE_NAME = "com.shockkid.aicoder.pojo";
/**
* pojo生成
*/
public void pojoGeneration() {
//数据源
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName("com.mysql.cj.jdbc.Driver");
hikariConfig.setJdbcUrl("jdbc:mysql://192.168.56.204:3306/onlinegit");
hikariConfig.setUsername("root");
hikariConfig.setPassword("123456");
//设置可以获取tables remarks信息
hikariConfig.addDataSourceProperty("useInformationSchema", "true");
hikariConfig.setMinimumIdle(2);
hikariConfig.setMaximumPoolSize(5);
DataSource dataSource = new HikariDataSource(hikariConfig);
ProcessConfig processConfig = ProcessConfig.builder()
//指定生成逻辑当存在指定表指定表前缀指定表后缀时将生成指定表其余表不生成并跳过忽略表配置
//根据名称指定表生成
.designatedTableName(new ArrayList<>())
//根据表前缀生成
.designatedTablePrefix(new ArrayList<>())
//根据表后缀生成
.designatedTableSuffix(new ArrayList<>()).build();
//设置生成pojo相关配置
PojoConfiguration config = new PojoConfiguration();
//设置文件存放路径
config.setPath(POJOFILE_PATH);
//设置包名
config.setPackageName(PACKAGE_NAME);
//设置是否使用lombok
config.setUseLombok(false);
//设置数据源
config.setDataSource(dataSource);
//设置命名策略
config.setNameStrategy(new HumpNameStrategy());
//设置表过滤逻辑
config.setProcessConfig(processConfig);
//执行生成
new PojoExecute(config).execute();
}
}

View File

@ -1 +1,15 @@
server.port=8520
# \u914D\u7F6E\u57FA\u7840\u7684\u6570\u636E\u6E90
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/aicoder
#spring.datasource.username=root
#spring.datasource.password=123456
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# \u6253\u5F00\u9A7C\u5CF0\u547D\u540D
mybatis-plus.configuration.map-underscore-to-camel-case=true
# \u63A7\u5236\u53F0\u6253\u5370SQL
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# \u65E5\u5FD7\u65B9\u5F0F\u6253\u5370SQL
logging.level.com.lisang.boot.swagger.service=debug

View File

@ -0,0 +1,44 @@
spring:
application:
# 应用名称
name: AiCoder
# 配置基础的数据源
datasource:
url: jdbc:mysql://127.0.0.1:3306/aicoder
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
knife4j:
enable: true
openapi:
title: AI模块
description: "AI模块相关接口"
concat: ShockKid
version: v1.0
terms-of-service-url: https://mlisan.com
group:
default:
group-name: 默认分组
api-rule: package
api-rule-resources:
- com.shockkid.aicoder.controller
shockkid:
ai:
hunyuan:
enable: true
url: "https://api.hunyuan.cloud.tencent.com/v1/chat/completions"
apiKey: "xxxx"
model: "hunyuan-lite"
tongyi:
enable: false
url: "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
apiKey: "xxxx"
model: "qwen-max"
ollama:
enable: false
url: "http://127.0.0.1:11434/api/generate"
model: "llama3"
info:
version: 0.0.1

View File

@ -0,0 +1,6 @@
Application Name: ${spring.application.name}
Application Version: ${shockkid.info.version}
Spring Boot Version: ${spring-boot.version}
+-+-+-+-+-+-+-+
|A|i|C|o|d|e|r|
+-+-+-+-+-+-+-+

View File

@ -1,5 +1,6 @@
package com.shockkid.aicoder;
import com.shockkid.aicoder.util.MakePojoUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@ -8,6 +9,8 @@ class AiCoderApplicationTests {
@Test
void contextLoads() {
MakePojoUtil makePojoUtil = new MakePojoUtil();
makePojoUtil.pojoGeneration();
}
}