From d55903f0b7b105408f9e46d4050a1bc180a8e31c Mon Sep 17 00:00:00 2001 From: Gabo Esquivel Date: Tue, 23 Apr 2024 09:44:35 -0600 Subject: [PATCH] wip: supabase search --- .../app/(browse)/[category]/page.tsx | 2 +- apps/masterbots.ai/app/(browse)/page.tsx | 5 +- apps/masterbots.ai/app/actions.ts | 100 ++++++++++++++++-- bun.lockb | Bin 393816 -> 393816 bytes 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/apps/masterbots.ai/app/(browse)/[category]/page.tsx b/apps/masterbots.ai/app/(browse)/[category]/page.tsx index 97851750..790e2629 100644 --- a/apps/masterbots.ai/app/(browse)/[category]/page.tsx +++ b/apps/masterbots.ai/app/(browse)/[category]/page.tsx @@ -25,7 +25,7 @@ export default async function CategoryPage({ const limit = searchParams.limit ? parseInt(searchParams.limit) : 20 const page = searchParams.page ? parseInt(searchParams.page) : 1 - const threads = await getThreads({ query }) + const threads = await getThreads() // Extract users and total number of users from the result // const users = result.users.items diff --git a/apps/masterbots.ai/app/(browse)/page.tsx b/apps/masterbots.ai/app/(browse)/page.tsx index 0771d1eb..216125e5 100644 --- a/apps/masterbots.ai/app/(browse)/page.tsx +++ b/apps/masterbots.ai/app/(browse)/page.tsx @@ -3,15 +3,16 @@ import { CategoryTabs } from '@/components/shared/category-tabs/category-tabs' import { SearchInput } from '@/components/shared/search-input' import { Card } from '@/components/ui/card' import { decodeQuery } from '@/lib/url-params' -import { getThreads } from '../actions' +import { getThreads, getThreadsLike } from '../actions' export default async function HomePage({ searchParams }: HomePageProps) { const query = searchParams.query ? decodeQuery(searchParams.query) : null const limit = searchParams.limit ? parseInt(searchParams.limit) : 20 const page = searchParams.page ? parseInt(searchParams.page) : 1 // console.log({ query, limit, page }) - const threads = await getThreads({ query }) + const threads = await (query? getThreadsLike({ query }) : getThreads()) + console.log(' ============== THREADS ============== ') return (
diff --git a/apps/masterbots.ai/app/actions.ts b/apps/masterbots.ai/app/actions.ts index aa04b36b..a27cda3c 100644 --- a/apps/masterbots.ai/app/actions.ts +++ b/apps/masterbots.ai/app/actions.ts @@ -1,10 +1,13 @@ 'use server' + import { createSupabaseServerClient } from '@/services/supabase' import { objectToCamel } from 'ts-case-convert' import type { MB } from '@repo/supabase' -import { omit } from 'lodash' +import { omit, uniq } from 'lodash' import { getFirstMessages } from '@/lib/threads' +// TODO: move complex queries to postgres funciton, maybe even ts gen works + // Shared ThreadFull like filter for supabase queries // It ensure you get the data you need to construct the ThreadFull object // Important to select only the data you need, nothing more @@ -15,14 +18,22 @@ const ThreadFullFilter = ` user (user_id,username,avatar) ` as const -export async function getThreads({ query }: { query?: string }): Promise { +export async function getThreads(): Promise { const supabase = await createSupabaseServerClient() - const threadsQuery = supabase.from('thread').select(ThreadFullFilter).range(0, 20) - const { data, error } = await threadsQuery - if (error) return [] - return data.map(createThreadFull) + + let threadsQuery = supabase + .from('thread') + .select(ThreadFullFilter, { count: 'exact' }); + + const { data, error, count } = await threadsQuery.range(30, 39) + console.log('🤌🏻', count); + + if (error) return []; + const filteredData = data.filter(thread => thread.message && thread.message.length > 0); + return filteredData.map(createThreadFull); } + export async function getThread({ threadId }: { @@ -49,15 +60,82 @@ function createThreadFull(threadData: any, messageCount = 0) { }) as unknown as MB.ThreadFull } + +export async function getThreadsLike({ query }: { query?: string }) { + console.log('🧑🏻‍💻 get threads like', query) + const supabase = await createSupabaseServerClient(); + + // Fetch message IDs that match the content criteria and prioritize by role + let messageResults = await supabase + .from('message') + .select('id, thread_id') // Assuming messages have a 'thread_id' to link to their thread + .filter('content', 'ilike', `%${query}%`) // Using 'like' for content matching + .order('role', { ascending: false }) // Order by role descending to prioritize 'user' over 'assistant' + .in('role', ['user', 'assistant']); // Ensure only 'user' and 'assistant' roles are considered + + if (messageResults.error || messageResults.data.length === 0) return []; + + + // Map to thread IDs for the next query + const threadIds = uniq(messageResults.data.map(msg => msg.thread_id)) + console.log('🙌🏻 threadIds', threadIds.length) + + // Fetch threads that have these message IDs + const threadsQuery = supabase + .from('thread') + .select(ThreadFullFilter) + // TODO: verify slicing doesnt affect priority + .in('thread_id', threadIds.slice(0,20)) + + const { data, error, count } = await threadsQuery; + + console.log('🤌🏻', error, count, data?.length) + + if (error) return []; + + return data.map(createThreadFull) +} + +export async function searchThreads({ query }: { query?: string }): Promise { + console.log('🧑🏻‍💻 search threads for', query) + const supabase = await createSupabaseServerClient() + + // First, fetch message IDs that match the text search criteria + const threadIds = await supabase + .from('message') + .select(`thread_id`) + .filter('role', 'eq', 'user') + .textSearch('content', query, { + config: 'english', + type: 'websearch' // Using 'websearch' for more natural queries + }); + + console.log(threadIds.data?.length, threadIds?.data) + + if (threadIds.error || threadIds.data?.length === 0) return []; + + // Extract the message IDs to use in the main query + const ids = threadIds.data.map(msg => msg.thread_id); + + // Now fetch threads that have these messages + const threadsQuery = supabase + .from('thread') + .select(ThreadFullFilter, { count: 'exact' }) + .in('thread_id', ids.slice(0,20)); + + const { data, error, count } = await threadsQuery + console.log('🤌🏻', error, count, data?.length); + + if (error) return []; + return data.map(createThreadFull) +} + + export async function getMessagePairs(threadId: string) { console.log('get message pairs for', threadId) return [] as MB.MessagePair[] } -// if (query) { -// supaQuery = supaQuery -// .filter('message.role', 'neq', 'system') -// .textSearch('message.content', query.toString()) -// } + diff --git a/bun.lockb b/bun.lockb index f3d6e89a19503f0965be32639055e0c08b98b316..fb6c1e6907736d8d2930043f3918ffa5c50cc501 100755 GIT binary patch delta 358 zcmV-s0h#{Tgc#U_7?3U?hg{{HPSp{jyI0JWu|I@T?8?usNTWd`;_eT?#GsrWmwE72h7_U^D@kzt10ZvSrbf-nwAK z+-V_Vez$!y0$@u(_)XNg)Gcbc@$?R{hL{Xxs&W_RiG0vT6vznUpGBS9gl44w^r%i+ za}J&6T7j>x$e9IY}0mmPls7(i!tvh&I;VA6jc997&v(zF2;9%G1?t=a^NJIFf#809dh>e_o`L`05d%=8o}YKbJKY4FVLm!EaO8(|e*%Yfe*?F5 ze*}Ub12HZzmk^Nz6t@na1cLOJ;|&EMx3H51E<^z_m*3X~T9>hY1tOOX+XV`@W!MGt EDYpBU8~^|S