mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
feat: add data-provider
This commit is contained in:
parent
21920dd864
commit
2589754171
7 changed files with 578 additions and 0 deletions
81
client/src/data-provider/data-service.ts
Normal file
81
client/src/data-provider/data-service.ts
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
import * as t from './types';
|
||||
import request from './request';
|
||||
import * as endpoints from './endpoints';
|
||||
|
||||
export function getOpenAIModels(): Promise<t.TOpenAIModels> {
|
||||
return request.get(endpoints.openAiModels());
|
||||
}
|
||||
|
||||
export function postAICompletion(payload: t.TAICompletionRequest) {
|
||||
return request.post(endpoints.getAICompletion(), payload);
|
||||
}
|
||||
|
||||
export function getConversations(pageNumber: string): Promise<t.TGetConversationsResponse> {
|
||||
return request.get(endpoints.getConversations(pageNumber));
|
||||
}
|
||||
|
||||
export function deleteConversation(payload: t.TDeleteConversationRequest) {
|
||||
//todo: this should be a DELETE request
|
||||
return request.post(endpoints.deleteConversation(), payload);
|
||||
}
|
||||
|
||||
export function clearAllConversations() {
|
||||
return request.post(endpoints.deleteConversation());
|
||||
}
|
||||
|
||||
export function getMessagesByConvoId(id: string): Promise<t.TMessage[]> {
|
||||
return request.get(endpoints.getMessages(id));
|
||||
}
|
||||
|
||||
export function getConversationById(id: string): Promise<t.TConversation> {
|
||||
return request.get(endpoints.getConversationById(id));
|
||||
}
|
||||
|
||||
export function updateConversation(
|
||||
payload: t.TUpdateConversationRequest
|
||||
): Promise<t.TUpdateConversationResponse> {
|
||||
return request.post(endpoints.updateConversation(), payload);
|
||||
}
|
||||
|
||||
export function updateCustomGpt(payload: t.TUpdateCustomGptRequest) {
|
||||
return request.post(endpoints.customGpts(), payload);
|
||||
}
|
||||
|
||||
export function getCustomGpts(): Promise<t.TGetCustomGptsResponse> {
|
||||
return request.get(endpoints.customGpts());
|
||||
}
|
||||
|
||||
export function deleteCustomGpt(payload: t.TDeleteCustomGptRequest): Promise<t.TDeleteCustomGptResponse> {
|
||||
return request.post(endpoints.deleteCustomGpt(), payload);
|
||||
}
|
||||
|
||||
export function getModels(): Promise<t.TGetModelsResponse> {
|
||||
return request.get(endpoints.getModels());
|
||||
}
|
||||
|
||||
export function getSearchEnabled(): Promise<boolean> {
|
||||
return request.get(endpoints.searchEnabled());
|
||||
}
|
||||
|
||||
export function getSearchResults(q: string, pageNumber: string): Promise<t.TSearchResults> {
|
||||
return request.get(endpoints.search(q, pageNumber));
|
||||
}
|
||||
|
||||
export function getUser(): Promise<t.TUser> {
|
||||
return request.get(endpoints.user());
|
||||
}
|
||||
|
||||
type TSearchFetcherProps = {
|
||||
pre: () => void,
|
||||
q: string,
|
||||
pageNumber: string,
|
||||
callback: (data: any) => void
|
||||
};
|
||||
|
||||
export const searchFetcher = async ({ pre, q, pageNumber, callback }: TSearchFetcherProps) => {
|
||||
pre();
|
||||
//@ts-ignore
|
||||
const { data } = await request.get(endpoints.search(q, pageNumber));
|
||||
console.log('search data', data);
|
||||
callback(data);
|
||||
};
|
||||
60
client/src/data-provider/endpoints.ts
Normal file
60
client/src/data-provider/endpoints.ts
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
export const openAiModels = () => {
|
||||
return `/api/open-ai-models`;
|
||||
};
|
||||
|
||||
export const getModels = () => {
|
||||
return `/api/models`;
|
||||
};
|
||||
|
||||
export const getAICompletion = () => {
|
||||
return `/api/ask `;
|
||||
};
|
||||
|
||||
export const user = () => {
|
||||
return `/api/me`;
|
||||
};
|
||||
|
||||
export const getMessages = (id: string) => {
|
||||
return `/api/messages/${id}`;
|
||||
};
|
||||
|
||||
export const getConversations = (pageNumber: string) => {
|
||||
return `/api/convos?pageNumber=${pageNumber}`;
|
||||
};
|
||||
|
||||
export const getConversationById = (id: string) => {
|
||||
return `/api/convos/${id}`;
|
||||
};
|
||||
|
||||
export const updateConversation = () => {
|
||||
return `/api/convos/update`;
|
||||
};
|
||||
|
||||
export const deleteConversation = () => {
|
||||
return `/api/convos/clear`;
|
||||
};
|
||||
|
||||
export const prompts = () => {
|
||||
return `/api/prompts`;
|
||||
};
|
||||
|
||||
export const customGpts = () => {
|
||||
return `/api/customGpts`;
|
||||
};
|
||||
|
||||
// TODO: turn this into a DELETE instead of POST on the backend
|
||||
export const deleteCustomGpt = () => {
|
||||
return `/api/customGpts/delete`;
|
||||
};
|
||||
|
||||
export const generateTitle = () => {
|
||||
return `/api/convos/gen_title`;
|
||||
};
|
||||
|
||||
export const search = (q: string, pageNumber: string) => {
|
||||
return `/api/search?q=${q}&pageNumber=${pageNumber}`;
|
||||
}
|
||||
|
||||
export const searchEnabled = () => {
|
||||
return `/api/search/enable`;
|
||||
}
|
||||
9
client/src/data-provider/headers-helpers.ts
Normal file
9
client/src/data-provider/headers-helpers.ts
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import axios from 'axios';
|
||||
|
||||
export function setAcceptLanguageHeader(value: string): void {
|
||||
axios.defaults.headers.common['Accept-Language'] = value;
|
||||
}
|
||||
|
||||
export function setTokenHeader(token: string) {
|
||||
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token;
|
||||
}
|
||||
7
client/src/data-provider/index.ts
Normal file
7
client/src/data-provider/index.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export * from './data-service';
|
||||
// export * from './endpoints';
|
||||
export * from './request';
|
||||
export * from './types';
|
||||
export * from './react-query-service';
|
||||
export * from './headers-helpers';
|
||||
// export * from './events';
|
||||
172
client/src/data-provider/react-query-service.ts
Normal file
172
client/src/data-provider/react-query-service.ts
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
import {
|
||||
UseQueryOptions,
|
||||
useQuery,
|
||||
useMutation,
|
||||
useQueryClient,
|
||||
UseMutationResult,
|
||||
QueryObserverResult,
|
||||
} from "@tanstack/react-query";
|
||||
import * as t from "./types";
|
||||
import * as dataService from "./data-service";
|
||||
|
||||
export enum QueryKeys {
|
||||
messages = "messsages",
|
||||
allConversations = "allConversations",
|
||||
conversation = "conversation",
|
||||
models = "models",
|
||||
customGpts = "customGpts",
|
||||
searchEnabled = "searchEnabled",
|
||||
user = "user",
|
||||
}
|
||||
|
||||
export const useGetUserQuery = (): QueryObserverResult<t.TUser> => {
|
||||
return useQuery<t.TUser>([QueryKeys.user], () => dataService.getUser(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetMessagesByConvoId = (
|
||||
id: string,
|
||||
config?: UseQueryOptions<t.TMessage[]>
|
||||
): QueryObserverResult<t.TMessage[]> => {
|
||||
return useQuery<t.TMessage[]>([QueryKeys.messages, id], () =>
|
||||
dataService.getMessagesByConvoId(id),
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetConversationByIdQuery = (
|
||||
id: string,
|
||||
config?: UseQueryOptions<t.TConversation>
|
||||
): QueryObserverResult<t.TConversation> => {
|
||||
return useQuery<t.TConversation>([QueryKeys.conversation, id], () =>
|
||||
dataService.getConversationById(id),
|
||||
{
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
enabled: false,
|
||||
...config
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const useUpdateConversationMutation = (
|
||||
id: string
|
||||
): UseMutationResult<
|
||||
t.TUpdateConversationResponse,
|
||||
unknown,
|
||||
t.TUpdateConversationRequest,
|
||||
unknown
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(
|
||||
(payload: t.TUpdateConversationRequest) =>
|
||||
dataService.updateConversation(payload),
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries([QueryKeys.conversation, id]);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// export const useDeleteConversationMutation = (
|
||||
// id: string
|
||||
// ): UseMutationResult<
|
||||
|
||||
|
||||
export const useUpdateCustomGptMutation = (): UseMutationResult<
|
||||
t.TUpdateCustomGptResponse,
|
||||
unknown,
|
||||
t.TUpdateCustomGptRequest,
|
||||
unknown
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(
|
||||
(payload: t.TUpdateCustomGptRequest) =>
|
||||
dataService.updateCustomGpt(payload),
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries([QueryKeys.customGpts]);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetCustomGptsQuery = (): QueryObserverResult<
|
||||
t.TCustomGpt[],
|
||||
unknown
|
||||
> => {
|
||||
return useQuery([QueryKeys.customGpts], () => dataService.getCustomGpts(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteCustomGptMutation = (): UseMutationResult<
|
||||
t.TDeleteCustomGptResponse,
|
||||
unknown,
|
||||
t.TDeleteCustomGptRequest,
|
||||
unknown
|
||||
> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(
|
||||
(payload: t.TDeleteCustomGptRequest) =>
|
||||
dataService.deleteCustomGpt(payload),
|
||||
{
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries([QueryKeys.customGpts]);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetModelsQuery = (): QueryObserverResult<
|
||||
t.TGetModelsResponse,
|
||||
unknown
|
||||
> => {
|
||||
return useQuery([QueryKeys.models], () => dataService.getModels(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
});
|
||||
};
|
||||
|
||||
export const useClearConversationsMutation = (): UseMutationResult<unknown> => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(() => dataService.clearAllConversations(), {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries([QueryKeys.allConversations]);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useGetConversationsQuery = (pageNumber: string): QueryObserverResult<t.TGetConversationsResponse> => {
|
||||
return useQuery([QueryKeys.allConversations, pageNumber], () =>
|
||||
dataService.getConversations(pageNumber), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export const useGetSearchEnabledQuery = (config?: UseQueryOptions<boolean>): QueryObserverResult<boolean> => {
|
||||
return useQuery<boolean>([QueryKeys.searchEnabled], () =>
|
||||
dataService.getSearchEnabled(), {
|
||||
refetchOnWindowFocus: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
...config,
|
||||
}
|
||||
);
|
||||
}
|
||||
66
client/src/data-provider/request.ts
Normal file
66
client/src/data-provider/request.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
import axios, { AxiosRequestConfig } from "axios";
|
||||
|
||||
async function _get<T>(url: string, options?: AxiosRequestConfig): Promise<T> {
|
||||
const response = await axios.get(url, { withCredentials: true, ...options});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _post(url: string, data?: any) {
|
||||
const response = await axios.post(url, JSON.stringify(data), {
|
||||
withCredentials: true,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _postMultiPart(
|
||||
url: string,
|
||||
formData: FormData,
|
||||
options?: AxiosRequestConfig
|
||||
) {
|
||||
const response = await axios.post(url, formData, {
|
||||
withCredentials: true,
|
||||
...options,
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _put(url: string, data?: any) {
|
||||
const response = await axios.put(url, JSON.stringify(data), {
|
||||
withCredentials: true,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _delete<T>(url: string): Promise<T> {
|
||||
const response = await axios.delete(url, { withCredentials: true });
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _deleteWithOptions<T>(
|
||||
url: string,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<T> {
|
||||
const response = await axios.delete(url, { withCredentials: true, ...options});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async function _patch(url: string, data?: any) {
|
||||
const response = await axios.patch(url, JSON.stringify(data), {
|
||||
withCredentials: true,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
return response.data;
|
||||
}
|
||||
|
||||
export default {
|
||||
get: _get,
|
||||
post: _post,
|
||||
postMultiPart: _postMultiPart,
|
||||
put: _put,
|
||||
delete: _delete,
|
||||
deleteWithOptions: _deleteWithOptions,
|
||||
patch: _patch,
|
||||
};
|
||||
183
client/src/data-provider/types.ts
Normal file
183
client/src/data-provider/types.ts
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
export type TMessage = {
|
||||
messageId: string,
|
||||
conversationId: string,
|
||||
conversationSignature: string | null,
|
||||
clientId: string,
|
||||
invocationId: string,
|
||||
parentMessageId: string,
|
||||
sender: string,
|
||||
text: string,
|
||||
isCreatedByUser: boolean,
|
||||
error: boolean,
|
||||
createdAt: string,
|
||||
updatedAt: string,
|
||||
searchResult: string[],
|
||||
submitting: boolean,
|
||||
children?: any[] | undefined,
|
||||
bgColor?: string,
|
||||
model?: string,
|
||||
cancelled?: boolean
|
||||
};
|
||||
|
||||
export type TMessageTreeNode = {}
|
||||
|
||||
export type TSearchMessage = {}
|
||||
|
||||
export type TSearchMessageTreeNode = {}
|
||||
|
||||
export type TMessageToAsk = {}
|
||||
|
||||
|
||||
export enum EModelEndpoint {
|
||||
azureOpenAI = 'azureOpenAI',
|
||||
openAI = 'openAI',
|
||||
bingAI = 'bingAI',
|
||||
chatGPTBrowser = 'chatGPTBrowser'
|
||||
}
|
||||
|
||||
export type TConversation = {
|
||||
conversationId: string;
|
||||
title: string;
|
||||
user: string | null;
|
||||
endpoint: EModelEndpoint;
|
||||
model: string; // for azureOpenAI, openAI, chatGPTBrowser only, eg. gpt-3.5-turbo
|
||||
// for azureOpenAI, openAI only
|
||||
chatGptLabel?: string;
|
||||
promptPrefix?: string;
|
||||
temperature?: number;
|
||||
top_p?: number;
|
||||
presence_penalty?: number;
|
||||
// for bingAI only
|
||||
jailbreak?: boolean;
|
||||
jailbreakConversationId?: string;
|
||||
conversationSignature?: string;
|
||||
clientId?: string;
|
||||
invocationId?: string;
|
||||
toneStyle?: string;
|
||||
suggestions?: string[];
|
||||
messages?: TMessage[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export type TPrompt = {
|
||||
title: string,
|
||||
prompt: string,
|
||||
category: string,
|
||||
createdAt: string,
|
||||
updatedAt: string
|
||||
};
|
||||
|
||||
export type TCustomGpt = {
|
||||
chatGptLabel: string,
|
||||
promptPrefix: string,
|
||||
value: string,
|
||||
createdAt: string,
|
||||
updatedAt: string,
|
||||
_id: string
|
||||
};
|
||||
|
||||
export type TModel = {
|
||||
_id: string,
|
||||
name: string,
|
||||
value: string,
|
||||
model: string,
|
||||
chatGptLabel?: string,
|
||||
promptPrefix?: string
|
||||
};
|
||||
|
||||
export type TUser = {
|
||||
username: string,
|
||||
display: string
|
||||
};
|
||||
|
||||
export type TGetConversationsResponse = {
|
||||
conversations: TConversation[],
|
||||
pageNumber: string,
|
||||
pageSize: string | number,
|
||||
pages: string | number
|
||||
};
|
||||
|
||||
export type TGetConversationResponse = {
|
||||
data: TConversation
|
||||
};
|
||||
|
||||
export type TGetMessagesResponse = {
|
||||
data: TMessage[]
|
||||
};
|
||||
|
||||
export type TDeleteConversationRequest = {
|
||||
conversationId: string
|
||||
};
|
||||
|
||||
export type TAICompletionRequest = {
|
||||
chatGptLabel?: string,
|
||||
conversationId: string,
|
||||
current: boolean,
|
||||
isCreatedByUser: boolean,
|
||||
model: string,
|
||||
messageId: string,
|
||||
parentMessageId: string,
|
||||
overrideParentMessageId?: boolean,
|
||||
promptPrefix?: string,
|
||||
sender: string,
|
||||
text: string
|
||||
};
|
||||
|
||||
export type TGetModelsResponse = {
|
||||
hasOpenAI: boolean,
|
||||
hasChatGpt: boolean,
|
||||
hasBing: boolean
|
||||
};
|
||||
|
||||
export type TOpenAIModel = {
|
||||
object: string,
|
||||
id: string,
|
||||
ready: boolean,
|
||||
owner: string,
|
||||
created: string | null,
|
||||
permissions: string[] | null
|
||||
};
|
||||
|
||||
export type TOpenAIModels = {
|
||||
models: {
|
||||
object: string,
|
||||
data: TOpenAIModel[]
|
||||
}
|
||||
};
|
||||
|
||||
export type TConversationUpdate = {
|
||||
conversationId: string,
|
||||
title?: string
|
||||
};
|
||||
export type TUpdateConversationRequest = {
|
||||
arg: {},
|
||||
withCredentials?: boolean
|
||||
};
|
||||
|
||||
export type TUpdateConversationResponse = {
|
||||
data: TConversation
|
||||
};
|
||||
|
||||
export type TUpdateCustomGptRequest = {
|
||||
value: string,
|
||||
chatGptLabel: string,
|
||||
promptPrefix?: string,
|
||||
prevLabel?: string
|
||||
};
|
||||
|
||||
export type TUpdateCustomGptResponse = {};
|
||||
|
||||
export type TDeleteCustomGptRequest = {
|
||||
id: string
|
||||
};
|
||||
|
||||
export type TDeleteCustomGptResponse = {};
|
||||
|
||||
export type TClearConversationsRequest = {};
|
||||
|
||||
export type TClearConversationsResponse = {};
|
||||
|
||||
export type TGetCustomGptsResponse = {};
|
||||
|
||||
export type TSearchResults = {};
|
||||
Loading…
Add table
Add a link
Reference in a new issue