diff --git a/backend/src/songs/songs.resolver.ts b/backend/src/songs/songs.resolver.ts index 3e38f84..ff55adc 100644 --- a/backend/src/songs/songs.resolver.ts +++ b/backend/src/songs/songs.resolver.ts @@ -31,6 +31,17 @@ export class SongsResolver { return this.songsService.getSongData(songID); } + @Subscription(() => String, { resolve: (payload: { aiResponse: string | undefined }) => payload.aiResponse, }) + async *responseSub( + @Args('genres', { type: () => [String], defaultValue: ["Rock"] } ) genres: string[], + @Args('userVector', { type: () => [Float], defaultValue: USER_VECTOR }) userVector: number[], + ) : AsyncGenerator<{ aiResponse: string | undefined }> { + const aiStream = await this.songsService.getAIStream(genres, userVector); + for await (const chunk of aiStream) { + yield { aiResponse: chunk.text }; + } + } + @Subscription(() => String) aiResponse() { return this.pubSub.asyncIterableIterator('AI_RESPONSE') diff --git a/frontend/src/components/Utils/hooks/useSongRec.tsx b/frontend/src/components/Utils/hooks/useSongRec.tsx index 3ca0823..b8a72d6 100644 --- a/frontend/src/components/Utils/hooks/useSongRec.tsx +++ b/frontend/src/components/Utils/hooks/useSongRec.tsx @@ -1,42 +1,28 @@ -import { useEffect, useRef, useState } from "react"; +import { useState } from "react"; import { useAppSelector } from "../redux-hooks"; -import { aiSubscription, streamAIAnswer } from "@/queries/LaraRecQuerie"; -import { useMutation, useSubscription } from "@apollo/client"; +import { responseSub } from "@/queries/LaraRecQuerie"; +import { useSubscription } from "@apollo/client"; import generateUserVector from "../generateUserVector"; const useSongRec = () => { - const hasFetched = useRef(false); const [visibleCount, setVisibleCount] = useState(20); const [aiResponse, setAIResponse] = useState(""); - const [isSub, setIsSub] = useState(false); - const [streamAnswer] = useMutation(streamAIAnswer); const { genres, energy, speechLevel, danceability, tempo, sentiment, voiceType, mood, acousticness } = useAppSelector(state => state.songData); - const recommendations = useAppSelector(state => state.songData.results); - const visibleSongs = recommendations.slice(0, visibleCount); const userVector = generateUserVector(tempo, danceability, energy, mood, speechLevel, acousticness, voiceType, sentiment); - const { loading } = useSubscription(aiSubscription, { + useSubscription(responseSub, { + variables: { genres, userVector }, onData({ data }) { - const chunkText = data.data.aiResponse; - console.log(chunkText); - setAIResponse(prev => prev + chunkText) - }, + console.log(data) + const chunkText = data.data.responseSub; + setAIResponse(prev => prev + chunkText); + } }); - useEffect(() => { - const timer = setTimeout(() => setIsSub(false), 500); - return () => clearTimeout(timer) - }, []) - - useEffect(() => { - if (hasFetched.current || !loading || !isSub) return; - hasFetched.current = true; - setAIResponse(""); - console.log("using stream answer!") - streamAnswer({ variables: { genres, userVector } }); - }, [genres, userVector, streamAnswer, loading, isSub]); + const recommendations = useAppSelector(state => state.songData.results); + const visibleSongs = recommendations.slice(0, visibleCount); const loadMoreSongs = () => { if (visibleSongs.length < recommendations.length) { diff --git a/frontend/src/queries/LaraRecQuerie.ts b/frontend/src/queries/LaraRecQuerie.ts index 4ccc6b1..fdfee05 100644 --- a/frontend/src/queries/LaraRecQuerie.ts +++ b/frontend/src/queries/LaraRecQuerie.ts @@ -18,6 +18,12 @@ subscription { } `; +export const responseSub = gql` +subscription GetAIResponse($genres: [String!], $userVector: [Float!]) { + responseSub(genres: $genres, userVector: $userVector) +} +`; + export const streamAIAnswer = gql` mutation streamResponse($genres: [String!], $userVector: [Float!]) { streamAIResponse(genres: $genres, userVector: $userVector)