Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: updated /section/generate endpoint to fix 429 error #122

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 57 additions & 26 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -821,19 +821,29 @@ async def ensure_cosmos():
async def generate_section_content():
request_json = await request.get_json()
try:
# verify that section title and section description are provided
if "sectionTitle" not in request_json:
return jsonify({"error": "sectionTitle is required"}), 400

if "sectionDescription" not in request_json:
return jsonify({"error": "sectionDescription is required"}), 400

if not request_json or not isinstance(request_json, list):
return jsonify({"error": "Request must be a non-empty list."}), 400

if (
"sectionTitle" not in request_json[0]
or "sectionDescription" not in request_json[0]
):
return (
jsonify(
{
"error": "Each item in request must contain 'sectionTitle' and 'sectionDescription'."
}
),
400,
)

content = await generate_section_content(request_json, request.headers)
return jsonify({"section_content": content}), 200
except Exception as e:
logging.exception("Exception in /section/generate")
return jsonify({"error": str(e)}), 500


@bp.route("/document/<filepath>")
async def get_document(filepath):
try:
Expand All @@ -843,6 +853,7 @@ async def get_document(filepath):
logging.exception("Exception in /document/<filepath>")
return jsonify({"error": str(e)}), 500


async def generate_title(conversation_messages):
## make sure the messages are sorted by _ts descending
title_prompt = app_settings.azure_openai.title_prompt
Expand All @@ -864,35 +875,54 @@ async def generate_title(conversation_messages):
except Exception as e:
return messages[-2]["content"]

async def generate_section_content(request_body, request_headers):
prompt = f"""{app_settings.azure_openai.generate_section_content_prompt}

Section Title: {request_body['sectionTitle']}
Section Description: {request_body['sectionDescription']}
"""

messages = [
{
"role": "system",
"content": app_settings.azure_openai.system_message
}
]
messages.append({"role": "user", "content": prompt})

request_body['messages'] = messages
model_args = prepare_model_args(request_body, request_headers)
async def generate_section_content(request_body, request_headers):
user_prompt = f"{app_settings.azure_openai.generate_section_content_prompt}\n\n"
for section in request_body:
user_prompt += f"Section Title: {section['sectionTitle']}\nSection Description: {section['sectionDescription']}\n\n"

messages = [{"role": "system", "content": app_settings.azure_openai.system_message}]
messages.append({"role": "user", "content": user_prompt})
model_args = prepare_model_args({"messages": messages}, request_headers)
try:
azure_openai_client = init_openai_client()
raw_response = await azure_openai_client.chat.completions.with_raw_response.create(**model_args)
raw_response = (
await azure_openai_client.chat.completions.with_raw_response.create(
**model_args
)
)
response = raw_response.parse()

response_content = response.choices[0].message.content
if "The requested information is not available" in response_content:
return response_content

# Split the response content into individual sections
if len(request_body) == 1:
return [
{
"sectionTitle": request_body[0]["sectionTitle"],
"content": response.choices[0].message.content,
}
]
else:
response_content = response_content.strip().split("\n\n")

results = []
for i, section in enumerate(request_body):
results.append(
{
"sectionTitle": section["sectionTitle"],
"content": response_content[i],
}
)
return results

except Exception as e:
logging.exception("Exception in send_chat_request")
raise e

return response.choices[0].message.content


def retrieve_document(filepath):
try:
search_client = init_ai_search_client()
Expand All @@ -907,4 +937,5 @@ def retrieve_document(filepath):
logging.exception("Exception in retrieve_document")
raise e


app = create_app()
23 changes: 13 additions & 10 deletions frontend/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,19 +371,22 @@ export const historyMessageFeedback = async (messageId: string, feedback: string
return response
}

