chatGpt如何融入自己的项目
最近chatGpt也是相当的火,各位小伙伴应该都挺喜欢这个能取代自己的家伙的。
我这里利用webSocket + chatGpt实现了简单的聊天室。代码真的非常简单!
后端
核心依赖
<!-- websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- openai-->
<dependency>
<groupId>com.unfbx</groupId>
<artifactId>chatgpt-java</artifactId>
<version>1.0.8</version>
</dependency>
webSocket相关
@Slf4j
@ServerEndpoint("/chat/{userId}")
@Component
public class ChatServer {
/**
* 与某个客户端的连接对话,需要通过它来给客户端发送消息
*/
private Session session;
/**
* 标识当前连接客户端的用户名
*/
private Long userId;
/**
* 用于存所有的连接服务的客户端,这个对象存储是安全的
*/
private static ConcurrentHashMap<Long, ChatServer> webSocketSet = new ConcurrentHashMap<>();
public static ChatServer chatServer;
@Autowired
AiService aiService;
@PostConstruct
private void initChatServer(){
chatServer = this;
chatServer.aiService = this.aiService;
}
@OnOpen
public void OnOpen(Session session, @PathParam(value = "userId") Long userId){
this.session = session;
this.userId = userId;
// name是用来表示唯一客户端,如果需要指定发送,需要指定发送通过name来区分
webSocketSet.put(userId,this);
log.info("[WebSocket] 连接成功,当前连接人数为:={}",webSocketSet.size());
}
@OnClose
public void onClose(){
webSocketSet.remove(this.userId);
log.info("[WebSocket] 退出成功,当前连接人数为:={}",webSocketSet.size());
}
@OnMessage
public void OnMessage(String message){
log.info("[WebSocket] 收到消息:{}",message);
String response = chatServer.aiService.getResponseFromOpenAi(message);
appointSending(userId,response);
}
@OnError
public void onError(Session session, Throwable t) {
//什么都不想打印都去掉就好了
log.info("【websocket消息】出现未知错误 ");
//打印错误信息,如果你不想打印错误信息,去掉就好了
//这里打印的也是 java.io.EOFException: null
t.printStackTrace();
}
/**
* 群发
* @param message
*/
public void groupSending(String message){
for (Long userId : webSocketSet.keySet()){
try {
webSocketSet.get(userId).session.getBasicRemote().sendText(message);
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* 指定发送
* @param userId
* @param message
*/
public void appointSending(Long userId,String message){
try {
webSocketSet.get(userId).session.getBasicRemote().sendText(message);
}catch (Exception e){
e.printStackTrace();
}
}
}
ChatGpt相关
申请key
复制,保存好!
业务
@Service
public class AiServiceImpl implements AiService {
@Value("${openai.key}")
private String openaiKey;
@Value("${openai.host}")
private String apiHost;
private static String PRESET ="下面的对话你都需要以一个小可爱的身份进行对话,语气欢快;";
@Override
public String getResponseFromOpenAi(String content) {
OpenAiClient openAiClient = OpenAiClient.builder()
.apiKey(Arrays.asList(openaiKey))
.apiHost(apiHost)
.build();
//聊天模型:gpt-3.5
ChatCompletionResponse chatCompletionResponse = getMessage(content,openAiClient);
StringBuilder response = new StringBuilder();
chatCompletionResponse.getChoices().forEach(e -> {
response.append(e.getMessage().getContent()).append("\n");
});
return response.toString();
}
public ChatCompletionResponse getMessage(String content, OpenAiClient openAiClient) {
Message preMessage = Message.builder().role(Message.Role.USER).content(PRESET).build();
Message userMessage = Message.builder().role(Message.Role.USER).content(content).build();
ChatCompletion chatCompletion = ChatCompletion.builder().messages(Arrays.asList(preMessage,userMessage)).build();
ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
return chatCompletionResponse;
}
}
application.yml
openai:
host: https://****** //代理网址
key: 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 //secretKey
代理网址
登录这个网址www.ichati.cn/deploy/proj…,把key传进去,把返回的网址填入上面的
openai:
host: https://****** //代理网址
前端
<template>
<div style="">
<div class="basic" style="overflow: hidden;">
<div style="padding: 10px;font-size: 14px;display: flex;flex-direction: row;" v-for="msg in msgList" class="animate__animated animate__fadeInLeft ">
<a-avatar :src="avatar" v-show="msg.auth === 'user'"></a-avatar>
<div :style="msg.style">
{{ msg.text }}
</div>
</div>
</div>
<div style="position:absolute;bottom:0px;width: 100%;padding: 10px;display: flex;flex-direction: column">
<a-button type="dashed" style="width: 150px;margin: 0 auto 20px auto " @click="sendMessageAgain">regenerate
answer
</a-button>
<a-input v-model:value="inputText" @keyup.enter="sendMessage" type="primary" placeholder="Send a message ..."/>
</div>
</div>
</template>
<script setup lang="ts">
import SocketService from '../utils/WebSocketUtils';
import {onMounted, reactive, ref} from "vue";
import {message} from "ant-design-vue";
import {useUserStore} from "../store/userStore";
import '../../node_modules/animate.css/animate.css'
const userStore = useUserStore();
const inputText = ref('')
const againText = ref('')
const msgList: any = ref([])
const avatar = ref()
onMounted(()=>{
if (!userStore.getUserAvatar() || userStore.getUserAvatar() === '') {
avatar.value = "https://***.com"
return;
}
avatar.value = userStore.getUserAvatar()
})
const data = reactive({
socketServe: SocketService.Instance,
});
//@ts-ignore
SocketService.Instance.connect(userStore.getUserId());
data.socketServe = SocketService.Instance;
const sendMessage = () => {
if (inputText.value.length >= 200) {
message.error("不得超过200字")
return;
}
//@ts-ignore
data.socketServe.send(inputText.value);
let showText: any = {}
showText.text = inputText.value
showText.auth = 'user'
showText.style = {
padding: '10px',
fontSize: '14px',
color: 'black'
}
msgList.value.push(showText);
console.log('发送数据', showText.text)
againText.value = inputText.value
inputText.value = ''
};
//@ts-ignore
data.socketServe.ws.onmessage = async (msg: any) => {
console.log(msg, '从服务端获取到了数据');
let showText: any = {}
showText.text = msg.data
showText.auth = 'robot'
showText.style = {
padding: '10px',
fontSize: '8px',
color: 'black',
borderTop: '1px solid #e5e5e5',
borderBottom: '1px solid #e5e5e5',
backgroundColor: '#f7f7f8'
}
await msgList.value.push(showText)
};
const sendMessageAgain = () => {
//@ts-ignore
data.socketServe.send(againText.value);
}
</script>
<style scoped>
.basic {
display: flex;
flex-direction: column;
max-height: 550px;
overflow: scroll;
}
</style>
export default class SocketService {
static instance = null;
static get Instance() {
if (!this.instance) {
// @ts-ignore
this.instance = new SocketService();
}
return this.instance;
}
// 和服务端连接的socket对象
ws = null;
// 标识是否连接成功
connected = false;
// 记录重试的次数
sendRetryCount = 0;
// 重新连接尝试的次数
connectRetryCount = 0;
baseURL_TEMP = import.meta.env.DEV ? import.meta.env.VITE_BASE_WEBSOCKET_URL_DEV : import.meta.env.VITE_BASE_WEBSOCKET_URL_PROD;
// 定义连接服务器的方法
connect(userId:number) {
// 连接服务器
if (!window.WebSocket) {
return console.log('您的浏览器不支持WebSocket');
}
let url = this.baseURL_TEMP + userId;
// @ts-ignore
this.ws = new WebSocket(url);
// 连接成功的事件
// @ts-ignore
this.ws.onopen = () => {
console.log('连接服务端成功了');
this.connected = true;
// 重置重新连接的次数
this.connectRetryCount = 0;
};
// 1.连接服务端失败
// 2.当连接成功之后, 服务器关闭的情况
// @ts-ignore
this.ws.onclose = () => {
console.log('连接服务端失败');
this.connected = false;
this.connectRetryCount++;
setTimeout(() => {
this.connect(userId);
}, 500 * this.connectRetryCount);
};
// 得到服务端发送过来的数据
// @ts-ignore
this.ws.onmessage = msg => {
console.log(msg.data, '从服务端获取到了数据');
};
}
// 发送数据的方法
send(data:string) {
// 判断此时此刻有没有连接成功
if (this.connected) {
this.sendRetryCount = 0;
try {
// @ts-ignore
this.ws.send(JSON.stringify(data));
} catch (e) {
// @ts-ignore
this.ws.send(data);
}
} else {
this.sendRetryCount++;
setTimeout(() => {
this.send(data);
}, this.sendRetryCount * 500);
}
}
}
Over!!!!