From f6ea13ebede8071fe229692f6ff8da6be06a1816 Mon Sep 17 00:00:00 2001 From: rupert-openai Date: Thu, 25 Jul 2024 15:41:27 +0100 Subject: [PATCH] Fixes to Sharepoint (Return Text) GPT Action Page (#1308) Co-authored-by: Aaron Wilkowitz <157151487+aaronwilkowitz-openai@users.noreply.github.com> --- .../gpt_action_sharepoint_text.ipynb | 59 ++++++++++++++++--- .../solution_two_preprocessing.js | 4 +- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_text.ipynb b/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_text.ipynb index 0450900d..42dd550b 100644 --- a/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_text.ipynb +++ b/examples/chatgpt/gpt_actions_library/gpt_action_sharepoint_text.ipynb @@ -185,7 +185,7 @@ "source": [ "Now that you have an authenticated Azure Function, we can update the function to search SharePoint / O365\n", "\n", - "2. Go to your test function and paste in the code from [this file]((https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js)). Save the function.\n", + "2. Go to your test function and paste in the code from [this file](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js). Save the function.\n", "\n", "> **This code is meant to be directional** - while it should work out of the box, it is designed to be customized to your needs (see examples towards the end of this document).\n", "\n", @@ -195,9 +195,7 @@ "\n", " 2. `CLIENT_ID`: copied from previous section \n", "\n", - " 3. _Solution 2 only:_\n", - "\n", - " 1. `OPENAI_API_KEY:` spin up an OpenAI API key on platform.openai.com.\n", + " 3. `OPENAI_API_KEY:` spin up an OpenAI API key on platform.openai.com.\n", "\n", "4. Go to the **Console** tab under the **Development Tools**\n", "\n", @@ -207,11 +205,9 @@ "\n", " 2. `npm install axios`\n", "\n", - " 3. _Solution 2 only:_\n", - "\n", - " 1. `npm install pdf-parse`\n", + " 3. `npm install pdf-parse`\n", "\n", - " 2. `npm install openai`\n", + " 4. `npm install openai`\n", "\n", "5. Once this is complete, try calling the function (POST call) from Postman again, putting the below into body (using a query and search term you think will generate responses).\n", "\n", @@ -242,8 +238,53 @@ "\n", "#### Implementing the Authentication \n", "\n", - "This solution follows the same authentication steps as solution 1 above - see [Initializing the Microsoft Graph Client](#initializing-the-microsoft-graph-client) and [Obtaining an On-Behalf-Of (OBO) Token](#obtaining-an-on-behalf-of-obo-token) sections.\n", + "Below we have a few helper functions that we’ll use in the function.\n", + "\n", + "#### Initializing the Microsoft Graph Client\n", + "Create a function to initialize the Graph client with an access token. This will be used to search through Office 365 and SharePoint.\n", + "\n", + "```javascript\n", + "const { Client } = require('@microsoft/microsoft-graph-client');\n", + "\n", + "function initGraphClient(accessToken) {\n", + " return Client.init({\n", + " authProvider: (done) => {\n", + " done(null, accessToken);\n", + " }\n", + " });\n", + "}\n", + "```\n", + "\n", + "#### Obtaining an On-Behalf-Of (OBO) Token\n", + "This function uses an existing bearer token to request an OBO token from Microsoft's identity platform. This enables passing through the credentials to ensure the search only returns files the logged-in user can access.\n", "\n", + "```javascript\n", + "const axios = require('axios');\n", + "const qs = require('querystring');\n", + "\n", + "async function getOboToken(userAccessToken) {\n", + " const { TENANT_ID, CLIENT_ID, MICROSOFT_PROVIDER_AUTHENTICATION_SECRET } = process.env;\n", + " const params = {\n", + " client_id: CLIENT_ID,\n", + " client_secret: MICROSOFT_PROVIDER_AUTHENTICATION_SECRET,\n", + " grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n", + " assertion: userAccessToken,\n", + " requested_token_use: 'on_behalf_of',\n", + " scope: 'https://graph.microsoft.com/.default'\n", + " };\n", + "\n", + " const url = `https\\://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;\n", + " try {\n", + " const response = await axios.post(url, qs.stringify(params), {\n", + " headers: { 'Content-Type': 'application/x-www-form-urlencoded' }\n", + " });\n", + " return response.data.access\\_token;\n", + " } catch (error) {\n", + " console.error('Error obtaining OBO token:', error.response?.data || error.message);\n", + " throw error;\n", + " }\n", + "}\n", + "```\n", "\n", "#### Retrieving Content from O365 / SharePoint Items\n", "\n", diff --git a/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js b/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js index 494b962a..39d149d1 100644 --- a/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js +++ b/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js @@ -97,8 +97,8 @@ const getRelevantParts = async (text, query) => { apiKey: openAIKey, }); const response = await openai.chat.completions.create({ - // Using got-4o-mini due to speed to prevent timeouts. You can tweak this prompt as needed - model: "got-4o-mini", + // Using gpt-4o-mini due to speed to prevent timeouts. You can tweak this prompt as needed + model: "gpt-4o-mini", messages: [ {"role": "system", "content": "You are a helpful assistant that finds relevant content in text based on a query. You only return the relevant sentences, and you return a maximum of 10 sentences"}, {"role": "user", "content": `Based on this question: **"${query}"**, get the relevant parts from the following text:*****\n\n${text}*****. If you cannot answer the question based on the text, respond with 'No information provided'`}