Skip to content

Commit

Permalink
Fixes for reloading from database
Browse files Browse the repository at this point in the history
  • Loading branch information
amrit110 committed Oct 3, 2024
1 parent 5240834 commit 78fbd65
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 104 deletions.
242 changes: 143 additions & 99 deletions ui/src/app/answer/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import React, { useEffect, useState, useCallback, useRef } from 'react'
import { useParams, useRouter } from 'next/navigation'
import React, { useEffect, useState, useCallback } from 'react'
import { useParams, useRouter, useSearchParams } from 'next/navigation'
import {
Box, Flex, VStack, useColorModeValue, Container, Card, CardBody,
useToast, Skeleton, Text, Heading, Progress
Expand All @@ -15,16 +15,25 @@ import StepsCard from '../../components/steps-card'

const MotionBox = motion<Omit<React.ComponentProps<typeof Box> & MotionProps, "transition">>(Box)

interface Step {
step: string;
reasoning: string;
}

interface Query {
query: string;
patient_id?: number;
steps?: Step[];
}

interface Answer {
answer: string;
reasoning: string;
}

interface QueryAnswer {
query: {
query: string;
patient_id?: number;
steps?: Array<{ step: string; reasoning: string }>;
};
answer?: {
answer: string;
reasoning: string;
};
query: Query;
answer?: Answer;
is_first: boolean;
}

Expand All @@ -42,25 +51,55 @@ const AnswerPage: React.FC = () => {
const [isGeneratingSteps, setIsGeneratingSteps] = useState<boolean>(false)
const [isGeneratingAnswer, setIsGeneratingAnswer] = useState<boolean>(false)
const params = useParams()
const searchParams = useSearchParams()
const id = params?.id as string
const isNewQuery = searchParams?.get('new') === 'true'
const router = useRouter()
const toast = useToast()

const generationStartedRef = useRef(false)

const bgColor = useColorModeValue('gray.50', 'gray.900')
const cardBgColor = useColorModeValue('white', 'gray.800')

const generateStepsAndAnswer = useCallback(async (query: string, patientId?: number) => {
if (generationStartedRef.current) return
generationStartedRef.current = true
setIsGeneratingSteps(true)
const fetchPageData = useCallback(async (): Promise<PageData | null> => {
setIsLoading(true)
try {
const token = localStorage.getItem('token')
if (!token) throw new Error('No token found')

const response = await fetch(`/api/pages/${id}`, {
headers: { 'Authorization': `Bearer ${token}` },
})

if (!response.ok) {
const errorData = await response.json()
throw new Error(`Failed to fetch page data: ${errorData.message}`)
}

const data: PageData = await response.json()
setPageData(data)
return data
} catch (error) {
console.error('Error loading page data:', error)
toast({
title: "Error",
description: error instanceof Error ? error.message : "An error occurred while loading page data",
status: "error",
duration: 3000,
isClosable: true,
})
return null
} finally {
setIsLoading(false)
}
}, [id, toast])


const generateSteps = useCallback(async (query: string, patientId?: number): Promise<Step[] | null> => {
setIsGeneratingSteps(true)
try {
const token = localStorage.getItem('token')
if (!token) throw new Error('No token found')

// Generate steps
const stepsResponse = await fetch('/api/generate_cot_steps', {
method: 'POST',
headers: {
Expand All @@ -71,26 +110,33 @@ const AnswerPage: React.FC = () => {
})

if (!stepsResponse.ok) {
throw new Error('Failed to generate steps')
const errorData = await stepsResponse.json()
throw new Error(`Failed to generate steps: ${errorData.message}`)
}

const stepsData = await stepsResponse.json()

setPageData(prevData => {
if (!prevData) return null
const updatedQueryAnswers = prevData.query_answers.map(qa => {
if (qa.is_first) {
return { ...qa, query: { ...qa.query, steps: stepsData.cot_steps } }
}
return qa
})
return { ...prevData, query_answers: updatedQueryAnswers }
return stepsData.cot_steps
} catch (error) {
console.error('Error generating steps:', error)
toast({
title: "Error",
description: error instanceof Error ? error.message : "An error occurred while generating steps",
status: "error",
duration: 3000,
isClosable: true,
})

return null
} finally {
setIsGeneratingSteps(false)
setIsGeneratingAnswer(true)
}
}, [toast])

const generateAnswer = useCallback(async (query: string, patientId?: number, steps?: Step[]): Promise<Answer | null> => {
setIsGeneratingAnswer(true)
try {
const token = localStorage.getItem('token')
if (!token) throw new Error('No token found')

// Generate answer
const answerResponse = await fetch('/api/generate_cot_answer', {
method: 'POST',
headers: {
Expand All @@ -100,86 +146,60 @@ const AnswerPage: React.FC = () => {
body: JSON.stringify({
query,
patient_id: patientId,
steps: stepsData.cot_steps
steps
}),
})

if (!answerResponse.ok) {
throw new Error('Failed to generate answer')
const errorData = await answerResponse.json()
throw new Error(`Failed to generate answer: ${errorData.message}`)
}

const answerData = await answerResponse.json()

setPageData(prevData => {
if (!prevData) return null
const updatedQueryAnswers = prevData.query_answers.map(qa => {
if (qa.is_first) {
return { ...qa, answer: answerData }
}
return qa
})
return { ...prevData, query_answers: updatedQueryAnswers }
})

return answerData
} catch (error) {
console.error('Error:', error)
console.error('Error generating answer:', error)
toast({
title: "Error",
description: error instanceof Error ? error.message : "An error occurred while generating steps and answer",
description: error instanceof Error ? error.message : "An error occurred while generating the answer",
status: "error",
duration: 3000,
isClosable: true,
})
return null
} finally {
setIsGeneratingSteps(false)
setIsGeneratingAnswer(false)
}
}, [toast])

useEffect(() => {
const fetchPageData = async () => {
setIsLoading(true)
try {
const token = localStorage.getItem('token')
if (!token) throw new Error('No token found')

const response = await fetch(`/api/pages/${id}`, {
headers: { 'Authorization': `Bearer ${token}` },
})

if (!response.ok) {
throw new Error('Failed to fetch page data')
}

const data: PageData = await response.json()
setPageData(data)
setIsLoading(false)
const [hasGeneratedAnswer, setHasGeneratedAnswer] = useState<boolean>(false)

const firstQueryAnswer = data.query_answers.find(qa => qa.is_first)
useEffect(() => {
const initializePage = async () => {
const data = await fetchPageData()
if (data && isNewQuery) {
const firstQueryAnswer = data.query_answers[0]
if (firstQueryAnswer && !firstQueryAnswer.query.steps) {
await generateStepsAndAnswer(firstQueryAnswer.query.query, firstQueryAnswer.query.patient_id)
const steps = await generateSteps(firstQueryAnswer.query.query, firstQueryAnswer.query.patient_id)
if (steps) {
const answer = await generateAnswer(firstQueryAnswer.query.query, firstQueryAnswer.query.patient_id, steps)
if (answer) {
setPageData(prevData => {
if (!prevData) return data
const updatedQueryAnswers = [
{ ...firstQueryAnswer, query: { ...firstQueryAnswer.query, steps }, answer },
...prevData.query_answers.slice(1)
]
return { ...prevData, query_answers: updatedQueryAnswers }
})
}
}
}
} catch (error) {
console.error('Error loading page data:', error)
toast({
title: "Error",
description: error instanceof Error ? error.message : "An error occurred while loading page data",
status: "error",
duration: 3000,
isClosable: true,
})
setIsLoading(false)
}
}

if (id) {
fetchPageData()
}

return () => {
generationStartedRef.current = false
}
}, [id, generateStepsAndAnswer, toast])
initializePage()
}, [fetchPageData, generateSteps, generateAnswer, isNewQuery])

const handleSearch = async (query: string) => {
if (!query.trim()) {
Expand All @@ -197,22 +217,48 @@ const AnswerPage: React.FC = () => {
const token = localStorage.getItem('token')
if (!token) throw new Error('No token found')

const createPageResponse = await fetch('/api/pages/create', {
// Append the new query to the existing page
const appendResponse = await fetch(`/api/pages/${id}/append`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query }),
body: JSON.stringify({ question: query }),
})

if (!createPageResponse.ok) {
throw new Error('Failed to create new page')
if (!appendResponse.ok) {
const errorData = await appendResponse.json()
throw new Error(`Failed to append to page: ${errorData.message}`)
}

const { page_id } = await createPageResponse.json()
// Generate steps for the new query
setIsGeneratingSteps(true)
const steps = await generateSteps(query)
setIsGeneratingSteps(false)

router.push(`/answer/${page_id}`)
if (steps) {
// Generate answer using the steps
setIsGeneratingAnswer(true)
const answer = await generateAnswer(query, undefined, steps)
setIsGeneratingAnswer(false)

if (answer) {
// Update the page data with the new query, steps, and answer
setPageData(prevData => {
if (!prevData) return null
const updatedQueryAnswers = [
...prevData.query_answers,
{
query: { query, steps },
answer,
is_first: false
}
]
return { ...prevData, query_answers: updatedQueryAnswers }
})
}
}
} catch (error) {
console.error('Error:', error)
toast({
Expand All @@ -225,7 +271,7 @@ const AnswerPage: React.FC = () => {
}
}

const firstQueryAnswer = pageData?.query_answers.find(qa => qa.is_first)
const firstQueryAnswer = pageData?.query_answers[0]

return (
<Flex minHeight="100vh" bg={bgColor}>
Expand Down Expand Up @@ -318,11 +364,9 @@ const AnswerPage: React.FC = () => {
</>
)}

{!pageData && (
<Box>
<SearchBox onSearch={handleSearch} isLoading={isLoading} />
</Box>
)}
<Box>
<SearchBox onSearch={handleSearch} isLoading={isLoading || isGeneratingSteps || isGeneratingAnswer} />
</Box>
</VStack>
</Container>
</Box>
Expand Down
12 changes: 7 additions & 5 deletions ui/src/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import Sidebar from '../components/sidebar'
import { withAuth } from '../components/with-auth'
import SearchBox from '../components/search-box'

interface CreatePageResponse {
page_id: string;
}

const HomePage: React.FC = () => {
const [isLoading, setIsLoading] = useState<boolean>(false)
const router = useRouter()
Expand Down Expand Up @@ -43,26 +47,24 @@ const HomePage: React.FC = () => {
}
router.push(`/patient/${patientId}`)
} else {
// Create a new page
const createPageResponse = await fetch('/api/pages/create', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: query }),
body: JSON.stringify({ query }),
})

if (!createPageResponse.ok) {
const errorData = await createPageResponse.json();
throw new Error(`Failed to create new page: ${JSON.stringify(errorData)}`);
}

const { page_id } = await createPageResponse.json()
const { page_id }: CreatePageResponse = await createPageResponse.json()

if (page_id) {
// Redirect to the new page
router.push(`/answer/${page_id}`)
router.push(`/answer/${page_id}?new=true`)
} else {
throw new Error('Failed to get page ID')
}
Expand Down

0 comments on commit 78fbd65

Please sign in to comment.