diff --git a/application/app.py b/application/app.py index 8f30dcf8..5e823faa 100644 --- a/application/app.py +++ b/application/app.py @@ -136,7 +136,6 @@ def complete_stream(question): ], stream=True, max_tokens=1000, temperature=0) for line in completion: - print(line, file=sys.stderr) if 'content' in line['choices'][0]['delta']: # check if the delta contains content data = json.dumps({"answer": str(line['choices'][0]['delta']['content'])}) @@ -197,16 +196,9 @@ def api_answer(): elif settings.EMBEDDINGS_NAME == "cohere_medium": docsearch = FAISS.load_local(vectorstore, CohereEmbeddings(cohere_api_key=embeddings_key)) - # create a prompt template - if history: - history = json.loads(history) - template_temp = template_hist.replace("{historyquestion}", history[0]).replace("{historyanswer}", - history[1]) - c_prompt = PromptTemplate(input_variables=["summaries", "question"], template=template_temp, - template_format="jinja2") - else: - c_prompt = PromptTemplate(input_variables=["summaries", "question"], template=template, - template_format="jinja2") + + c_prompt = PromptTemplate(input_variables=["summaries", "question"], template=template, + template_format="jinja2") q_prompt = PromptTemplate(input_variables=["context", "question"], template=template_quest, template_format="jinja2") diff --git a/frontend/src/conversation/conversationApi.ts b/frontend/src/conversation/conversationApi.ts index 6c3ff03e..98cfd6f9 100644 --- a/frontend/src/conversation/conversationApi.ts +++ b/frontend/src/conversation/conversationApi.ts @@ -4,6 +4,58 @@ import { Doc } from '../preferences/preferenceApi'; const apiHost = import.meta.env.VITE_API_HOST || 'https://docsapi.arc53.com'; export function fetchAnswerApi( + question: string, + apiKey: string, + selectedDocs: Doc, + history: Array = [], +): Promise { + let namePath = selectedDocs.name; + if (selectedDocs.language === namePath) { + namePath = '.project'; + } + + let docPath = 'default'; + if (selectedDocs.location === 'local') { + docPath = 'local' + '/' + selectedDocs.name + '/'; + } else if (selectedDocs.location === 'remote') { + docPath = + selectedDocs.language + + '/' + + namePath + + '/' + + selectedDocs.version + + '/' + + selectedDocs.model + + '/'; + } + + return fetch(apiHost + '/api/answer', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + question: question, + api_key: apiKey, + embeddings_key: apiKey, + history: history, + 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 }; + }); +} + +export function fetchAnswerSteaming( question: string, apiKey: string, selectedDocs: Doc, diff --git a/frontend/src/conversation/conversationSlice.ts b/frontend/src/conversation/conversationSlice.ts index 743f2afc..20e3e4b7 100644 --- a/frontend/src/conversation/conversationSlice.ts +++ b/frontend/src/conversation/conversationSlice.ts @@ -1,7 +1,7 @@ import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'; import store from '../store'; -import { fetchAnswerApi } from './conversationApi'; -import { ConversationState, Query } from './conversationModels'; +import { fetchAnswerApi, fetchAnswerSteaming } from './conversationApi'; +import { Answer, ConversationState, Query } from './conversationModels'; import { Dispatch } from 'react'; const initialState: ConversationState = { @@ -9,36 +9,58 @@ const initialState: ConversationState = { status: 'idle', }; +const API_STREAMING = import.meta.env.API_STREAMING || false; + export const fetchAnswer = createAsyncThunk< - void, + Answer | void, { question: string }, - { dispatch: Dispatch; state: RootState } ->('fetchAnswer', ({ question }, { dispatch, getState }) => { + { dispatch: Dispatch; state: RootState } +>('fetchAnswer', async ({ question }, { dispatch, getState }) => { const state = getState(); - fetchAnswerApi( - question, - state.preference.apiKey, - state.preference.selectedDocs!, - (event) => { - const data = JSON.parse(event.data); - console.log(data); + if (API_STREAMING) { + fetchAnswerSteaming( + 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 = data.answer; - dispatch( - updateQuery({ - index: state.conversation.queries.length - 1, - query: { response: result }, - }), - ); - } - }, - ); + // check if the 'end' event has been received + if (data.type === 'end') { + // set status to 'idle' + dispatch(conversationSlice.actions.setStatus('idle')); + } else { + const result = data.answer; + dispatch( + updateStreamingQuery({ + index: state.conversation.queries.length - 1, + query: { response: result }, + }), + ); + } + }, + ); + } else { + const answer = await fetchAnswerApi( + question, + state.preference.apiKey, + state.preference.selectedDocs!, + state.conversation.queries, + ); + dispatch( + // conversationSlice.actions.addQuery({ + // question: question, + // response: answer, + // }), + updateQuery({ + index: state.conversation.queries.length - 1, + query: { response: answer.answer }, + }), + ); + dispatch(conversationSlice.actions.setStatus('idle')); + } }); export const conversationSlice = createSlice({ @@ -48,7 +70,7 @@ export const conversationSlice = createSlice({ addQuery(state, action: PayloadAction) { state.queries.push(action.payload); }, - updateQuery( + updateStreamingQuery( state, action: PayloadAction<{ index: number; query: Partial }>, ) { @@ -64,6 +86,16 @@ export const conversationSlice = createSlice({ }; } }, + updateQuery( + state, + action: PayloadAction<{ index: number; query: Partial }>, + ) { + const index = action.payload.index; + state.queries[index] = { + ...state.queries[index], + ...action.payload.query, + }; + }, setStatus(state, action: PayloadAction) { state.status = action.payload; }, @@ -92,5 +124,6 @@ export const selectQueries = (state: RootState) => state.conversation.queries; export const selectStatus = (state: RootState) => state.conversation.status; -export const { addQuery, updateQuery } = conversationSlice.actions; +export const { addQuery, updateQuery, updateStreamingQuery } = + conversationSlice.actions; export default conversationSlice.reducer;