streaming experiments

This commit is contained in:
Alex
2023-05-18 23:52:59 +01:00
parent e49dd0cc6a
commit ff2e79fe7b
3 changed files with 70 additions and 35 deletions

View File

@@ -7,6 +7,7 @@ export function fetchAnswerApi(
question: string,
apiKey: string,
selectedDocs: Doc,
onEvent: (event: MessageEvent) => void,
): Promise<Answer> {
let namePath = selectedDocs.name;
if (selectedDocs.language === namePath) {
@@ -28,30 +29,23 @@ export function fetchAnswerApi(
'/';
}
return fetch(apiHost + '/api/answer', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
question: question,
api_key: apiKey,
embeddings_key: apiKey,
history: localStorage.getItem('chatHistory'),
active_docs: docPath,
}),
})
.then((response) => {
if (response.ok) {
return response.json();
} else {
Promise.reject(response);
}
})
.then((data) => {
const result = data.answer;
return { answer: result, query: question, result };
});
return new Promise<Answer>((resolve, reject) => {
const url = new URL(apiHost + '/stream');
url.searchParams.append('question', question);
url.searchParams.append('api_key', apiKey);
url.searchParams.append('embeddings_key', apiKey);
url.searchParams.append('history', localStorage.getItem('chatHistory'));
url.searchParams.append('active_docs', docPath);
const eventSource = new EventSource(url.href);
eventSource.onmessage = onEvent;
eventSource.onerror = (error) => {
console.log('Connection failed.');
eventSource.close();
};
});
}
export function sendFeedback(

View File

@@ -1,7 +1,8 @@
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import store from '../store';
import { fetchAnswerApi } from './conversationApi';
import { Answer, ConversationState, Query } from './conversationModels';
import { ConversationState, Query } from './conversationModels';
import { Dispatch } from 'react';
const initialState: ConversationState = {
queries: [],
@@ -9,18 +10,35 @@ const initialState: ConversationState = {
};
export const fetchAnswer = createAsyncThunk<
Answer,
void,
{ question: string },
{ state: RootState }
>('fetchAnswer', async ({ question }, { getState }) => {
{ dispatch: Dispatch; state: RootState }
>('fetchAnswer', ({ question }, { dispatch, getState }) => {
const state = getState();
const answer = await fetchAnswerApi(
fetchAnswerApi(
question,
state.preference.apiKey,
state.preference.selectedDocs!,
(event) => {
const data = JSON.parse(event.data);
console.log(data);
// check if the 'end' event has been received
if (data.type === 'end') {
// set status to 'idle'
dispatch(conversationSlice.actions.setStatus('idle'));
} else {
const result = JSON.stringify(data.answer);
dispatch(
updateQuery({
index: state.conversation.queries.length - 1,
query: { response: result },
}),
);
}
},
);
return answer;
});
export const conversationSlice = createSlice({
@@ -35,10 +53,18 @@ export const conversationSlice = createSlice({
action: PayloadAction<{ index: number; query: Partial<Query> }>,
) {
const index = action.payload.index;
state.queries[index] = {
...state.queries[index],
...action.payload.query,
};
if (action.payload.query.response) {
state.queries[index].response =
(state.queries[index].response || '') + action.payload.query.response;
} else {
state.queries[index] = {
...state.queries[index],
...action.payload.query,
};
}
},
setStatus(state, action: PayloadAction<string>) {
state.status = action.payload;
},
},
extraReducers(builder) {