From 1130746f5de0b04f7fd03bf0340d24c3012ee863 Mon Sep 17 00:00:00 2001 From: ItzCrazyKns <95534749+ItzCrazyKns@users.noreply.github.com> Date: Wed, 19 Mar 2025 13:38:40 +0530 Subject: [PATCH] feat(app): add image & video search functionality --- ui/app/api/images/route.ts | 83 ++++++++++++++++++++++++++ ui/app/api/videos/route.ts | 83 ++++++++++++++++++++++++++ ui/components/SearchImages.tsx | 41 +++++++------ ui/components/SearchVideos.tsx | 41 +++++++------ ui/lib/chains/imageSearchAgent.ts | 90 ++++++++++++++++++++++++++++ ui/lib/chains/videoSearchAgent.ts | 97 +++++++++++++++++++++++++++++++ 6 files changed, 393 insertions(+), 42 deletions(-) create mode 100644 ui/app/api/images/route.ts create mode 100644 ui/app/api/videos/route.ts create mode 100644 ui/lib/chains/imageSearchAgent.ts create mode 100644 ui/lib/chains/videoSearchAgent.ts diff --git a/ui/app/api/images/route.ts b/ui/app/api/images/route.ts new file mode 100644 index 0000000..4114cbd --- /dev/null +++ b/ui/app/api/images/route.ts @@ -0,0 +1,83 @@ +import handleImageSearch from '@/lib/chains/imageSearchAgent'; +import { + getCustomOpenaiApiKey, + getCustomOpenaiApiUrl, + getCustomOpenaiModelName, +} from '@/lib/config'; +import { getAvailableChatModelProviders } from '@/lib/providers'; +import { BaseChatModel } from '@langchain/core/language_models/chat_models'; +import { AIMessage, HumanMessage } from '@langchain/core/messages'; +import { ChatOpenAI } from '@langchain/openai'; + +interface ChatModel { + provider: string; + model: string; +} + +interface ImageSearchBody { + query: string; + chatHistory: any[]; + chatModel?: ChatModel; +} + +export const POST = async (req: Request) => { + try { + const body: ImageSearchBody = await req.json(); + + const chatHistory = body.chatHistory + .map((msg: any) => { + if (msg.role === 'user') { + return new HumanMessage(msg.content); + } else if (msg.role === 'assistant') { + return new AIMessage(msg.content); + } + }) + .filter((msg) => msg !== undefined); + + const chatModelProviders = await getAvailableChatModelProviders(); + + const chatModelProvider = + chatModelProviders[ + body.chatModel?.provider || Object.keys(chatModelProviders)[0] + ]; + const chatModel = + chatModelProvider[ + body.chatModel?.model || Object.keys(chatModelProvider)[0] + ]; + + let llm: BaseChatModel | undefined; + + if (body.chatModel?.provider === 'custom_openai') { + llm = new ChatOpenAI({ + openAIApiKey: getCustomOpenaiApiKey(), + modelName: getCustomOpenaiModelName(), + temperature: 0.7, + configuration: { + baseURL: getCustomOpenaiApiUrl(), + }, + }); + } else if (chatModelProvider && chatModel) { + llm = chatModel.model; + } + + if (!llm) { + return Response.json({ error: 'Invalid chat model' }, { status: 400 }); + } + + const images = await handleImageSearch( + { + chat_history: chatHistory, + query: body.query, + }, + llm, + ); + + return Response.json({ images }, { status: 200 }); + } catch (err) { + console.error(`An error ocurred while searching images: ${err}`); + return Response.json( + { message: 'An error ocurred while searching images' }, + { status: 500 }, + ); + } +}; diff --git a/ui/app/api/videos/route.ts b/ui/app/api/videos/route.ts new file mode 100644 index 0000000..9b4bf9f --- /dev/null +++ b/ui/app/api/videos/route.ts @@ -0,0 +1,83 @@ +import handleVideoSearch from '@/lib/chains/videoSearchAgent'; +import { + getCustomOpenaiApiKey, + getCustomOpenaiApiUrl, + getCustomOpenaiModelName, +} from '@/lib/config'; +import { getAvailableChatModelProviders } from '@/lib/providers'; +import { BaseChatModel } from '@langchain/core/language_models/chat_models'; +import { AIMessage, HumanMessage } from '@langchain/core/messages'; +import { ChatOpenAI } from '@langchain/openai'; + +interface ChatModel { + provider: string; + model: string; +} + +interface VideoSearchBody { + query: string; + chatHistory: any[]; + chatModel?: ChatModel; +} + +export const POST = async (req: Request) => { + try { + const body: VideoSearchBody = await req.json(); + + const chatHistory = body.chatHistory + .map((msg: any) => { + if (msg.role === 'user') { + return new HumanMessage(msg.content); + } else if (msg.role === 'assistant') { + return new AIMessage(msg.content); + } + }) + .filter((msg) => msg !== undefined); + + const chatModelProviders = await getAvailableChatModelProviders(); + + const chatModelProvider = + chatModelProviders[ + body.chatModel?.provider || Object.keys(chatModelProviders)[0] + ]; + const chatModel = + chatModelProvider[ + body.chatModel?.model || Object.keys(chatModelProvider)[0] + ]; + + let llm: BaseChatModel | undefined; + + if (body.chatModel?.provider === 'custom_openai') { + llm = new ChatOpenAI({ + openAIApiKey: getCustomOpenaiApiKey(), + modelName: getCustomOpenaiModelName(), + temperature: 0.7, + configuration: { + baseURL: getCustomOpenaiApiUrl(), + }, + }); + } else if (chatModelProvider && chatModel) { + llm = chatModel.model; + } + + if (!llm) { + return Response.json({ error: 'Invalid chat model' }, { status: 400 }); + } + + const videos = await handleVideoSearch( + { + chat_history: chatHistory, + query: body.query, + }, + llm, + ); + + return Response.json({ videos }, { status: 200 }); + } catch (err) { + console.error(`An error ocurred while searching videos: ${err}`); + return Response.json( + { message: 'An error ocurred while searching videos' }, + { status: 500 }, + ); + } +}; diff --git a/ui/components/SearchImages.tsx b/ui/components/SearchImages.tsx index 383f780..08c16ee 100644 --- a/ui/components/SearchImages.tsx +++ b/ui/components/SearchImages.tsx @@ -14,9 +14,11 @@ type Image = { const SearchImages = ({ query, chatHistory, + messageId, }: { query: string; chatHistory: Message[]; + messageId: string; }) => { const [images, setImages] = useState(null); const [loading, setLoading] = useState(false); @@ -27,7 +29,7 @@ const SearchImages = ({ <> {!loading && images === null && (