mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-11-29 10:37:57 +08:00
[Core] Support chatgpt
This commit is contained in:
parent
dc36186d30
commit
e289057d25
1
.java-version
Normal file
1
.java-version
Normal file
@ -0,0 +1 @@
|
||||
11.0
|
@ -91,6 +91,11 @@
|
||||
<artifactId>UserAgentUtils</artifactId>
|
||||
<version>1.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.unfbx</groupId>
|
||||
<artifactId>chatgpt-java</artifactId>
|
||||
<version>1.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.edurt.datacap</groupId>
|
||||
<artifactId>datacap-spi</artifactId>
|
||||
|
@ -0,0 +1,16 @@
|
||||
package io.edurt.datacap.server.body;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@Data
|
||||
@ToString
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UserQuestionBody
|
||||
{
|
||||
private String question;
|
||||
private String type;
|
||||
}
|
@ -3,6 +3,7 @@ package io.edurt.datacap.server.controller.user;
|
||||
import io.edurt.datacap.server.body.FilterBody;
|
||||
import io.edurt.datacap.server.body.UserNameBody;
|
||||
import io.edurt.datacap.server.body.UserPasswordBody;
|
||||
import io.edurt.datacap.server.body.UserQuestionBody;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.entity.PageEntity;
|
||||
import io.edurt.datacap.server.entity.UserEntity;
|
||||
@ -18,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/v1/user")
|
||||
public class UserController
|
||||
@ -49,9 +52,21 @@ public class UserController
|
||||
return this.userService.changeUsername(configure);
|
||||
}
|
||||
|
||||
@PutMapping(value = "changeThirdConfigure")
|
||||
public Response<Long> changeThirdConfigure(@Validated @RequestBody Map<String, Map<String, Object>> configure)
|
||||
{
|
||||
return this.userService.changeThirdConfigure(configure);
|
||||
}
|
||||
|
||||
@PostMapping(value = "log")
|
||||
public Response<PageEntity<UserLogEntity>> getAllLogByFilter(@RequestBody FilterBody filter)
|
||||
{
|
||||
return this.userLogService.getAllByFilter(filter);
|
||||
}
|
||||
|
||||
@PostMapping(value = "startChat")
|
||||
public Response<Object> startChat(@RequestBody UserQuestionBody configure)
|
||||
{
|
||||
return this.userService.startChat(configure);
|
||||
}
|
||||
}
|
||||
|
@ -66,6 +66,9 @@ public class UserEntity
|
||||
@Column(name = "password")
|
||||
private String password;
|
||||
|
||||
@Column(name = "third_configure")
|
||||
private String thirdConfigure;
|
||||
|
||||
@Column(name = "create_time", columnDefinition = "datetime(5) default CURRENT_TIMESTAMP()")
|
||||
private Timestamp createTime;
|
||||
|
||||
|
@ -2,10 +2,13 @@ package io.edurt.datacap.server.service;
|
||||
|
||||
import io.edurt.datacap.server.body.UserNameBody;
|
||||
import io.edurt.datacap.server.body.UserPasswordBody;
|
||||
import io.edurt.datacap.server.body.UserQuestionBody;
|
||||
import io.edurt.datacap.server.common.JwtResponse;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.entity.UserEntity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface UserService
|
||||
{
|
||||
Response<UserEntity> saveOrUpdate(UserEntity configure);
|
||||
@ -17,4 +20,8 @@ public interface UserService
|
||||
Response<Long> changePassword(UserPasswordBody configure);
|
||||
|
||||
Response<Long> changeUsername(UserNameBody configure);
|
||||
|
||||
Response<Long> changeThirdConfigure(Map<String, Map<String, Object>> configure);
|
||||
|
||||
Response<Object> startChat(UserQuestionBody configure);
|
||||
}
|
||||
|
@ -1,8 +1,14 @@
|
||||
package io.edurt.datacap.server.service.impl;
|
||||
|
||||
import com.unfbx.chatgpt.OpenAiClient;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
|
||||
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
|
||||
import com.unfbx.chatgpt.entity.chat.Message;
|
||||
import io.edurt.datacap.server.audit.AuditUserLog;
|
||||
import io.edurt.datacap.server.body.UserNameBody;
|
||||
import io.edurt.datacap.server.body.UserPasswordBody;
|
||||
import io.edurt.datacap.server.body.UserQuestionBody;
|
||||
import io.edurt.datacap.server.common.JSON;
|
||||
import io.edurt.datacap.server.common.JwtResponse;
|
||||
import io.edurt.datacap.server.common.Response;
|
||||
import io.edurt.datacap.server.common.ServiceState;
|
||||
@ -14,6 +20,7 @@ import io.edurt.datacap.server.security.JwtService;
|
||||
import io.edurt.datacap.server.security.UserDetailsService;
|
||||
import io.edurt.datacap.server.service.UserService;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -21,8 +28,11 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -134,4 +144,54 @@ public class UserServiceImpl
|
||||
this.userRepository.save(user);
|
||||
return Response.success(user.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Long> changeThirdConfigure(Map<String, Map<String, Object>> configure)
|
||||
{
|
||||
Optional<UserEntity> userOptional = this.userRepository.findById(UserDetailsService.getUser().getId());
|
||||
if (!userOptional.isPresent()) {
|
||||
return Response.failure(ServiceState.USER_NOT_FOUND);
|
||||
}
|
||||
UserEntity user = userOptional.get();
|
||||
user.setThirdConfigure(JSON.toJSON(configure));
|
||||
this.userRepository.save(user);
|
||||
return Response.success(user.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Object> startChat(UserQuestionBody configure)
|
||||
{
|
||||
Optional<UserEntity> userOptional = this.userRepository.findById(UserDetailsService.getUser().getId());
|
||||
if (!userOptional.isPresent()) {
|
||||
return Response.failure(ServiceState.USER_NOT_FOUND);
|
||||
}
|
||||
if (!configure.getType().equals("ChatGPT")) {
|
||||
return Response.failure("Not supported");
|
||||
}
|
||||
|
||||
UserEntity user = userOptional.get();
|
||||
List<String> content = new ArrayList<>();
|
||||
if (StringUtils.isNotEmpty(user.getThirdConfigure())) {
|
||||
Map<String, Object> configureMap = JSON.toMap(user.getThirdConfigure());
|
||||
if (configureMap.containsKey("chatgpt")) {
|
||||
Map<String, Object> chatGPTMap = (Map<String, Object>) configureMap.get("chatgpt");
|
||||
if (chatGPTMap.containsKey("token")) {
|
||||
String token = (String) chatGPTMap.get("token");
|
||||
if (StringUtils.isNotEmpty(token)) {
|
||||
OpenAiClient openAiClient = OpenAiClient.builder()
|
||||
.apiKey(token)
|
||||
.build();
|
||||
Message message = Message.builder()
|
||||
.role(Message.Role.USER)
|
||||
.content(configure.getQuestion())
|
||||
.build();
|
||||
ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(message)).build();
|
||||
ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
|
||||
chatCompletionResponse.getChoices().forEach(e -> content.add(e.getMessage().getContent()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Response.success(content);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,2 @@
|
||||
alter table users
|
||||
add third_configure text;
|
1
core/datacap-server/src/main/schema/1.7.0/update.sql
Normal file
1
core/datacap-server/src/main/schema/1.7.0/update.sql
Normal file
@ -0,0 +1 @@
|
||||
source schema/users.sql;
|
@ -80,5 +80,8 @@ export default {
|
||||
ssl: 'SSL',
|
||||
id: 'ID',
|
||||
authority: 'Authority',
|
||||
code: 'Code'
|
||||
code: 'Code',
|
||||
chatgpt: 'ChatGPT',
|
||||
send: 'Send',
|
||||
token: 'Token'
|
||||
}
|
||||
|
@ -81,4 +81,7 @@ export default {
|
||||
id: 'ID',
|
||||
authority: '权限',
|
||||
code: '代码',
|
||||
chatgpt: 'ChatGPT',
|
||||
send: '发送',
|
||||
token: '密钥'
|
||||
}
|
||||
|
@ -1,5 +1,17 @@
|
||||
export interface User
|
||||
{
|
||||
username: string;
|
||||
thirdConfigure: { chatgpt: ThirdConfigure };
|
||||
createTime?: string;
|
||||
}
|
||||
|
||||
export class UserQuestion
|
||||
{
|
||||
question: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export class ThirdConfigure
|
||||
{
|
||||
token = '';
|
||||
}
|
||||
|
@ -182,6 +182,13 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
component: () => import("../views/pages/profile/ProfileLog.vue")
|
||||
},
|
||||
{
|
||||
path: 'chatgpt',
|
||||
meta: {
|
||||
roles: ['Admin', 'User']
|
||||
},
|
||||
component: () => import("../views/pages/profile/ProfileChatGPT.vue")
|
||||
},
|
||||
{
|
||||
path: 'account',
|
||||
meta: {
|
||||
|
@ -3,6 +3,7 @@ import {ResponseModel} from "@/model/ResponseModel";
|
||||
import {UserPassword} from "@/model/UserPassword";
|
||||
import {UserName} from "@/model/UserName";
|
||||
import {Filter} from "@/model/Filter";
|
||||
import {UserQuestion} from "@/model/User";
|
||||
|
||||
const baseUrl = "/api/v1/user";
|
||||
|
||||
@ -23,6 +24,16 @@ class UserService
|
||||
return new HttpCommon().put(baseUrl + '/changeUsername', configure);
|
||||
}
|
||||
|
||||
changeThirdConfigure(configure: any): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpCommon().put(baseUrl + '/changeThirdConfigure', configure);
|
||||
}
|
||||
|
||||
startChat(configure: UserQuestion): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpCommon().post(baseUrl + '/startChat', configure);
|
||||
}
|
||||
|
||||
getLogs(filter: Filter): Promise<ResponseModel>
|
||||
{
|
||||
return new HttpCommon().post(baseUrl + '/log', filter);
|
||||
|
@ -0,0 +1,142 @@
|
||||
<template>
|
||||
<div>
|
||||
<Card style="width:100%; minHeight: 150px;">
|
||||
<template #title>
|
||||
{{ $t('common.chatgpt') }}
|
||||
</template>
|
||||
<template #extra>
|
||||
<Tooltip :content="$t('common.settings')" transfer>
|
||||
<Button type="primary" size="small" shape="circle" icon="ios-cog" @click="handlerVisibleDetail(true)"></Button>
|
||||
</Tooltip>
|
||||
</template>
|
||||
<div>
|
||||
<Layout>
|
||||
<Content style="padding: 24px 50px;">
|
||||
<Input v-model="userQuestionResponse" :disabled="!userInfo?.thirdConfigure?.chatgpt?.token" type="textarea" :rows="10"/>
|
||||
</Content>
|
||||
<Footer>
|
||||
<Row>
|
||||
<Col span="20">
|
||||
<Input v-model="userQuestion.question" :disabled="!userInfo?.thirdConfigure?.chatgpt?.token" type="textarea" :autosize="{minRows: 2,maxRows: 5}"/>
|
||||
</Col>
|
||||
<Col span="2" offset="1">
|
||||
<Button :disabled="!userInfo?.thirdConfigure?.chatgpt?.token" type="primary" icon="md-send"
|
||||
:loading="startChatLoading" @click="handlerStartChat()">{{ $t('common.send') }}
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</Footer>
|
||||
</Layout>
|
||||
</div>
|
||||
<Spin size="large" fix :show="loading"></Spin>
|
||||
</Card>
|
||||
|
||||
<Modal v-if="visibleModel" v-model="visibleModel" :title="$t('common.chatgpt') +' ' + $t('common.settings')"
|
||||
:mask-closable="false" :closable="false">
|
||||
<Form :label-width="80">
|
||||
<FormItem :label="$t('common.token')">
|
||||
<Input v-model="userInfo.thirdConfigure.chatgpt.token" type="text" placeholder="example: sk-xxxx"/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
<template #footer>
|
||||
<Space>
|
||||
<Button type="error" @click="handlerVisibleDetail(false)">{{ $t('common.cancel') }}</Button>
|
||||
<Button type="primary" icon="md-document" @click="handlerSave()">{{ $t('common.save') }}</Button>
|
||||
</Space>
|
||||
</template>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
import UserService from "@/services/UserService";
|
||||
import {ThirdConfigure, User, UserQuestion} from '@/model/User';
|
||||
|
||||
const userQuestion = new UserQuestion();
|
||||
userQuestion.type = 'ChatGPT';
|
||||
export default defineComponent({
|
||||
setup()
|
||||
{
|
||||
return {
|
||||
userQuestion
|
||||
}
|
||||
},
|
||||
created()
|
||||
{
|
||||
this.handlerInitialize()
|
||||
},
|
||||
data()
|
||||
{
|
||||
return {
|
||||
loading: false,
|
||||
visibleModel: false,
|
||||
startChatLoading: false,
|
||||
userInfo: null as User,
|
||||
userQuestionResponse: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlerInitialize()
|
||||
{
|
||||
this.loading = true;
|
||||
UserService.getInfo()
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.userInfo = response.data;
|
||||
// If the initialization property has not been set
|
||||
if (!this.userInfo.thirdConfigure) {
|
||||
this.userInfo.thirdConfigure = {
|
||||
chatgpt: new ThirdConfigure()
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.userInfo.thirdConfigure = JSON.parse(this.userInfo.thirdConfigure);
|
||||
}
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handlerVisibleDetail(value: boolean)
|
||||
{
|
||||
this.visibleModel = value;
|
||||
if (!value) {
|
||||
this.handlerInitialize();
|
||||
}
|
||||
},
|
||||
handlerSave()
|
||||
{
|
||||
UserService.changeThirdConfigure(this.userInfo.thirdConfigure)
|
||||
.then(response => {
|
||||
this.$Message.success(response.message);
|
||||
this.handlerVisibleDetail(false);
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handlerStartChat()
|
||||
{
|
||||
this.startChatLoading = true;
|
||||
UserService.startChat(this.userQuestion)
|
||||
.then(response => {
|
||||
if (response.status) {
|
||||
this.userQuestionResponse = response.data;
|
||||
}
|
||||
else {
|
||||
this.$Message.error(response.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
this.startChatLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
.content {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
</style>
|
@ -20,6 +20,11 @@
|
||||
<Icon type="md-egg"/>
|
||||
{{ $t('setting.log') }}
|
||||
</MenuItem>
|
||||
<MenuItem name="setting_chatgpt" to="/profile/chatgpt">
|
||||
<Icon type="md-chatbubbles"/>
|
||||
{{ $t('common.chatgpt') }}
|
||||
<Badge text="new"></Badge>
|
||||
</MenuItem>
|
||||
<MenuItem name="security" to="/profile/account">
|
||||
<Icon type="ios-contact"/>
|
||||
{{ $t('setting.accountSetting') }}
|
||||
|
Loading…
Reference in New Issue
Block a user