# embeddings_queue

created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 7848bf6c-3848-4c35-9fd0-f75b3c9bac4b
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb", "title": "Getting Started with OpenAI Evals", "tokens": 15953, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"7848bf6c-3848-4c35-9fd0-f75b3c9bac4b\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a7ec993c-08fc-4643-844a-c524bc7c3f16\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"768291709437390dd549b3ed69ab84d94f65bcf3ff582852d98e4f92a5a40095\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"32de8531-d78f-4cae-869b-643bfc2439a7\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"bac33913ada2e5360bf72540fb18a424adeee8410530d3cfbcad0f4b23840045\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"0d21d848-2c0c-4065-945f-aa629eb21e1d\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"42e338f1df2f76b100b9cbf663bcd88ce512a131678cd3692062fe336d720aea\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 58213, \"end_char_idx\": 61303, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "ref_doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "chroma:document": "```python\n# Inspect metrics where choice is made and print only the prompt, result, and expected result if the choice is incorrect\nfor i, row in events_df[events_df['type'] == 'metrics'].iterrows():\n    if row['data']['choice'] == 'Incorrect':\n        # Get the previous row's data, which contains the prompt and the expected result\n        prev_row = events_df.iloc[i-1]\n        prompt = prev_row['data']['prompt'][0]['content'] if 'prompt' in prev_row['data'] and len(prev_row['data']['prompt']) > 0 else \"Prompt not available\"\n        expected_result = prev_row['data'].get('ideal', 'Expected result not provided')\n        \n        # Current row's data will be the actual result\n        result = row['data'].get('result', 'Actual result not provided')\n        \n        pretty_print_text(prompt)\n        print(\"-\" * 40)\n```\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>How many countries have a republic as their form of government?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT count(*) FROM country WHERE GovernmentForm  =  \"Republic\"\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT COUNT(*) \nFROM country \nWHERE GovernmentForm LIKE '%Republic%'\n\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>Return the document id, template id, and description for the document with the name Robbin CV.\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT document_id ,  template_id ,  Document_Description FROM Documents WHERE document_name  =  \"Robbin CV\"\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT Documents.Document_ID, Documents.Template_ID, Documents.Document_Description\nFROM Documents\nJOIN Templates ON Documents.Template_ID = Templates.Template_ID\nWHERE Documents.Document_Name = 'Robbin CV';\n\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>Which professionals live in the state of Indiana or have done treatment on more than 2 treatments? List his or her id, last name and cell phone.\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT professional_id ,  last_name ,  cell_number FROM Professionals WHERE state  =  'Indiana' UNION SELECT T1.professional_id ,  T1.last_name ,  T1.cell_number FROM Professionals AS T1 JOIN Treatments AS T2 ON T1.professional_id  =  T2.professional_id GROUP BY T1.professional_id HAVING count(*)  >  2\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT professional_id, last_name, cell_number\nFROM Professionals\nWHERE state = 'Indiana'\nOR professional_id IN (\n    SELECT professional_id\n    FROM Treatments\n    GROUP BY professional_id\n    HAVING COUNT(*) > 2\n);\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>What is the continent name which Anguilla belongs to?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT Continent FROM country WHERE Name  =  \"Anguilla\"\n************</span>"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 0d21d848-2c0c-4065-945f-aa629eb21e1d
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb", "title": "Getting Started with OpenAI Evals", "tokens": 15953, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"0d21d848-2c0c-4065-945f-aa629eb21e1d\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a7ec993c-08fc-4643-844a-c524bc7c3f16\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"768291709437390dd549b3ed69ab84d94f65bcf3ff582852d98e4f92a5a40095\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"7848bf6c-3848-4c35-9fd0-f75b3c9bac4b\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"59cd05af2fba430ae2c191492e8cc7f531aefe1341d9053270aa4ce8dfd55449\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"0c727f9d-090f-4ca0-80a3-8d14dad639f6\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"d93fb102df7799c5f49af1b446e5f57ad73eee8ef49a7ad1a8e6aaa7035ae59f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 59651, \"end_char_idx\": 61846, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "ref_doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "chroma:document": "<span style=\"color: #008000;\">EXPECTED:<br>SELECT document_id ,  template_id ,  Document_Description FROM Documents WHERE document_name  =  \"Robbin CV\"\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT Documents.Document_ID, Documents.Template_ID, Documents.Document_Description\nFROM Documents\nJOIN Templates ON Documents.Template_ID = Templates.Template_ID\nWHERE Documents.Document_Name = 'Robbin CV';\n\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>Which professionals live in the state of Indiana or have done treatment on more than 2 treatments? List his or her id, last name and cell phone.\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT professional_id ,  last_name ,  cell_number FROM Professionals WHERE state  =  'Indiana' UNION SELECT T1.professional_id ,  T1.last_name ,  T1.cell_number FROM Professionals AS T1 JOIN Treatments AS T2 ON T1.professional_id  =  T2.professional_id GROUP BY T1.professional_id HAVING count(*)  >  2\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT professional_id, last_name, cell_number\nFROM Professionals\nWHERE state = 'Indiana'\nOR professional_id IN (\n    SELECT professional_id\n    FROM Treatments\n    GROUP BY professional_id\n    HAVING COUNT(*) > 2\n);\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>What is the continent name which Anguilla belongs to?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT Continent FROM country WHERE Name  =  \"Anguilla\"\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT c.Continent\nFROM country c\nWHERE c.Code = 'AIA';\n\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>How many airlines do we have?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT count(*) FROM AIRLINES\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT COUNT(DISTINCT Airline) AS TotalAirlines\nFROM airlines;\n************</span>\n\n\n    ----------------------------------------"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 0c727f9d-090f-4ca0-80a3-8d14dad639f6
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb", "title": "Getting Started with OpenAI Evals", "tokens": 15953, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"0c727f9d-090f-4ca0-80a3-8d14dad639f6\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"a7ec993c-08fc-4643-844a-c524bc7c3f16\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"768291709437390dd549b3ed69ab84d94f65bcf3ff582852d98e4f92a5a40095\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"0d21d848-2c0c-4065-945f-aa629eb21e1d\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Getting_Started_with_OpenAI_Evals.ipynb\", \"title\": \"Getting Started with OpenAI Evals\", \"tokens\": 15953, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"fff891177ef2fbb3dfbc338898f05a9ac776770b836b585d37c049a8cde026c7\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 60362, \"end_char_idx\": 63108, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "ref_doc_id": "a7ec993c-08fc-4643-844a-c524bc7c3f16", "chroma:document": "<span style=\"color: #008000;\">EXPECTED:<br>SELECT professional_id ,  last_name ,  cell_number FROM Professionals WHERE state  =  'Indiana' UNION SELECT T1.professional_id ,  T1.last_name ,  T1.cell_number FROM Professionals AS T1 JOIN Treatments AS T2 ON T1.professional_id  =  T2.professional_id GROUP BY T1.professional_id HAVING count(*)  >  2\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT professional_id, last_name, cell_number\nFROM Professionals\nWHERE state = 'Indiana'\nOR professional_id IN (\n    SELECT professional_id\n    FROM Treatments\n    GROUP BY professional_id\n    HAVING COUNT(*) > 2\n);\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>What is the continent name which Anguilla belongs to?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT Continent FROM country WHERE Name  =  \"Anguilla\"\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT c.Continent\nFROM country c\nWHERE c.Code = 'AIA';\n\n************</span>\n\n\n    ----------------------------------------\n\n\n\n<span style=\"color: #0000FF;\">QUESTION:<br>How many airlines do we have?\n\n************</span>\n\n\n\n<span style=\"color: #008000;\">EXPECTED:<br>SELECT count(*) FROM AIRLINES\n************</span>\n\n\n\n<span style=\"color: #FFA500;\">SUBMISSION:<br>SELECT COUNT(DISTINCT Airline) AS TotalAirlines\nFROM airlines;\n************</span>\n\n\n    ----------------------------------------\n\n\nReviewing some of the failures we see the following:\n* The second incorrect answer had an unnecessary join with the 'Templates' table. Our eval was able to accurately identify this and flag this as incorrect. \n* Few other answers have minor syntax differences that caused the answers to get flagged.\n  * In situations like this, it would be worthwhile exploring whether we should continue iterating on the prompt to ensure certain stylistic choices, or if we should modify the evaluation suite to capture this variation.\n  * This type of failure hints at the potential need for model-graded evals as a way to ensure accuracy in grading the results\n\n# Conclusion\n\nBuilding out effective evals is a core part of the development cycle of LLM-based applications. The OpenAI Evals framework provides the core structure of building evals out of the box, and allows you to quickly spin up new tests for your various use cases. In this guide, we demonstrated step-by-step how to create an eval, run it, and analyze the results.\n\nThe example shown in this guide represent a straightfoward use case for evals. As you continue to explore this framework, we recommend you explore creating more complex model-graded evals for actual production use cases. Happy evaluating!"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c6a66e83-a6f1-4772-a174-1323d2df995c
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c6a66e83-a6f1-4772-a174-1323d2df995c\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"fbaa895d-5682-484b-97ff-699217657376\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4987a94b9964c66fd52540d6ed08d64f33ec1c0cc7725cb5e845dbc12a104f94\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 3549, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "# Evaluate RAG with LlamaIndex\n\nIn this notebook we will look into building an RAG pipeline and evaluating it with LlamaIndex. It has following 3 sections.\n\n1. Understanding Retrieval Augmented Generation (RAG).\n2. Building RAG with LlamaIndex.\n3. Evaluating RAG with LlamaIndex.\n\n**Retrieval Augmented Generation (RAG)**\n\nLLMs are trained on vast datasets, but these will not include your specific data. Retrieval-Augmented Generation (RAG) addresses this by dynamically incorporating your data during the generation process. This is done not by altering the training data of LLMs, but by allowing the model to access and utilize your data in real-time to provide more tailored and contextually relevant responses.\n\nIn RAG, your data is loaded and and prepared for queries or \u201cindexed\u201d. User queries act on the index, which filters your data down to the most relevant context. This context and your query then go to the LLM along with a prompt, and the LLM provides a response.\n\nEven if what you\u2019re building is a chatbot or an agent, you\u2019ll want to know RAG techniques for getting data into your application.\n\n![RAG Overview](../../images/llamaindex_rag_overview.png)\n\n**Stages within RAG**\n\nThere are five key stages within RAG, which in turn will be a part of any larger application you build. These are:\n\n**Loading:** this refers to getting your data from where it lives \u2013 whether it\u2019s text files, PDFs, another website, a database, or an API \u2013 into your pipeline. LlamaHub provides hundreds of connectors to choose from.\n\n**Indexing:** this means creating a data structure that allows for querying the data. For LLMs this nearly always means creating vector embeddings, numerical representations of the meaning of your data, as well as numerous other metadata strategies to make it easy to accurately find contextually relevant data.\n\n**Storing:** Once your data is indexed, you will want to store your index, along with any other metadata, to avoid the need to re-index it.\n\n**Querying:** for any given indexing strategy there are many ways you can utilize LLMs and LlamaIndex data structures to query, including sub-queries, multi-step queries and hybrid strategies.\n\n**Evaluation:** a critical step in any pipeline is checking how effective it is relative to other strategies, or when you make changes. Evaluation provides objective measures of how accurate, faithful and fast your responses to queries are.\n\n## Build RAG system.\n\nNow that we have understood the significance of RAG system, let's build a simple RAG pipeline.\n\n\n```python\n!pip install llama-index\n```\n\n\n```python\n# The nest_asyncio module enables the nesting of asynchronous functions within an already running async loop.\n# This is necessary because Jupyter notebooks inherently operate in an asynchronous loop.\n# By applying nest_asyncio, we can run additional async functions within this existing loop without conflicts.\nimport nest_asyncio\n\nnest_asyncio.apply()\n\nfrom llama_index.evaluation import generate_question_context_pairs\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\nfrom llama_index.node_parser import SimpleNodeParser\nfrom llama_index.evaluation import generate_question_context_pairs\nfrom llama_index.evaluation import RetrieverEvaluator\nfrom llama_index.llms import OpenAI\n\nimport os\nimport pandas as pd\n```\n\nSet Your OpenAI API Key\n\n\n```python\nos.environ['OPENAI_API_KEY'] = 'YOUR OPENAI API KEY'\n```\n\nLet's use [Paul Graham Essay text](https://www.paulgraham.com/worked.html) for building RAG pipeline.\n\n#### Download Data"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: fbaa895d-5682-484b-97ff-699217657376
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"fbaa895d-5682-484b-97ff-699217657376\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c6a66e83-a6f1-4772-a174-1323d2df995c\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"0faf228e5bc8a80222528f722a0c78d455d584894cd1b845a2c73dc0ab710031\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"2327a528-3ed7-48a0-ac0b-4c80e409d1bb\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"61da286d96fb963babd58cdeeadd7f9bc332f4579fcbc66c3f1f1b17c7cb20ea\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2536, \"end_char_idx\": 5052, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "```python\n!pip install llama-index\n```\n\n\n```python\n# The nest_asyncio module enables the nesting of asynchronous functions within an already running async loop.\n# This is necessary because Jupyter notebooks inherently operate in an asynchronous loop.\n# By applying nest_asyncio, we can run additional async functions within this existing loop without conflicts.\nimport nest_asyncio\n\nnest_asyncio.apply()\n\nfrom llama_index.evaluation import generate_question_context_pairs\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\nfrom llama_index.node_parser import SimpleNodeParser\nfrom llama_index.evaluation import generate_question_context_pairs\nfrom llama_index.evaluation import RetrieverEvaluator\nfrom llama_index.llms import OpenAI\n\nimport os\nimport pandas as pd\n```\n\nSet Your OpenAI API Key\n\n\n```python\nos.environ['OPENAI_API_KEY'] = 'YOUR OPENAI API KEY'\n```\n\nLet's use [Paul Graham Essay text](https://www.paulgraham.com/worked.html) for building RAG pipeline.\n\n#### Download Data\n\n\n```python\n!mkdir -p 'data/paul_graham/'\n!curl 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt' -o 'data/paul_graham/paul_graham_essay.txt'\n```\n\n      % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current\n                                     Dload  Upload   Total   Spent    Left  Speed\n    100 75042  100 75042    0     0   190k      0 --:--:-- --:--:-- --:--:--  190k--:--  0:00:03 24586\n\n\n#### Load Data and Build Index.\n\n\n```python\ndocuments = SimpleDirectoryReader(\"./data/paul_graham/\").load_data()\n\n# Define an LLM\nllm = OpenAI(model=\"gpt-4\")\n\n# Build index with a chunk_size of 512\nnode_parser = SimpleNodeParser.from_defaults(chunk_size=512)\nnodes = node_parser.get_nodes_from_documents(documents)\nvector_index = VectorStoreIndex(nodes)\n```\n\nBuild a QueryEngine and start querying.\n\n\n```python\nquery_engine = vector_index.as_query_engine()\n```\n\n\n```python\nresponse_vector = query_engine.query(\"What did the author do growing up?\")\n```\n\nCheck response.\n\n\n```python\nresponse_vector.response\n```\n\n\n\n\n    'The author wrote short stories and worked on programming, specifically on an IBM 1401 computer using an early version of Fortran.'\n\n\n\nBy default it retrieves `two` similar nodes/ chunks. You can modify that in `vector_index.as_query_engine(similarity_top_k=k)`.\n\nLet's check the text in each of these retrieved nodes.\n\n\n```python\n# First retrieved node\nresponse_vector.source_nodes[0].get_text()\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 2327a528-3ed7-48a0-ac0b-4c80e409d1bb
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2327a528-3ed7-48a0-ac0b-4c80e409d1bb\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"fbaa895d-5682-484b-97ff-699217657376\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"4776de8bd34aa62c6ac9e6f8020b6b188b3d52d21a6e2cd3601f82e94aebe17f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4ea5f7bf-0ddd-4b38-924a-96835c00f885\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"81bd1a393b6cb99db4709af65021450a8d4448932336a3cef5fe84a52cdd8971\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4034, \"end_char_idx\": 7154, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "#### Load Data and Build Index.\n\n\n```python\ndocuments = SimpleDirectoryReader(\"./data/paul_graham/\").load_data()\n\n# Define an LLM\nllm = OpenAI(model=\"gpt-4\")\n\n# Build index with a chunk_size of 512\nnode_parser = SimpleNodeParser.from_defaults(chunk_size=512)\nnodes = node_parser.get_nodes_from_documents(documents)\nvector_index = VectorStoreIndex(nodes)\n```\n\nBuild a QueryEngine and start querying.\n\n\n```python\nquery_engine = vector_index.as_query_engine()\n```\n\n\n```python\nresponse_vector = query_engine.query(\"What did the author do growing up?\")\n```\n\nCheck response.\n\n\n```python\nresponse_vector.response\n```\n\n\n\n\n    'The author wrote short stories and worked on programming, specifically on an IBM 1401 computer using an early version of Fortran.'\n\n\n\nBy default it retrieves `two` similar nodes/ chunks. You can modify that in `vector_index.as_query_engine(similarity_top_k=k)`.\n\nLet's check the text in each of these retrieved nodes.\n\n\n```python\n# First retrieved node\nresponse_vector.source_nodes[0].get_text()\n```\n\n\n\n\n    'What I Worked On\\n\\nFebruary 2021\\n\\nBefore college the two main things I worked on, outside of school, were writing and programming. I didn\\'t write essays. I wrote what beginning writers were supposed to write then, and probably still are: short stories. My stories were awful. They had hardly any plot, just characters with strong feelings, which I imagined made them deep.\\n\\nThe first programs I tried writing were on the IBM 1401 that our school district used for what was then called \"data processing.\" This was in 9th grade, so I was 13 or 14. The school district\\'s 1401 happened to be in the basement of our junior high school, and my friend Rich Draves and I got permission to use it. It was like a mini Bond villain\\'s lair down there, with all these alien-looking machines \u2014 CPU, disk drives, printer, card reader \u2014 sitting up on a raised floor under bright fluorescent lights.\\n\\nThe language we used was an early version of Fortran. You had to type programs on punch cards, then stack them in the card reader and press a button to load the program into memory and run it. The result would ordinarily be to print something on the spectacularly loud printer.\\n\\nI was puzzled by the 1401. I couldn\\'t figure out what to do with it. And in retrospect there\\'s not much I could have done with it. The only form of input to programs was data stored on punched cards, and I didn\\'t have any data stored on punched cards. The only other option was to do things that didn\\'t rely on any input, like calculate approximations of pi, but I didn\\'t know enough math to do anything interesting of that type. So I\\'m not surprised I can\\'t remember any programs I wrote, because they can\\'t have done much. My clearest memory is of the moment I learned it was possible for programs not to terminate, when one of mine didn\\'t. On a machine without time-sharing, this was a social as well as a technical error, as the data center manager\\'s expression made clear.\\n\\nWith microcomputers, everything changed.'\n\n\n\n\n```python\n# Second retrieved node\nresponse_vector.source_nodes[1].get_text()\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 4ea5f7bf-0ddd-4b38-924a-96835c00f885
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4ea5f7bf-0ddd-4b38-924a-96835c00f885\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2327a528-3ed7-48a0-ac0b-4c80e409d1bb\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"41469b2004099464480bf9ddf983ad852d923e2c5b371f2a0807b4061e4c58e0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"588f2f3f-a86e-4639-8cf0-d322c5f2879c\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c04fa934ab1372695a643ad2181d320704d196e8cbcd866226719624c27f30ca\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7074, \"end_char_idx\": 9296, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "```python\n# Second retrieved node\nresponse_vector.source_nodes[1].get_text()\n```\n\n\n\n\n    \"It felt like I was doing life right. I remember that because I was slightly dismayed at how novel it felt. The good news is that I had more moments like this over the next few years.\\n\\nIn the summer of 2016 we moved to England. We wanted our kids to see what it was like living in another country, and since I was a British citizen by birth, that seemed the obvious choice. We only meant to stay for a year, but we liked it so much that we still live there. So most of Bel was written in England.\\n\\nIn the fall of 2019, Bel was finally finished. Like McCarthy's original Lisp, it's a spec rather than an implementation, although like McCarthy's Lisp it's a spec expressed as code.\\n\\nNow that I could write essays again, I wrote a bunch about topics I'd had stacked up. I kept writing essays through 2020, but I also started to think about other things I could work on. How should I choose what to do? Well, how had I chosen what to work on in the past? I wrote an essay for myself to answer that question, and I was surprised how long and messy the answer turned out to be. If this surprised me, who'd lived it, then I thought perhaps it would be interesting to other people, and encouraging to those with similarly messy lives. So I wrote a more detailed version for others to read, and this is the last sentence of it.\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nNotes\\n\\n[1] My experience skipped a step in the evolution of computers: time-sharing machines with interactive OSes. I went straight from batch processing to microcomputers, which made microcomputers seem all the more exciting.\\n\\n[2] Italian words for abstract concepts can nearly always be predicted from their English cognates (except for occasional traps like polluzione). It's the everyday words that differ. So if you string together a lot of abstract concepts with a few simple verbs, you can make a little Italian go a long way.\\n\\n[3] I lived at Piazza San Felice 4, so my walk to the Accademia went straight down the spine of old Florence: past the Pitti, across the bridge, past Orsanmichele, between the Duomo and the Baptistery, and then up Via Ricasoli to Piazza San Marco.\""}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 588f2f3f-a86e-4639-8cf0-d322c5f2879c
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"588f2f3f-a86e-4639-8cf0-d322c5f2879c\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4ea5f7bf-0ddd-4b38-924a-96835c00f885\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"6f011ed0db493d5c4e165df089c4b780d3302efa11ac001c3de1418cedf7b846\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ecbcd0ba-b2a4-485c-bfb2-010bede41053\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"b73f12652763c10651caedcb96949757445bf1aea680b1f95df7293ebc735e5f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9300, \"end_char_idx\": 12800, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "We have built a RAG pipeline and now need to evaluate its performance. We can assess our RAG system/query engine using LlamaIndex's core evaluation modules. Let's examine how to leverage these tools to quantify the quality of our retrieval-augmented generation system.\n\n## Evaluation\n\nEvaluation should serve as the primary metric for assessing your RAG application. It determines whether the pipeline will produce accurate responses based on the data sources and a range of queries.\n\nWhile it's beneficial to examine individual queries and responses at the start, this approach may become impractical as the volume of edge cases and failures increases. Instead, it may be more effective to establish a suite of summary metrics or automated evaluations. These tools can provide insights into overall system performance and indicate specific areas that may require closer scrutiny.\n\nIn a RAG system, evaluation focuses on two critical aspects:\n\n*   **Retrieval Evaluation:** This assesses the accuracy and relevance of the information retrieved by the system.\n*   **Response Evaluation:** This measures the quality and appropriateness of the responses generated by the system based on the retrieved information.\n\n#### Question-Context Pair Generation:\n\nFor the evaluation of a RAG system, it's essential to have queries that can fetch the correct context and subsequently generate an appropriate response. `LlamaIndex` offers a `generate_question_context_pairs` module specifically for crafting questions and context pairs which can be used in the assessment of the RAG system of both Retrieval and Response Evaluation. For more details on Question Generation, please refer to the [documentation](https://docs.llamaindex.ai/en/stable/examples/evaluation/QuestionGeneration.html).\n\n\n```python\nqa_dataset = generate_question_context_pairs(\n    nodes,\n    llm=llm,\n    num_questions_per_chunk=2\n)\n```\n\n    100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 58/58 [06:26<00:00,  6.67s/it]\n\n\n#### Retrieval Evaluation:\n\nWe are now prepared to conduct our retrieval evaluations. We will execute our `RetrieverEvaluator` using the evaluation dataset we have generated.\n\nWe first create the `Retriever` and then define two functions: `get_eval_results`, which operates our retriever on the dataset, and `display_results`, which presents the outcomes of the evaluation.\n\nLet's create the retriever.\n\n\n```python\nretriever = vector_index.as_retriever(similarity_top_k=2)\n```\n\nDefine `RetrieverEvaluator`. We use **Hit Rate** and **MRR** metrics to evaluate our Retriever.\n\n**Hit Rate:**\n\nHit rate calculates the fraction of queries where the correct answer is found within the top-k retrieved documents. In simpler terms, it\u2019s about how often our system gets it right within the top few guesses.\n\n**Mean Reciprocal Rank (MRR):**\n\nFor each query, MRR evaluates the system\u2019s accuracy by looking at the rank of the highest-placed relevant document. Specifically, it\u2019s the average of the reciprocals of these ranks across all the queries. So, if the first relevant document is the top result, the reciprocal rank is 1; if it\u2019s second, the reciprocal rank is 1/2, and so on.\n\nLet's check these metrics to check the performance of out retriever.\n\n\n```python\nretriever_evaluator = RetrieverEvaluator.from_metric_names(\n    [\"mrr\", \"hit_rate\"], retriever=retriever\n)\n```\n\n\n```python\n# Evaluate\neval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)\n```\n\nLet's define a function to display the Retrieval evaluation results in table format."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: ecbcd0ba-b2a4-485c-bfb2-010bede41053
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ecbcd0ba-b2a4-485c-bfb2-010bede41053\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"588f2f3f-a86e-4639-8cf0-d322c5f2879c\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7944b33bcec19cba256b20f74f99120037af9ad27b8eb2ca5160f4d21b219b29\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"41c48007-c539-48f0-979e-218f5498dc83\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f0c32c09851d0ec78ec39e7758ebb04c7f7983d69d4700d7061f846cfd345133\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11252, \"end_char_idx\": 13969, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "#### Retrieval Evaluation:\n\nWe are now prepared to conduct our retrieval evaluations. We will execute our `RetrieverEvaluator` using the evaluation dataset we have generated.\n\nWe first create the `Retriever` and then define two functions: `get_eval_results`, which operates our retriever on the dataset, and `display_results`, which presents the outcomes of the evaluation.\n\nLet's create the retriever.\n\n\n```python\nretriever = vector_index.as_retriever(similarity_top_k=2)\n```\n\nDefine `RetrieverEvaluator`. We use **Hit Rate** and **MRR** metrics to evaluate our Retriever.\n\n**Hit Rate:**\n\nHit rate calculates the fraction of queries where the correct answer is found within the top-k retrieved documents. In simpler terms, it\u2019s about how often our system gets it right within the top few guesses.\n\n**Mean Reciprocal Rank (MRR):**\n\nFor each query, MRR evaluates the system\u2019s accuracy by looking at the rank of the highest-placed relevant document. Specifically, it\u2019s the average of the reciprocals of these ranks across all the queries. So, if the first relevant document is the top result, the reciprocal rank is 1; if it\u2019s second, the reciprocal rank is 1/2, and so on.\n\nLet's check these metrics to check the performance of out retriever.\n\n\n```python\nretriever_evaluator = RetrieverEvaluator.from_metric_names(\n    [\"mrr\", \"hit_rate\"], retriever=retriever\n)\n```\n\n\n```python\n# Evaluate\neval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)\n```\n\nLet's define a function to display the Retrieval evaluation results in table format.\n\n\n```python\ndef display_results(name, eval_results):\n    \"\"\"Display results from evaluate.\"\"\"\n\n    metric_dicts = []\n    for eval_result in eval_results:\n        metric_dict = eval_result.metric_vals_dict\n        metric_dicts.append(metric_dict)\n\n    full_df = pd.DataFrame(metric_dicts)\n\n    hit_rate = full_df[\"hit_rate\"].mean()\n    mrr = full_df[\"mrr\"].mean()\n\n    metric_df = pd.DataFrame(\n        {\"Retriever Name\": [name], \"Hit Rate\": [hit_rate], \"MRR\": [mrr]}\n    )\n\n    return metric_df\n```\n\n\n```python\ndisplay_results(\"OpenAI Embedding Retriever\", eval_results)\n```\n\n\n\n\n<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Retriever Name</th>\n      <th>Hit Rate</th>\n      <th>MRR</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>OpenAI Embedding Retriever</td>\n      <td>0.758621</td>\n      <td>0.62069</td>\n    </tr>\n  </tbody>\n</table>\n</div>"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 41c48007-c539-48f0-979e-218f5498dc83
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"41c48007-c539-48f0-979e-218f5498dc83\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ecbcd0ba-b2a4-485c-bfb2-010bede41053\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"51f9e6e0f79a9aa24393431eadcff2f8124fd66df028e16c46e2706035e69a48\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"4429f711-4749-4bc0-9d76-591fc7cd7a80\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"549106f8cb76e64f06462e529b22bf76d9967224215f05a7db7b7fad0c367dee\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 12619, \"end_char_idx\": 15282, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "```python\n# Evaluate\neval_results = await retriever_evaluator.aevaluate_dataset(qa_dataset)\n```\n\nLet's define a function to display the Retrieval evaluation results in table format.\n\n\n```python\ndef display_results(name, eval_results):\n    \"\"\"Display results from evaluate.\"\"\"\n\n    metric_dicts = []\n    for eval_result in eval_results:\n        metric_dict = eval_result.metric_vals_dict\n        metric_dicts.append(metric_dict)\n\n    full_df = pd.DataFrame(metric_dicts)\n\n    hit_rate = full_df[\"hit_rate\"].mean()\n    mrr = full_df[\"mrr\"].mean()\n\n    metric_df = pd.DataFrame(\n        {\"Retriever Name\": [name], \"Hit Rate\": [hit_rate], \"MRR\": [mrr]}\n    )\n\n    return metric_df\n```\n\n\n```python\ndisplay_results(\"OpenAI Embedding Retriever\", eval_results)\n```\n\n\n\n\n<div>\n<style scoped>\n    .dataframe tbody tr th:only-of-type {\n        vertical-align: middle;\n    }\n\n    .dataframe tbody tr th {\n        vertical-align: top;\n    }\n\n    .dataframe thead th {\n        text-align: right;\n    }\n</style>\n<table border=\"1\" class=\"dataframe\">\n  <thead>\n    <tr style=\"text-align: right;\">\n      <th></th>\n      <th>Retriever Name</th>\n      <th>Hit Rate</th>\n      <th>MRR</th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr>\n      <th>0</th>\n      <td>OpenAI Embedding Retriever</td>\n      <td>0.758621</td>\n      <td>0.62069</td>\n    </tr>\n  </tbody>\n</table>\n</div>\n\n\n\n#### Observation:\n\nThe Retriever with OpenAI Embedding  demonstrates a performance with a hit rate of `0.7586`, while the MRR, at `0.6206`, suggests there's room for improvement in ensuring the most relevant results appear at the top. The observation that MRR is less than the hit rate indicates that the top-ranking results aren't always the most relevant. Enhancing MRR could involve the use of rerankers, which refine the order of retrieved documents. For a deeper understanding of how rerankers can optimize retrieval metrics, refer to the detailed discussion in our [blog post](https://blog.llamaindex.ai/boosting-rag-picking-the-best-embedding-reranker-models-42d079022e83).\n\n#### Response Evaluation:\n\n1. FaithfulnessEvaluator: Measures if the response from a query engine matches any source nodes which is useful for measuring if the response is hallucinated.\n2. Relevancy Evaluator: Measures if the response + source nodes match the query.\n\n\n```python\n# Get the list of queries from the above created dataset\n\nqueries = list(qa_dataset.queries.values())\n```\n\n#### Faithfulness Evaluator\n\nLet's start with FaithfulnessEvaluator.\n\nWe will use `gpt-3.5-turbo` for generating response for a given query and `gpt-4` for evaluation.\n\nLet's create service_context seperately for `gpt-3.5-turbo` and `gpt-4`."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 4429f711-4749-4bc0-9d76-591fc7cd7a80
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"4429f711-4749-4bc0-9d76-591fc7cd7a80\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"41c48007-c539-48f0-979e-218f5498dc83\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"5eb97467bb193a103c8e6a850a974b9c4fcc3c3b1cfe2ee03fef586f40a5a743\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c11070c4-617a-4159-961b-59187d5109bb\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4c2c05e99bc0e5d6ed09c4eb42b8b5e8d04fb4adfcd0cbafe1145c8497b96755\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13973, \"end_char_idx\": 17109, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "#### Observation:\n\nThe Retriever with OpenAI Embedding  demonstrates a performance with a hit rate of `0.7586`, while the MRR, at `0.6206`, suggests there's room for improvement in ensuring the most relevant results appear at the top. The observation that MRR is less than the hit rate indicates that the top-ranking results aren't always the most relevant. Enhancing MRR could involve the use of rerankers, which refine the order of retrieved documents. For a deeper understanding of how rerankers can optimize retrieval metrics, refer to the detailed discussion in our [blog post](https://blog.llamaindex.ai/boosting-rag-picking-the-best-embedding-reranker-models-42d079022e83).\n\n#### Response Evaluation:\n\n1. FaithfulnessEvaluator: Measures if the response from a query engine matches any source nodes which is useful for measuring if the response is hallucinated.\n2. Relevancy Evaluator: Measures if the response + source nodes match the query.\n\n\n```python\n# Get the list of queries from the above created dataset\n\nqueries = list(qa_dataset.queries.values())\n```\n\n#### Faithfulness Evaluator\n\nLet's start with FaithfulnessEvaluator.\n\nWe will use `gpt-3.5-turbo` for generating response for a given query and `gpt-4` for evaluation.\n\nLet's create service_context seperately for `gpt-3.5-turbo` and `gpt-4`.\n\n\n```python\n# gpt-3.5-turbo\ngpt35 = OpenAI(temperature=0, model=\"gpt-3.5-turbo\")\nservice_context_gpt35 = ServiceContext.from_defaults(llm=gpt35)\n\n# gpt-4\ngpt4 = OpenAI(temperature=0, model=\"gpt-4\")\nservice_context_gpt4 = ServiceContext.from_defaults(llm=gpt4)\n```\n\nCreate a `QueryEngine` with `gpt-3.5-turbo` service_context to generate response for the query.\n\n\n```python\nvector_index = VectorStoreIndex(nodes, service_context = service_context_gpt35)\nquery_engine = vector_index.as_query_engine()\n```\n\nCreate a  FaithfulnessEvaluator.\n\n\n\n\n\n```python\nfrom llama_index.evaluation import FaithfulnessEvaluator\nfaithfulness_gpt4 = FaithfulnessEvaluator(service_context=service_context_gpt4)\n```\n\nLet's evaluate on one question.\n\n\n```python\neval_query = queries[10]\n\neval_query\n```\n\n\n\n\n    \"Based on the author's experience and observations, why did he consider the AI practices during his first year of grad school as a hoax? Provide specific examples from the text to support your answer.\"\n\n\n\nGenerate response first and use faithfull evaluator.\n\n\n```python\nresponse_vector = query_engine.query(eval_query)\n```\n\n\n```python\n# Compute faithfulness evaluation\n\neval_result = faithfulness_gpt4.evaluate_response(response=response_vector)\n```\n\n\n```python\n# You can check passing parameter in eval_result if it passed the evaluation.\neval_result.passing\n```\n\n\n\n\n    True\n\n\n\n#### Relevancy Evaluator\n\nRelevancyEvaluator is useful to measure if the response and source nodes (retrieved context) match the query. Useful to see if response actually answers the query.\n\nInstantiate `RelevancyEvaluator` for relevancy evaluation with `gpt-4`\n\n\n```python\nfrom llama_index.evaluation import RelevancyEvaluator\n\nrelevancy_gpt4 = RelevancyEvaluator(service_context=service_context_gpt4)\n```\n\nLet's do relevancy evaluation for one of the query."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c11070c4-617a-4159-961b-59187d5109bb
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c11070c4-617a-4159-961b-59187d5109bb\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"4429f711-4749-4bc0-9d76-591fc7cd7a80\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"512b06e91036f3f8068628ddfbd58047555177c8911aa6f1414a643ec3489b9f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"6005e630-a0cf-4519-b795-fa4667ae78bd\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"029bba2fa3cccf385dc9a81d85edb398af99c2381665be7e9461197e76b7cbc1\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15646, \"end_char_idx\": 18901, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "```python\nvector_index = VectorStoreIndex(nodes, service_context = service_context_gpt35)\nquery_engine = vector_index.as_query_engine()\n```\n\nCreate a  FaithfulnessEvaluator.\n\n\n\n\n\n```python\nfrom llama_index.evaluation import FaithfulnessEvaluator\nfaithfulness_gpt4 = FaithfulnessEvaluator(service_context=service_context_gpt4)\n```\n\nLet's evaluate on one question.\n\n\n```python\neval_query = queries[10]\n\neval_query\n```\n\n\n\n\n    \"Based on the author's experience and observations, why did he consider the AI practices during his first year of grad school as a hoax? Provide specific examples from the text to support your answer.\"\n\n\n\nGenerate response first and use faithfull evaluator.\n\n\n```python\nresponse_vector = query_engine.query(eval_query)\n```\n\n\n```python\n# Compute faithfulness evaluation\n\neval_result = faithfulness_gpt4.evaluate_response(response=response_vector)\n```\n\n\n```python\n# You can check passing parameter in eval_result if it passed the evaluation.\neval_result.passing\n```\n\n\n\n\n    True\n\n\n\n#### Relevancy Evaluator\n\nRelevancyEvaluator is useful to measure if the response and source nodes (retrieved context) match the query. Useful to see if response actually answers the query.\n\nInstantiate `RelevancyEvaluator` for relevancy evaluation with `gpt-4`\n\n\n```python\nfrom llama_index.evaluation import RelevancyEvaluator\n\nrelevancy_gpt4 = RelevancyEvaluator(service_context=service_context_gpt4)\n```\n\nLet's do relevancy evaluation for one of the query.\n\n\n```python\n# Pick a query\nquery = queries[10]\n\nquery\n```\n\n\n\n\n    \"Based on the author's experience and observations, why did he consider the AI practices during his first year of grad school as a hoax? Provide specific examples from the text to support your answer.\"\n\n\n\n\n```python\n# Generate response.\n# response_vector has response and source nodes (retrieved context)\nresponse_vector = query_engine.query(query)\n\n# Relevancy evaluation\neval_result = relevancy_gpt4.evaluate_response(\n    query=query, response=response_vector\n)\n```\n\n\n```python\n# You can check passing parameter in eval_result if it passed the evaluation.\neval_result.passing\n```\n\n\n\n\n    True\n\n\n\n\n```python\n# You can get the feedback for the evaluation.\neval_result.feedback\n```\n\n\n\n\n    'YES'\n\n\n\n#### Batch Evaluator:\n\nNow that we have done FaithFulness and Relevancy Evaluation independently. LlamaIndex has `BatchEvalRunner` to compute multiple evaluations in batch wise manner.\n\n\n```python\nfrom llama_index.evaluation import BatchEvalRunner\n\n# Let's pick top 10 queries to do evaluation\nbatch_eval_queries = queries[:10]\n\n# Initiate BatchEvalRunner to compute FaithFulness and Relevancy Evaluation.\nrunner = BatchEvalRunner(\n    {\"faithfulness\": faithfulness_gpt4, \"relevancy\": relevancy_gpt4},\n    workers=8,\n)\n\n# Compute evaluation\neval_results = await runner.aevaluate_queries(\n    query_engine, queries=batch_eval_queries\n)\n```\n\n\n```python\n# Let's get faithfulness score\n\nfaithfulness_score = sum(result.passing for result in eval_results['faithfulness']) / len(eval_results['faithfulness'])\n\nfaithfulness_score\n```\n\n\n\n\n    1.0\n\n\n\n\n```python\n# Let's get relevancy score\n\nrelevancy_score = sum(result.passing for result in eval_results['relevancy']) / len(eval_results['relevancy'])\n\nrelevancy_score\n\n```\n\n\n\n\n    1.0"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 6005e630-a0cf-4519-b795-fa4667ae78bd
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb", "title": "Evaluate RAG with LlamaIndex", "tokens": 4522, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"6005e630-a0cf-4519-b795-fa4667ae78bd\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"99de0ab8-a81a-4792-80de-b1084e9bd657\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"3d87226cf3e1ecbc42d0bed8b11ca11fa5c935369f6c9e45c85efd4d1eec2978\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c11070c4-617a-4159-961b-59187d5109bb\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/evaluation/Evaluate_RAG_with_LlamaIndex.ipynb\", \"title\": \"Evaluate RAG with LlamaIndex\", \"tokens\": 4522, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"ce531dd10450efe578a6e37a674d623bea6daa1ef24f646395d62a410b313f26\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 17176, \"end_char_idx\": 19579, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "ref_doc_id": "99de0ab8-a81a-4792-80de-b1084e9bd657", "chroma:document": "\"Based on the author's experience and observations, why did he consider the AI practices during his first year of grad school as a hoax? Provide specific examples from the text to support your answer.\"\n\n\n\n\n```python\n# Generate response.\n# response_vector has response and source nodes (retrieved context)\nresponse_vector = query_engine.query(query)\n\n# Relevancy evaluation\neval_result = relevancy_gpt4.evaluate_response(\n    query=query, response=response_vector\n)\n```\n\n\n```python\n# You can check passing parameter in eval_result if it passed the evaluation.\neval_result.passing\n```\n\n\n\n\n    True\n\n\n\n\n```python\n# You can get the feedback for the evaluation.\neval_result.feedback\n```\n\n\n\n\n    'YES'\n\n\n\n#### Batch Evaluator:\n\nNow that we have done FaithFulness and Relevancy Evaluation independently. LlamaIndex has `BatchEvalRunner` to compute multiple evaluations in batch wise manner.\n\n\n```python\nfrom llama_index.evaluation import BatchEvalRunner\n\n# Let's pick top 10 queries to do evaluation\nbatch_eval_queries = queries[:10]\n\n# Initiate BatchEvalRunner to compute FaithFulness and Relevancy Evaluation.\nrunner = BatchEvalRunner(\n    {\"faithfulness\": faithfulness_gpt4, \"relevancy\": relevancy_gpt4},\n    workers=8,\n)\n\n# Compute evaluation\neval_results = await runner.aevaluate_queries(\n    query_engine, queries=batch_eval_queries\n)\n```\n\n\n```python\n# Let's get faithfulness score\n\nfaithfulness_score = sum(result.passing for result in eval_results['faithfulness']) / len(eval_results['faithfulness'])\n\nfaithfulness_score\n```\n\n\n\n\n    1.0\n\n\n\n\n```python\n# Let's get relevancy score\n\nrelevancy_score = sum(result.passing for result in eval_results['relevancy']) / len(eval_results['relevancy'])\n\nrelevancy_score\n\n```\n\n\n\n\n    1.0\n\n\n\n#### Observation:\n\nFaithfulness score of `1.0` signifies that the generated answers contain no hallucinations and are entirely based on retrieved context.\n\nRelevancy score of `1.0` suggests that the answers generated are consistently aligned with the retrieved context and the queries.\n\n## Conclusion\n\nIn this notebook, we have explored how to build and evaluate a RAG pipeline using LlamaIndex, with a specific focus on evaluating the retrieval system and generated responses within the pipeline. \n\nLlamaIndex offers a variety of other evaluation modules as well, which you can explore further [here](https://docs.llamaindex.ai/en/stable/module_guides/evaluating/root.html)"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c977feff-b0e1-4f7a-bf3e-a74e92aebe27
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c977feff-b0e1-4f7a-bf3e-a74e92aebe27\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"d83f4722-5cd5-48f1-a614-94e57bee184b\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"55eed429aec6c27c9bdf5797d80594800ff9cf6a85932198ef18202f8ac12339\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2064, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "# Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\n\nThis notebook provides step by step instuctions on using Azure AI Search (f.k.a Azure Cognitive Search) as a vector database with OpenAI embeddings, then creating an Azure Function on top to plug into a Custom GPT in ChatGPT. \n\nThis can be a solution for customers looking to set up RAG infrastructure contained within Azure, and exposing it as an endpoint to integrate that with other platforms such as ChatGPT.\n\nAzure AI Search is a cloud search service that gives developers infrastructure, APIs, and tools for building a rich search experience over private, heterogeneous content in web, mobile, and enterprise applications. \n\nAzure Functions is a serverless compute service that runs event-driven code, automatically managing infrastructure, scaling, and integrating with other Azure services.\n\n## Prerequisites:\nFor the purposes of this exercise you must have the following:\n- Azure user with permission to create [Azure AI Search Service](https://learn.microsoft.com/azure/search/) and Azure Function Apps\n- Azure subscription ID and a resource group.\n- [OpenAI Key](https://platform.openai.com/account/api-keys) \n\n# Architecture\nBelow is a diagram of the architecture of this solution, which we'll walk through step-by-step.\n\n![azure-rag-architecture.png](../../../../images/azure-rag-architecture.png)\n\n\n> Note: This architecture pattern of vector data store + serverless functions can be extrapolated to other vector data stores. For example, if you would want to use something like Postgres within Azure, you'd change the [Configure Azure AI Search Settings](#configure-azure-ai-search-settings) step to set-up the requirements for Postgres, you'd modify the [Create Azure AI Vector Search](#create-azure-ai-vector-search) to create the database and table in Postgres instead, and you'd update the `function_app.py` code in this repository to query Postgres instead of Azure AI Search. The data preparation and creation of the Azure Function would stay consistent."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: d83f4722-5cd5-48f1-a614-94e57bee184b
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"d83f4722-5cd5-48f1-a614-94e57bee184b\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c977feff-b0e1-4f7a-bf3e-a74e92aebe27\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"5ba85cea8ed56930c58a15b0a691baf4b4558f36f0510b22fea47a413019b210\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"678698b6-6d92-48d7-96ba-07d8e06858d6\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"d5e5ff2e1959591ad2c62a929fa8af3de32e3f5cc13cb74fbd3d787c163e437e\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1402, \"end_char_idx\": 4481, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "> Note: This architecture pattern of vector data store + serverless functions can be extrapolated to other vector data stores. For example, if you would want to use something like Postgres within Azure, you'd change the [Configure Azure AI Search Settings](#configure-azure-ai-search-settings) step to set-up the requirements for Postgres, you'd modify the [Create Azure AI Vector Search](#create-azure-ai-vector-search) to create the database and table in Postgres instead, and you'd update the `function_app.py` code in this repository to query Postgres instead of Azure AI Search. The data preparation and creation of the Azure Function would stay consistent. \n\n\n# Table of Contents:\n\n1. **[Setup of Environment](#set-up-environment)**\n    Setup environment by installing and importing the required libraries and configuring our Azure settings. Includes:\n     - [Install and Import Required Libraries](#install-and-import-required-libraries)\n     - [Configure OpenAI Settings](#configure-openai-settings)\n     - [Configure Azure AI Search Settings](#configure-azure-ai-search-settings)\n \n\n2. **[Prepare Data](#prepare-data)** Prepare the data for uploading by embedding the documents, as well as capturing additional metadata. We will use a subset of OpenAI's docs as example data for this.\n \n3. **[Create Azure AI Vector Search](#create-azure-ai-vector-search)** Create an Azure AI Vector Search and upload the data we've prepared. Includes:\n     - [Create Index](#create-index): Steps to create an index in Azure AI Search.\n     - [Upload Data](#upload-data): Instructions to upload data to Azure AI Search.\n     - [Test Search](#test-search): Steps to test the search functionality.\n \n4. **[Create Azure Function](#create-azure-function)** Create an Azure Function to interact with the Azure AI Vector Search. Includes:\n     - [Create Storage Account](#create-storage-account): Steps to create a storage account for the Azure Function.\n     - [Create Function App](#create-function-app): Instructions to create a function app in Azure.\n \n5. **[Input in a Custom GPT in ChatGPT](#input-in-a-custom-gpt-in-chatgpt)** Integrate the Azure Function with a Custom GPT in ChatGPT. Includes:\n     - [Create OpenAPI Spec](#create-openapi-spec): Steps to create an OpenAPI specification for the Azure Function.\n     - [Create GPT Instructions](#create-gpt-instructions): Instructions to create GPT-specific instructions for the integration.\n\n\n\n\n# Set up environment\nWe'll set up our environment by importing the required libraries and configuring our Azure settings.\n\n## Install and import required libraries\nWe categorize these libraries into standard Python libraries, third-party libraries, and Azure-related libraries for readability.\n\n\n```python\n! pip install -q wget\n! pip install -q azure-search-documents \n! pip install -q azure-identity\n! pip install -q openai\n! pip install -q azure-mgmt-search\n! pip install -q pandas\n! pip install -q azure-mgmt-resource \n! pip install -q azure-mgmt-storage\n! pip install -q pyperclip\n! pip install -q PyPDF2\n! pip install -q tiktoken\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 678698b6-6d92-48d7-96ba-07d8e06858d6
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"678698b6-6d92-48d7-96ba-07d8e06858d6\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"d83f4722-5cd5-48f1-a614-94e57bee184b\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"c891640ca6e94ee5afb409917d4b535b88dd3ddd7374e8514432cccdb675375d\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"cf98f97a-2445-4efb-8e6b-a711a9fb2c85\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"fac34c7bfe3727c21a1238c42e099bb83f0148da3f07d7da94308f4af2a37770\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3843, \"end_char_idx\": 6713, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "# Set up environment\nWe'll set up our environment by importing the required libraries and configuring our Azure settings.\n\n## Install and import required libraries\nWe categorize these libraries into standard Python libraries, third-party libraries, and Azure-related libraries for readability.\n\n\n```python\n! pip install -q wget\n! pip install -q azure-search-documents \n! pip install -q azure-identity\n! pip install -q openai\n! pip install -q azure-mgmt-search\n! pip install -q pandas\n! pip install -q azure-mgmt-resource \n! pip install -q azure-mgmt-storage\n! pip install -q pyperclip\n! pip install -q PyPDF2\n! pip install -q tiktoken\n```\n\n\n```python\n# Standard Libraries\nimport json  \nimport os\nimport platform\nimport subprocess\nimport csv\nfrom itertools import islice\nimport uuid\nimport shutil\nimport concurrent.futures\n\n# Third-Party Libraries\nimport pandas as pd\nfrom PyPDF2 import PdfReader\nimport tiktoken\nfrom dotenv import load_dotenv\nimport pyperclip\n\n# OpenAI Libraries (note we use OpenAI directly here, but you can replace with Azure OpenAI as needed)\nfrom openai import OpenAI\n\n# Azure Identity and Credentials\nfrom azure.identity import DefaultAzureCredential, InteractiveBrowserCredential\nfrom azure.core.credentials import AzureKeyCredential  \nfrom azure.core.exceptions import HttpResponseError\n\n# Azure Search Documents\nfrom azure.search.documents import SearchClient, SearchIndexingBufferedSender  \nfrom azure.search.documents.indexes import SearchIndexClient  \nfrom azure.search.documents.models import (\n    VectorizedQuery\n)\nfrom azure.search.documents.indexes.models import (\n    HnswAlgorithmConfiguration,\n    HnswParameters,\n    SearchField,\n    SearchableField,\n    SearchFieldDataType,\n    SearchIndex,\n    SimpleField,\n    VectorSearch,\n    VectorSearchAlgorithmKind,\n    VectorSearchAlgorithmMetric,\n    VectorSearchProfile,\n)\n\n# Azure Management Clients\nfrom azure.mgmt.search import SearchManagementClient\nfrom azure.mgmt.resource import ResourceManagementClient, SubscriptionClient\nfrom azure.mgmt.storage import StorageManagementClient\n```\n\n## Configure OpenAI settings\n\nBefore going through this section, make sure you have your OpenAI API key.\n\n\n\n```python\nopenai_api_key = os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as an env var>\") # Saving this as a variable to reference in function app in later step\nopenai_client = OpenAI(api_key=openai_api_key)\nembeddings_model = \"text-embedding-3-small\" # We'll use this by default, but you can change to your text-embedding-3-large if desired\n```\n\n## Configure Azure AI Search Settings\nYou can locate your Azure AI Search service details in the Azure Portal or programmatically via the [Search Management SDK](https://learn.microsoft.com/rest/api/searchmanagement/).\n\n\n#### Prerequisites:\n- Subscription ID from Azure\n- Resource Group name from Azure\n- Region in Azure"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: cf98f97a-2445-4efb-8e6b-a711a9fb2c85
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"cf98f97a-2445-4efb-8e6b-a711a9fb2c85\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"678698b6-6d92-48d7-96ba-07d8e06858d6\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"53a4f03c09ddefb4bacf7c45a5411bb838ad586e33f33ef017eaddd095b4cef9\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"f3ae4ec7-d1f8-432c-bd92-e5d74f799774\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"8b072004b85a152337416fbe4fe776eee7fd5b9e4dad835a6a57bf19c37fd374\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 6026, \"end_char_idx\": 9267, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\nopenai_api_key = os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as an env var>\") # Saving this as a variable to reference in function app in later step\nopenai_client = OpenAI(api_key=openai_api_key)\nembeddings_model = \"text-embedding-3-small\" # We'll use this by default, but you can change to your text-embedding-3-large if desired\n```\n\n## Configure Azure AI Search Settings\nYou can locate your Azure AI Search service details in the Azure Portal or programmatically via the [Search Management SDK](https://learn.microsoft.com/rest/api/searchmanagement/).\n\n\n#### Prerequisites:\n- Subscription ID from Azure\n- Resource Group name from Azure\n- Region in Azure\n\n\n```python\n# Update the below with your values\nsubscription_id=\"<enter_your_subscription_id>\"\nresource_group=\"<enter_your_resource_group>\"\n\n## Make sure to choose a region that supports the proper products. We've defaulted to \"eastus\" below. https://azure.microsoft.com/en-us/explore/global-infrastructure/products-by-region/#products-by-region_tab5\nregion = \"eastus\"\ncredential = InteractiveBrowserCredential()\nsubscription_client = SubscriptionClient(credential)\nsubscription = next(subscription_client.subscriptions.list())\n```\n\n#### Create and Configure Azure AI Search Service\nBelow we'll generate a unique name for the search service, set up the service properties, and create the search service.\n\n\n```python\n# Initialize the SearchManagementClient with the provided credentials and subscription ID\nsearch_management_client = SearchManagementClient(\n    credential=credential,\n    subscription_id=subscription_id,\n)\n\n# Generate a unique name for the search service using UUID, but you can change this if you'd like.\ngenerated_uuid = str(uuid.uuid4())\nsearch_service_name = \"search-service-gpt-demo\" + generated_uuid\n## The below is the default endpoint structure that is created when you create a search service. This may differ based on your Azure settings.\nsearch_service_endpoint = 'https://'+search_service_name+'.search.windows.net'\n\n# Create or update the search service with the specified parameters\nresponse = search_management_client.services.begin_create_or_update(\n    resource_group_name=resource_group,\n    search_service_name=search_service_name,\n    service={\n        \"location\": region,\n        \"properties\": {\"hostingMode\": \"default\", \"partitionCount\": 1, \"replicaCount\": 1},\n        # We are using the free pricing tier for this demo. You are only allowed one free search service per subscription.\n        \"sku\": {\"name\": \"free\"},\n        \"tags\": {\"app-name\": \"Search service demo\"},\n    },\n).result()\n\n# Convert the response to a dictionary and then to a pretty-printed JSON string\nresponse_dict = response.as_dict()\nresponse_json = json.dumps(response_dict, indent=4)\n\nprint(response_json)\nprint(\"Search Service Name:\" + search_service_name)\nprint(\"Search Service Endpoint:\" + search_service_endpoint)\n\n```\n\n#### Get the Search Service API Key\nNow that we have the search service up and running, we need the [Search Service API Key](https://learn.microsoft.com/en-us/azure/search/search-security-api-keys?tabs=rest-use,portal-find,portal-query), which we'll use to initiate the index creation, and later to execute the search."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: f3ae4ec7-d1f8-432c-bd92-e5d74f799774
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"f3ae4ec7-d1f8-432c-bd92-e5d74f799774\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"cf98f97a-2445-4efb-8e6b-a711a9fb2c85\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"b745a46e58552127728ef862a0063e9b5ab79e2189c4d20bbf083c10189220a8\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"694d2eab-3742-496d-940f-d23a740a903e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"43ae46e9a96cffdd57e67dd4216650cd12021baa719055bc26b55c64691191a2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 7420, \"end_char_idx\": 10245, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n# Initialize the SearchManagementClient with the provided credentials and subscription ID\nsearch_management_client = SearchManagementClient(\n    credential=credential,\n    subscription_id=subscription_id,\n)\n\n# Generate a unique name for the search service using UUID, but you can change this if you'd like.\ngenerated_uuid = str(uuid.uuid4())\nsearch_service_name = \"search-service-gpt-demo\" + generated_uuid\n## The below is the default endpoint structure that is created when you create a search service. This may differ based on your Azure settings.\nsearch_service_endpoint = 'https://'+search_service_name+'.search.windows.net'\n\n# Create or update the search service with the specified parameters\nresponse = search_management_client.services.begin_create_or_update(\n    resource_group_name=resource_group,\n    search_service_name=search_service_name,\n    service={\n        \"location\": region,\n        \"properties\": {\"hostingMode\": \"default\", \"partitionCount\": 1, \"replicaCount\": 1},\n        # We are using the free pricing tier for this demo. You are only allowed one free search service per subscription.\n        \"sku\": {\"name\": \"free\"},\n        \"tags\": {\"app-name\": \"Search service demo\"},\n    },\n).result()\n\n# Convert the response to a dictionary and then to a pretty-printed JSON string\nresponse_dict = response.as_dict()\nresponse_json = json.dumps(response_dict, indent=4)\n\nprint(response_json)\nprint(\"Search Service Name:\" + search_service_name)\nprint(\"Search Service Endpoint:\" + search_service_endpoint)\n\n```\n\n#### Get the Search Service API Key\nNow that we have the search service up and running, we need the [Search Service API Key](https://learn.microsoft.com/en-us/azure/search/search-security-api-keys?tabs=rest-use,portal-find,portal-query), which we'll use to initiate the index creation, and later to execute the search.\n\n\n```python\n# Retrieve the admin keys for the search service\ntry:\n    response = search_management_client.admin_keys.get(\n        resource_group_name=resource_group,\n        search_service_name=search_service_name,\n    )\n    # Extract the primary API key from the response and save as a variable to be used later\n    search_service_api_key = response.primary_key\n    print(\"Successfully retrieved the API key.\")\nexcept Exception as e:\n    print(f\"Failed to retrieve the API key: {e}\")\n```\n\n# Prepare data\nWe're going to embed and store a few pages of the OpenAI docs in the oai_docs folder. We'll first embed each, add it to a CSV, and then use that CSV to upload to the index.\n\nIn order to handle longer text files beyond the context of 8191 tokens, we can either use the chunk embeddings separately, or combine them in some way, such as averaging (weighted by the size of each chunk).\n\nWe will take a function from Python's own cookbook that breaks up a sequence into chunks."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 694d2eab-3742-496d-940f-d23a740a903e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"694d2eab-3742-496d-940f-d23a740a903e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"f3ae4ec7-d1f8-432c-bd92-e5d74f799774\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"e7c6b08311452a9d5c95438328c8c45604a40e793f5d3ca2f3cb0ef1d163ae4f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c96e6ae5-f365-44e5-9a2e-53c632a9fe38\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3d9749de9765f0c484cdf81bc66dc55f49e425a7732f978a7a12119851d90473\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9270, \"end_char_idx\": 12536, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n# Retrieve the admin keys for the search service\ntry:\n    response = search_management_client.admin_keys.get(\n        resource_group_name=resource_group,\n        search_service_name=search_service_name,\n    )\n    # Extract the primary API key from the response and save as a variable to be used later\n    search_service_api_key = response.primary_key\n    print(\"Successfully retrieved the API key.\")\nexcept Exception as e:\n    print(f\"Failed to retrieve the API key: {e}\")\n```\n\n# Prepare data\nWe're going to embed and store a few pages of the OpenAI docs in the oai_docs folder. We'll first embed each, add it to a CSV, and then use that CSV to upload to the index.\n\nIn order to handle longer text files beyond the context of 8191 tokens, we can either use the chunk embeddings separately, or combine them in some way, such as averaging (weighted by the size of each chunk).\n\nWe will take a function from Python's own cookbook that breaks up a sequence into chunks.\n\n\n```python\ndef batched(iterable, n):\n    \"\"\"Batch data into tuples of length n. The last batch may be shorter.\"\"\"\n    # batched('ABCDEFG', 3) --> ABC DEF G\n    if n < 1:\n        raise ValueError('n must be at least one')\n    it = iter(iterable)\n    while (batch := tuple(islice(it, n))):\n        yield batch\n\n```\n\nNow we define a function that encodes a string into tokens and then breaks it up into chunks. We'll use tiktoken, a fast open-source tokenizer by OpenAI.\n\nTo read more about counting tokens with Tiktoken, check out [this cookbook](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken). \n\n\n\n\n```python\ndef chunked_tokens(text, chunk_length, encoding_name='cl100k_base'):\n    # Get the encoding object for the specified encoding name. OpenAI's tiktoken library, which is used in this notebook, currently supports two encodings: 'bpe' and 'cl100k_base'. The 'bpe' encoding is used for GPT-3 and earlier models, while 'cl100k_base' is used for newer models like GPT-4.\n    encoding = tiktoken.get_encoding(encoding_name)\n    # Encode the input text into tokens\n    tokens = encoding.encode(text)\n    # Create an iterator that yields chunks of tokens of the specified length\n    chunks_iterator = batched(tokens, chunk_length)\n    # Yield each chunk from the iterator\n    yield from chunks_iterator\n```\n\nFinally, we can write a function that safely handles embedding requests, even when the input text is longer than the maximum context length, by chunking the input tokens and embedding each chunk individually. The average flag can be set to True to return the weighted average of the chunk embeddings, or False to simply return the unmodified list of chunk embeddings.\n\n> Note: there are other, more sophisticated techniques you can take here, including:\n> - using GPT-4o to capture images/chart descriptions for embedding.\n> - keeping text overlap between the chunks to minimize cutting off important context.\n> - chunking based on paragraphs or sections.\n> - adding more descriptive metadata about each article.\n\n\n```python\n## Change the below based on model. The below is for the latest embeddings models from OpenAI, so you can leave as is unless you are using a different embedding model..\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c96e6ae5-f365-44e5-9a2e-53c632a9fe38
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c96e6ae5-f365-44e5-9a2e-53c632a9fe38\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"694d2eab-3742-496d-940f-d23a740a903e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"8c6e87519f24b94726cf128870bddb44bd48b8cc221c2ddb23bd982ee4f8f9bb\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"dbace265-84df-48c7-8e60-49ab714fa678\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3fad5a39935ab46eecd10c3b745833bc1065f43e8c6abf8c64398510f00eede6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 10870, \"end_char_idx\": 13962, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\ndef chunked_tokens(text, chunk_length, encoding_name='cl100k_base'):\n    # Get the encoding object for the specified encoding name. OpenAI's tiktoken library, which is used in this notebook, currently supports two encodings: 'bpe' and 'cl100k_base'. The 'bpe' encoding is used for GPT-3 and earlier models, while 'cl100k_base' is used for newer models like GPT-4.\n    encoding = tiktoken.get_encoding(encoding_name)\n    # Encode the input text into tokens\n    tokens = encoding.encode(text)\n    # Create an iterator that yields chunks of tokens of the specified length\n    chunks_iterator = batched(tokens, chunk_length)\n    # Yield each chunk from the iterator\n    yield from chunks_iterator\n```\n\nFinally, we can write a function that safely handles embedding requests, even when the input text is longer than the maximum context length, by chunking the input tokens and embedding each chunk individually. The average flag can be set to True to return the weighted average of the chunk embeddings, or False to simply return the unmodified list of chunk embeddings.\n\n> Note: there are other, more sophisticated techniques you can take here, including:\n> - using GPT-4o to capture images/chart descriptions for embedding.\n> - keeping text overlap between the chunks to minimize cutting off important context.\n> - chunking based on paragraphs or sections.\n> - adding more descriptive metadata about each article.\n\n\n```python\n## Change the below based on model. The below is for the latest embeddings models from OpenAI, so you can leave as is unless you are using a different embedding model..\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```\n\n\n```python\ndef generate_embeddings(text, model):\n    # Generate embeddings for the provided text using the specified model\n    embeddings_response = openai_client.embeddings.create(model=model, input=text)\n    # Extract the embedding data from the response\n    embedding = embeddings_response.data[0].embedding\n    return embedding\n\ndef len_safe_get_embedding(text, model=embeddings_model, max_tokens=EMBEDDING_CTX_LENGTH, encoding_name=EMBEDDING_ENCODING):\n    # Initialize lists to store embeddings and corresponding text chunks\n    chunk_embeddings = []\n    chunk_texts = []\n    # Iterate over chunks of tokens from the input text\n    for chunk in chunked_tokens(text, chunk_length=max_tokens, encoding_name=encoding_name):\n        # Generate embeddings for each chunk and append to the list\n        chunk_embeddings.append(generate_embeddings(chunk, model=model))\n        # Decode the chunk back to text and append to the list\n        chunk_texts.append(tiktoken.get_encoding(encoding_name).decode(chunk))\n    # Return the list of chunk embeddings and the corresponding text chunks\n    return chunk_embeddings, chunk_texts\n```\n\nNext, we can define a helper function that will capture additional metadata about the documents. This is useful to use as a metadata filter for search queries, and capturing richer data for search. \n\nIn this example, I'll choose from a list of categories to use later on in a metadata filter."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: dbace265-84df-48c7-8e60-49ab714fa678
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"dbace265-84df-48c7-8e60-49ab714fa678\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c96e6ae5-f365-44e5-9a2e-53c632a9fe38\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"4c26def1a147344a116bae0584e005976bdcad661f0217404a88662a578060f0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"d30d367d-84c4-434c-bbc4-18a174e4f2ae\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"b31bb4a6fc5a48e1591deb96ac6db9d49beb87daf6417a8ea1bb02b6065157ab\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 12293, \"end_char_idx\": 15261, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n## Change the below based on model. The below is for the latest embeddings models from OpenAI, so you can leave as is unless you are using a different embedding model..\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```\n\n\n```python\ndef generate_embeddings(text, model):\n    # Generate embeddings for the provided text using the specified model\n    embeddings_response = openai_client.embeddings.create(model=model, input=text)\n    # Extract the embedding data from the response\n    embedding = embeddings_response.data[0].embedding\n    return embedding\n\ndef len_safe_get_embedding(text, model=embeddings_model, max_tokens=EMBEDDING_CTX_LENGTH, encoding_name=EMBEDDING_ENCODING):\n    # Initialize lists to store embeddings and corresponding text chunks\n    chunk_embeddings = []\n    chunk_texts = []\n    # Iterate over chunks of tokens from the input text\n    for chunk in chunked_tokens(text, chunk_length=max_tokens, encoding_name=encoding_name):\n        # Generate embeddings for each chunk and append to the list\n        chunk_embeddings.append(generate_embeddings(chunk, model=model))\n        # Decode the chunk back to text and append to the list\n        chunk_texts.append(tiktoken.get_encoding(encoding_name).decode(chunk))\n    # Return the list of chunk embeddings and the corresponding text chunks\n    return chunk_embeddings, chunk_texts\n```\n\nNext, we can define a helper function that will capture additional metadata about the documents. This is useful to use as a metadata filter for search queries, and capturing richer data for search. \n\nIn this example, I'll choose from a list of categories to use later on in a metadata filter.\n\n\n```python\n## These are the categories I will be using for the categorization task. You can change these as needed based on your use case.\ncategories = ['authentication','models','techniques','tools','setup','billing_limits','other']\n\ndef categorize_text(text, categories):\n    # Create a prompt for categorization\n    messages = [\n        {\"role\": \"system\", \"content\": f\"\"\"You are an expert in LLMs, and you will be given text that corresponds to an article in OpenAI's documentation.\n         Categorize the document into one of these categories: {', '.join(categories)}. Only respond with the category name and nothing else.\"\"\"},\n        {\"role\": \"user\", \"content\": text}\n    ]\n    try:\n        # Call the OpenAI API to categorize the text\n        response = openai_client.chat.completions.create(\n            model=\"gpt-4o\",\n            messages=messages\n        )\n        # Extract the category from the response\n        category = response.choices[0].message.content\n        return category\n    except Exception as e:\n        print(f\"Error categorizing text: {str(e)}\")\n        return None\n```\n\nNow, we can define some helper functions to process the .txt files in the oai_docs folder within the data folder. You can use this with your own data as well and supports both .txt and .pdf files."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: d30d367d-84c4-434c-bbc4-18a174e4f2ae
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"d30d367d-84c4-434c-bbc4-18a174e4f2ae\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"dbace265-84df-48c7-8e60-49ab714fa678\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"4674f112dbc0736065b247c4a3ed9be1100d60aac532b80770941de18f27eead\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"29efb7d2-e435-40ca-86b2-dd29a9f4964f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"5ab9ebcfaaf610da64bfd282c681175b718da1a6aab53fad94b53ae79559cad4\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 13965, \"end_char_idx\": 17109, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n## These are the categories I will be using for the categorization task. You can change these as needed based on your use case.\ncategories = ['authentication','models','techniques','tools','setup','billing_limits','other']\n\ndef categorize_text(text, categories):\n    # Create a prompt for categorization\n    messages = [\n        {\"role\": \"system\", \"content\": f\"\"\"You are an expert in LLMs, and you will be given text that corresponds to an article in OpenAI's documentation.\n         Categorize the document into one of these categories: {', '.join(categories)}. Only respond with the category name and nothing else.\"\"\"},\n        {\"role\": \"user\", \"content\": text}\n    ]\n    try:\n        # Call the OpenAI API to categorize the text\n        response = openai_client.chat.completions.create(\n            model=\"gpt-4o\",\n            messages=messages\n        )\n        # Extract the category from the response\n        category = response.choices[0].message.content\n        return category\n    except Exception as e:\n        print(f\"Error categorizing text: {str(e)}\")\n        return None\n```\n\nNow, we can define some helper functions to process the .txt files in the oai_docs folder within the data folder. You can use this with your own data as well and supports both .txt and .pdf files.\n\n\n```python\ndef extract_text_from_pdf(pdf_path):\n    # Initialize the PDF reader\n    reader = PdfReader(pdf_path)\n    text = \"\"\n    # Iterate through each page in the PDF and extract text\n    for page in reader.pages:\n        text += page.extract_text()\n    return text\n\ndef process_file(file_path, idx, categories, embeddings_model):\n    file_name = os.path.basename(file_path)\n    print(f\"Processing file {idx + 1}: {file_name}\")\n    \n    # Read text content from .txt files\n    if file_name.endswith('.txt'):\n        with open(file_path, 'r', encoding='utf-8') as file:\n            text = file.read()\n    # Extract text content from .pdf files\n    elif file_name.endswith('.pdf'):\n        text = extract_text_from_pdf(file_path)\n    \n    title = file_name\n    # Generate embeddings for the title\n    title_vectors, title_text = len_safe_get_embedding(title, embeddings_model)\n    print(f\"Generated title embeddings for {file_name}\")\n    \n    # Generate embeddings for the content\n    content_vectors, content_text = len_safe_get_embedding(text, embeddings_model)\n    print(f\"Generated content embeddings for {file_name}\")\n    \n    category = categorize_text(' '.join(content_text), categories)\n    print(f\"Categorized {file_name} as {category}\")\n    \n    # Prepare the data to be appended\n    data = []\n    for i, content_vector in enumerate(content_vectors):\n        data.append({\n            \"id\": f\"{idx}_{i}\",\n            \"vector_id\": f\"{idx}_{i}\",\n            \"title\": title_text[0],\n            \"text\": content_text[i],\n            \"title_vector\": json.dumps(title_vectors[0]),  # Assuming title is short and has only one chunk\n            \"content_vector\": json.dumps(content_vector),\n            \"category\": category\n        })\n        print(f\"Appended data for chunk {i + 1}/{len(content_vectors)} of {file_name}\")\n    \n    return data"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 29efb7d2-e435-40ca-86b2-dd29a9f4964f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"29efb7d2-e435-40ca-86b2-dd29a9f4964f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"d30d367d-84c4-434c-bbc4-18a174e4f2ae\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"bed8e7562514244dcd97355e8100012f30c569f1abb05848d34f3367570760c5\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b684d357-584e-456e-9423-96425f6711ba\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"e7146340321845649d3b045caf59e98d38150892b0d9f6f0f95d8b51b08d50a2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 17112, \"end_char_idx\": 20019, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```\n\nWe'll now use this helper function to process our OpenAI documentation. Feel free to update this to use your own data by changing the folder in `process_files` below.\n\nNote that this will process the documents in chosen folder concurrently, so this should take <30 seconds if using txt files, and slightly longer if using PDFs.\n\n\n```python\n## Customize the location below if you are using different data besides the OpenAI documentation. Note that if you are using a different dataset, you will need to update the categories list as well.\nfolder_name = \"../../../data/oai_docs\"\n\nfiles = [os.path.join(folder_name, f) for f in os.listdir(folder_name) if f.endswith('.txt') or f.endswith('.pdf')]\ndata = []\n\n# Process each file concurrently\nwith concurrent.futures.ThreadPoolExecutor() as executor:\n    futures = {executor.submit(process_file, file_path, idx, categories, embeddings_model): idx for idx, file_path in enumerate(files)}\n    for future in concurrent.futures.as_completed(futures):\n        try:\n            result = future.result()\n            data.extend(result)\n        except Exception as e:\n            print(f\"Error processing file: {str(e)}\")\n\n# Write the data to a CSV file\ncsv_file = os.path.join(\"..\", \"embedded_data.csv\")\nwith open(csv_file, 'w', newline='', encoding='utf-8') as csvfile:\n    fieldnames = [\"id\", \"vector_id\", \"title\", \"text\", \"title_vector\", \"content_vector\",\"category\"]\n    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n    writer.writeheader()\n    for row in data:\n        writer.writerow(row)\n        print(f\"Wrote row with id {row['id']} to CSV\")\n\n# Convert the CSV file to a Dataframe\narticle_df = pd.read_csv(\"../embedded_data.csv\")\n# Read vectors from strings back into a list using json.loads\narticle_df[\"title_vector\"] = article_df.title_vector.apply(json.loads)\narticle_df[\"content_vector\"] = article_df.content_vector.apply(json.loads)\narticle_df[\"vector_id\"] = article_df[\"vector_id\"].apply(str)\narticle_df[\"category\"] = article_df[\"category\"].apply(str)\narticle_df.head()\n\n```\n\nWe now have an `embedded_data.csv` file with six columns that we can upload to our vector database! \n\n# Create Azure AI Vector Search\n\n##  Create index\nWe'll define and create a search index using the `SearchIndexClient` from the Azure AI Search Python SDK. The index incorporates both vector search and hybrid search capabilities. For more details, visit Microsoft's documentation on how to [Create a Vector Index](https://learn.microsoft.com/azure/search/vector-search-how-to-create-index?.tabs=config-2023-11-01%2Crest-2023-11-01%2Cpush%2Cportal-check-index)\n\n\n```python\nindex_name = \"azure-ai-search-openai-cookbook-demo\"\n# index_name = \"<insert_name_for_index>\"\n\nindex_client = SearchIndexClient(\n    endpoint=search_service_endpoint, credential=AzureKeyCredential(search_service_api_key)\n)\n# Define the fields for the index. Update these based on your data."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: b684d357-584e-456e-9423-96425f6711ba
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b684d357-584e-456e-9423-96425f6711ba\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"29efb7d2-e435-40ca-86b2-dd29a9f4964f\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"3032ea66e4af260e1262a0e1b1a616ff310ac6644fa2177f863f1debe5b34949\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"563cc870-4bda-4f9f-9ebd-dfa9f1606ad0\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"09095bd7aa3b65d85450acf1978e92b20e1e3294808891f48d59b508d7cf2d89\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 19720, \"end_char_idx\": 23108, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\nindex_name = \"azure-ai-search-openai-cookbook-demo\"\n# index_name = \"<insert_name_for_index>\"\n\nindex_client = SearchIndexClient(\n    endpoint=search_service_endpoint, credential=AzureKeyCredential(search_service_api_key)\n)\n# Define the fields for the index. Update these based on your data.\n# Each field represents a column in the search index\nfields = [\n    SimpleField(name=\"id\", type=SearchFieldDataType.String),  # Simple string field for document ID\n    SimpleField(name=\"vector_id\", type=SearchFieldDataType.String, key=True),  # Key field for the index\n    # SimpleField(name=\"url\", type=SearchFieldDataType.String),  # URL field (commented out)\n    SearchableField(name=\"title\", type=SearchFieldDataType.String),  # Searchable field for document title\n    SearchableField(name=\"text\", type=SearchFieldDataType.String),  # Searchable field for document text\n    SearchField(\n        name=\"title_vector\",\n        type=SearchFieldDataType.Collection(SearchFieldDataType.Single),  # Collection of single values for title vector\n        vector_search_dimensions=1536,  # Number of dimensions in the vector\n        vector_search_profile_name=\"my-vector-config\",  # Profile name for vector search configuration\n    ),\n    SearchField(\n        name=\"content_vector\",\n        type=SearchFieldDataType.Collection(SearchFieldDataType.Single),  # Collection of single values for content vector\n        vector_search_dimensions=1536,  # Number of dimensions in the vector\n        vector_search_profile_name=\"my-vector-config\",  # Profile name for vector search configuration\n    ),\n    SearchableField(name=\"category\", type=SearchFieldDataType.String, filterable=True),  # Searchable field for document category\n]\n\n# This configuration defines the algorithm and parameters for vector search\nvector_search = VectorSearch(\n    algorithms=[\n        HnswAlgorithmConfiguration(\n            name=\"my-hnsw\",  # Name of the HNSW algorithm configuration\n            kind=VectorSearchAlgorithmKind.HNSW,  # Type of algorithm\n            parameters=HnswParameters(\n                m=4,  # Number of bi-directional links created for every new element\n                ef_construction=400,  # Size of the dynamic list for the nearest neighbors during construction\n                ef_search=500,  # Size of the dynamic list for the nearest neighbors during search\n                metric=VectorSearchAlgorithmMetric.COSINE,  # Distance metric used for the search\n            ),\n        )\n    ],\n    profiles=[\n        VectorSearchProfile(\n            name=\"my-vector-config\",  # Name of the vector search profile\n            algorithm_configuration_name=\"my-hnsw\",  # Reference to the algorithm configuration\n        )\n    ],\n)\n\n# Create the search index with the vector search configuration\n# This combines all the configurations into a single search index\nindex = SearchIndex(\n    name=index_name,  # Name of the index\n    fields=fields,  # Fields defined for the index\n    vector_search=vector_search  # Vector search configuration\n\n)\n\n# Create or update the index\n# This sends the index definition to the Azure Search service\nresult = index_client.create_index(index)\nprint(f\"{result.name} created\")  # Output the name of the created index\n```\n\n## Upload Data\n\nNow we'll upload the articles from above that we've stored in `embedded_data.csv` from a pandas DataFrame to an Azure AI Search index."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 563cc870-4bda-4f9f-9ebd-dfa9f1606ad0
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"563cc870-4bda-4f9f-9ebd-dfa9f1606ad0\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b684d357-584e-456e-9423-96425f6711ba\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d0959856d8e889ffea7877ca07c26b36dba43a2cb0cf0fe5b24953bc45f21b0c\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"5d8a9e2d-819e-4499-ab62-50a6d12ba09e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"e139fca35c98549565441e2770a6762598fb370601f11d77955b961d92712860\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 23109, \"end_char_idx\": 25723, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "For a detailed guide on data import strategies and best practices, refer to  [Data Import in Azure AI Search](https://learn.microsoft.com/azure/search/search-what-is-data-import).\n\n\n\n```python\n# Convert the 'id' and 'vector_id' columns to string so one of them can serve as our key field\narticle_df[\"id\"] = article_df[\"id\"].astype(str)\narticle_df[\"vector_id\"] = article_df[\"vector_id\"].astype(str)\n\n# Convert the DataFrame to a list of dictionaries\ndocuments = article_df.to_dict(orient=\"records\")\n\n# Log the number of documents to be uploaded\nprint(f\"Number of documents to upload: {len(documents)}\")\n\n# Create a SearchIndexingBufferedSender\nbatch_client = SearchIndexingBufferedSender(\n    search_service_endpoint, index_name, AzureKeyCredential(search_service_api_key)\n)\n# Get the first document to check its schema\nfirst_document = documents[0]\n\n# Get the index schema\nindex_schema = index_client.get_index(index_name)\n\n# Get the field names from the index schema\nindex_fields = {field.name: field.type for field in index_schema.fields}\n\n# Check each field in the first document\nfor field, value in first_document.items():\n    if field not in index_fields:\n        print(f\"Field '{field}' is not in the index schema.\")\n\n# Check for any fields in the index schema that are not in the documents\nfor field in index_fields:\n    if field not in first_document:\n        print(f\"Field '{field}' is in the index schema but not in the documents.\")\n\ntry:\n    if documents:\n        # Add upload actions for all documents in a single call\n        upload_result = batch_client.upload_documents(documents=documents)\n\n        # Check if the upload was successful\n        # Manually flush to send any remaining documents in the buffer\n        batch_client.flush()\n        \n        print(f\"Uploaded {len(documents)} documents in total\")\n    else:\n        print(\"No documents to upload.\")\nexcept HttpResponseError as e:\n    print(f\"An error occurred: {e}\")\n    raise  # Re-raise the exception to ensure it errors out\nfinally:\n    # Clean up resources\n    batch_client.close()\n```\n\n## Test search\nNow that the data is uploaded, we'll test both vector similarity search and hybrid search locally below to make sure it is working as expected.\n\nYou can test both a pure vector search and hybrid search. Pure vector search passes in `None` to the `search_text` below and will only search on vector similarity. Hybrid search will combines the capabilities of traditional keyword-based search by passing in the query text `query` to the `search_text` with vector-based similarity search to provide more relevant and contextual results."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 5d8a9e2d-819e-4499-ab62-50a6d12ba09e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"5d8a9e2d-819e-4499-ab62-50a6d12ba09e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"563cc870-4bda-4f9f-9ebd-dfa9f1606ad0\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"70f6a25494fed03c0bbe225a2111886e8113816649c32418fc925a6da3941cbc\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"86c8eaf4-1f53-46ef-bdad-075a2c4f25b2\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"bb4beb9b584c369cccb62e2d23a84ebf72500450ed5c571d1a03c4f1ad43c0aa\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 25727, \"end_char_idx\": 27870, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\nquery = \"What model should I use to embed?\"\n# Note: we'll have the GPT choose the category automatically once we put it in ChatGPT\ncategory =\"models\"\n\nsearch_client = SearchClient(search_service_endpoint, index_name, AzureKeyCredential(search_service_api_key))\nvector_query = VectorizedQuery(vector=generate_embeddings(query, embeddings_model), k_nearest_neighbors=3, fields=\"content_vector\")\n  \nresults = search_client.search(  \n    search_text=None, # Pass in None if you want to use pure vector search, and `query` if you want to use hybrid search\n    vector_queries= [vector_query], \n    select=[\"title\", \"text\"],\n    filter=f\"category eq '{category}'\" \n)\n\nfor result in results:  \n    print(result)\n\n```\n\n## Create Azure Function\n\nAzure Functions are an easy way to build an API on top of our new AI search. Our code (see the `function_app.py` file in this folder, or linked [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/function_app.py)) does the following:\n\n1. Takes in an input of the user's query, search index endpoint, the index name, the k_nearest_neighbors*, the search column to use (either content_vector or title_vector), and whether it should use a hybrid query\n2. Takes the user's query and embeds it.\n3. Conducts a vector search and retrieves relevant text chunks.\n4. Returns those relevant text chunks as the response body. \n\n*In the context of vector search, k_nearest_neighbors specifies the number of \"closest\" vectors (in terms of cosine similarity) that the search should return. For example, if k_nearest_neighbors is set to 3, the search will return the 3 vectors in the index that are most similar to the query vector.\n\n> Note that this Azure Function _does not have any authentication_. However, you can set authentication on it following docs [here](https://learn.microsoft.com/en-us/azure/azure-functions/security-concepts?tabs=v4)\n\n### Create storage account\n\nWe can create a new storage account using the code below, but feel free to skip that block and modify the subsequent steps to use an existing storage account. This may take up to 30 seconds."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 86c8eaf4-1f53-46ef-bdad-075a2c4f25b2
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"86c8eaf4-1f53-46ef-bdad-075a2c4f25b2\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"5d8a9e2d-819e-4499-ab62-50a6d12ba09e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d86410606f7e1d5391dc53d600bf49fcf18adccd138880158388d080885773b1\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"5fea35b9-32e2-40fc-bb21-3fc8d7e0b453\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"d39ef8b1882dbf951f971da693677e563d83c5a644cd2f797b5123549bf259f9\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 27873, \"end_char_idx\": 29766, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n## Update below with a different name\nstorage_account_name = \"<enter-storage-account-name>\"\n\n## Use below SKU or any other SKU as per your requirement\nsku = \"Standard_LRS\"\nresource_client = ResourceManagementClient(credential, subscription_id)\nstorage_client = StorageManagementClient(credential, subscription_id)\n\n# Create resource group if it doesn't exist\nrg_result = resource_client.resource_groups.create_or_update(resource_group, {\"location\": region})\n\n# Create storage account\nstorage_async_operation = storage_client.storage_accounts.begin_create(\n    resource_group,\n    storage_account_name,\n    {\n        \"sku\": {\"name\": sku},\n        \"kind\": \"StorageV2\",\n        \"location\": region,\n    },\n)\nstorage_account = storage_async_operation.result()\n\nprint(f\"Storage account {storage_account.name} created\")\n\n```\n\n### Create Function App\nThis Function App is where the python code will execute once it is triggered via a GPT Action. To read more about Function Apps, see the docs [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp). \n\nTo deploy Function Apps, we'll need to use the Azure CLI and Azure Functions Core Tools. \n\n> The below will attempt to install it and run it based on your platform type in your virtual environment, but if that does not work, read the Azure documentation to figure out how to install [Azure Function Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-python?tabs=linux,bash,azure-cli,browser) and [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). After doing that, run the below `subprocess.run` commands in your terminal after navigating to this folder.\n\nFirst we'll make sure we have the relevant tools in the environment in order to run the Azure commands necessary. This may take a few minutes to install."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 5fea35b9-32e2-40fc-bb21-3fc8d7e0b453
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"5fea35b9-32e2-40fc-bb21-3fc8d7e0b453\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"86c8eaf4-1f53-46ef-bdad-075a2c4f25b2\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"2a7551b5bb2b30a73d32f32c5c6e3e95e50a59fda34880384bb2873607203643\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ba3ae13b-caea-4268-a761-e863f7bc923e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"cce1f9e13ec7f459778f6b35924847e19ac9e435703b7c3a2f1992ce004177f4\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 27873, \"end_char_idx\": 32120, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n## Update below with a different name\nstorage_account_name = \"<enter-storage-account-name>\"\n\n## Use below SKU or any other SKU as per your requirement\nsku = \"Standard_LRS\"\nresource_client = ResourceManagementClient(credential, subscription_id)\nstorage_client = StorageManagementClient(credential, subscription_id)\n\n# Create resource group if it doesn't exist\nrg_result = resource_client.resource_groups.create_or_update(resource_group, {\"location\": region})\n\n# Create storage account\nstorage_async_operation = storage_client.storage_accounts.begin_create(\n    resource_group,\n    storage_account_name,\n    {\n        \"sku\": {\"name\": sku},\n        \"kind\": \"StorageV2\",\n        \"location\": region,\n    },\n)\nstorage_account = storage_async_operation.result()\n\nprint(f\"Storage account {storage_account.name} created\")\n\n```\n\n### Create Function App\nThis Function App is where the python code will execute once it is triggered via a GPT Action. To read more about Function Apps, see the docs [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp). \n\nTo deploy Function Apps, we'll need to use the Azure CLI and Azure Functions Core Tools. \n\n> The below will attempt to install it and run it based on your platform type in your virtual environment, but if that does not work, read the Azure documentation to figure out how to install [Azure Function Core Tools](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-python?tabs=linux,bash,azure-cli,browser) and [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli). After doing that, run the below `subprocess.run` commands in your terminal after navigating to this folder.\n\nFirst we'll make sure we have the relevant tools in the environment in order to run the Azure commands necessary. This may take a few minutes to install.\n\n\n```python\nos_type = platform.system()\n\nif os_type == \"Windows\":\n    # Install Azure Functions Core Tools on Windows\n    subprocess.run([\"npm\", \"install\", \"-g\", \"azure-functions-core-tools@3\", \"--unsafe-perm\", \"true\"], check=True)\n    # Install Azure CLI on Windows\n    subprocess.run([\"powershell\", \"-Command\", \"Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\\\\AzureCLI.msi; Start-Process msiexec.exe -ArgumentList '/I AzureCLI.msi /quiet' -Wait\"], check=True)\nelif os_type == \"Darwin\":  # MacOS\n    # Install Azure Functions Core Tools on MacOS\n    if platform.machine() == 'arm64':\n        # For M1 Macs\n        subprocess.run([\"arch\", \"-arm64\", \"brew\", \"install\", \"azure-functions-core-tools@3\"], check=True)\n    else:\n        # For Intel Macs\n        subprocess.run([\"brew\", \"install\", \"azure-functions-core-tools@3\"], check=True)\n    # Install Azure CLI on MacOS\n    subprocess.run([\"brew\", \"update\"], check=True)\n    subprocess.run([\"brew\", \"install\", \"azure-cli\"], check=True)\nelif os_type == \"Linux\":\n    # Install Azure Functions Core Tools on Linux\n    subprocess.run([\"curl\", \"https://packages.microsoft.com/keys/microsoft.asc\", \"|\", \"gpg\", \"--dearmor\", \">\", \"microsoft.gpg\"], check=True, shell=True)\n    subprocess.run([\"sudo\", \"mv\", \"microsoft.gpg\", \"/etc/apt/trusted.gpg.d/microsoft.gpg\"], check=True)\n    subprocess.run([\"sudo\", \"sh\", \"-c\", \"'echo \\\"deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main\\\" > /etc/apt/sources.list.d/dotnetdev.list'\"], check=True, shell=True)\n    subprocess.run([\"sudo\", \"apt-get\", \"update\"], check=True)\n    subprocess.run([\"sudo\", \"apt-get\", \"install\", \"azure-functions-core-tools-3\"], check=True)\n    # Install Azure CLI on Linux\n    subprocess.run([\"curl\", \"-sL\", \"https://aka.ms/InstallAzureCLIDeb\", \"|\", \"sudo\", \"bash\"], check=True, shell=True)\nelse:\n    # Raise an error if the operating system is not supported\n    raise OSError(\"Unsupported operating system\")\n\n# Verify the installation of Azure Functions Core Tools\nsubprocess.run([\"func\", \"--version\"], check=True)\n# Verify the installation of Azure CLI\nsubprocess.run([\"az\", \"--version\"], check=True)\n\nsubprocess.run([\n    \"az\", \"login\"\n], check=True)\n```\n\nNow, we need to create a `local.settings.json` file with our key environment variables for Azure"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: ba3ae13b-caea-4268-a761-e863f7bc923e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ba3ae13b-caea-4268-a761-e863f7bc923e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"5fea35b9-32e2-40fc-bb21-3fc8d7e0b453\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"12aa7973ee8daa149e24b7add66fe72a0cf5e20987326182ee43cddf2239c85f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"24409061-b68d-4c16-b3d6-e00b093c011a\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f8e113bb04626d5e684065345efc6974796b1f58d61f345249e97a92ff125c70\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 32123, \"end_char_idx\": 34773, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\nlocal_settings_content = f\"\"\"\n{{\n  \"IsEncrypted\": false,\n  \"Values\": {{\n    \"AzureWebJobsStorage\": \"UseDevelopmentStorage=true\",\n    \"FUNCTIONS_WORKER_RUNTIME\": \"python\",\n    \"OPENAI_API_KEY\": \"{openai_api_key}\",\n    \"EMBEDDINGS_MODEL\": \"{embeddings_model}\",\n    \"SEARCH_SERVICE_API_KEY\": \"{search_service_api_key}\",\n  }}\n}}\n\"\"\"\n\nwith open(\"local.settings.json\", \"w\") as file:\n    file.write(local_settings_content)\n```\n\nCheck the `local.settings.json` file and make sure that the environment variables match what you expect. \n\nNow, give your app a name below, and you are ready to create your Function App and then publish your function. \n\n\n```python\n# Replace this with your own values. This name will appear in the URL of the API call https://<app_name>.azurewebsites.net\napp_name = \"<app-name>\"\n\nsubprocess.run([\n    \"az\", \"functionapp\", \"create\",\n    \"--resource-group\", resource_group,\n    \"--consumption-plan-location\", region,\n    \"--runtime\", \"python\",\n    \"--name\", app_name,\n    \"--storage-account\", storage_account_name,\n    \"--os-type\", \"Linux\",\n], check=True)\n```\n\nOnce we've created the Function App, we now want to add the configuration variables to the function app to use in the function. Specifically, we need the `OPENAI_API_KEY`, the `SEARCH_SERVICE_API_KEY`, and the `EMBEDDINGS_MODEL` as these are all used in the `function_app.py` code.\n\n\n```python\n# Collect the relevant environment variables \nenv_vars = {\n    \"OPENAI_API_KEY\": openai_api_key,\n    \"SEARCH_SERVICE_API_KEY\": search_service_api_key,\n    \"EMBEDDINGS_MODEL\": embeddings_model\n}\n\n# Create the settings argument for the az functionapp create command\nsettings_args = []\nfor key, value in env_vars.items():\n    settings_args.append(f\"{key}={value}\")\n\nsubprocess.run([\n    \"az\", \"functionapp\", \"config\", \"appsettings\", \"set\",\n    \"--name\", app_name,\n    \"--resource-group\", resource_group,\n    \"--settings\", *settings_args\n], check=True)\n```\n\nWe are now ready to publish your function code `function_app.py` to the Azure Function. This may take up to 10 minutes to deploy. Once this is finished, we now have an API endpoint using an Azure Function on top of Azure AI Search.\n\n\n```python\nsubprocess.run([\n    \"func\", \"azure\", \"functionapp\", \"publish\", app_name\n], check=True)\n```\n\n## Input in a Custom GPT in ChatGPT\nNow that we have an Azure Function that queries this Vector Search Index, let's put it as a GPT Action!\n\nSee documentation [here](https://openai.com/index/introducing-gpts/) on GPTs and [here](https://platform.openai.com/docs/actions) on GPT Actions. Use the below as the instructions for the GPT and as the OpenAPI spec for the GPT Action."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 24409061-b68d-4c16-b3d6-e00b093c011a
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"24409061-b68d-4c16-b3d6-e00b093c011a\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ba3ae13b-caea-4268-a761-e863f7bc923e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"5d97d29d4cbddc89f4cb9ad10573cac28991b67d652be83ac6e7b83276c16f49\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c1e36bba-b819-457a-9f6b-78097156f93e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"db47f4fc4659cd63107b42684fcbba220fb24903d26e9ef7289139908389dbc0\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 33496, \"end_char_idx\": 35367, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\n# Collect the relevant environment variables \nenv_vars = {\n    \"OPENAI_API_KEY\": openai_api_key,\n    \"SEARCH_SERVICE_API_KEY\": search_service_api_key,\n    \"EMBEDDINGS_MODEL\": embeddings_model\n}\n\n# Create the settings argument for the az functionapp create command\nsettings_args = []\nfor key, value in env_vars.items():\n    settings_args.append(f\"{key}={value}\")\n\nsubprocess.run([\n    \"az\", \"functionapp\", \"config\", \"appsettings\", \"set\",\n    \"--name\", app_name,\n    \"--resource-group\", resource_group,\n    \"--settings\", *settings_args\n], check=True)\n```\n\nWe are now ready to publish your function code `function_app.py` to the Azure Function. This may take up to 10 minutes to deploy. Once this is finished, we now have an API endpoint using an Azure Function on top of Azure AI Search.\n\n\n```python\nsubprocess.run([\n    \"func\", \"azure\", \"functionapp\", \"publish\", app_name\n], check=True)\n```\n\n## Input in a Custom GPT in ChatGPT\nNow that we have an Azure Function that queries this Vector Search Index, let's put it as a GPT Action!\n\nSee documentation [here](https://openai.com/index/introducing-gpts/) on GPTs and [here](https://platform.openai.com/docs/actions) on GPT Actions. Use the below as the instructions for the GPT and as the OpenAPI spec for the GPT Action.\n\n\n### Create OpenAPI Spec\nBelow is a sample OpenAPI spec. When we run the block below, a functional spec should be copied to the clipboard to paste in the GPT Action.\n\nNote that this does not have any authentication by default, but you can set up Azure Functions with OAuth by following the pattern in [this cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function#part-2-set-up-auth) in the Authentication section or looking at the documentation [here](https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c1e36bba-b819-457a-9f6b-78097156f93e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c1e36bba-b819-457a-9f6b-78097156f93e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"24409061-b68d-4c16-b3d6-e00b093c011a\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"c93a11e6315b8a63a3eec04d827520891fb3cd3dc2fd235cc377f753922519a6\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"071cd804-ffd2-4e98-9191-e0ab4584a5e7\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"656140e72a3e6217c4006e5160f1f47f0387be5d092554f2077a7aeeb402c574\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 34294, \"end_char_idx\": 38270, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\nsubprocess.run([\n    \"func\", \"azure\", \"functionapp\", \"publish\", app_name\n], check=True)\n```\n\n## Input in a Custom GPT in ChatGPT\nNow that we have an Azure Function that queries this Vector Search Index, let's put it as a GPT Action!\n\nSee documentation [here](https://openai.com/index/introducing-gpts/) on GPTs and [here](https://platform.openai.com/docs/actions) on GPT Actions. Use the below as the instructions for the GPT and as the OpenAPI spec for the GPT Action.\n\n\n### Create OpenAPI Spec\nBelow is a sample OpenAPI spec. When we run the block below, a functional spec should be copied to the clipboard to paste in the GPT Action.\n\nNote that this does not have any authentication by default, but you can set up Azure Functions with OAuth by following the pattern in [this cookbook](https://cookbook.openai.com/examples/chatgpt/gpt_actions_library/gpt_middleware_azure_function#part-2-set-up-auth) in the Authentication section or looking at the documentation [here](https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization).\n\n\n```python\n\nspec = f\"\"\"\nopenapi: 3.1.0\ninfo:\n  title: Vector Similarity Search API\n  description: API for performing vector similarity search.\n  version: 1.0.0\nservers:\n  - url: https://{app_name}.azurewebsites.net/api\n    description: Main (production) server\npaths:\n  /vector_similarity_search:\n    post:\n      operationId: vectorSimilaritySearch\n      summary: Perform a vector similarity search.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                search_service_endpoint:\n                  type: string\n                  description: The endpoint of the search service.\n                index_name:\n                  type: string\n                  description: The name of the search index.\n                query:\n                  type: string\n                  description: The search query.\n                k_nearest_neighbors:\n                  type: integer\n                  description: The number of nearest neighbors to return.\n                search_column:\n                  type: string\n                  description: The name of the search column.\n                use_hybrid_query:\n                  type: boolean\n                  description: Whether to use a hybrid query.\n                category:\n                  type: string\n                  description: category to filter.\n              required:\n                - search_service_endpoint\n                - index_name\n                - query\n                - k_nearest_neighbors\n                - search_column\n                - use_hybrid_query\n      responses:\n        '200':\n          description: A successful response with the search results.\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  results:\n                    type: array\n                    items:\n                      type: object\n                      properties:\n                        id:\n                          type: string\n                          description: The identifier of the result item.\n                        score:\n                          type: number\n                          description: The similarity score of the result item.\n                        content:\n                          type: object\n                          description: The content of the result item.\n        '400':\n          description: Bad request due to missing or invalid parameters.\n        '500':\n          description: Internal server error.\n\"\"\"\npyperclip.copy(spec)\nprint(\"OpenAPI spec copied to clipboard\")\nprint(spec)\n```\n\n### Create GPT Instructions\n\nFeel free to modify instructions as you see fit. Check out our docs [here](https://platform.openai.com/docs/guides/prompt-engineering) for some tips on prompt engineering."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 071cd804-ffd2-4e98-9191-e0ab4584a5e7
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb", "title": "Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT", "tokens": 8713, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"071cd804-ffd2-4e98-9191-e0ab4584a5e7\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"b0987757-cb7f-4604-90a1-17aede6900d7\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"9ea262c5cfe1d5088303e0fa4d72d2d33cdf85e20df26faa3a3a20edfa01e0a7\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c1e36bba-b819-457a-9f6b-78097156f93e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/azure/Azure_AI_Search_with_Azure_Functions_and_GPT_Actions_in_ChatGPT.ipynb\", \"title\": \"Azure AI Search as a vector database + Azure Functions for GPT integration in ChatGPT\", \"tokens\": 8713, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"33116bfd0af99e5de1443a758a47a8bfb2542d8dd545598eb9e9842b190608a2\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 38273, \"end_char_idx\": 39941, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "ref_doc_id": "b0987757-cb7f-4604-90a1-17aede6900d7", "chroma:document": "```python\ninstructions = f'''\nYou are an OAI docs assistant. You have an action in your knowledge base where you can make a POST request to search for information. The POST request should always include: {{\n    \"search_service_endpoint\": \"{search_service_endpoint}\",\n    \"index_name\": {index_name},\n    \"query\": \"<user_query>\",\n    \"k_nearest_neighbors\": 1,\n    \"search_column\": \"content_vector\",\n    \"use_hybrid_query\": true,\n    \"category\": \"<category>\"\n}}. Only the query and category change based on the user's request. Your goal is to assist users by performing searches using this POST request and providing them with relevant information based on the query.\n\nYou must only include knowledge you get from your action in your response.\nThe category must be from the following list: {categories}, which you should determine based on the user's query. If you cannot determine, then do not include the category in the POST request.\n'''\npyperclip.copy(instructions)\nprint(\"GPT Instructions copied to clipboard\")\nprint(instructions)\n```\n\nWe now have a GPT that queries a vector database! \n\n# Recap\nWe've now successfully integrated Azure AI Search with GPT Actions in ChatGPT by doing the following:\n1. embedded them using OpenAI's embeddings, while adding some additional metadata using gpt-4o.\n2. uploaded that data to Azure AI Search.\n3. created an endpoint to query it using Azure Functions.\n4. incorporated it into a Custom GPT. \n\nOur GPT can now retrieve information to help answer user queries, making it much more accurate and customized to our data. Here's the GPT in action:\n\n# ![azure-rag-quickstart-gpt.png](../../../../images/azure-rag-quickstart-gpt.png)"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: d9d35db3-0fa0-4167-b92e-c040a878ac59
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"d9d35db3-0fa0-4167-b92e-c040a878ac59\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"2e8300b6-1321-41f3-a981-1ab111468643\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c5bafd3bc8794b4db019664a796c0d8b29846910e4b65edfbdcb2924a6a95fdd\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 3391, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "# GCP Bigquery with GCP Functions and GPT actions in ChatGPT\n\nThis notebook provides step-by-step instructions on using Google Cloud BigQuery as a database with vector search capabilities, with OpenAI embeddings, then creating a Google Cloud Function on top to plug into a Custom GPT in ChatGPT.\n\nThis can be a solution for customers looking to set up RAG infrastructure contained within Google Cloud Platform (GCP), and exposing it as an endpoint to integrate that with other platforms such as ChatGPT.\n\nGoogle Cloud BigQuery is a fully-managed, serverless data warehouse that enables super-fast SQL queries using the processing power of Google's infrastructure. It allows developers to store and analyze massive datasets with ease.\n\nGoogle Cloud Functions is a lightweight, event-based, asynchronous compute solution that allows you to create small, single-purpose functions that respond to cloud events without managing servers or runtime environments.\n\n## Pre-requisites:\n\nTo run this cookbook, you must have:\n- A GCP project you have access to\n- GCP user with permission to create a BigQuery dataset and Google Cloud Function\n- [GCP CLI](https://cloud.google.com/sdk/docs/downloads-interactive) installed and connected\n- OpenAI API key\n- ChatGPT Plus, Teams or Enterprise subscription\n\n\n## Architecture\n\nBelow is a diagram of the architecture of this solution, which we'll walk through step-by-step:\n\n![bigquery-rag-architecture.png](../../../../images/bigquery_rag_architecture.png)\n\n## Table of Contents\n\n1. **[Setup of Environment](#set-up-environment)** Setup environment by installing and importing the required libraries and configuring our GCP settings. Includes:\n    - [Install and Import Required Libraries](#install-and-import-required-libraries)\n    - [Configure GCP project](#configure-gcp-project)\n    - [Configure OpenAI Settings](#configure-openai-settings)\n\n\n2. **[Prepare Data](#prepare-data)** Prepare the data for uploading by embedding the documents, as well as capturing additional metadata. We will use a subset of OpenAI's docs as example data for this.\n\n3. **[Create BigQuery Table with Vector search](#create-bigquery-table-with-vector-search)**  \nCreate a BigQuery table and upload the data we've prepared. Includes:\n\n    - [Create Dataset](#create-bigquery-dataset): Steps to create a dataset in BigQuery.\n    - [Create Table and upload data](#creating-table-and-upload-data): Instructions to create a table in BigQuery.\n\n4. **[Create GCP Function](#create-gcp-function)** using gcloud CLI and environment variables computed previously\n\n5. **[Input in a Custom GPT in ChatGPT](#input-in-a-custom-gpt-in-chatgpt)** Perform searches on the embedded data in BigQuery:\n\n    - [Vector Search](#test-search): Steps to perform vector-based search queries.\n    - [Metadata filtering Search](#perform-search-with-metadata-filtering): Instructions for performing metadata filtering.\n\n# Set up environment\n\n## Install and import required libraries\nThe below libraries can be categorized as standard Python libraries, third-party libraries, and GCP-related libraries.\n\n\n```python\n! pip install -q google-auth\n! pip install -q openai\n! pip install -q pandas\n! pip install -q google-cloud-functions\n! pip install -q python-dotenv\n! pip install -q pyperclip\n! pip install -q PyPDF2\n! pip install -q tiktoken\n! pip install -q google-cloud-bigquery\n! pip install -q pyyaml\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 2e8300b6-1321-41f3-a981-1ab111468643
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2e8300b6-1321-41f3-a981-1ab111468643\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"d9d35db3-0fa0-4167-b92e-c040a878ac59\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"d23a421ed82039aafafd0373b97df9bc1aef28acc7eced23d89f50612decb183\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"3cbb42a3-e59d-4462-963b-b41181817c9d\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"4cd030e92db96cce29e305a931a4f97ad05cb06f9e0b0a11e61a52f736143000\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1880, \"end_char_idx\": 4717, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "2. **[Prepare Data](#prepare-data)** Prepare the data for uploading by embedding the documents, as well as capturing additional metadata. We will use a subset of OpenAI's docs as example data for this.\n\n3. **[Create BigQuery Table with Vector search](#create-bigquery-table-with-vector-search)**  \nCreate a BigQuery table and upload the data we've prepared. Includes:\n\n    - [Create Dataset](#create-bigquery-dataset): Steps to create a dataset in BigQuery.\n    - [Create Table and upload data](#creating-table-and-upload-data): Instructions to create a table in BigQuery.\n\n4. **[Create GCP Function](#create-gcp-function)** using gcloud CLI and environment variables computed previously\n\n5. **[Input in a Custom GPT in ChatGPT](#input-in-a-custom-gpt-in-chatgpt)** Perform searches on the embedded data in BigQuery:\n\n    - [Vector Search](#test-search): Steps to perform vector-based search queries.\n    - [Metadata filtering Search](#perform-search-with-metadata-filtering): Instructions for performing metadata filtering.\n\n# Set up environment\n\n## Install and import required libraries\nThe below libraries can be categorized as standard Python libraries, third-party libraries, and GCP-related libraries.\n\n\n```python\n! pip install -q google-auth\n! pip install -q openai\n! pip install -q pandas\n! pip install -q google-cloud-functions\n! pip install -q python-dotenv\n! pip install -q pyperclip\n! pip install -q PyPDF2\n! pip install -q tiktoken\n! pip install -q google-cloud-bigquery\n! pip install -q pyyaml\n```\n\n\n```python\n# Standard Libraries\nimport json  \nimport os\nimport csv\nimport shutil\nfrom itertools import islice\nimport concurrent.futures\nimport yaml\n\n# Third-Party Libraries\nimport pandas as pd\nimport numpy as np\nfrom PyPDF2 import PdfReader\nimport tiktoken\nfrom dotenv import load_dotenv\nimport pyperclip\n\n# OpenAI Libraries\nfrom openai import OpenAI\n\n# Google Cloud Identity and Credentials\nfrom google.auth import default\nfrom google.cloud import bigquery\nfrom google.cloud import functions_v1\n\n```\n\n## Configure GCP project\n\nIf not already set-up, we'll install GCP CLI's, authenticate to GCP and set your default project.\n\n\n```python\n# Add gcloud to PATH\nos.environ['PATH'] += os.pathsep + os.path.expanduser('~/google-cloud-sdk/bin')\n\n# Verify gcloud is in PATH\n! gcloud --version\n```\n\n\n```python\n! gcloud auth application-default login\n```\n\n\n```python\nproject_id = \"<insert_project_id>\"  # Replace with your actual project ID\n! gcloud config set project {project_id}\n```\n\n\n```python\n! gcloud services enable cloudfunctions.googleapis.com\n! gcloud services enable cloudbuild.googleapis.com\n! gcloud services enable bigquery.googleapis.com\n```\n\n## Configure OpenAI settings\n\nThis section guides you through setting up authentication for  OpenAI. Before going through this section, make sure you have your OpenAI API key."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 3cbb42a3-e59d-4462-963b-b41181817c9d
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"3cbb42a3-e59d-4462-963b-b41181817c9d\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2e8300b6-1321-41f3-a981-1ab111468643\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"b4cb7839ff84c4a9a8b54b49afeed7a27f917d7b0559e7dc362da34d52363b85\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"11925185-6512-45e5-9dac-e22fe24920ce\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"6b9295ddbfda570c14f3a67cebd57f417a21591783af65ddafdb6eae88c0066a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 3394, \"end_char_idx\": 6320, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\n# Standard Libraries\nimport json  \nimport os\nimport csv\nimport shutil\nfrom itertools import islice\nimport concurrent.futures\nimport yaml\n\n# Third-Party Libraries\nimport pandas as pd\nimport numpy as np\nfrom PyPDF2 import PdfReader\nimport tiktoken\nfrom dotenv import load_dotenv\nimport pyperclip\n\n# OpenAI Libraries\nfrom openai import OpenAI\n\n# Google Cloud Identity and Credentials\nfrom google.auth import default\nfrom google.cloud import bigquery\nfrom google.cloud import functions_v1\n\n```\n\n## Configure GCP project\n\nIf not already set-up, we'll install GCP CLI's, authenticate to GCP and set your default project.\n\n\n```python\n# Add gcloud to PATH\nos.environ['PATH'] += os.pathsep + os.path.expanduser('~/google-cloud-sdk/bin')\n\n# Verify gcloud is in PATH\n! gcloud --version\n```\n\n\n```python\n! gcloud auth application-default login\n```\n\n\n```python\nproject_id = \"<insert_project_id>\"  # Replace with your actual project ID\n! gcloud config set project {project_id}\n```\n\n\n```python\n! gcloud services enable cloudfunctions.googleapis.com\n! gcloud services enable cloudbuild.googleapis.com\n! gcloud services enable bigquery.googleapis.com\n```\n\n## Configure OpenAI settings\n\nThis section guides you through setting up authentication for  OpenAI. Before going through this section, make sure you have your OpenAI API key.\n\n\n```python\nopenai_api_key = os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as an env var>\") # Saving this as a variable to reference in function app in later step\nopenai_client = OpenAI(api_key=openai_api_key)\nembeddings_model = \"text-embedding-3-small\" # We'll use this by default, but you can change to your text-embedding-3-large if desired\n```\n\n## Configure GCP BigQuery with Vector Search capabilities\n\nThis section explains how to create a dataset in BigQuery and store vectors of float, used for embeddings & vector search.\n\n\n```python\nfrom google.auth import default\n\n# Use default credentials\ncredentials, project_id = default()\nregion = \"us-central1\" # e.g: \"us-central1\"\nprint(\"Default Project ID:\", project_id)\n```\n\n# Prepare data\nWe're going to embed and store a few pages of the OpenAI docs in the oai_docs folder. We'll first embed each, add it to a CSV, and then use that CSV to upload to the index.\n\nWe are going to use some techniques highlighted in [this cookbook](khttps://github.com/openai/openai-cookbook/blob/main/examples/Embedding_long_inputs.ipynb). This is a quick way to embed text, without taking into account variables like sections, using our vision model to describe images/graphs/diagrams, overlapping text between chunks for longer documents, etc. \n\nIn order to handle longer text files beyond the context of 8191 tokens, we can either use the chunk embeddings separately, or combine them in some way, such as averaging (weighted by the size of each chunk).\n\nWe will take a function from Python's own cookbook that breaks up a sequence into chunks."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 11925185-6512-45e5-9dac-e22fe24920ce
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"11925185-6512-45e5-9dac-e22fe24920ce\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"3cbb42a3-e59d-4462-963b-b41181817c9d\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"c47eb9144a08411c4cf8c2003542c555afaabf2120b7beb09f7279b05f9c5d7a\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"37526d93-f835-42f6-a51b-ee82291e8711\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f3fb08707aa80906a3f571bca14128050c2a2bf69974d9ff55d91f6a77283445\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 4720, \"end_char_idx\": 6939, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\nopenai_api_key = os.environ.get(\"OPENAI_API_KEY\", \"<your OpenAI API key if not set as an env var>\") # Saving this as a variable to reference in function app in later step\nopenai_client = OpenAI(api_key=openai_api_key)\nembeddings_model = \"text-embedding-3-small\" # We'll use this by default, but you can change to your text-embedding-3-large if desired\n```\n\n## Configure GCP BigQuery with Vector Search capabilities\n\nThis section explains how to create a dataset in BigQuery and store vectors of float, used for embeddings & vector search.\n\n\n```python\nfrom google.auth import default\n\n# Use default credentials\ncredentials, project_id = default()\nregion = \"us-central1\" # e.g: \"us-central1\"\nprint(\"Default Project ID:\", project_id)\n```\n\n# Prepare data\nWe're going to embed and store a few pages of the OpenAI docs in the oai_docs folder. We'll first embed each, add it to a CSV, and then use that CSV to upload to the index.\n\nWe are going to use some techniques highlighted in [this cookbook](khttps://github.com/openai/openai-cookbook/blob/main/examples/Embedding_long_inputs.ipynb). This is a quick way to embed text, without taking into account variables like sections, using our vision model to describe images/graphs/diagrams, overlapping text between chunks for longer documents, etc. \n\nIn order to handle longer text files beyond the context of 8191 tokens, we can either use the chunk embeddings separately, or combine them in some way, such as averaging (weighted by the size of each chunk).\n\nWe will take a function from Python's own cookbook that breaks up a sequence into chunks.\n\n\n```python\ndef batched(iterable, n):\n    \"\"\"Batch data into tuples of length n. The last batch may be shorter.\"\"\"\n    # batched('ABCDEFG', 3) --> ABC DEF G\n    if n < 1:\n        raise ValueError('n must be at least one')\n    it = iter(iterable)\n    while (batch := tuple(islice(it, n))):\n        yield batch\n\n```\n\nNow we define a function that encodes a string into tokens and then breaks it up into chunks. We'll use tiktoken, a fast open-source tokenizer by OpenAI.\n\nTo read more about counting tokens with Tiktoken, check out [this cookbook](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 37526d93-f835-42f6-a51b-ee82291e8711
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"37526d93-f835-42f6-a51b-ee82291e8711\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"11925185-6512-45e5-9dac-e22fe24920ce\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a0cdcda9e01b5cabb9a7c97a7bebfa59f7004400b1d922351dd04c33fa346b64\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"d7490cf5-1ea1-4762-b2b9-0f0f47d886f4\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"0bbaedbdefd83c5e44bc6134ff43612eb435216189896806d8ff5d396e83ad2b\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5271, \"end_char_idx\": 8333, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\nfrom google.auth import default\n\n# Use default credentials\ncredentials, project_id = default()\nregion = \"us-central1\" # e.g: \"us-central1\"\nprint(\"Default Project ID:\", project_id)\n```\n\n# Prepare data\nWe're going to embed and store a few pages of the OpenAI docs in the oai_docs folder. We'll first embed each, add it to a CSV, and then use that CSV to upload to the index.\n\nWe are going to use some techniques highlighted in [this cookbook](khttps://github.com/openai/openai-cookbook/blob/main/examples/Embedding_long_inputs.ipynb). This is a quick way to embed text, without taking into account variables like sections, using our vision model to describe images/graphs/diagrams, overlapping text between chunks for longer documents, etc. \n\nIn order to handle longer text files beyond the context of 8191 tokens, we can either use the chunk embeddings separately, or combine them in some way, such as averaging (weighted by the size of each chunk).\n\nWe will take a function from Python's own cookbook that breaks up a sequence into chunks.\n\n\n```python\ndef batched(iterable, n):\n    \"\"\"Batch data into tuples of length n. The last batch may be shorter.\"\"\"\n    # batched('ABCDEFG', 3) --> ABC DEF G\n    if n < 1:\n        raise ValueError('n must be at least one')\n    it = iter(iterable)\n    while (batch := tuple(islice(it, n))):\n        yield batch\n\n```\n\nNow we define a function that encodes a string into tokens and then breaks it up into chunks. We'll use tiktoken, a fast open-source tokenizer by OpenAI.\n\nTo read more about counting tokens with Tiktoken, check out [this cookbook](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken). \n\n\n\n\n```python\ndef chunked_tokens(text, chunk_length, encoding_name='cl100k_base'):\n    # Get the encoding object for the specified encoding name. OpenAI's tiktoken library, which is used in this notebook, currently supports two encodings: 'bpe' and 'cl100k_base'. The 'bpe' encoding is used for GPT-3 and earlier models, while 'cl100k_base' is used for newer models like GPT-4.\n    encoding = tiktoken.get_encoding(encoding_name)\n    # Encode the input text into tokens\n    tokens = encoding.encode(text)\n    # Create an iterator that yields chunks of tokens of the specified length\n    chunks_iterator = batched(tokens, chunk_length)\n    # Yield each chunk from the iterator\n    yield from chunks_iterator\n```\n\nFinally, we can write a function that safely handles embedding requests, even when the input text is longer than the maximum context length, by chunking the input tokens and embedding each chunk individually. The average flag can be set to True to return the weighted average of the chunk embeddings, or False to simply return the unmodified list of chunk embeddings.\n\n> Note: there are other techniques you can take here, including:\n> - using GPT-4o to capture images/chart descriptions for embedding\n> - chunking based on paragraphs or sections\n> - adding more descriptive metadata about each article.\n\n\n```python\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: d7490cf5-1ea1-4762-b2b9-0f0f47d886f4
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"d7490cf5-1ea1-4762-b2b9-0f0f47d886f4\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"37526d93-f835-42f6-a51b-ee82291e8711\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"7e7631cb37ba540368952374d3eea8afd542cc3e6fbe167e8b979bc8546a90f0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"193f08b4-1ce8-4e61-9a4d-312ee78e6778\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"2b5e1b9f7608212a2ec302776456580097b7d74222eff2d0240c7430e00fa9e6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 6945, \"end_char_idx\": 9655, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\ndef chunked_tokens(text, chunk_length, encoding_name='cl100k_base'):\n    # Get the encoding object for the specified encoding name. OpenAI's tiktoken library, which is used in this notebook, currently supports two encodings: 'bpe' and 'cl100k_base'. The 'bpe' encoding is used for GPT-3 and earlier models, while 'cl100k_base' is used for newer models like GPT-4.\n    encoding = tiktoken.get_encoding(encoding_name)\n    # Encode the input text into tokens\n    tokens = encoding.encode(text)\n    # Create an iterator that yields chunks of tokens of the specified length\n    chunks_iterator = batched(tokens, chunk_length)\n    # Yield each chunk from the iterator\n    yield from chunks_iterator\n```\n\nFinally, we can write a function that safely handles embedding requests, even when the input text is longer than the maximum context length, by chunking the input tokens and embedding each chunk individually. The average flag can be set to True to return the weighted average of the chunk embeddings, or False to simply return the unmodified list of chunk embeddings.\n\n> Note: there are other techniques you can take here, including:\n> - using GPT-4o to capture images/chart descriptions for embedding\n> - chunking based on paragraphs or sections\n> - adding more descriptive metadata about each article.\n\n\n```python\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```\n\n\n```python\ndef generate_embeddings(text, model):\n    # Generate embeddings for the provided text using the specified model\n    embeddings_response = openai_client.embeddings.create(model=model, input=text)\n    # Extract the embedding data from the response\n    embedding = embeddings_response.data[0].embedding\n    return embedding\n\ndef len_safe_get_embedding(text, model=embeddings_model, max_tokens=EMBEDDING_CTX_LENGTH, encoding_name=EMBEDDING_ENCODING):\n    # Initialize lists to store embeddings and corresponding text chunks\n    chunk_embeddings = []\n    chunk_texts = []\n    # Iterate over chunks of tokens from the input text\n    for chunk in chunked_tokens(text, chunk_length=max_tokens, encoding_name=encoding_name):\n        # Generate embeddings for each chunk and append to the list\n        chunk_embeddings.append(generate_embeddings(chunk, model=model))\n        # Decode the chunk back to text and append to the list\n        chunk_texts.append(tiktoken.get_encoding(encoding_name).decode(chunk))\n    # Return the list of chunk embeddings and the corresponding text chunks\n    return chunk_embeddings, chunk_texts\n```\n\nNext, we can define a helper function that will capture additional metadata about the documents. In this example, I'll choose from a list of categories to use later on in a metadata filter"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 193f08b4-1ce8-4e61-9a4d-312ee78e6778
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"193f08b4-1ce8-4e61-9a4d-312ee78e6778\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"d7490cf5-1ea1-4762-b2b9-0f0f47d886f4\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"9bb3442c9bc7bba34887ed6f0fd954454314daae4093255cce1e9d91ee0a2e9e\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"1668009c-2d50-48aa-a186-17bac7fe754e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"623f1fecfebe40b62e2a23264c8595063edee949efa1dc755eef4c9bce04154c\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 8259, \"end_char_idx\": 10819, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\nEMBEDDING_CTX_LENGTH = 8191\nEMBEDDING_ENCODING='cl100k_base'\n```\n\n\n```python\ndef generate_embeddings(text, model):\n    # Generate embeddings for the provided text using the specified model\n    embeddings_response = openai_client.embeddings.create(model=model, input=text)\n    # Extract the embedding data from the response\n    embedding = embeddings_response.data[0].embedding\n    return embedding\n\ndef len_safe_get_embedding(text, model=embeddings_model, max_tokens=EMBEDDING_CTX_LENGTH, encoding_name=EMBEDDING_ENCODING):\n    # Initialize lists to store embeddings and corresponding text chunks\n    chunk_embeddings = []\n    chunk_texts = []\n    # Iterate over chunks of tokens from the input text\n    for chunk in chunked_tokens(text, chunk_length=max_tokens, encoding_name=encoding_name):\n        # Generate embeddings for each chunk and append to the list\n        chunk_embeddings.append(generate_embeddings(chunk, model=model))\n        # Decode the chunk back to text and append to the list\n        chunk_texts.append(tiktoken.get_encoding(encoding_name).decode(chunk))\n    # Return the list of chunk embeddings and the corresponding text chunks\n    return chunk_embeddings, chunk_texts\n```\n\nNext, we can define a helper function that will capture additional metadata about the documents. In this example, I'll choose from a list of categories to use later on in a metadata filter\n\n\n```python\ncategories = ['authentication','models','techniques','tools','setup','billing_limits','other']\n\ndef categorize_text(text, categories):\n\n    # Create a prompt for categorization\n    messages = [\n        {\"role\": \"system\", \"content\": f\"\"\"You are an expert in LLMs, and you will be given text that corresponds to an article in OpenAI's documentation.\n         Categorize the document into one of these categories: {', '.join(categories)}. Only respond with the category name and nothing else.\"\"\"},\n        {\"role\": \"user\", \"content\": text}\n    ]\n    try:\n        # Call the OpenAI API to categorize the text\n        response = openai_client.chat.completions.create(\n            model=\"gpt-4o\",\n            messages=messages\n        )\n\n        # Extract the category from the response\n        category = response.choices[0].message.content\n        return category\n    except Exception as e:\n        print(f\"Error categorizing text: {str(e)}\")\n        return None\n\n# Example usage\n```\n\nNow, we can define some helper functions to process the .txt files in the oai_docs folder. Feel free to use this on your own data, this supports both .txt and .pdf files."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 1668009c-2d50-48aa-a186-17bac7fe754e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"1668009c-2d50-48aa-a186-17bac7fe754e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"193f08b4-1ce8-4e61-9a4d-312ee78e6778\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"cd7400dbeb1b4a5831e2744614f17a057d9f6591e16bce76219aabb908c64123\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b2f0ff1c-2de3-41e8-81e4-a90f0e02abe5\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"e08e2c5fd0170b7c8cc8e6e3df85e67796414bb52220b59e469ff6663b4dee41\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 9658, \"end_char_idx\": 13000, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\ncategories = ['authentication','models','techniques','tools','setup','billing_limits','other']\n\ndef categorize_text(text, categories):\n\n    # Create a prompt for categorization\n    messages = [\n        {\"role\": \"system\", \"content\": f\"\"\"You are an expert in LLMs, and you will be given text that corresponds to an article in OpenAI's documentation.\n         Categorize the document into one of these categories: {', '.join(categories)}. Only respond with the category name and nothing else.\"\"\"},\n        {\"role\": \"user\", \"content\": text}\n    ]\n    try:\n        # Call the OpenAI API to categorize the text\n        response = openai_client.chat.completions.create(\n            model=\"gpt-4o\",\n            messages=messages\n        )\n\n        # Extract the category from the response\n        category = response.choices[0].message.content\n        return category\n    except Exception as e:\n        print(f\"Error categorizing text: {str(e)}\")\n        return None\n\n# Example usage\n```\n\nNow, we can define some helper functions to process the .txt files in the oai_docs folder. Feel free to use this on your own data, this supports both .txt and .pdf files.\n\n\n```python\ndef extract_text_from_pdf(pdf_path):\n    # Initialize the PDF reader\n    reader = PdfReader(pdf_path)\n    text = \"\"\n    # Iterate through each page in the PDF and extract text\n    for page in reader.pages:\n        text += page.extract_text()\n    return text\n\ndef process_file(file_path, idx, categories, embeddings_model):\n    file_name = os.path.basename(file_path)\n    print(f\"Processing file {idx + 1}: {file_name}\")\n    \n    # Read text content from .txt files\n    if file_name.endswith('.txt'):\n        with open(file_path, 'r', encoding='utf-8') as file:\n            text = file.read()\n    # Extract text content from .pdf files\n    elif file_name.endswith('.pdf'):\n        text = extract_text_from_pdf(file_path)\n    \n    title = file_name\n    # Generate embeddings for the title\n    title_vectors, title_text = len_safe_get_embedding(title, embeddings_model)\n    print(f\"Generated title embeddings for {file_name}\")\n    \n    # Generate embeddings for the content\n    content_vectors, content_text = len_safe_get_embedding(text, embeddings_model)\n    print(f\"Generated content embeddings for {file_name}\")\n    \n    category = categorize_text(' '.join(content_text), categories)\n    print(f\"Categorized {file_name} as {category}\")\n    \n    # Prepare the data to be appended\n    data = []\n    for i, content_vector in enumerate(content_vectors):\n        data.append({\n            \"id\": f\"{idx}_{i}\",\n            \"vector_id\": f\"{idx}_{i}\",\n            \"title\": title_text[0],\n            \"text\": content_text[i],\n            \"title_vector\": json.dumps(title_vectors[0]),  # Assuming title is short and has only one chunk\n            \"content_vector\": json.dumps(content_vector),\n            \"category\": category\n        })\n        print(f\"Appended data for chunk {i + 1}/{len(content_vectors)} of {file_name}\")\n    \n    return data\n\n\n```\n\nWe'll now use this helper function to process our OpenAI documentation. Feel free to update this to use your own data by changing the folder in process_files below.\n\nNote that this will process the documents in chosen folder concurrently, so this should take <30 seconds if using txt files, and slightly longer if using PDFs."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: b2f0ff1c-2de3-41e8-81e4-a90f0e02abe5
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b2f0ff1c-2de3-41e8-81e4-a90f0e02abe5\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"1668009c-2d50-48aa-a186-17bac7fe754e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"082174960000d20a34b09973c3fbd7bfad5086696b28786c7e0b45f45ca374f1\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"8c1c4ec3-21cc-4778-b373-cdb713bf1b53\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f2085f28758fdb0c73ed95052e135a043109b2ea71298089988ad8cbdcd40127\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 12670, \"end_char_idx\": 16063, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```\n\nWe'll now use this helper function to process our OpenAI documentation. Feel free to update this to use your own data by changing the folder in process_files below.\n\nNote that this will process the documents in chosen folder concurrently, so this should take <30 seconds if using txt files, and slightly longer if using PDFs.\n\n\n```python\n## Customize the location below if you are using different data besides the OpenAI documentation. Note that if you are using a different dataset, you will need to update the categories list as well.\nfolder_name = \"../../../data/oai_docs\"\n\nfiles = [os.path.join(folder_name, f) for f in os.listdir(folder_name) if f.endswith('.txt') or f.endswith('.pdf')]\ndata = []\n\n# Process each file concurrently\nwith concurrent.futures.ThreadPoolExecutor() as executor:\n    futures = {executor.submit(process_file, file_path, idx, categories, embeddings_model): idx for idx, file_path in enumerate(files)}\n    for future in concurrent.futures.as_completed(futures):\n        try:\n            result = future.result()\n            data.extend(result)\n        except Exception as e:\n            print(f\"Error processing file: {str(e)}\")\n\n# Write the data to a CSV file\ncsv_file = os.path.join(\"..\", \"embedded_data.csv\")\nwith open(csv_file, 'w', newline='', encoding='utf-8') as csvfile:\n    fieldnames = [\"id\", \"vector_id\", \"title\", \"text\", \"title_vector\", \"content_vector\",\"category\"]\n    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)\n    writer.writeheader()\n    for row in data:\n        writer.writerow(row)\n        print(f\"Wrote row with id {row['id']} to CSV\")\n\n# Convert the CSV file to a Dataframe\narticle_df = pd.read_csv(\"../embedded_data.csv\")\n# Read vectors from strings back into a list using json.loads\narticle_df[\"title_vector\"] = article_df.title_vector.apply(json.loads)\narticle_df[\"content_vector\"] = article_df.content_vector.apply(json.loads)\narticle_df[\"vector_id\"] = article_df[\"vector_id\"].apply(str)\narticle_df[\"category\"] = article_df[\"category\"].apply(str)\narticle_df.head()\n```\n\nWe now have an `embedded_data.csv` file with six columns that we can upload to our vector database! \n\n# Create BigQuery table with Vector Search\n\n## Create BigQuery dataset\n\nWe'll leverage Google SDK and create a dataset named \"oai_docs\" with a table name of \"embedded_data\", but feel free to change those variables (you can also change regions).\n\n*PS: We won't create a BigQuery index, that could improve the performance of the vector search, because such index requires more than 1k rows in our dataset which we don't have in our example, but feel free to leverage that for your own use-case.*\n\n\n```python\n# Create bigquery table\n\nfrom google.cloud import bigquery\nfrom google.api_core.exceptions import Conflict\n\n# Define the dataset ID (project_id.dataset_id)\nraw_dataset_id = 'oai_docs'\ndataset_id = project_id + '.' + raw_dataset_id\n\nclient = bigquery.Client(credentials=credentials, project=project_id)\n\n# Construct a full Dataset object to send to the API\ndataset = bigquery.Dataset(dataset_id)\n\n# Specify the geographic location where the dataset should reside\ndataset.location = \"US\"\n\n# Send the dataset to the API for creation\ntry:\n    dataset = client.create_dataset(dataset, timeout=30)\n    print(f\"Created dataset {client.project}.{dataset.dataset_id}\")\nexcept Conflict:\n    print(f\"dataset {dataset.dataset_id } already exists\")\n    \n```"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 8c1c4ec3-21cc-4778-b373-cdb713bf1b53
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"8c1c4ec3-21cc-4778-b373-cdb713bf1b53\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b2f0ff1c-2de3-41e8-81e4-a90f0e02abe5\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"5afaaf11ac9e333d7247c43a3561e3fba47488faf4cc0ba6ce67cbffde4fc700\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"42a16ca5-c2b4-4287-a43b-cf6936acc404\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"003341fcda74a53d30a7b84fa016d50c6e9a114908a9843fa4043648939c0572\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15309, \"end_char_idx\": 16819, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\n# Create bigquery table\n\nfrom google.cloud import bigquery\nfrom google.api_core.exceptions import Conflict\n\n# Define the dataset ID (project_id.dataset_id)\nraw_dataset_id = 'oai_docs'\ndataset_id = project_id + '.' + raw_dataset_id\n\nclient = bigquery.Client(credentials=credentials, project=project_id)\n\n# Construct a full Dataset object to send to the API\ndataset = bigquery.Dataset(dataset_id)\n\n# Specify the geographic location where the dataset should reside\ndataset.location = \"US\"\n\n# Send the dataset to the API for creation\ntry:\n    dataset = client.create_dataset(dataset, timeout=30)\n    print(f\"Created dataset {client.project}.{dataset.dataset_id}\")\nexcept Conflict:\n    print(f\"dataset {dataset.dataset_id } already exists\")\n    \n```\n\n\n```python\n# Read the CSV file, properly handling multiline fields\ncsv_file_path = \"../embedded_data.csv\"\ndf = pd.read_csv(csv_file_path, engine='python', quotechar='\"', quoting=1)\n\n# Display the first few rows of the dataframe\ndf.head()\n\n```\n\n## Creating table and upload data\n\nWe'll create the table with the attribute name and types. Note the 'content_vector' attribute that allows to store a vector of float for a single row, which we'll use for our vector search.\n\nThis code will then loop on our CSVs previously created to insert the rows into Bigquery. \nIf you run this code multiple time, multiple identical rows will be inserted which will give less accurate results when doing search (you could put uniqueness on IDs or clean the DB each time)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 42a16ca5-c2b4-4287-a43b-cf6936acc404
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"42a16ca5-c2b4-4287-a43b-cf6936acc404\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"8c1c4ec3-21cc-4778-b373-cdb713bf1b53\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"52fc3546cedfc595efeb9e5d64dfe227913aedf908368c4c8f6e42f93c67e4b6\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"459d5a93-d77d-41b5-bb19-3e7866abffb8\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"59f81da7ede3c10aee2cbbeffb071bd1445387e05f33083c260beb115b90706f\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15309, \"end_char_idx\": 19086, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\n# Create bigquery table\n\nfrom google.cloud import bigquery\nfrom google.api_core.exceptions import Conflict\n\n# Define the dataset ID (project_id.dataset_id)\nraw_dataset_id = 'oai_docs'\ndataset_id = project_id + '.' + raw_dataset_id\n\nclient = bigquery.Client(credentials=credentials, project=project_id)\n\n# Construct a full Dataset object to send to the API\ndataset = bigquery.Dataset(dataset_id)\n\n# Specify the geographic location where the dataset should reside\ndataset.location = \"US\"\n\n# Send the dataset to the API for creation\ntry:\n    dataset = client.create_dataset(dataset, timeout=30)\n    print(f\"Created dataset {client.project}.{dataset.dataset_id}\")\nexcept Conflict:\n    print(f\"dataset {dataset.dataset_id } already exists\")\n    \n```\n\n\n```python\n# Read the CSV file, properly handling multiline fields\ncsv_file_path = \"../embedded_data.csv\"\ndf = pd.read_csv(csv_file_path, engine='python', quotechar='\"', quoting=1)\n\n# Display the first few rows of the dataframe\ndf.head()\n\n```\n\n## Creating table and upload data\n\nWe'll create the table with the attribute name and types. Note the 'content_vector' attribute that allows to store a vector of float for a single row, which we'll use for our vector search.\n\nThis code will then loop on our CSVs previously created to insert the rows into Bigquery. \nIf you run this code multiple time, multiple identical rows will be inserted which will give less accurate results when doing search (you could put uniqueness on IDs or clean the DB each time).\n\n\n```python\n# Read the CSV file, properly handling multiline fields\ndataset_id = project_id + '.' + raw_dataset_id\nclient = bigquery.Client(credentials=credentials, project=project_id)\ncsv_file_path = \"../embedded_data.csv\"\ndf = pd.read_csv(csv_file_path, engine='python', quotechar='\"', quoting=1)\n\n# Preprocess the data to ensure content_vector is correctly formatted\n# removing last and first character which are brackets [], comma splitting and converting to float\ndef preprocess_content_vector(row):\n    row['content_vector'] = [float(x) for x in row['content_vector'][1:-1].split(',')]\n    return row\n\n# Apply preprocessing to the dataframe\ndf = df.apply(preprocess_content_vector, axis=1)\n\n# Define the schema of the final table\nfinal_schema = [\n    bigquery.SchemaField(\"id\", \"STRING\"),\n    bigquery.SchemaField(\"vector_id\", \"STRING\"),\n    bigquery.SchemaField(\"title\", \"STRING\"),\n    bigquery.SchemaField(\"text\", \"STRING\"),\n    bigquery.SchemaField(\"title_vector\", \"STRING\"),\n    bigquery.SchemaField(\"content_vector\", \"FLOAT64\", mode=\"REPEATED\"),\n    bigquery.SchemaField(\"category\", \"STRING\"),\n]\n\n# Define the final table ID\nraw_table_id = 'embedded_data'\nfinal_table_id = f'{dataset_id}.' + raw_table_id\n\n# Create the final table object\nfinal_table = bigquery.Table(final_table_id, schema=final_schema)\n\n# Send the table to the API for creation\nfinal_table = client.create_table(final_table, exists_ok=True)  # API request\nprint(f\"Created final table {project_id}.{final_table.dataset_id}.{final_table.table_id}\")\n\n# Convert DataFrame to list of dictionaries for BigQuery insertion\nrows_to_insert = df.to_dict(orient='records')\n\n# Upload data to the final table\nerrors = client.insert_rows_json(f\"{final_table.dataset_id}.{final_table.table_id}\", rows_to_insert)  # API request\n\nif errors:\n    print(f\"Encountered errors while inserting rows: {errors}\")\nelse:\n    print(f\"Successfully loaded data into {dataset_id}:{final_table_id}\")\n```\n\n# Test search\nNow that the data is uploaded, we'll test both pure vector similarity search and with metadata filtering locally below to make sure it is working as expected.\n\nYou can test both a pure vector search and metadata filtering.\n\nThe query below is pure vector search, where we don't filter out on category."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 459d5a93-d77d-41b5-bb19-3e7866abffb8
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"459d5a93-d77d-41b5-bb19-3e7866abffb8\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"42a16ca5-c2b4-4287-a43b-cf6936acc404\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"a959916ed8d8c1c39ff77a87fdc6f6b24f0d7d5e39433b8e670d1bec64c1ac15\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"91a942a1-247a-46ad-9fd3-603558a03223\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ab2130edfcb8bbe698d982ed63d3d8ffccc2d2c34625df1ee31ee6243f932e96\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 19089, \"end_char_idx\": 21729, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\nquery = \"What model should I use to embed?\"\ncategory = \"models\"\n\nembedding_query = generate_embeddings(query, embeddings_model)\nembedding_query_list = ', '.join(map(str, embedding_query))\n\nquery = f\"\"\"\nWITH search_results AS (\n  SELECT query.id AS query_id, base.id AS base_id, distance\n  FROM VECTOR_SEARCH(\n    TABLE oai_docs.embedded_data, 'content_vector',\n    (SELECT ARRAY[{embedding_query_list}] AS content_vector, 'query_vector' AS id),\n    top_k => 2, distance_type => 'COSINE', options => '{{\"use_brute_force\": true}}')\n)\nSELECT sr.query_id, sr.base_id, sr.distance, ed.text, ed.title\nFROM search_results sr\nJOIN oai_docs.embedded_data ed ON sr.base_id = ed.id\nORDER BY sr.distance ASC\n\"\"\"\n\nquery_job = client.query(query)\nresults = query_job.result()  # Wait for the job to complete\n\nfor row in results:\n    print(f\"query_id: {row['query_id']}, base_id: {row['base_id']}, distance: {row['distance']}, text_truncated: {row['text'][0:100]}\")\n\n```\n\n## Perform search with metadata filtering\nMetadata filtering allows to restrict findings that have certain attributes on top of having the closest semantic findings of vector search.\n\nThe provided code snippet demonstrates how to execute a query with metadata filtering:\n\n\n```python\n\nquery = \"What model should I use to embed?\"\ncategory = \"models\"\n\nembedding_query = generate_embeddings(query, embeddings_model)\nembedding_query_list = ', '.join(map(str, embedding_query))\n\n\nquery = f\"\"\"\nWITH search_results AS (\n  SELECT query.id AS query_id, base.id AS base_id, distance\n  FROM VECTOR_SEARCH(\n    (SELECT * FROM oai_docs.embedded_data WHERE category = '{category}'), \n    'content_vector',\n    (SELECT ARRAY[{embedding_query_list}] AS content_vector, 'query_vector' AS id),\n    top_k => 4, distance_type => 'COSINE', options => '{{\"use_brute_force\": true}}')\n)\nSELECT sr.query_id, sr.base_id, sr.distance, ed.text, ed.title, ed.category\nFROM search_results sr\nJOIN oai_docs.embedded_data ed ON sr.base_id = ed.id\nORDER BY sr.distance ASC\n\"\"\"\n\n\nquery_job = client.query(query)\nresults = query_job.result()  # Wait for the job to complete\n\nfor row in results:\n    print(f\"category: {row['category']}, title: {row['title']}, base_id: {row['base_id']}, distance: {row['distance']}, text_truncated: {row['text'][0:100]}\")\n\n```\n\n# Create GCP function\n\n## Exporting variables\n\nWe'll deploy the function in `main.py` in this folder (also available [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/main.py)).\n\nIn a first step, we'll export the variables to target our table/dataset as well as to generate Embeddings using OpenAI's API."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 91a942a1-247a-46ad-9fd3-603558a03223
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"91a942a1-247a-46ad-9fd3-603558a03223\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"459d5a93-d77d-41b5-bb19-3e7866abffb8\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"0b1b81765eba46fbc2873fb7f328eb60e7e0fc58be5d2541019025b43e3bb6b0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"3fa737df-7e98-4621-b267-d847aad08cab\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"b97fd9c62afe7a50f9f0171b909e00403e4bdda0468e1ca5916711ef0486cc7d\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 20329, \"end_char_idx\": 22620, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\n\nquery = \"What model should I use to embed?\"\ncategory = \"models\"\n\nembedding_query = generate_embeddings(query, embeddings_model)\nembedding_query_list = ', '.join(map(str, embedding_query))\n\n\nquery = f\"\"\"\nWITH search_results AS (\n  SELECT query.id AS query_id, base.id AS base_id, distance\n  FROM VECTOR_SEARCH(\n    (SELECT * FROM oai_docs.embedded_data WHERE category = '{category}'), \n    'content_vector',\n    (SELECT ARRAY[{embedding_query_list}] AS content_vector, 'query_vector' AS id),\n    top_k => 4, distance_type => 'COSINE', options => '{{\"use_brute_force\": true}}')\n)\nSELECT sr.query_id, sr.base_id, sr.distance, ed.text, ed.title, ed.category\nFROM search_results sr\nJOIN oai_docs.embedded_data ed ON sr.base_id = ed.id\nORDER BY sr.distance ASC\n\"\"\"\n\n\nquery_job = client.query(query)\nresults = query_job.result()  # Wait for the job to complete\n\nfor row in results:\n    print(f\"category: {row['category']}, title: {row['title']}, base_id: {row['base_id']}, distance: {row['distance']}, text_truncated: {row['text'][0:100]}\")\n\n```\n\n# Create GCP function\n\n## Exporting variables\n\nWe'll deploy the function in `main.py` in this folder (also available [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/main.py)).\n\nIn a first step, we'll export the variables to target our table/dataset as well as to generate Embeddings using OpenAI's API.\n\n\n```python\n# Create a dictionary to store the environment variables (they were used previously and are just retrieved)\nenv_variables = {\n    'OPENAI_API_KEY': openai_api_key,\n    'EMBEDDINGS_MODEL': embeddings_model,\n    'PROJECT_ID': project_id,\n    'DATASET_ID': raw_dataset_id,\n    'TABLE_ID': raw_table_id\n}\n\n# Write the environment variables to a YAML file\nwith open('env.yml', 'w') as yaml_file:\n    yaml.dump(env_variables, yaml_file, default_flow_style=False)\n\nprint(\"env.yml file created successfully.\")\n```\n\n## Deploying the function\n\nWe will now create a google function called \"openai_docs_search\" for our current project, for that we'll launch the CLI command below, leveraging the previously created environment variables. Note that this function can be called from everywhere without authentication, do not use that for production or add additional authentication mechanism."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 3fa737df-7e98-4621-b267-d847aad08cab
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"3fa737df-7e98-4621-b267-d847aad08cab\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"91a942a1-247a-46ad-9fd3-603558a03223\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"37a7055d448f5369cbbcc01d08805781ec47989b3ce1442d0fd10bb6a3b365af\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"2f0bfd84-cd12-43af-993d-0ce0c2fa1700\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"f8f3f553e768f0d0e5a77438a1ae0a9b4f8694871b68d87345440a48fcdeb7d5\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 21101, \"end_char_idx\": 23521, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "query_job = client.query(query)\nresults = query_job.result()  # Wait for the job to complete\n\nfor row in results:\n    print(f\"category: {row['category']}, title: {row['title']}, base_id: {row['base_id']}, distance: {row['distance']}, text_truncated: {row['text'][0:100]}\")\n\n```\n\n# Create GCP function\n\n## Exporting variables\n\nWe'll deploy the function in `main.py` in this folder (also available [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/main.py)).\n\nIn a first step, we'll export the variables to target our table/dataset as well as to generate Embeddings using OpenAI's API.\n\n\n```python\n# Create a dictionary to store the environment variables (they were used previously and are just retrieved)\nenv_variables = {\n    'OPENAI_API_KEY': openai_api_key,\n    'EMBEDDINGS_MODEL': embeddings_model,\n    'PROJECT_ID': project_id,\n    'DATASET_ID': raw_dataset_id,\n    'TABLE_ID': raw_table_id\n}\n\n# Write the environment variables to a YAML file\nwith open('env.yml', 'w') as yaml_file:\n    yaml.dump(env_variables, yaml_file, default_flow_style=False)\n\nprint(\"env.yml file created successfully.\")\n```\n\n## Deploying the function\n\nWe will now create a google function called \"openai_docs_search\" for our current project, for that we'll launch the CLI command below, leveraging the previously created environment variables. Note that this function can be called from everywhere without authentication, do not use that for production or add additional authentication mechanism.\n\n\n```python\n! gcloud functions deploy openai_docs_search \\\n  --runtime python39 \\\n  --trigger-http \\\n  --allow-unauthenticated \\\n  --env-vars-file env.yml\n```\n\n# Input in a Custom GPT in ChatGPT\n\nNow that we have a GCP Function that queries this Vector Search Index, let's put it as a GPT Action!\n\nSee documentation [here](https://openai.com/index/introducing-gpts/) on GPTs and [here](https://platform.openai.com/docs/actions) on GPT Actions. Use the below as the instructions for the GPT and as the OpenAPI spec for the GPT Action.\n\n## Create OpenAPI Spec\n\nBelow is a sample OpenAPI spec. When we run the block below, a functional spec should be copied to the clipboard to paste in the GPT Action.\n\nNote that this does not have any authentication by default, but you can set up GCP Functions with Auth by following GCP's docs [here](https://cloud.google.com/functions/docs/securing/authenticating)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 2f0bfd84-cd12-43af-993d-0ce0c2fa1700
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"2f0bfd84-cd12-43af-993d-0ce0c2fa1700\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"3fa737df-7e98-4621-b267-d847aad08cab\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"76ec8f020a054e5ba9ec509cc0d95948a0912aa83b7acaa13baa7841a329cba5\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a091cfd5-5c24-47e0-b164-466b86b2506f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"9ebbf33d9db916355e19f23e778580af184f1f3ce927be54cc11c1333a93d159\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 22623, \"end_char_idx\": 25836, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\n! gcloud functions deploy openai_docs_search \\\n  --runtime python39 \\\n  --trigger-http \\\n  --allow-unauthenticated \\\n  --env-vars-file env.yml\n```\n\n# Input in a Custom GPT in ChatGPT\n\nNow that we have a GCP Function that queries this Vector Search Index, let's put it as a GPT Action!\n\nSee documentation [here](https://openai.com/index/introducing-gpts/) on GPTs and [here](https://platform.openai.com/docs/actions) on GPT Actions. Use the below as the instructions for the GPT and as the OpenAPI spec for the GPT Action.\n\n## Create OpenAPI Spec\n\nBelow is a sample OpenAPI spec. When we run the block below, a functional spec should be copied to the clipboard to paste in the GPT Action.\n\nNote that this does not have any authentication by default, but you can set up GCP Functions with Auth by following GCP's docs [here](https://cloud.google.com/functions/docs/securing/authenticating).\n\n\n```python\nspec = f\"\"\"\nopenapi: 3.1.0\ninfo:\n  title: OpenAI API documentation search\n  description: API to perform a semantic search over OpenAI APIs\n  version: 1.0.0\nservers:\n  - url: https://{region}-{project_id}.cloudfunctions.net\n    description: Main (production) server\npaths:\n  /openai_docs_search:\n    post:\n      operationId: openai_docs_search\n      summary: Perform a search\n      description: Returns search results for the given query parameters.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                query:\n                  type: string\n                  description: The search query string\n                top_k:\n                  type: integer\n                  description: Number of top results to return. Maximum is 3.\n                category:\n                  type: string\n                  description: The category to filter on, on top of similarity search (used for metadata filtering). Possible values are {categories}.\n      responses:\n        '200':\n          description: A JSON response with the search results\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  items:\n                    type: array\n                    items:\n                      type: object\n                      properties:\n                        text:\n                          type: string\n                          example: \"Learn how to turn text into numbers, unlocking use cases like search...\"\n                        title:\n                          type: string\n                          example: \"embeddings.txt\"\n                        distance:\n                          type: number\n                          format: float\n                          example: 0.484939891778730\n                        category:\n                          type: string\n                          example: \"models\"\n\"\"\"\nprint(spec)\npyperclip.copy(spec)\nprint(\"OpenAPI spec copied to clipboard\")\n\n```\n\n## Create GPT Instructions\n\nFeel free to modify instructions as you see fit. Check out our docs [here](https://platform.openai.com/docs/guides/prompt-engineering) for some tips on prompt engineering."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: a091cfd5-5c24-47e0-b164-466b86b2506f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb", "title": "GCP Bigquery with GCP Functions and GPT actions in ChatGPT", "tokens": 6067, "retrieve_doc": true, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a091cfd5-5c24-47e0-b164-466b86b2506f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"6d8bb99b-2027-4815-90bd-14a51cfd3979\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"f33c7ece243df97d2c659b7677c9ac7a517784feee18f15772f79b17a9198eda\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"2f0bfd84-cd12-43af-993d-0ce0c2fa1700\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/rag-quickstart/gcp/Getting_started_with_bigquery_vector_search_and_openai.ipynb\", \"title\": \"GCP Bigquery with GCP Functions and GPT actions in ChatGPT\", \"tokens\": 6067, \"retrieve_doc\": true, \"source\": \"openai_cookbooks\"}, \"hash\": \"470d63c28e55d3089c80fe8a49cf8d59f7e7b9152900783a839e3104cc8f2bb9\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 25839, \"end_char_idx\": 27271, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "ref_doc_id": "6d8bb99b-2027-4815-90bd-14a51cfd3979", "chroma:document": "```python\ninstructions = f'''\nYou are an OpenAI docs assistant. You have an action in your knowledge base where you can make a POST request to search for information. The POST request should always include: {{\n    \"query\": \"<user_query>\",\n    \"k_\": <integer>,\n    \"category\": <string, but optional>\n}}. Your goal is to assist users by performing searches using this POST request and providing them with relevant information based on the query.\n\nYou must only include knowledge you get from your action in your response.\nThe category must be from the following list: {categories}, which you should determine based on the user's query. If you cannot determine, then do not include the category in the POST request.\n'''\npyperclip.copy(instructions)\nprint(\"GPT Instructions copied to clipboard\")\nprint(instructions)\n```\n\n# Recap\n\nWe've now succesfully integrated GCP BigQuery Vector Search with GPT Actions in ChatGPT by doing the following:\n1. Embedded docs using OpenAI's embeddings, while adding some additional metadata using gpt-4o.\n2. Uploaded that data to GCP BigQuery (raw data and vectors of embeddings)\n3. Created an endpoint on GCP Functions to retrieve those\n4. Incorporated it into a custom GPT.\n\nOur GPT can now retrieve informaiton to help answer user queries, making it much more accurate and customized to our data. Here's the GPT in action:\n\n![gcp-rag-quickstart-gpt.png](../../../../images/gcp_rag_quickstart_gpt.png)"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: e58d5f85-7c8f-4933-b3b7-69c87d748413
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e58d5f85-7c8f-4933-b3b7-69c87d748413\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"eda104a5-e296-4bed-8bb7-b728f6ec56b6\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"d92159f1fd1c7fd540d2a233c74b4ebe8dfc72e9c790502457153290acef14f9\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 0, \"end_char_idx\": 2662, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "# Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\n\n\n\n## Overview\n\nThis solution enables a GPT action to answer a user\u2019s question with the context of files the user can access in SharePoint or Office365, using Microsoft\u2019s Graph API [search capabilities](https://learn.microsoft.com/en-us/graph/api/resources/search-api-overview?view=graph-rest-1.0) and the ability to [retrieve files](https://learn.microsoft.com/en-us/graph/api/driveitem-get?view=graph-rest-1.0\\&tabs=http). It uses Azure Functions to process the Graph API response and convert it to a human readable format or structure it in a way ChatGPT understands. This code is meant to be directional, and you should modify it to your requirements.\n\n\n## How it Works\n\nThere are two solutions below, with code for each in the repository.\u00a0\n\nThe first solution **Solution 1** uses the ability to[ retrieve files in Actions](https://platform.openai.com/docs/actions/sending-files) and use them as if you had uploaded them directly to a conversation. The Azure Function returns a base64 string that ChatGPT converts into a file, treated the same way as if you uploaded the file directly to the conversation. This solution can handle more types of files than the other solution below, but does have size volume limitations (see docs [here](https://platform.openai.com/docs/actions/sending-files))\n\nThe second solution **Solution 2** pre-processes the file within the Azure Function. The Azure Function returns text, instead of the base64 encoded file. Due to the pre-processing and the conversion to text, this solution is best used for large, unstructured documents, and for when you want to analyze more than the amount of files supported in the first solution (see documentation [here](https://platform.openai.com/docs/actions/sending-files)).\n\n\n### Solution 1: Returning the file to GPT using the [Returning Files](https://platform.openai.com/docs/actions/sending-files) pattern\n\n![](../../../images/solution_1.gif)\n\nThis solution uses a Node.js Azure Function to, based on the logged in user:\n\n1. Search for a relevant file that the user has access to, based on the user\u2019s initial question.\u00a0\n\n2. For each file that is found, convert it to a base64 string.\n\n3. Format the data in the structure ChatGPT is expecting [here](https://platform.openai.com/docs/actions/sending-files/inline-option).\n\n4. Return that to ChatGPT. The GPT then can use those files as if you had uploaded it to the conversation.\n\n\n![](../../../images/solution_1_architecture.png)\n\n\n### Solution 2: Converting the file to text in the Azure Function\n\n\n![](../../../images/solution_2.gif)"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: eda104a5-e296-4bed-8bb7-b728f6ec56b6
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"eda104a5-e296-4bed-8bb7-b728f6ec56b6\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e58d5f85-7c8f-4933-b3b7-69c87d748413\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"1e002a58db811701eefc14ed6dd81e84505b4b9d7edc5b8621126a5e6ad5ab31\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"16b75b13-49d7-4e17-b55a-a194d1580657\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"16da118ca5df00633330efd515c170b36a862e194322564dbb63f6bebec31e94\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 1850, \"end_char_idx\": 3649, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "### Solution 1: Returning the file to GPT using the [Returning Files](https://platform.openai.com/docs/actions/sending-files) pattern\n\n![](../../../images/solution_1.gif)\n\nThis solution uses a Node.js Azure Function to, based on the logged in user:\n\n1. Search for a relevant file that the user has access to, based on the user\u2019s initial question.\u00a0\n\n2. For each file that is found, convert it to a base64 string.\n\n3. Format the data in the structure ChatGPT is expecting [here](https://platform.openai.com/docs/actions/sending-files/inline-option).\n\n4. Return that to ChatGPT. The GPT then can use those files as if you had uploaded it to the conversation.\n\n\n![](../../../images/solution_1_architecture.png)\n\n\n### Solution 2: Converting the file to text in the Azure Function\n\n\n![](../../../images/solution_2.gif)\n\n\nThis solution uses a Node.js Azure Function to, based on the logged in user:\n\n1. Search for a relevant file that the user has access to, based on the user\u2019s initial question.\n\n2. For each file that is found, convert it to a consistent readable format and retrieve all the text.\n\n3. Use GPT 3.5-turbo (gpt-3.5-turbo-0125) to extract the relevant text from the files based on the initial user\u2019s question. Note the pricing of GPT 3.5 turbo [here](https://openai.com/pricing#language-models) - since we are dealing with small token chunks, the cost of this step is nominal.\u00a0\u00a0\n\n4. Returns that data to ChatGPT. The GPT then uses that information to respond to the user's initial question.\n\nAs you can see from the below architecture diagram, the first three steps are the same as Solution 1. The main difference is that this solution converts the file to text instead of a base64 string, and then summarizes that text using GPT 3.5 Turbo.\n\n\n![](../../../images/solution_2_architecture.png)"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 16b75b13-49d7-4e17-b55a-a194d1580657
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"16b75b13-49d7-4e17-b55a-a194d1580657\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"eda104a5-e296-4bed-8bb7-b728f6ec56b6\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"e668c0c2bd50b087d4d6df0b58cb6753cb444bd8a3c9d228ceaff87c4443a374\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b8b46222-e5f8-4854-b0d7-66a016c1a2be\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3bbd4e827c05984ebbc5515eb87a59d2433d2793d2beb9ac38446c4c68b0c329\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 2508, \"end_char_idx\": 5776, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "![](../../../images/solution_1_architecture.png)\n\n\n### Solution 2: Converting the file to text in the Azure Function\n\n\n![](../../../images/solution_2.gif)\n\n\nThis solution uses a Node.js Azure Function to, based on the logged in user:\n\n1. Search for a relevant file that the user has access to, based on the user\u2019s initial question.\n\n2. For each file that is found, convert it to a consistent readable format and retrieve all the text.\n\n3. Use GPT 3.5-turbo (gpt-3.5-turbo-0125) to extract the relevant text from the files based on the initial user\u2019s question. Note the pricing of GPT 3.5 turbo [here](https://openai.com/pricing#language-models) - since we are dealing with small token chunks, the cost of this step is nominal.\u00a0\u00a0\n\n4. Returns that data to ChatGPT. The GPT then uses that information to respond to the user's initial question.\n\nAs you can see from the below architecture diagram, the first three steps are the same as Solution 1. The main difference is that this solution converts the file to text instead of a base64 string, and then summarizes that text using GPT 3.5 Turbo.\n\n\n![](../../../images/solution_2_architecture.png)\n\n\n### Why is this necessary instead of interacting with the Microsoft API directly?\n\n- Following the guide [here](https://learn.microsoft.com/en-us/graph/search-concept-files), the [Microsoft Graph Search API](https://learn.microsoft.com/en-us/graph/search-concept-files) returns references to files that fit the criteria, but not the file contents themselves. So, we need have two options, corresponding to the two solutions above:\n\n  - **Solution 1: restructure the response for compatibility:**\u00a0\n\n    1. We need to restructure the response from that API so that it matches the expected structure in `openaiFileResponse` outlined [here](https://platform.openai.com/docs/actions/getting-started/inline-option).\n\n  - **Solution 2: extract the text from the files directly:**\n\n    1. loop through the returned files and download the files using the [Download File endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0\\&tabs=http) or [Convert File endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0\\&tabs=http)\n\n    2. convert that Binary stream to human readable text using [pdf-parse](https://www.npmjs.com/package/pdf-parse)\n\n    3. Then, we can optimize further by summarizing using gpt-3.5-turbo in the function to help with the 100,000 character limit we impose on Actions today.\u00a0\n\n\n## Prerequisites\n\n- Azure Portal with access to create Azure Function Apps and Azure Entra App Registrations\n\n- Postman (and knowledge of APIs and OAuth)\n\n- _Solution 2 Only:_ An OpenAI API Key from platform.openai.com\n\n\n## Solution 1 + Solution 2 Installation Instructions\n\nThe below are the instructions for setting up the Azure Function with Authentication. Please make sure to follow these steps before implementing the code. \n\n> These installation instructions apply to both Solution 1 and Solution 2. We encourage setting both solutions up as separate functions within the same Function App to test which works best for you, as once you set up one function, it takes only a few minutes to set up another function in that same function app."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: b8b46222-e5f8-4854-b0d7-66a016c1a2be
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b8b46222-e5f8-4854-b0d7-66a016c1a2be\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"16b75b13-49d7-4e17-b55a-a194d1580657\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"7716109ce1fb491321135a810a28239f001a9ff49a2f6cc399d4ad82b55441f4\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"f77f8f45-220d-46bd-9555-a01e6da9d32f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"71ccef29f47fb8ba5b9d2066fc28bd7013953d4e5ed671526fa00bfc0e96e3f6\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 5031, \"end_char_idx\": 7862, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "## Prerequisites\n\n- Azure Portal with access to create Azure Function Apps and Azure Entra App Registrations\n\n- Postman (and knowledge of APIs and OAuth)\n\n- _Solution 2 Only:_ An OpenAI API Key from platform.openai.com\n\n\n## Solution 1 + Solution 2 Installation Instructions\n\nThe below are the instructions for setting up the Azure Function with Authentication. Please make sure to follow these steps before implementing the code. \n\n> These installation instructions apply to both Solution 1 and Solution 2. We encourage setting both solutions up as separate functions within the same Function App to test which works best for you, as once you set up one function, it takes only a few minutes to set up another function in that same function app.\n\n\n### Installing the app\n\nYou can read more about languages and deployment options for Azure Functions on the left hand side of the documentation [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp).\u00a0\n\n\n#### Option 1: Use VSCode\n\nSee Microsoft\u2019s documentation [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs-code?tabs=node-v4,python-v2,isolated-process\\&pivots=programming-language-javascript) for how to deploy using VSCode. If you have familiarity with this approach, feel free to use it.\u00a0\n\n\n#### Option 2: Directly in Azure Portal\n\nSee the documentation [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-function-app-portal?pivots=programming-language-javascript) for how to deploy using the Azure portal. We\u2019ll walk through an example here step by step.\n\n> Note: you can use Part 1 - Part 4 below to set up any Azure Function App with Entra Authentication\n\n\n##### Part 1: Create Function\n\n\n![](../../../images/create_function_app.png)\n\n\n1. Create an [Azure Function app](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp). I used the following settings but you can use anything you are comfortable with. Note that not every language / operating system allows for editing the functions in the console directly - the combination I chose below does. For my walkthrough, I left everything as default and made the selections below\n\n   1. Basics\n\n      1. _Do you want to deploy code or container image?:_\u00a0 **Code**\n\n      2. _Runtime stack:_ **Node.js**\n\n      3. _Operating system:_ **Windows**\n\n   2. Networking\n\n      1. _Enable public access_: **on (need this on to connect to the GPT)**\n\n2. After completing the above, you\u2019ll land on the \u201cDeployments\u201d page. Once the deployment completes (which should only take a few minutes) click on **\u201cGo to Resource\u201d** to go back to the Function App\n\n  > You may get an error the first time you attempt this, click create again and it will likely work."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: f77f8f45-220d-46bd-9555-a01e6da9d32f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"f77f8f45-220d-46bd-9555-a01e6da9d32f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b8b46222-e5f8-4854-b0d7-66a016c1a2be\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"df8a98ae81c37de4d1d33fbf0ee0962efc7f05808eb80889440b8cd727aecb86\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"bcefb22c-2c47-4893-8e5c-9e6dcb41be05\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"e0d2712dbc56c9c372c202f365e757622269b5d94db053d911f13a8132b38e31\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 6372, \"end_char_idx\": 10316, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "#### Option 2: Directly in Azure Portal\n\nSee the documentation [here](https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-function-app-portal?pivots=programming-language-javascript) for how to deploy using the Azure portal. We\u2019ll walk through an example here step by step.\n\n> Note: you can use Part 1 - Part 4 below to set up any Azure Function App with Entra Authentication\n\n\n##### Part 1: Create Function\n\n\n![](../../../images/create_function_app.png)\n\n\n1. Create an [Azure Function app](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview?pivots=programming-language-csharp). I used the following settings but you can use anything you are comfortable with. Note that not every language / operating system allows for editing the functions in the console directly - the combination I chose below does. For my walkthrough, I left everything as default and made the selections below\n\n   1. Basics\n\n      1. _Do you want to deploy code or container image?:_\u00a0 **Code**\n\n      2. _Runtime stack:_ **Node.js**\n\n      3. _Operating system:_ **Windows**\n\n   2. Networking\n\n      1. _Enable public access_: **on (need this on to connect to the GPT)**\n\n2. After completing the above, you\u2019ll land on the \u201cDeployments\u201d page. Once the deployment completes (which should only take a few minutes) click on **\u201cGo to Resource\u201d** to go back to the Function App\n\n  > You may get an error the first time you attempt this, click create again and it will likely work. \n\n\n##### Part 2: Set up Auth\n\n3. On the left-hand side menu of the Azure Function App, click on **Authentication** under the **Settings** menu.\u00a0\n\n   1. Add identity provider\n\n   2. Select **Microsoft** as identity provider.\u00a0\n\n   3. **Workforce** as tenant type\n\n   4. **Create a new application.** The instructions are fairly similar if you are using an existing application, but it is easier to create a new application as it will have the callback URLs and the API exposed automatically using \u201cEasy Auth\u201d. You can read more about that [**here**](https://learn.microsoft.com/en-us/azure/app-service/overview-authentication-authorization).\n\n   5. Leave all the other settings on this page as the default, but feel free to change based on your internal guidelines.\n\n   6. On the **permissions** tab, click **Add Permission** and add **Files.Read.All** and **Sites.ReadAll**, then **Add.** This allows this application to read files which is important in order to use the Microsoft Graph Search API.\n\n4. Once it is created, **click on the enterprise application you just created** (so, leave the Function App page and land on the Enterprise Application that you just spun up)**.** We are now going to give it one more permission, to execute the Azure Function by impersonating the user logging into the application. See [here](https://learn.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad?tabs=workforce-tenant) for more details.\n\n   1. On the main page, click \u201c**View API Permissions\u201d**\n\n   2. Search for **Microsoft Azure App Service** in the **APIs my organization uses** and find **user\\_impersonation**\u00a0\n\n   3. Add it, then you\u2019ll need an Admin on Azure Portal to **Grant Admin Consent.**\n\n5) **Within that enterprise application**, Click on **\u201cExpose an API\u201d** on the left hand menu under **Manage,** then copy the **scope** that was created using the **Copy to Clipboard** button. The scope should look like \u201capi://\\<insert-uuid>/user\\_impersonation\u201d. **Save this for later as** `SCOPE`**.**\n\n6) Click on **\u201cAuthentication\u201d** on the left hand menu under **Manage**\n\n   1. Under the **Web** section, you\u2019ll notice one callback URI was added automatically. Add the Postman redirect URI (<https://oauth.pstmn.io/v1/callback>) for testing.\n\n7) On the left-hand side, go to **Overview**. Copy the **application (client) ID** and and the **directory (tenant) ID** and **save for later as** `CLIENT_ID` **and** `TENANT_ID`**.**"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: bcefb22c-2c47-4893-8e5c-9e6dcb41be05
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"bcefb22c-2c47-4893-8e5c-9e6dcb41be05\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"f77f8f45-220d-46bd-9555-a01e6da9d32f\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"2a001a9a346f822207466ef64f2a1c4b780c29437d5c2736ceb01e5c2de8945f\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"aabc6d80-b2e3-4bc3-b10e-aff3aa1ef2d1\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"9b820fab1b9917b0146cbd3e8a290c12184ea4af4c62d4c10932c66f19f8e5e8\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 10319, \"end_char_idx\": 12971, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "##### Part 3: Set up Test Function\n\n8. Leave the page by going home and then back to your **Function App.**\n\n9. Click on **Create Function.** For this example, I\u2019m going to develop it in the portal, but you can also use VSCode or another IDE.\n\n   1. Choose **HTTP trigger**\n\n   2. For **Authorization Level,** you can choose any key type you want.\n\n      1. Note this may error out the first time, but it is likely the Function did create, do a refresh of the page to check.\n\n10. Click on the function you just created (You may need to click refresh to see it). Click on **Get Function URL** and save it to test in Postman. You will also use this when creating the OpenAPI spec later when you put it into the GPT.\u00a0\n\n\n![](../../../images/get_function_url.png)\n\n11. Go back to the function app and click on **Configuration.** Show the value for the `MICROSOFT_PROVIDER_AUTHENTICATION_SECRET` variable, copy it (click advanced edit to copy it), and **save it for later.**\u00a0\u00a0\n\nAt this point, you should have a test function created, and you should have saved a **client id, tenant id, secret, scope, and function URL**. You are now ready to test out the authentication in Postman\n\n\n##### Part 4: Test Authentication in Postman\n\n12. Try to hit endpoint you created in Postman using those OAuth settings:\n\n    1. **Grant Type:** Authorization Code\n\n    2. **Auth URL**: [https://login.microsoftonline.com/](about:blank)`TENANT_ID`[/oauth2/v2.0/authorize](about:blank)\n\n    3. **Auth Token URL**: [https://login.microsoftonline.com/`TENANT_ID`/oauth2/v2.0/token](about:blank)\n\n    4. **Client ID:** `CLIENT_ID` from step 7 above\n\n    5. **Client secret:** `MICROSOFT_PROVIDER_AUTHENTICATION_SECRET `from step 11 above\n\n    6. **Scope**: `SCOPE` from step 5 above\n\n    7. **Client credentials**: Send client credentials in body\n\n13. You will need to click **Get New Access Token**, and then hit the endpoint you saved in step 10 above. If it was successful, you should get this response: `\u201dThis HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.\u201d`\n\n\n##### Part 5: Add in Function Code\n\nNow that you have an authenticated Azure Function, we can update the function to search SharePoint / O365\n\n\n14. 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_one_file_retrieval.js) for Solution 1 and [this file](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js) for Solution 2.  Save the function."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: aabc6d80-b2e3-4bc3-b10e-aff3aa1ef2d1
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"aabc6d80-b2e3-4bc3-b10e-aff3aa1ef2d1\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"bcefb22c-2c47-4893-8e5c-9e6dcb41be05\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"b5e797bec402d7a45b829a188ada7a65276540f99e37904b73be2430915f6826\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"cca905d4-adef-4e70-8249-5d405fe8b320\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7ab420b16a47b82ab049250898583c5bc8401310a2430cc8b7e899ca8619e537\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 11496, \"end_char_idx\": 14361, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "##### Part 4: Test Authentication in Postman\n\n12. Try to hit endpoint you created in Postman using those OAuth settings:\n\n    1. **Grant Type:** Authorization Code\n\n    2. **Auth URL**: [https://login.microsoftonline.com/](about:blank)`TENANT_ID`[/oauth2/v2.0/authorize](about:blank)\n\n    3. **Auth Token URL**: [https://login.microsoftonline.com/`TENANT_ID`/oauth2/v2.0/token](about:blank)\n\n    4. **Client ID:** `CLIENT_ID` from step 7 above\n\n    5. **Client secret:** `MICROSOFT_PROVIDER_AUTHENTICATION_SECRET `from step 11 above\n\n    6. **Scope**: `SCOPE` from step 5 above\n\n    7. **Client credentials**: Send client credentials in body\n\n13. You will need to click **Get New Access Token**, and then hit the endpoint you saved in step 10 above. If it was successful, you should get this response: `\u201dThis HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.\u201d`\n\n\n##### Part 5: Add in Function Code\n\nNow that you have an authenticated Azure Function, we can update the function to search SharePoint / O365\n\n\n14. 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_one_file_retrieval.js) for Solution 1 and [this file](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js) for Solution 2.  Save the function.\u00a0\n\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\n15. Set up the following env variables by going to the **Configuration** tab on the left under **Settings.** Note that this may be listed directly in **Environment Variables** depending on your Azure UI.\n\n    1. `TENANT_ID`: copied from previous section\n\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\n16. Go to the **Console** tab under the **Development Tools**\n\n    1. Install the following packages in console\n\n       1. `npm install @microsoft/microsoft-graph-client`\n\n       2. `npm install axios`\n\n       3. _Solution 2 only:_\n\n          1. `npm install pdf-parse`\n\n          2. `npm install openai`\n\n17. 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     *Solution 1*:\n     ```json\n    {\n        \"searchTerm\": \"<choose a search term>\"\n    }\n    ```\n    *Solution 2*: \n    ```json\n    {\n        \"query\": \"<choose a question>\",\n        \"searchTerm\": \"<choose a search term>\"\n    }\n    ```\n18. If you get a response, you are ready to set this up with a Custom GPT!"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: cca905d4-adef-4e70-8249-5d405fe8b320
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"cca905d4-adef-4e70-8249-5d405fe8b320\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"aabc6d80-b2e3-4bc3-b10e-aff3aa1ef2d1\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"07a11b33de0b525d4402ad3daf93ebd50c20d540f0cde96de7e57159ed38cc8c\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"9a13815c-d34b-4047-9a5e-eb48affd1e9e\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"10348bb134bcf4ba4429bcc99563c05ef9681541e341bed5291c233eaf562e6a\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 12975, \"end_char_idx\": 16131, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "> **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\n15. Set up the following env variables by going to the **Configuration** tab on the left under **Settings.** Note that this may be listed directly in **Environment Variables** depending on your Azure UI.\n\n    1. `TENANT_ID`: copied from previous section\n\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\n16. Go to the **Console** tab under the **Development Tools**\n\n    1. Install the following packages in console\n\n       1. `npm install @microsoft/microsoft-graph-client`\n\n       2. `npm install axios`\n\n       3. _Solution 2 only:_\n\n          1. `npm install pdf-parse`\n\n          2. `npm install openai`\n\n17. 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     *Solution 1*:\n     ```json\n    {\n        \"searchTerm\": \"<choose a search term>\"\n    }\n    ```\n    *Solution 2*: \n    ```json\n    {\n        \"query\": \"<choose a question>\",\n        \"searchTerm\": \"<choose a search term>\"\n    }\n    ```\n18. If you get a response, you are ready to set this up with a Custom GPT!\n\n\n##### Part 6: Setting it up in a Custom GPT\n\n19. Generate an OpenAPI spec for your endpoint.\u00a0\n\n20. Paste that into the Actions section of a GPT, and choose OAuth as the authentication type. Fill out the OAuth settings the same way you did for Postman above.\u00a0\n\n21. Once you save the action, you will see a callback URI at the bottom of the GPT configuration. Copy that URL, then go **back to your Function App in the Azure Portal**.\n\n22. Click on **Authentication** under **Settings**, then click on your Entra application.\n\n23. Once you are there, then click **Authentication** under the **Manage** section.\n\n24. Add a new Redirect URI under the **Web** section of that page, and paste in the Callback URI you got from step 20, then click Save.\u00a0\n\n25. Customize the prompt to use this action. You can see a sample prompt in the Sample GPT Instructions in this document, which is customized to try three times to find an answer by changing the searchTerm.\u00a0\n\n26. Test out the GPT and it should work as expected.\n\n\n## Solution 1 Detailed Walkthrough: Returning the File to GPT using the [Returning Files](https://platform.openai.com/docs/actions/sending-files) Pattern\n\n\nThe below walks through setup instructions and walkthrough unique to this solution. You can find the entire code [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_one_file_retrieval.js). If you are interested in Solution 2 instead, you can jump [here](#solution-2-converting-the-file-to-text-in-the-azure-function-1). \n\n### Code Walkthrough\n\nThe below walks through the different parts of the function. Before you begin, ensure you have the required packages installed and environment variables set up (see the Installation Steps section)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 9a13815c-d34b-4047-9a5e-eb48affd1e9e
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"9a13815c-d34b-4047-9a5e-eb48affd1e9e\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"cca905d4-adef-4e70-8249-5d405fe8b320\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"86f3dda9acd5072aa0bad1bef81477082b9c586d3b83cfddd490bc2a669caacb\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"e39633f7-74c7-4ab8-bb4f-7a4017f727d6\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7c463bcf130770fb3ec03be51a77c0c55d51607aaf65f6f016f151477c6f8220\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 15375, \"end_char_idx\": 18123, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "## Solution 1 Detailed Walkthrough: Returning the File to GPT using the [Returning Files](https://platform.openai.com/docs/actions/sending-files) Pattern\n\n\nThe below walks through setup instructions and walkthrough unique to this solution. You can find the entire code [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_one_file_retrieval.js). If you are interested in Solution 2 instead, you can jump [here](#solution-2-converting-the-file-to-text-in-the-azure-function-1). \n\n### Code Walkthrough\n\nThe below walks through the different parts of the function. Before you begin, ensure you have the required packages installed and environment variables set up (see the Installation Steps section).\n\n\n#### Implementing the Authentication\u00a0\n\nBelow we have a few helper functions that we\u2019ll use in the function.\n\n\n##### Initializing the Microsoft Graph Client\n\nCreate 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\nconst { Client } = require('@microsoft/microsoft-graph-client');\n\nfunction 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\nThis 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\nconst axios = require('axios');\nconst qs = require('querystring');\n\nasync function getOboToken(userAccessToken) {\n\u00a0\u00a0\u00a0\u00a0const { TENANT_ID, CLIENT_ID, MICROSOFT_PROVIDER_AUTHENTICATION_SECRET } = process.env;\n\u00a0\u00a0\u00a0\u00a0const params = {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0client_id: CLIENT_ID,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0client_secret: MICROSOFT\\_PROVIDER\\_AUTHENTICATION\\_SECRET,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertion: userAccessToken,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requested_token_use: 'on_behalf_of',\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scope: 'https://graph.microsoft.com/.default'\n\u00a0\u00a0\u00a0\u00a0};\n\n\u00a0\u00a0\u00a0\u00a0const url = `https\\://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;\n\u00a0\u00a0\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const response = await axios.post(url, qs.stringify(params), {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0headers: { 'Content-Type': 'application/x-www-form-urlencoded' }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return response.data.access\\_token;\n\u00a0\u00a0\u00a0\u00a0} catch (error) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.error('Error obtaining OBO token:', error.response?.data || error.message);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw error;\n\u00a0\u00a0\u00a0\u00a0}\n}\n```\n\n#### Retrieving Content from O365 / SharePoint Items\n\nThis function fetches the content of drive items, converts it to a base64 string, and restructures to match the `openaiFileResponse` format."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: e39633f7-74c7-4ab8-bb4f-7a4017f727d6
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"e39633f7-74c7-4ab8-bb4f-7a4017f727d6\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"9a13815c-d34b-4047-9a5e-eb48affd1e9e\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"e3a38b43bcaf3ecc673b312addfff882445c16555a79e83e39607f1ed301d947\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"5664d442-5dfd-48ad-9592-8eaa389bf6c9\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"7db814d396dcc8e6ee55df676c6bb3bd6db91b0492137bfde266e988f624d8bb\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 16816, \"end_char_idx\": 20015, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "This enables passing through the credentials to ensure the search only returns files the logged-in user can access.\n\n```javascript\nconst axios = require('axios');\nconst qs = require('querystring');\n\nasync function getOboToken(userAccessToken) {\n\u00a0\u00a0\u00a0\u00a0const { TENANT_ID, CLIENT_ID, MICROSOFT_PROVIDER_AUTHENTICATION_SECRET } = process.env;\n\u00a0\u00a0\u00a0\u00a0const params = {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0client_id: CLIENT_ID,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0client_secret: MICROSOFT\\_PROVIDER\\_AUTHENTICATION\\_SECRET,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertion: userAccessToken,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0requested_token_use: 'on_behalf_of',\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0scope: 'https://graph.microsoft.com/.default'\n\u00a0\u00a0\u00a0\u00a0};\n\n\u00a0\u00a0\u00a0\u00a0const url = `https\\://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`;\n\u00a0\u00a0\u00a0\u00a0try {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const response = await axios.post(url, qs.stringify(params), {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0headers: { 'Content-Type': 'application/x-www-form-urlencoded' }\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return response.data.access\\_token;\n\u00a0\u00a0\u00a0\u00a0} catch (error) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.error('Error obtaining OBO token:', error.response?.data || error.message);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw error;\n\u00a0\u00a0\u00a0\u00a0}\n}\n```\n\n#### Retrieving Content from O365 / SharePoint Items\n\nThis function fetches the content of drive items, converts it to a base64 string, and restructures to match the `openaiFileResponse` format.\n```javascript\nconst getDriveItemContent = async (client, driveId, itemId, name) => {\n\u00a0\u00a0\u00a0try\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const filePath = `/drives/${driveId}/items/${itemId}`;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const downloadPath = filePath + `/content`\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0// this is where we get the contents and convert to base64\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const fileStream = await client.api(downloadPath).getStream();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0let chunks = [];\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0for await (let chunk of fileStream) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0chunks.push(chunk);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const base64String = Buffer.concat(chunks).toString('base64');\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0// this is where we get the other metadata to include in response\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const file = await client.api(filePath).get();\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const mime_type = file.file.mimeType;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0const name = file.name;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0return {\"name\":name, \"mime_type\":mime_type, \"content\":base64String}\n\u00a0\u00a0\u00a0} catch (error) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0console.error('Error fetching drive content:', error);\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0throw new Error(`Failed to fetch content for ${name}: ${error.message}`);\n\u00a0\u00a0\u00a0}\n```\n\n#### Creating the Azure Function to Handle Requests\n\nNow that we have all these helper functions, the Azure Function will orchestrate the flow, by authenticating the user, performing the search, and iterating through the search results to extract the text and retrieve the relevant parts of the text to the GPT.\n\n**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.\n\n**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.\n\n**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above.\n\n**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 5664d442-5dfd-48ad-9592-8eaa389bf6c9
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"5664d442-5dfd-48ad-9592-8eaa389bf6c9\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"e39633f7-74c7-4ab8-bb4f-7a4017f727d6\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"e4704f7f1723f856d7653ce4c4deaaa12a4a2315c619ad4e27e0bad82bf1e156\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"c48f485e-948b-4d92-9219-a2e9a37c0378\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"ef6c3b8a6b4665a0d472a2b7133e174a5ed33000c03d484aa182a46bbb94ae8d\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 19420, \"end_char_idx\": 21757, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.\n\n**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.\n\n**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above.\n\n**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.\n\n**Document Processing**: For each document returned by the search:\n\n- It retrieves the document content using getDriveItemContent.\n\n- It converts the document to base64 string and restructures it to match the `openaiFileResponse` structure.\n\n**Response**: The function sends them back in the HTTP response.\n```javascript\nmodule.exports = async function (context, req) {\n   // const query = req.query.query || (req.body && req.body.query);\n   const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);\n   if (!req.headers.authorization) {\n       context.res = {\n           status: 400,\n           body: 'Authorization header is missing'\n       };\n       return;\n   }\n   /// The below takes the token passed to the function, to use to get an OBO token.\n   const bearerToken = req.headers.authorization.split(' ')[1];\n   let accessToken;\n   try {\n       accessToken = await getOboToken(bearerToken);\n   } catch (error) {\n       context.res = {\n           status: 500,\n           body: `Failed to obtain OBO token: ${error.message}`\n       };\n       return;\n   }\n   // Initialize the Graph Client using the initGraphClient function defined above\n   let client = initGraphClient(accessToken);\n   // this is the search body to be used in the Microsft Graph Search API: https://learn.microsoft.com/en-us/graph/search-concept-files\n   const requestBody = {\n       requests: [\n           {\n               entityTypes: ['driveItem'],\n               query: {\n                   queryString: searchTerm\n               },\n               from: 0,\n               // the below is set to summarize the top 10 search results from the Graph API, but can configure based on your documents.\n               size: 10\n           }\n       ]\n   };"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: c48f485e-948b-4d92-9219-a2e9a37c0378
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"c48f485e-948b-4d92-9219-a2e9a37c0378\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"5664d442-5dfd-48ad-9592-8eaa389bf6c9\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"68cfe30c5b02e9cb43278fa6370fa054e049176d772e460a08a3a40ec3961a8b\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"ac2197e4-4d3f-405d-958e-a85e7e22c269\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"0f067d4e1f335db5a83b7310db87dfc1010700e2f7c636c90907f9f21b6297ba\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 19883, \"end_char_idx\": 24905, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.\n\n**Document Processing**: For each document returned by the search:\n\n- It retrieves the document content using getDriveItemContent.\n\n- It converts the document to base64 string and restructures it to match the `openaiFileResponse` structure.\n\n**Response**: The function sends them back in the HTTP response.\n```javascript\nmodule.exports = async function (context, req) {\n   // const query = req.query.query || (req.body && req.body.query);\n   const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);\n   if (!req.headers.authorization) {\n       context.res = {\n           status: 400,\n           body: 'Authorization header is missing'\n       };\n       return;\n   }\n   /// The below takes the token passed to the function, to use to get an OBO token.\n   const bearerToken = req.headers.authorization.split(' ')[1];\n   let accessToken;\n   try {\n       accessToken = await getOboToken(bearerToken);\n   } catch (error) {\n       context.res = {\n           status: 500,\n           body: `Failed to obtain OBO token: ${error.message}`\n       };\n       return;\n   }\n   // Initialize the Graph Client using the initGraphClient function defined above\n   let client = initGraphClient(accessToken);\n   // this is the search body to be used in the Microsft Graph Search API: https://learn.microsoft.com/en-us/graph/search-concept-files\n   const requestBody = {\n       requests: [\n           {\n               entityTypes: ['driveItem'],\n               query: {\n                   queryString: searchTerm\n               },\n               from: 0,\n               // the below is set to summarize the top 10 search results from the Graph API, but can configure based on your documents.\n               size: 10\n           }\n       ]\n   };\n\n\n   try {\n       // This is where we are doing the search\n       const list = await client.api('/search/query').post(requestBody);\n       const processList = async () => {\n           // This will go through and for each search response, grab the contents of the file and summarize with gpt-3.5-turbo\n           const results = [];\n           await Promise.all(list.value[0].hitsContainers.map(async (container) => {\n               for (const hit of container.hits) {\n                   if (hit.resource[\"@odata.type\"] === \"#microsoft.graph.driveItem\") {\n                       const { name, id } = hit.resource;\n                       // The below is where the file lives\n                       const driveId = hit.resource.parentReference.driveId;\n                       // we use the helper function we defined above to get the contents, convert to base64, and restructure it\n                       const contents = await getDriveItemContent(client, driveId, id, name);\n                       results.push(contents)\n               }\n           }));\n           return results;\n       };\n       let results;\n       if (list.value[0].hitsContainers[0].total == 0) {\n           // Return no results found to the API if the Microsoft Graph API returns no results\n           results = 'No results found';\n       } else {\n           // If the Microsoft Graph API does return results, then run processList to iterate through.\n           results = await processList();\n           // this is where we structure the response so ChatGPT knows they are files\n           results = {'openaiFileResponse': results}\n       }\n       context.res = {\n           status: 200,\n           body: results\n       };\n   } catch (error) {\n       context.res = {\n           status: 500,\n           body: `Error performing search or processing results: ${error.message}`,\n       };\n   }\n};\n```\n### Customizations\n\nBelow are some potential areas to customize.\u00a0\n\n- You can customize the GPT prompt to search again a certain amount of times if nothing is found.\n\n- You can customize the code to only search through specific SharePoint sites or O365 Drives by customizing the search query. This will help focus the search and improve the retrieval. The function as setup now looks through all files the logged-in user can access.\n\n- You can update the code to only return certain types of files. For example, only return structured data / CSVs.\u00a0\n\n- You can customize the amount of files it searches through within the call to Microsoft Graph. Note that you should only put a maximum of 10 files based on the documentation [here](https://platform.openai.com/docs/actions/getting-started).\u00a0\n\n### Considerations\n\nNote that all the same limitations of Actions apply here, with regards to returning 100K characters or less and the [45 second timeout](https://platform.openai.com/docs/actions/production/timeouts).\n\n- Make sure you read the documentation here around [returning files](https://platform.openai.com/docs/actions/sending-files) and [file uploads](https://help.openai.com/en/articles/8555545-file-uploads-faq), as those limitations apply here.\n\n### Sample GPT Instructions"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: ac2197e4-4d3f-405d-958e-a85e7e22c269
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"ac2197e4-4d3f-405d-958e-a85e7e22c269\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"c48f485e-948b-4d92-9219-a2e9a37c0378\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"3de81f97f5f75f6c6c2417a90043b975a8268ef686de912d2d6eb6532ae9c6e4\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"1f2d15f8-8ce2-4cb8-bfa3-2d45c246a32c\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"3e313ed78309cf1f662323f8bad2f4af993c8e2888d637aa73e3c998248f2f1e\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 24908, \"end_char_idx\": 28638, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "```text\nYou are a Q&A helper that helps answer users questions. You have access to a documents repository through your API action. When a user asks a question, you pass in the \"searchTerm\" a single keyword or term you think you should use for the search.\n\n****\n\nScenario 1: There are answers\n\nIf your action returns results, then you take the results from the action and try to answer the users question.\u00a0\n\n****\n\nScenario 2: No results found\n\nIf the response you get from the action is \"No results found\", stop there and let the user know there were no results and that you are going to try a different search term, and explain why. You must always let the user know before conducting another search.\n\nExample:\n\n****\n\nI found no results for \"DEI\". I am now going to try [insert term] because [insert explanation]\n\n****\n\nThen, try a different searchTerm that is similar to the one you tried before, with a single word.\u00a0\n\nTry this three times. After the third time, then let the user know you did not find any relevant documents to answer the question, and to check SharePoint. \nBe sure to be explicit about what you are searching for at each step.\n\n****\n\nIn either scenario, try to answer the user's question. If you cannot answer the user's question based on the knowledge you find, let the user know and ask them to go check the HR Docs in SharePoint.\u00a0\n```\n### Sample OpenAPI Spec\nThis expects a response that matches the file retrieval structure in our doc [here](https://platform.openai.com/docs/actions/sending-files) and passes in a `searchTerm` parameter to inform the search.\n>Make sure to switch the function app name, function name and code based on link copied in screenshot [here](#part-3-set-up-test-function)\n\n```yaml\nopenapi: 3.0.0\ninfo:\n  title: SharePoint Search API\n  description: API for searching SharePoint documents.\n  version: 1.0.0\nservers:\n  - url: https://{your_function_app_name}.azurewebsites.net/api\n    description: SharePoint Search API server\npaths:\n  /{your_function_name}?code={enter your specific endpoint id here}:\n    post:\n      operationId: searchSharePoint\n      summary: Searches SharePoint for documents matching a query and term.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                searchTerm:\n                  type: string\n                  description: A specific term to search for within the documents.\n      responses:\n        '200':\n          description: A CSV file of query results encoded in base64.\n          content:\n            application/json:\n              schema:\n                type: object\n                properties:\n                  openaiFileResponseData:\n                    type: array\n                    items:\n                      type: object\n                      properties:\n                        name:\n                          type: string\n                          description: The name of the file.\n                        mime_type:\n                          type: string\n                          description: The MIME type of the file.\n                        content:\n                          type: string\n                          format: byte\n                          description: The base64 encoded contents of the file.\n        '400':\n          description: Bad request when the SQL query parameter is missing.\n        '413':\n          description: Payload too large if the response exceeds the size limit.\n        '500':\n          description: Server error when there are issues executing the query or encoding the results.\n```\n\n## Solution 2 Detailed Walkthrough: Converting the file to text in the Azure Function"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 1f2d15f8-8ce2-4cb8-bfa3-2d45c246a32c
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"1f2d15f8-8ce2-4cb8-bfa3-2d45c246a32c\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"ac2197e4-4d3f-405d-958e-a85e7e22c269\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"1524a96ca4844be7a27043b10408efdaa983ceb0ad13216377e5ffb75139912c\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"07633c00-ff90-4546-a4f1-0fd61db7d302\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"c930271d7bfe294e892e48097475080244411c50ddecec5aedf3c7f907dd14fc\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 28641, \"end_char_idx\": 31076, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "The below walks through setup instructions and walkthrough unique to this solution of pre-processing the files and extracting summaries in the Azure Function. You can find the entire code [here](https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/solution_two_preprocessing.js).\n\n### Code Walkthrough\n\n#### Implementing the Authentication\u00a0\n\nThis 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\n\n#### Retrieving Content from O365 / SharePoint Items\n\nThis function fetches the content of drive items, handling different file types and converting files to PDF when necessary for text extraction. This uses the [download endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0\\&tabs=http) for PDFs and the [convert endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0\\&tabs=http) for other supported file types.\n```javascript\nconst getDriveItemContent = async (client, driveId, itemId, name) => {\n    try {\n        const fileType = path.extname(name).toLowerCase();\n        // the below files types are the ones that are able to be converted to PDF to extract the text. See https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0&tabs=http\n        const allowedFileTypes = ['.pdf', '.doc', '.docx', '.odp', '.ods', '.odt', '.pot', '.potm', '.potx', '.pps', '.ppsx', '.ppsxm', '.ppt', '.pptm', '.pptx', '.rtf'];\n        // filePath changes based on file type, adding ?format=pdf to convert non-pdf types to pdf for text extraction, so all files in allowedFileTypes above are converted to pdf\n        const filePath = `/drives/${driveId}/items/${itemId}/content` + ((fileType === '.pdf' || fileType === '.txt' || fileType === '.csv') ? '' : '?format=pdf');\n        if (allowedFileTypes.includes(fileType)) {\n            response = await client.api(filePath).getStream();\n            // The below takes the chunks in response and combines\n            let chunks = [];\n            for await (let chunk of response) {\n                chunks.push(chunk);\n            }\n            let buffer = Buffer.concat(chunks);\n            // the below extracts the text from the PDF."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 07633c00-ff90-4546-a4f1-0fd61db7d302
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"07633c00-ff90-4546-a4f1-0fd61db7d302\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"1f2d15f8-8ce2-4cb8-bfa3-2d45c246a32c\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"dac7a9fcb26bf941db013afe3bd2df44615a0fb7e628fa8fa558a544135bac38\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"5c9f37ea-c433-4840-a55e-0d8f22e81490\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"70b3611d472007836ddaef22121ee5c2bb33e28aefd027a18e24ef014a537771\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 29479, \"end_char_idx\": 32708, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "This uses the [download endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content?view=graph-rest-1.0\\&tabs=http) for PDFs and the [convert endpoint](https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0\\&tabs=http) for other supported file types.\n```javascript\nconst getDriveItemContent = async (client, driveId, itemId, name) => {\n    try {\n        const fileType = path.extname(name).toLowerCase();\n        // the below files types are the ones that are able to be converted to PDF to extract the text. See https://learn.microsoft.com/en-us/graph/api/driveitem-get-content-format?view=graph-rest-1.0&tabs=http\n        const allowedFileTypes = ['.pdf', '.doc', '.docx', '.odp', '.ods', '.odt', '.pot', '.potm', '.potx', '.pps', '.ppsx', '.ppsxm', '.ppt', '.pptm', '.pptx', '.rtf'];\n        // filePath changes based on file type, adding ?format=pdf to convert non-pdf types to pdf for text extraction, so all files in allowedFileTypes above are converted to pdf\n        const filePath = `/drives/${driveId}/items/${itemId}/content` + ((fileType === '.pdf' || fileType === '.txt' || fileType === '.csv') ? '' : '?format=pdf');\n        if (allowedFileTypes.includes(fileType)) {\n            response = await client.api(filePath).getStream();\n            // The below takes the chunks in response and combines\n            let chunks = [];\n            for await (let chunk of response) {\n                chunks.push(chunk);\n            }\n            let buffer = Buffer.concat(chunks);\n            // the below extracts the text from the PDF.\n            const pdfContents = await pdfParse(buffer);\n            return pdfContents.text;\n        } else if (fileType === '.txt') {\n            // If the type is txt, it does not need to create a stream and instead just grabs the content\n            response = await client.api(filePath).get();\n            return response;\n        }  else if (fileType === '.csv') {\n            response = await client.api(filePath).getStream();\n            let chunks = [];\n            for await (let chunk of response) {\n                chunks.push(chunk);\n            }\n            let buffer = Buffer.concat(chunks);\n            let dataString = buffer.toString('utf-8');\n            return dataString\n            \n    } else {\n        return 'Unsupported File Type';\n    }\n     \n    } catch (error) {\n        console.error('Error fetching drive content:', error);\n        throw new Error(`Failed to fetch content for ${name}: ${error.message}`);\n    }\n};\n```\n\n#### Integrating GPT 3.5-Turbo for Text Analysis\n\nThis function utilizes the OpenAI SDK to analyze text extracted from documents and find relevant information based on a user query. This helps to ensure only relevant text to the user\u2019s question is returned to the GPT.\u00a0\n\n```javascript\nconst getRelevantParts = async (text, query) => {\n    try {\n        // We use your OpenAI key to initialize the OpenAI client\n        const openAIKey = process.env[\"OPENAI_API_KEY\"];\n        const openai = new OpenAI({\n            apiKey: openAIKey,\n        });\n        const response = await openai.chat.completions.create({\n            // Using gpt-3.5-turbo due to speed to prevent timeouts."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 5c9f37ea-c433-4840-a55e-0d8f22e81490
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"5c9f37ea-c433-4840-a55e-0d8f22e81490\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"07633c00-ff90-4546-a4f1-0fd61db7d302\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"1a7068eb61c47047e4f602de908ee989262a8367529e65314fb4e385c288b432\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"92ae20bd-5de3-424b-8500-cc78b723a224\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"1d6b2c634281e3f181c15f8121224082806161ebb54580e3a5037c3e3aa42a9d\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 31089, \"end_char_idx\": 34540, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "const pdfContents = await pdfParse(buffer);\n            return pdfContents.text;\n        } else if (fileType === '.txt') {\n            // If the type is txt, it does not need to create a stream and instead just grabs the content\n            response = await client.api(filePath).get();\n            return response;\n        }  else if (fileType === '.csv') {\n            response = await client.api(filePath).getStream();\n            let chunks = [];\n            for await (let chunk of response) {\n                chunks.push(chunk);\n            }\n            let buffer = Buffer.concat(chunks);\n            let dataString = buffer.toString('utf-8');\n            return dataString\n            \n    } else {\n        return 'Unsupported File Type';\n    }\n     \n    } catch (error) {\n        console.error('Error fetching drive content:', error);\n        throw new Error(`Failed to fetch content for ${name}: ${error.message}`);\n    }\n};\n```\n\n#### Integrating GPT 3.5-Turbo for Text Analysis\n\nThis function utilizes the OpenAI SDK to analyze text extracted from documents and find relevant information based on a user query. This helps to ensure only relevant text to the user\u2019s question is returned to the GPT.\u00a0\n\n```javascript\nconst getRelevantParts = async (text, query) => {\n    try {\n        // We use your OpenAI key to initialize the OpenAI client\n        const openAIKey = process.env[\"OPENAI_API_KEY\"];\n        const openai = new OpenAI({\n            apiKey: openAIKey,\n        });\n        const response = await openai.chat.completions.create({\n            // Using gpt-3.5-turbo due to speed to prevent timeouts. You can tweak this prompt as needed\n            model: \"gpt-3.5-turbo-0125\",\n            messages: [\n                {\"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\"},\n                {\"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'`}\n            ],\n            // using temperature of 0 since we want to just extract the relevant content\n            temperature: 0,\n            // using max_tokens of 1000, but you can customize this based on the number of documents you are searching. \n            max_tokens: 1000\n        });\n        return response.choices[0].message.content;\n    } catch (error) {\n        console.error('Error with OpenAI:', error);\n        return 'Error processing text with OpenAI' + error;\n    }\n};\n```\n\n#### Creating the Azure Function to Handle Requests\n\nNow that we have all these helper functions, the Azure Function will orchestrate the flow, by authenticating the user, performing the search, and iterating through the search results to extract the text and retrieve the relevant parts of the text to the GPT.\n\n**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.\n\n**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.\n\n**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 92ae20bd-5de3-424b-8500-cc78b723a224
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"92ae20bd-5de3-424b-8500-cc78b723a224\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"5c9f37ea-c433-4840-a55e-0d8f22e81490\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d1c8651a554abaa2f97a2c83f4627037d0284bd96ed3e0b05610cbda3d7a0f11\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"8b9b460e-3a29-493e-b785-10bd8df3280f\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"1ec5993c3d924ff612b5843853f3c98473f9d6e47dbeb66f96bc834a05f6074b\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 32709, \"end_char_idx\": 35645, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "You can tweak this prompt as needed\n            model: \"gpt-3.5-turbo-0125\",\n            messages: [\n                {\"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\"},\n                {\"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'`}\n            ],\n            // using temperature of 0 since we want to just extract the relevant content\n            temperature: 0,\n            // using max_tokens of 1000, but you can customize this based on the number of documents you are searching. \n            max_tokens: 1000\n        });\n        return response.choices[0].message.content;\n    } catch (error) {\n        console.error('Error with OpenAI:', error);\n        return 'Error processing text with OpenAI' + error;\n    }\n};\n```\n\n#### Creating the Azure Function to Handle Requests\n\nNow that we have all these helper functions, the Azure Function will orchestrate the flow, by authenticating the user, performing the search, and iterating through the search results to extract the text and retrieve the relevant parts of the text to the GPT.\n\n**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.\n\n**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.\n\n**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above.\n\n**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.\n\n**Document Processing**: For each document returned by the search:\n\n- It retrieves the document content using getDriveItemContent.\n\n- If the file type is supported, it analyzes the content using getRelevantParts, which sends the text to OpenAI's model for extracting relevant information based on the query.\n\n- It collects the analysis results and includes metadata like the document name and URL.\n\n**Response**: The function sorts the results by relevance and sends them back in the HTTP response.\n\n```javascript\nmodule.exports = async function (context, req) {\n    const query = req.query.query || (req.body && req.body.query);\n    const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);\n    if (!req.headers.authorization) {\n        context.res = {\n            status: 400,\n            body: 'Authorization header is missing'\n        };\n        return;\n    }\n    /// The below takes the token passed to the function, to use to get an OBO token."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 8b9b460e-3a29-493e-b785-10bd8df3280f
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"8b9b460e-3a29-493e-b785-10bd8df3280f\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"92ae20bd-5de3-424b-8500-cc78b723a224\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"b5079bff4a7a0b43b637d17f78f339e561a7ed611ea754f45fb221828be9e8ed\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"b7e2a55c-19b5-40d8-b6ad-32b6ca4d8779\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"24bec4220dea7df050b359bc68d7a764141a262a901653298336f35bcad8be06\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 34079, \"end_char_idx\": 36720, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "**Handling HTTP Requests:** The function starts by extracting the query and searchTerm from the HTTP request. It checks if the Authorization header is present and extracts the bearer token.\n\n**Authentication:** Using the bearer token, it obtains an OBO token from Microsoft's identity platform using getOboToken defined above.\n\n**Initializing the Graph Client:** With the OBO token, it initializes the Microsoft Graph client using initGraphClient defined above.\n\n**Document Search:** It constructs a search query and sends it to the Microsoft Graph API to find documents based on the searchTerm.\n\n**Document Processing**: For each document returned by the search:\n\n- It retrieves the document content using getDriveItemContent.\n\n- If the file type is supported, it analyzes the content using getRelevantParts, which sends the text to OpenAI's model for extracting relevant information based on the query.\n\n- It collects the analysis results and includes metadata like the document name and URL.\n\n**Response**: The function sorts the results by relevance and sends them back in the HTTP response.\n\n```javascript\nmodule.exports = async function (context, req) {\n    const query = req.query.query || (req.body && req.body.query);\n    const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);\n    if (!req.headers.authorization) {\n        context.res = {\n            status: 400,\n            body: 'Authorization header is missing'\n        };\n        return;\n    }\n    /// The below takes the token passed to the function, to use to get an OBO token.\n    const bearerToken = req.headers.authorization.split(' ')[1];\n    let accessToken;\n    try {\n        accessToken = await getOboToken(bearerToken);\n    } catch (error) {\n        context.res = {\n            status: 500,\n            body: `Failed to obtain OBO token: ${error.message}`\n        };\n        return;\n    }\n    // Initialize the Graph Client using the initGraphClient function defined above\n    let client = initGraphClient(accessToken);\n    // this is the search body to be used in the Microsft Graph Search API: https://learn.microsoft.com/en-us/graph/search-concept-files\n    const requestBody = {\n        requests: [\n            {\n                entityTypes: ['driveItem'],\n                query: {\n                    queryString: searchTerm\n                },\n                from: 0,\n                // the below is set to summarize the top 10 search results from the Graph API, but can configure based on your documents. \n                size: 10\n            }\n        ]\n    };\n\n    try { \n        // Function to tokenize content (e.g., based on words)."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: b7e2a55c-19b5-40d8-b6ad-32b6ca4d8779
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"b7e2a55c-19b5-40d8-b6ad-32b6ca4d8779\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"8b9b460e-3a29-493e-b785-10bd8df3280f\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"694acc373cfb8f00cbd3e3414c9a5d011bba3119e472a44cf0a72d6bca2971a9\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"03b9fd3e-bbf6-48c1-8073-9f3905654c3d\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"5cb7e353546898a1873ca8d7202e402f50833c9dc4bde2184e3aed9f4adc7ec8\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 34808, \"end_char_idx\": 40012, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "- If the file type is supported, it analyzes the content using getRelevantParts, which sends the text to OpenAI's model for extracting relevant information based on the query.\n\n- It collects the analysis results and includes metadata like the document name and URL.\n\n**Response**: The function sorts the results by relevance and sends them back in the HTTP response.\n\n```javascript\nmodule.exports = async function (context, req) {\n    const query = req.query.query || (req.body && req.body.query);\n    const searchTerm = req.query.searchTerm || (req.body && req.body.searchTerm);\n    if (!req.headers.authorization) {\n        context.res = {\n            status: 400,\n            body: 'Authorization header is missing'\n        };\n        return;\n    }\n    /// The below takes the token passed to the function, to use to get an OBO token.\n    const bearerToken = req.headers.authorization.split(' ')[1];\n    let accessToken;\n    try {\n        accessToken = await getOboToken(bearerToken);\n    } catch (error) {\n        context.res = {\n            status: 500,\n            body: `Failed to obtain OBO token: ${error.message}`\n        };\n        return;\n    }\n    // Initialize the Graph Client using the initGraphClient function defined above\n    let client = initGraphClient(accessToken);\n    // this is the search body to be used in the Microsft Graph Search API: https://learn.microsoft.com/en-us/graph/search-concept-files\n    const requestBody = {\n        requests: [\n            {\n                entityTypes: ['driveItem'],\n                query: {\n                    queryString: searchTerm\n                },\n                from: 0,\n                // the below is set to summarize the top 10 search results from the Graph API, but can configure based on your documents. \n                size: 10\n            }\n        ]\n    };\n\n    try { \n        // Function to tokenize content (e.g., based on words). \n        const tokenizeContent = (content) => {\n            return content.split(/\\s+/);\n        };\n\n        // Function to break tokens into 10k token windows for gpt-3.5-turbo\n        const breakIntoTokenWindows = (tokens) => {\n            const tokenWindows = []\n            const maxWindowTokens = 10000; // 10k tokens\n            let startIndex = 0;\n\n            while (startIndex < tokens.length) {\n                const window = tokens.slice(startIndex, startIndex + maxWindowTokens);\n                tokenWindows.push(window);\n                startIndex += maxWindowTokens;\n            }\n\n            return tokenWindows;\n        };\n        // This is where we are doing the search\n        const list = await client.api('/search/query').post(requestBody);\n\n        const processList = async () => {\n            // This will go through and for each search response, grab the contents of the file and summarize with gpt-3.5-turbo\n            const results = [];\n\n            await Promise.all(list.value[0].hitsContainers.map(async (container) => {\n                for (const hit of container.hits) {\n                    if (hit.resource[\"@odata.type\"] === \"#microsoft.graph.driveItem\") {\n                        const { name, id } = hit.resource;\n                        // We use the below to grab the URL of the file to include in the response\n                        const webUrl = hit.resource.webUrl.replace(/\\s/g, \"%20\");\n                        // The Microsoft Graph API ranks the reponses, so we use this to order it\n                        const rank = hit.rank;\n                        // The below is where the file lives\n                        const driveId = hit.resource.parentReference.driveId;\n                        const contents = await getDriveItemContent(client, driveId, id, name);\n                        if (contents !== 'Unsupported File Type') {\n                            // Tokenize content using function defined previously\n                            const tokens = tokenizeContent(contents);\n\n                            // Break tokens into 10k token windows\n                            const tokenWindows = breakIntoTokenWindows(tokens);\n\n                            // Process each token window and combine results\n                            const relevantPartsPromises = tokenWindows.map(window => getRelevantParts(window.join(' '), query));\n                            const relevantParts = await Promise.all(relevantPartsPromises);\n                            const combinedResults = relevantParts.join('\\n'); // Combine results\n\n                            results.push({ name, webUrl, rank, contents: combinedResults });\n                        } \n                        else {\n                            results.push({ name, webUrl, rank, contents: 'Unsupported File Type' });\n                        }\n                    }\n                }\n            }));\n\n            return results;\n        };\n        let results;\n        if (list.value[0].hitsContainers[0].total == 0) {\n            // Return no results found to the API if the Microsoft Graph API returns no results\n            results = 'No results found';\n        } else {\n            // If the Microsoft Graph API does return results, then run processList to iterate through."}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: 03b9fd3e-bbf6-48c1-8073-9f3905654c3d
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"03b9fd3e-bbf6-48c1-8073-9f3905654c3d\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"b7e2a55c-19b5-40d8-b6ad-32b6ca4d8779\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"c81d3148b669ac70121acbfbe50ab31463f1455dcbb8e04c6ac8f418c53e410a\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"a1c74dad-e650-40f6-ad17-25ed84d97cdf\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"fa2758e04d5dbbf9b995263a270260bb5890be6d5e19ab8de300798e9a919c83\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 40025, \"end_char_idx\": 41624, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "results = await processList();\n            results.sort((a, b) => a.rank - b.rank);\n        }\n        context.res = {\n            status: 200,\n            body: results\n        };\n    } catch (error) {\n        context.res = {\n            status: 500,\n            body: `Error performing search or processing results: ${error.message}`,\n        };\n    }\n};\n```\n\n### Customizations\n\nBelow are some potential areas to customize.\u00a0\n\n- You can customize the GPT prompt to search again a certain amount of times if nothing is found.\n\n- You can customize the code to only search through specific SharePoint sites or O365 Drives by customizing the search query. This will help focus the search and improve the retrieval. The function as setup now looks through all files the logged-in user can access.\n\n- You could use gpt-4o instead of gpt-3.5 turbo for longer context. This would slightly increase the cost and latency, but you may get higher quality summarizations.\n\n- You can customize the amount of files it searches through within the call to Microsoft Graph.\n\n\n### Considerations\n\nNote that all the same limitations of Actions apply here, with regards to returning 100K characters or less and the [45 second timeout](https://platform.openai.com/docs/actions/production/timeouts).\n\n\n- This only works for text, not for images. With some additional code in the Azure Function, you could customize this by using GPT-4o to extract summarizations of images.\n\n- This does not work for structured data. We recommend Solution 1 if structured data is a major part of your use case.\n\n### Sample GPT Instructions"}


created_at: 2024-08-26 20:31:29
topic: persistent://default/default/47f0afae-77ee-4e4a-bcd4-0b050f4de62c
id: a1c74dad-e650-40f6-ad17-25ed84d97cdf
encoding: FLOAT32
metadata:
{"url": "https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb", "title": "Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT", "tokens": 10420, "retrieve_doc": false, "source": "openai_cookbooks", "_node_content": "{\"id_\": \"a1c74dad-e650-40f6-ad17-25ed84d97cdf\", \"embedding\": null, \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"excluded_embed_metadata_keys\": [\"url\", \"tokens\", \"retrieve_doc\", \"source\"], \"excluded_llm_metadata_keys\": [\"title\", \"tokens\", \"retrieve_doc\", \"source\"], \"relationships\": {\"1\": {\"node_id\": \"0aae3c52-be5a-4766-96d1-970b0e57f712\", \"node_type\": \"4\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"d431d2d02d5e396a3583077d51586bcf0ed0124b6aab36016c9a3724b8cce8a0\", \"class_name\": \"RelatedNodeInfo\"}, \"2\": {\"node_id\": \"03b9fd3e-bbf6-48c1-8073-9f3905654c3d\", \"node_type\": \"1\", \"metadata\": {\"url\": \"https://github.com/openai/openai-cookbook/blob/main/examples/chatgpt/sharepoint_azure_function/Using_Azure_Functions_and_Microsoft_Graph_to_Query_SharePoint.ipynb\", \"title\": \"Using Azure Functions with OAuth and Microsoft Graph API to Search O365 / SharePoint from ChatGPT\", \"tokens\": 10420, \"retrieve_doc\": false, \"source\": \"openai_cookbooks\"}, \"hash\": \"66bb30566f81846659d5973df1b9557f41dde3ab603bda2859412a8b881807f3\", \"class_name\": \"RelatedNodeInfo\"}, \"3\": {\"node_id\": \"7b679a2b-bd2a-4768-aa8f-3fa03de94185\", \"node_type\": \"1\", \"metadata\": {}, \"hash\": \"dfc699f9a3059359172b101f665f4cef13ab09f8bc1c1156bc67918c7630d3ea\", \"class_name\": \"RelatedNodeInfo\"}}, \"text\": \"\", \"mimetype\": \"text/plain\", \"start_char_idx\": 40025, \"end_char_idx\": 45157, \"text_template\": \"{metadata_str}\\n\\n{content}\", \"metadata_template\": \"{key}: {value}\", \"metadata_seperator\": \"\\n\", \"class_name\": \"TextNode\"}", "_node_type": "TextNode", "document_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "ref_doc_id": "0aae3c52-be5a-4766-96d1-970b0e57f712", "chroma:document": "results = await processList();\n            results.sort((a, b) => a.rank - b.rank);\n        }\n        context.res = {\n            status: 200,\n            body: results\n        };\n    } catch (error) {\n        context.res = {\n            status: 500,\n            body: `Error performing search or processing results: ${error.message}`,\n        };\n    }\n};\n```\n\n### Customizations\n\nBelow are some potential areas to customize.\u00a0\n\n- You can customize the GPT prompt to search again a certain amount of times if nothing is found.\n\n- You can customize the code to only search through specific SharePoint sites or O365 Drives by customizing the search query. This will help focus the search and improve the retrieval. The function as setup now looks through all files the logged-in user can access.\n\n- You could use gpt-4o instead of gpt-3.5 turbo for longer context. This would slightly increase the cost and latency, but you may get higher quality summarizations.\n\n- You can customize the amount of files it searches through within the call to Microsoft Graph.\n\n\n### Considerations\n\nNote that all the same limitations of Actions apply here, with regards to returning 100K characters or less and the [45 second timeout](https://platform.openai.com/docs/actions/production/timeouts).\n\n\n- This only works for text, not for images. With some additional code in the Azure Function, you could customize this by using GPT-4o to extract summarizations of images.\n\n- This does not work for structured data. We recommend Solution 1 if structured data is a major part of your use case.\n\n### Sample GPT Instructions\n\n\n```\nYou are a Q&A helper that helps answer users questions. You have access to a documents repository through your API action. When a user asks a question, you pass in that question exactly as stated to the \"query\" parameter, and for the \"searchTerm\" you use a single keyword or term you think you should use for the search.\n\n****\n\nScenario 1: There are answers\n\nIf your action returns results, then you take the results from the action and summarize concisely with the webUrl returned from the action. You answer the users question to the best of your knowledge from the action\n\n****\n\nScenario 2: No results found\n\nIf the response you get from the action is \"No results found\", stop there and let the user know there were no results and that you are going to try a different search term, and explain why. You must always let the user know before conducting another search.\n\nExample:\n\n****\n\nI found no results for \"DEI\". I am now going to try [insert term] because [insert explanation]\n\n****\n\nThen, try a different searchTerm that is similar to the one you tried before, with a single word.\u00a0\n\nTry this three times. After the third time, then let the user know you did not find any relevant documents to answer the question, and to check SharePoint. Be sure to be explicit about what you are searching for at each step.\n\n****\n\nIn either scenario, try to answer the user's question. If you cannot answer the user's question based on the knowledge you find, let the user know and ask them to go check the HR Docs in SharePoint. If the file is a CSV, XLSX, or XLS, you can tell the user to download the file using the link and re-upload to use Advanced Data Analysis.\n```\n\n### Sample OpenAPI Spec\nThe below spec passes in the `query` parameter to inform the pre-processing and a `searchTerm` to find the right files in Microsoft Graph.\n>Make sure to switch the function app name, function name and code based on link copied in screenshot [here](#part-3-set-up-test-function)\n\n```yaml\nopenapi: 3.0.0\ninfo:\n  title: SharePoint Search API\n  description: API for searching SharePoint documents.\n  version: 1.0.0\nservers:\n  - url: https://{your_function_app_name}.azurewebsites.net/api\n    description: SharePoint Search API server\npaths:\n  /{your_function_name}?code={enter your specific endpoint id here}:\n    post:\n      operationId: searchSharePoint\n      summary: Searches SharePoint for documents matching a query and term.\n      requestBody:\n        required: true\n        content:\n          application/json:\n            schema:\n              type: object\n              properties:\n                query:\n                  type: string\n                  description: The full query to search for in SharePoint documents.\n                searchTerm:\n                  type: string\n                  description: A specific term to search for within the documents.\n      responses:\n        '200':\n          description: Search results\n          content:\n            application/json:\n              schema:\n                type: array\n                items:\n                  type: object\n                  properties:\n                    documentName:\n                      type: string\n                      description: The name of the document.\n                    snippet:\n                      type: string\n                      description: A snippet from the document containing the search term.\n                    url:\n                      type: string\n                      description: The URL to access the document.\n```"}


