Ignore:
Timestamp:
2024-03-05T13:28:52+13:00 (2 months ago)
Author:
davidb
Message:

Cleaned up version; work done on processAnnotation() displaying quote as source in MarkDown

File:
1 edited

Legend:

Unmodified
Added
Removed
  • gs3-extensions/dl-chatgpt/trunk/src/react-gui/pages/api/chat.ts

    r38816 r38821  
    55//   OPENAI_API_KEY=sk-????????????????????????????????????????????????
    66//   ORGANIZATION_ID=org-????????????????????????
    7 //   ASSISTANT_ID=asst_????????????????????????
    87
    98
     
    3332
    3433async function initGS3AssistantsLookup() {
    35 //const initGS3AssistantsLookup = async () => {
    3634    GS3AssistantLookup = new Map<string, any>();
    3735
     
    4745    let paginated_items = assistants_list_cursor.getPaginatedItems();
    4846   
    49     //while (assistants_list_cursor !== null) {
    5047    while (paginated_items.length > 0) {
    5148    let last_checked_assistant_id = "";
     
    9794}
    9895
    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
     97async function processAnnotations(message : MessageContentText)
    13398{
    13499    console.log("Process Annotations");
     
    138103
    139104    const citations: string[] = [];
    140    
     105
     106    var from_gsdocid_regex = new RegExp(/<span fromGSDocId="(.*?)">/, "g");
     107   
    141108    // 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
    143114    // 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}]`);
    147118   
    148119    // Gather citations based on annotation attributes
     
    150121        const file_citation = annotation.file_citation;
    151122        console.log(`    Retrieving file_citation for ${file_citation.file_id}`);
    152         const citedFile = await openai.files.retrieve(file_citation.file_id);
     123        const cited_file = await openai.files.retrieve(file_citation.file_id);
    153124        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        }
    155145        console.log(`    quote = ${quote}`);
    156146       
    157         citations.push(`[${index}] ${file_citation.quote} from ${citedFile.filename}`);
     147        citations.push(`[${index+1}] ${quote} -- (from ${source_reference})`);
    158148    }
    159149    else if ("file_path" in annotation) {
    160150        const file_path = annotation.file_path;
    161151        console.log(`    Retrieving file_path for ${annotation.file_path.file_id}`);
    162         const citedFile = await openai.files.retrieve(annotation.file_path.file_id);
    163         citations.push(`[${index}] Click <here> to download ${citedFile.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}`);
    164154        // Note: File download functionality not implemented above for brevity
    165155    }
    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
    175166}
    176 
    177 
    178    
    179167
    180168   
     
    189177    }
    190178
    191 
    192     // const assistantIdToUse = process.env.ASSISTANT_ID || "";
    193     // // const assistantIdToUse = "asst_LwUi7f2YMkZG5qTIPtpyhCOD";
    194 
     179    // ****
    195180    const assistantIdToUse = GS3AssistantLookup["thewillow"]["community-contributions"];
    196181   
     
    200185   
    201186    // Create a new thread if it's the user's first message
    202     //if (!UserThreadIdLookup[userId]) {
    203187    if (!UserThreadIdLookup.has(userId)) {
    204188    try {
     
    207191        console.log(`Created new thread with ID: '${myThread.id}'"`);
    208192        console.log("========")
    209         //UserThreadIdLookup[userId] = myThread.id; // Store the thread ID for this user
    210193       
    211194        UserThreadIdLookup.set(userId,myThread.id); // Store the thread ID for this user
     
    223206   
    224207    const userMessage = req.body.messages[num_messages-1].content;   
    225     //const userMessage = "What was the name of the DJ at The Willow?";
     208    //const userMessage = "What were some of the names of the DJs who worked at The Willow?";
    226209
    227210    console.log("--------");
     
    243226    const myThreadMessage = await openai.beta.threads.messages.create(myThreadId,user_message);
    244227
    245     //console.log("This is the message object: ", myThreadMessage, "\n");
    246    
    247228    // Run the Assistant
    248229    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 });
    262231    console.log("myRun: ", myRun, "\n");
    263232
     
    281250            console.log("--------");
    282251            break;
    283         }
    284        
     252        }       
    285253        }
    286254    }
    287    
    288     // Periodically retrieve the Run to check on its status
    289     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/577833
    296        
    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 user
    301             myThreadId,
    302             myRun.id
    303         );
    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");
    317255   
    318256    // Retrieve the Messages added by the Assistant to the Thread
    319257    const waitForAssistantMessage = async () => {
    320258        console.log("waitForAssistantMessage() away to call await checkStatusUntilComplete()");
    321         //await retrieveRun("withinWait");
    322259        await checkStatusUntilCompleted(myThreadId,myRun.id);
    323260        console.log("waitForAssistantMessage() returned from checkRunUntilComplete()");
    324261       
    325262        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");
    334266
    335267        const user_request_message: MessageContentText = (myThreadMessage.content[0]) as MessageContentText;
     
    340272        console.log("#####")
    341273
    342         processAnnotations(assistant_response_message);
     274        await processAnnotations(assistant_response_message);
    343275       
    344276        console.log("User: ", user_request_message.text.value);
     
    370302    req: NextApiRequest,
    371303    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) {   
    398305    const assistant_message = await assistantHandler(req,res);
    399306
    400     console.log("**** (assistant) completion message: ");
     307    console.log("++++++++");
     308    console.log("Assistant completion message: ");
    401309    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 });   
    406313}
    407314
Note: See TracChangeset for help on using the changeset viewer.