feat: gen title by sperate api call

feat:

fix: rename of convo should based on real request.
This commit is contained in:
Wentao Lyu 2023-03-13 14:04:47 +08:00
parent 8773878be2
commit 9f8e9cb091
8 changed files with 65 additions and 28 deletions

View file

@ -10,7 +10,7 @@ const {
customClient, customClient,
detectCode detectCode
} = require('../../app/'); } = require('../../app/');
const { getConvo, saveMessage, deleteMessagesSince, deleteMessages, saveConvo } = require('../../models'); const { getConvo, saveMessage, getConvoTitle, saveConvo } = require('../../models');
const { handleError, sendMessage } = require('./handlers'); const { handleError, sendMessage } = require('./handlers');
router.use('/bing', askBing); router.use('/bing', askBing);
@ -156,6 +156,7 @@ router.post('/', async (req, res) => {
await saveMessage(gptResponse); await saveMessage(gptResponse);
await saveConvo(gptResponse); await saveConvo(gptResponse);
sendMessage(res, { sendMessage(res, {
title: await getConvoTitle(conversationId),
final: true, final: true,
requestMessage: userMessage, requestMessage: userMessage,
responseMessage: gptResponse responseMessage: gptResponse

View file

@ -2,7 +2,7 @@ const express = require('express');
const crypto = require('crypto'); const crypto = require('crypto');
const router = express.Router(); const router = express.Router();
const { titleConvo, getCitations, citeText, askBing } = require('../../app/'); const { titleConvo, getCitations, citeText, askBing } = require('../../app/');
const { saveMessage, deleteMessages, deleteMessagesSince, saveConvo } = require('../../models'); const { saveMessage, getConvoTitle, saveConvo } = require('../../models');
const { handleError, sendMessage } = require('./handlers'); const { handleError, sendMessage } = require('./handlers');
const citationRegex = /\[\^\d+?\^]/g; const citationRegex = /\[\^\d+?\^]/g;
@ -98,6 +98,7 @@ router.post('/', async (req, res) => {
await saveMessage(response); await saveMessage(response);
await saveConvo(response); await saveConvo(response);
sendMessage(res, { sendMessage(res, {
title: await getConvoTitle(conversationId),
final: true, final: true,
requestMessage: userMessage, requestMessage: userMessage,
responseMessage: gptResponse responseMessage: gptResponse

View file

@ -2,7 +2,7 @@ const express = require('express');
const crypto = require('crypto'); const crypto = require('crypto');
const router = express.Router(); const router = express.Router();
const { titleConvo, getCitations, citeText, askSydney } = require('../../app/'); const { titleConvo, getCitations, citeText, askSydney } = require('../../app/');
const { saveMessage, deleteMessages, saveConvo, deleteMessagesSince, getConvoTitle } = require('../../models'); const { saveMessage, saveConvo, getConvoTitle } = require('../../models');
const { handleError, sendMessage } = require('./handlers'); const { handleError, sendMessage } = require('./handlers');
const citationRegex = /\[\^\d+?\^]/g; const citationRegex = /\[\^\d+?\^]/g;
@ -108,6 +108,7 @@ router.post('/', async (req, res) => {
await saveMessage(response); await saveMessage(response);
await saveConvo(response); await saveConvo(response);
sendMessage(res, { sendMessage(res, {
title: await getConvoTitle(conversationId),
final: true, final: true,
requestMessage: userMessage, requestMessage: userMessage,
responseMessage: gptResponse responseMessage: gptResponse

View file

@ -1,12 +1,38 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { titleConvo } = require('../../app/');
const { getConvo, saveConvo, getConvoTitle } = require('../../models');
const { getConvos, deleteConvos, updateConvo } = require('../../models/Conversation'); const { getConvos, deleteConvos, updateConvo } = require('../../models/Conversation');
const { getMessages } = require('../../models/Message');
router.get('/', async (req, res) => { router.get('/', async (req, res) => {
const pageNumber = req.query.pageNumber || 1; const pageNumber = req.query.pageNumber || 1;
res.status(200).send(await getConvos(pageNumber)); res.status(200).send(await getConvos(pageNumber));
}); });
router.post('/gen_title', async (req, res) => {
const { conversationId } = req.body.arg;
const convo = await getConvo(conversationId)
const firstMessage = (await getMessages({ conversationId }))[0]
const secondMessage = (await getMessages({ conversationId }))[1]
const title = convo.jailbreakConversationId
? await getConvoTitle(conversationId)
: await titleConvo({
model: convo?.model,
message: firstMessage?.text,
response: JSON.stringify(secondMessage?.text || '')
});
await saveConvo({
conversationId,
title
})
res.status(200).send(title);
});
router.post('/clear', async (req, res) => { router.post('/clear', async (req, res) => {
let filter = {}; let filter = {};
const { conversationId } = req.body.arg; const { conversationId } = req.body.arg;

View file

@ -8,13 +8,14 @@ import { setMessages, setEmptyMessage } from '~/store/messageSlice';
import { setText } from '~/store/textSlice'; import { setText } from '~/store/textSlice';
import manualSWR from '~/utils/fetchers'; import manualSWR from '~/utils/fetchers';
import ConvoIcon from '../svg/ConvoIcon'; import ConvoIcon from '../svg/ConvoIcon';
import { refreshConversation } from '../../store/convoSlice';
export default function Conversation({ export default function Conversation({
id, id,
model, model,
parentMessageId, parentMessageId,
conversationId, conversationId,
title = 'New conversation', title,
chatGptLabel = null, chatGptLabel = null,
promptPrefix = null, promptPrefix = null,
bingData, bingData,
@ -95,6 +96,7 @@ export default function Conversation({
const renameHandler = (e) => { const renameHandler = (e) => {
e.preventDefault(); e.preventDefault();
setTitleInput(title);
setRenaming(true); setRenaming(true);
setTimeout(() => { setTimeout(() => {
inputRef.current.focus(); inputRef.current.focus();
@ -112,7 +114,10 @@ export default function Conversation({
if (titleInput === title) { if (titleInput === title) {
return; return;
} }
rename.trigger({ conversationId, title: titleInput }); rename.trigger({ conversationId, title: titleInput })
.then(() => {
dispatch(refreshConversation())
});
}; };
const handleKeyDown = (e) => { const handleKeyDown = (e) => {
@ -149,7 +154,7 @@ export default function Conversation({
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
/> />
) : ( ) : (
titleInput title
)} )}
</div> </div>
{conversationId === id ? ( {conversationId === id ? (

View file

@ -1,5 +1,6 @@
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { SSE } from '~/utils/sse'; import { SSE } from '~/utils/sse';
import axios from 'axios';
import SubmitButton from './SubmitButton'; import SubmitButton from './SubmitButton';
import Regenerate from './Regenerate'; import Regenerate from './Regenerate';
import ModelMenu from '../Models/ModelMenu'; import ModelMenu from '../Models/ModelMenu';
@ -7,10 +8,11 @@ import Footer from './Footer';
import TextareaAutosize from 'react-textarea-autosize'; import TextareaAutosize from 'react-textarea-autosize';
import handleSubmit from '~/utils/handleSubmit'; import handleSubmit from '~/utils/handleSubmit';
import { useSelector, useDispatch } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import { setConversation, setError } from '~/store/convoSlice'; import { setConversation, setError, refreshConversation } from '~/store/convoSlice';
import { setMessages } from '~/store/messageSlice'; import { setMessages } from '~/store/messageSlice';
import { setSubmitState, setSubmission } from '~/store/submitSlice'; import { setSubmitState, setSubmission } from '~/store/submitSlice';
import { setText } from '~/store/textSlice'; import { setText } from '~/store/textSlice';
import manualSWR from '~/utils/fetchers';
export default function TextChat({ messages }) { export default function TextChat({ messages }) {
const [errorMessage, setErrorMessage] = useState(''); const [errorMessage, setErrorMessage] = useState('');
@ -22,6 +24,7 @@ export default function TextChat({ messages }) {
useSelector((state) => state.submit); useSelector((state) => state.submit);
const { text } = useSelector((state) => state.text); const { text } = useSelector((state) => state.text);
const { error } = convo; const { error } = convo;
const genTitle = manualSWR(`/api/convos/gen_title`, 'post');
// auto focus to input, when enter a conversation. // auto focus to input, when enter a conversation.
useEffect(() => { useEffect(() => {
@ -45,26 +48,24 @@ export default function TextChat({ messages }) {
const convoHandler = (data, currentState, currentMsg) => { const convoHandler = (data, currentState, currentMsg) => {
const { requestMessage, responseMessage } = data; const { requestMessage, responseMessage } = data;
const { conversationId } = currentMsg;
const { messages, _currentMsg, message, isCustomModel, sender } = const { messages, _currentMsg, message, isCustomModel, sender } =
currentState; currentState;
const { model, chatGptLabel, promptPrefix } = message; const { model, chatGptLabel, promptPrefix } = message;
dispatch( dispatch(
setMessages([...messages, setMessages([...messages, requestMessage, responseMessage,])
{
...requestMessage,
// messageId: data?.parentMessageId,
},
{
...responseMessage,
// sender,
// text: data.text || data.response,
}
])
); );
const isBing = model === 'bingai' || model === 'sydney'; const isBing = model === 'bingai' || model === 'sydney';
// if (!message.messageId) if (requestMessage.parentMessageId == '00000000-0000-0000-0000-000000000000') {
genTitle.trigger({ conversationId }).then((ret) => {
const title = ret?.data
if (title)
dispatch(refreshConversation());
})
}
if (!isBing && convo.conversationId === null && convo.parentMessageId === null) { if (!isBing && convo.conversationId === null && convo.parentMessageId === null) {
const { title } = data; const { title } = data;

View file

@ -11,7 +11,7 @@ import { incrementPage, setConvos } from '~/store/convoSlice';
export default function Nav({ navVisible, setNavVisible }) { export default function Nav({ navVisible, setNavVisible }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isHovering, setIsHovering] = useState(false); const [isHovering, setIsHovering] = useState(false);
const { conversationId, convos, pageNumber } = useSelector((state) => state.convo); const { conversationId, convos, pageNumber, refreshConvoHint } = useSelector((state) => state.convo);
const onSuccess = (data) => { const onSuccess = (data) => {
dispatch(setConvos(data)); dispatch(setConvos(data));
}; };
@ -20,6 +20,7 @@ export default function Nav({ navVisible, setNavVisible }) {
`/api/convos?pageNumber=${pageNumber}`, `/api/convos?pageNumber=${pageNumber}`,
onSuccess onSuccess
); );
const containerRef = useRef(null); const containerRef = useRef(null);
const scrollPositionRef = useRef(null); const scrollPositionRef = useRef(null);
@ -35,7 +36,7 @@ export default function Nav({ navVisible, setNavVisible }) {
} }
}; };
useDidMountEffect(() => mutate(), [conversationId]); useDidMountEffect(() => mutate(), [conversationId, refreshConvoHint]);
useEffect(() => { useEffect(() => {
const container = containerRef.current; const container = containerRef.current;

View file

@ -13,6 +13,7 @@ const initialState = {
promptPrefix: null, promptPrefix: null,
convosLoading: false, convosLoading: false,
pageNumber: 1, pageNumber: 1,
refreshConvoHint: 0,
convos: [] convos: []
}; };
@ -20,6 +21,9 @@ const currentSlice = createSlice({
name: 'convo', name: 'convo',
initialState, initialState,
reducers: { reducers: {
refreshConversation: (state, action) => {
state.refreshConvoHint = state.refreshConvoHint + 1;
},
setConversation: (state, action) => { setConversation: (state, action) => {
return { ...state, ...action.payload }; return { ...state, ...action.payload };
}, },
@ -44,10 +48,7 @@ const currentSlice = createSlice({
state.pageNumber = 1; state.pageNumber = 1;
}, },
setConvos: (state, action) => { setConvos: (state, action) => {
const newConvos = action.payload.filter((convo) => { state.convos = action.payload.sort(
return !state.convos.some((c) => c.conversationId === convo.conversationId);
});
state.convos = [...state.convos, ...newConvos].sort(
(a, b) => new Date(b.createdAt) - new Date(a.createdAt) (a, b) => new Date(b.createdAt) - new Date(a.createdAt)
); );
}, },
@ -60,7 +61,7 @@ const currentSlice = createSlice({
} }
}); });
export const { setConversation, setConvos, setNewConvo, setError, incrementPage, removeConvo, removeAll } = export const { refreshConversation, setConversation, setConvos, setNewConvo, setError, incrementPage, removeConvo, removeAll } =
currentSlice.actions; currentSlice.actions;
export default currentSlice.reducer; export default currentSlice.reducer;