export const sectionGenerate = async (options: SectionGenerateRequest): Promise<Response> => {
export const sectionGenerate = async (options: SectionGenerateRequest[]): Promise<Response> => {
// set timeout to 10 seconds
const abortController = new AbortController()
const abortSignal = abortController.signal

const timeout = setTimeout(() => {
abortController.abort()
}, 10000)
// const timeout = setTimeout(() => {
// abortController.abort()
// }, 10000)

// let body = JSON.stringify({
// sectionTitle: options.sectionTitle,
// sectionDescription: options.sectionDescription
// })

let body = JSON.stringify(options)

let body = JSON.stringify({
sectionTitle: options.sectionTitle,
sectionDescription: options.sectionDescription
})

const response = await fetch('/section/generate', {
method: 'POST',
Expand All @@ -394,11 +397,11 @@ export const sectionGenerate = async (options: SectionGenerateRequest): Promise<
signal: abortSignal
})
.then(res => {
clearTimeout(timeout)
//clearTimeout(timeout)
return res
})
.catch(_err => {
clearTimeout(timeout)
// clearTimeout(timeout)
console.error('There was an issue fetching your data.')
return new Response(
JSON.stringify({ section_content: 'There was an issue fetching your data. Please try again.' })
Expand Down
24 changes: 15 additions & 9 deletions frontend/src/components/DraftCards/SectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const SectionCard = ({ sectionIdx }: SectionCardProps) => {
const appStateContext = useContext(AppStateContext)
const [charCount, setCharCount] = useState(0)
const [isManuallyCleared, setIsManuallyCleared] = useState(false)
const [sectionContent, setSectionContent] = useState('');

if (!appStateContext) {
throw new Error('useAppState must be used within a AppStateProvider')
Expand All @@ -131,26 +132,30 @@ const SectionCard = ({ sectionIdx }: SectionCardProps) => {

const sectionTitle = section.title
const sectionDescription = section.description
const sectionContent = section.content
const sectionCharacterLimit = 2000

useEffect(() => {
setCharCount(sectionContent.length)
}, [location])

useEffect(()=>{
setSectionContent(section.content)
},[section])

const handleOpenChange: PopoverProps['onOpenChange'] = (e, data) => setIsPopoverOpen(data.open || false)

async function fetchSectionContent(sectionTitle: string, sectionDescription: string) {
setIsLoading(true)
const sectionGenerateRequest: SectionGenerateRequest = { sectionTitle, sectionDescription }
const sectionGenerateRequest = [{'sectionTitle' : sectionTitle, 'sectionDescription': sectionDescription }]

const response = await sectionGenerate(sectionGenerateRequest)
const responseBody = await response.json()
const responseBody = await response.json();
const sContent = Array.isArray(responseBody.section_content) ? responseBody.section_content[0].content : responseBody.section_content;

const updatedSection: Section = {
title: sectionTitle,
description: sectionDescription,
content: responseBody.section_content
content: sContent
}
appStateContext?.dispatch({ type: 'UPDATE_SECTION', payload: { sectionIdx: sectionIdx, section: updatedSection } })
let content = updatedSection.content || ''
Expand All @@ -164,11 +169,11 @@ const SectionCard = ({ sectionIdx }: SectionCardProps) => {
setIsLoading(false)
}

useEffect(() => {
if (sectionContent === '' && !isLoading && !isManuallyCleared) {
fetchSectionContent(sectionTitle, sectionDescription)
}
}, [sectionContent, isLoading, isManuallyCleared])
// useEffect(() => {
// if (sectionContent === '' && !isLoading && !isManuallyCleared) {
// fetchSectionContent(sectionTitle, sectionDescription)
// }
// }, [sectionContent, isLoading, isManuallyCleared])

return (
<Stack className={classes.sectionCard}>
Expand Down Expand Up @@ -233,6 +238,7 @@ const SectionCard = ({ sectionIdx }: SectionCardProps) => {
appearance="outline"
size="large"
defaultValue={sectionContent}
value={sectionContent}
maxLength={sectionCharacterLimit}
onChange={(e, data) => {
const content = data.value || ''
Expand Down
Loading
Loading