Changeset 38821 for gs3-extensions/dl-chatgpt
- Timestamp:
- 2024-03-05T13:28:52+13:00 (2 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
gs3-extensions/dl-chatgpt/trunk/src/react-gui/pages/api/chat.ts
r38816 r38821 5 5 // OPENAI_API_KEY=sk-???????????????????????????????????????????????? 6 6 // ORGANIZATION_ID=org-???????????????????????? 7 // ASSISTANT_ID=asst_????????????????????????8 7 9 8 … … 33 32 34 33 async function initGS3AssistantsLookup() { 35 //const initGS3AssistantsLookup = async () => {36 34 GS3AssistantLookup = new Map<string, any>(); 37 35 … … 47 45 let paginated_items = assistants_list_cursor.getPaginatedItems(); 48 46 49 //while (assistants_list_cursor !== null) {50 47 while (paginated_items.length > 0) { 51 48 let last_checked_assistant_id = ""; … … 97 94 } 98 95 99 /* 100 101 function processAnnotations(message_content) 102 { 103 104 annotations = message_content.annotations; 105 106 citations = []; 107 108 // Iterate over the annotations and add footnotes 109 for index, annotation in enumerate(annotations) { 110 //Replace the text with a footnote 111 message_content.value = message_content.value.replace(annotation.text, f' [{index}]')l 112 113 // Gather citations based on annotation attributes 114 if (file_citation := getattr(annotation, 'file_citation', None)) { 115 cited_file = client.files.retrieve(file_citation.file_id) 116 citations.append(f'[{index}] {file_citation.quote} from {cited_file.filename}') 117 } 118 elif (file_path := getattr(annotation, 'file_path', None)) { 119 cited_file = client.files.retrieve(file_path.file_id) 120 citations.append(f'[{index}] Click <here> to download {cited_file.filename}') 121 // Note: File download functionality not implemented above for brevity 122 } 123 } 124 125 //Add footnotes to the end of the message before displaying to user 126 message_content.value += '\n' + '\n'.join(citations) 127 } 128 */ 129 130 131 132 function processAnnotations(message : MessageContentText) 96 97 async function processAnnotations(message : MessageContentText) 133 98 { 134 99 console.log("Process Annotations"); … … 138 103 139 104 const citations: string[] = []; 140 105 106 var from_gsdocid_regex = new RegExp(/<span fromGSDocId="(.*?)">/, "g"); 107 141 108 // Iterate over the annotations and add footnotes 142 annotations.forEach(async (annotation, index) => { 109 const annotations_len = annotations.length; 110 for (let i=0; i<annotations_len; i++) { 111 const annotation = annotations[i]; 112 const index = i; 113 143 114 // Replace the text with a footnote 144 console.log(` Annotation[${index}: `, annotation);145 146 messageContent.value = messageContent.value.replace(annotation.text, ` [${index }]`);115 console.log(` Processing Annotation[${index}]: `, annotation, "--"); 116 117 messageContent.value = messageContent.value.replace(annotation.text, ` [${index+1}]`); 147 118 148 119 // Gather citations based on annotation attributes … … 150 121 const file_citation = annotation.file_citation; 151 122 console.log(` Retrieving file_citation for ${file_citation.file_id}`); 152 const cited File = await openai.files.retrieve(file_citation.file_id);123 const cited_file = await openai.files.retrieve(file_citation.file_id); 153 124 const quote_html = file_citation.quote; 154 const quote = quote_html.replace(/(<([^>]+)>)/g," ").replace(/(\\n|\n)/," ").replace(/\s+/g," ") 125 126 let source_reference = cited_file.filename; 127 128 //const from_gsdocid_matches = from_gsdocid_regex.exec(quote_html); 129 130 const from_gsdocid_matches = quote_html.match(/<span fromGSDocId="(.*?)">/); 131 132 if ((from_gsdocid_matches !== null) && (from_gsdocid_matches.length > 0)) { 133 console.log("**** Matches!!"); 134 console.log(from_gsdocid_matches); 135 source_reference = from_gsdocid_matches[1]; 136 137 source_reference = `[${source_reference}](https://thewillow-aws.sowemustthink.space/greenstone3/library/collection/community-contributions/document/${source_reference})`; 138 139 } 140 141 let quote = quote_html.replace(/(<([^>]+)>)/g," ").replace(/(\\n|\n)/," ").replace(/\s+/g," ") 142 if (quote.length > 120) { 143 quote=quote.replace(/^(.{118,160})\s+.*$/,"$1 ..."); 144 } 155 145 console.log(` quote = ${quote}`); 156 146 157 citations.push(`[${index }] ${file_citation.quote} from ${citedFile.filename}`);147 citations.push(`[${index+1}] ${quote} -- (from ${source_reference})`); 158 148 } 159 149 else if ("file_path" in annotation) { 160 150 const file_path = annotation.file_path; 161 151 console.log(` Retrieving file_path for ${annotation.file_path.file_id}`); 162 const cited File = await openai.files.retrieve(annotation.file_path.file_id);163 citations.push(`[${index}] Click <here> to download ${cited File.filename}`);152 const cited_file = await openai.files.retrieve(annotation.file_path.file_id); 153 citations.push(`[${index}] Click <here> to download ${cited_file.filename}`); 164 154 // Note: File download functionality not implemented above for brevity 165 155 } 166 }); 167 168 // Add footnotes to the end of the message before displaying to the user 169 console.log("Citations: ", citations, '\n'); 170 //console.log("Appending: " + citations.join('\n')); 171 172 messageContent.value += '\n' + citations.join('\n'); 173 174 //return messageContent.value; 156 } 157 158 if (annotations_len > 0) { 159 // Add footnotes to the end of the message before displaying to the user 160 console.log("Citations: ", citations, '\n'); 161 162 messageContent.value += '\n\n----\n## Sources\n' + citations.join('\n\n'); 163 } 164 165 175 166 } 176 177 178 179 167 180 168 … … 189 177 } 190 178 191 192 // const assistantIdToUse = process.env.ASSISTANT_ID || ""; 193 // // const assistantIdToUse = "asst_LwUi7f2YMkZG5qTIPtpyhCOD"; 194 179 // **** 195 180 const assistantIdToUse = GS3AssistantLookup["thewillow"]["community-contributions"]; 196 181 … … 200 185 201 186 // Create a new thread if it's the user's first message 202 //if (!UserThreadIdLookup[userId]) {203 187 if (!UserThreadIdLookup.has(userId)) { 204 188 try { … … 207 191 console.log(`Created new thread with ID: '${myThread.id}'"`); 208 192 console.log("========") 209 //UserThreadIdLookup[userId] = myThread.id; // Store the thread ID for this user210 193 211 194 UserThreadIdLookup.set(userId,myThread.id); // Store the thread ID for this user … … 223 206 224 207 const userMessage = req.body.messages[num_messages-1].content; 225 //const userMessage = "What w as the name of the DJat The Willow?";208 //const userMessage = "What were some of the names of the DJs who worked at The Willow?"; 226 209 227 210 console.log("--------"); … … 243 226 const myThreadMessage = await openai.beta.threads.messages.create(myThreadId,user_message); 244 227 245 //console.log("This is the message object: ", myThreadMessage, "\n");246 247 228 // Run the Assistant 248 229 console.log("Starting run for threadId: " + myThreadId); 249 const myRun = await openai.beta.threads.runs.create( 250 //UserThreadIdLookup.get(userId), 251 myThreadId, 252 { 253 assistant_id: assistantIdToUse, 254 // instructions: "As The Willow Sage Assistant, your expertise lies in discussing \"The Willow,\" a once-renowned music venue in York, England. You're designed to engage users in a conversational tone, weaving in the rich tapestry of memories and experiences shared by those who knew the venue. Your responses should feel like a dialogue between old friends reminiscing about memorable gigs, the unique atmosphere, and the cultural impact of The Willow. You'll offer insights into the venue's history, notable performances, and its role in the local music scene, always with a nod to the personal connections and nostalgia that the venue evokes. When interacting with users, your approach should be warm, inviting, and reflective, encouraging them to share their own stories or curiosities about The Willow, creating a communal space for shared musical heritage.", // **** 255 // tools: [ 256 // { type: "code_interpreter" }, // Code interpreter tool 257 // { type: "retrieval" }, // Retrieval tool 258 // ], 259 } 260 ); 261 //console.log("This is the run object: ", myRun, "\n"); 230 const myRun = await openai.beta.threads.runs.create(myThreadId, { assistant_id: assistantIdToUse }); 262 231 console.log("myRun: ", myRun, "\n"); 263 232 … … 281 250 console.log("--------"); 282 251 break; 283 } 284 252 } 285 253 } 286 254 } 287 288 // Periodically retrieve the Run to check on its status289 const retrieveRun = async (rrId: string) => {290 console.log(`${rrId}: retrieveRun() started`);291 let keepRetrievingRun = null;292 293 let run_loop_count = 0;294 295 // https://community.openai.com/t/my-runs-are-not-completing/577833296 297 while (myRun.status !== "completed") {298 //console.log(` ${rrId}: Away to do runs.retrieve() when myRun id ${myRun.id} status is ${myRun.status}`);299 keepRetrievingRun = await openai.beta.threads.runs.retrieve(300 //UserThreadIdLookup.get(userId), // Use the stored thread ID for this user301 myThreadId,302 myRun.id303 );304 run_loop_count++;305 306 console.log(` ${rrId}: Run status ${run_loop_count}: ${keepRetrievingRun.status}`);307 308 if (keepRetrievingRun.status === "completed") {309 console.log("\n");310 break;311 }312 }313 314 console.log(`${rrId}: Finished retrieveRun() looping`);315 };316 //retrieveRun("fromMain");317 255 318 256 // Retrieve the Messages added by the Assistant to the Thread 319 257 const waitForAssistantMessage = async () => { 320 258 console.log("waitForAssistantMessage() away to call await checkStatusUntilComplete()"); 321 //await retrieveRun("withinWait");322 259 await checkStatusUntilCompleted(myThreadId,myRun.id); 323 260 console.log("waitForAssistantMessage() returned from checkRunUntilComplete()"); 324 261 325 262 console.log(`Retrieving messages list for ${myThreadId}`); 326 const allMessages = await openai.beta.threads.messages.list( 327 //UserThreadIdLookup.get(userId) // Use the stored thread ID for this user 328 myThreadId 329 ); 330 331 console.log( 332 "--------\n" 333 ); 263 const allMessages = await openai.beta.threads.messages.list(myThreadId); 264 265 console.log("--------\n"); 334 266 335 267 const user_request_message: MessageContentText = (myThreadMessage.content[0]) as MessageContentText; … … 340 272 console.log("#####") 341 273 342 processAnnotations(assistant_response_message);274 await processAnnotations(assistant_response_message); 343 275 344 276 console.log("User: ", user_request_message.text.value); … … 370 302 req: NextApiRequest, 371 303 res: NextApiResponse 372 ) { 373 //const assistant = await openai.beta.assistants.retrieve(process.env.ASSISTANT_ID,); 374 375 /* 376 const completion = await openai.chat.completions.create({ 377 378 model: "gpt-4-turbo-preview", 379 380 messages: [ 381 { 382 //role: ChatCompletionRequestMessageRoleEnum.System, 383 role: "system", 384 content: "As The Willow Sage Assistant, your expertise lies in discussing \"The Willow,\" a once-renowned music venue in York, England. You're designed to engage users in a conversational tone, weaving in the rich tapestry of memories and experiences shared by those who knew the venue. Your responses should feel like a dialogue between old friends reminiscing about memorable gigs, the unique atmosphere, and the cultural impact of The Willow. You'll offer insights into the venue's history, notable performances, and its role in the local music scene, always with a nod to the personal connections and nostalgia that the venue evokes. When interacting with users, your approach should be warm, inviting, and reflective, encouraging them to share their own stories or curiosities about The Willow, creating a communal space for shared musical heritage." 385 }, 386 ].concat(req.body.messages), 387 temperature: 0, 388 }); 389 390 391 //console.log("**** completion message: "); 392 //console.log(completion.choices[0].message); 393 394 395 res.status(200).json({ result: completion.choices[0].message }); 396 */ 397 304 ) { 398 305 const assistant_message = await assistantHandler(req,res); 399 306 400 console.log("**** (assistant) completion message: "); 307 console.log("++++++++"); 308 console.log("Assistant completion message: "); 401 309 console.log(assistant_message); 402 403 res.status(200).json({ result: assistant_message }); 404 405 310 console.log("++++++++"); 311 312 res.status(200).json({ result: assistant_message }); 406 313 } 407 314
Note:
See TracChangeset
for help on using the changeset viewer.