├── .gitignore ├── Dockerfile ├── Ingest data into Pinecone.ipynb ├── README.md ├── app.py ├── docs └── NET-Microservices-Architecture-for-Containerized-NET-Applications.pdf ├── imgs ├── qa-gpt-app-diagram.png ├── qa-gpt-app-openai-deployments.png └── qa-gpt-app-output.png └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9-slim 2 | 3 | WORKDIR /app 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | build-essential \ 7 | curl \ 8 | software-properties-common \ 9 | git \ 10 | && rm -rf /var/lib/apt/lists/* 11 | 12 | COPY ./app.py . 13 | COPY ./requirements.txt . 14 | 15 | RUN pip install -r requirements.txt 16 | 17 | EXPOSE 5050 18 | 19 | ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=5050", "--server.address=0.0.0.0"] -------------------------------------------------------------------------------- /Ingest data into Pinecone.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "attachments": {}, 5 | "cell_type": "markdown", 6 | "metadata": {}, 7 | "source": [ 8 | "# **How to ingest data to Pinecone using LangChain**\n", 9 | "\n", 10 | "- This notebook shows you how you can ingest data from a document into a Pinecone Database.\n", 11 | "- It uses Langchain to ease the process of split and ingest the data" 12 | ] 13 | }, 14 | { 15 | "attachments": {}, 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "### **1. Import dependencies**" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 1, 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "name": "stderr", 29 | "output_type": "stream", 30 | "text": [ 31 | "e:\\Coding\\ai\\building-qa-app-with-openai-pinecone-and-streamlit\\.venv\\lib\\site-packages\\pinecone\\index.py:4: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", 32 | " from tqdm.autonotebook import tqdm\n" 33 | ] 34 | } 35 | ], 36 | "source": [ 37 | "import os\n", 38 | "import pinecone\n", 39 | "from langchain.document_loaders import UnstructuredPDFLoader\n", 40 | "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", 41 | "from langchain.embeddings.openai import OpenAIEmbeddings\n", 42 | "from langchain.vectorstores import Pinecone\n", 43 | "from langchain.chat_models import AzureChatOpenAI\n", 44 | "from langchain.chains.question_answering import load_qa_chain" 45 | ] 46 | }, 47 | { 48 | "attachments": {}, 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "### **2. Read PineCone and Azure OpenAI environment variables**" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 8, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "PINECONE_API_KEY = os.getenv('PINECONE_API_KEY')\n", 62 | "PINECONE_API_ENV = os.getenv('PINECONE_ENVIRONMENT')\n", 63 | "PINECONE_INDEX_NAME = os.getenv('PINECONE_INDEX_NAME')\n", 64 | "AZURE_OPENAI_API_KEY = os.getenv('AZURE_OPENAI_APIKEY')\n", 65 | "AZURE_OPENAI_API_BASE = os.getenv('AZURE_OPENAI_BASE_URI')\n", 66 | "AZURE_OPENAI_API_TYPE = 'azure'\n", 67 | "AZURE_OPENAI_API_VERSION = '2023-03-15-preview'\n", 68 | "AZURE_OPENAI_EMBEDDINGS_MODEL_NAME= os.getenv('AZURE_OPENAI_EMBEDDINGS_MODEL_NAME')\n", 69 | "AZURE_OPENAI_GPT4_MODEL_NAME= os.getenv('AZURE_OPENAI_GPT4_MODEL_NAME')" 70 | ] 71 | }, 72 | { 73 | "attachments": {}, 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "### **3. Load your data files and split it into chunks**" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": 3, 83 | "metadata": {}, 84 | "outputs": [ 85 | { 86 | "name": "stderr", 87 | "output_type": "stream", 88 | "text": [ 89 | "detectron2 is not installed. Cannot use the hi_res partitioning strategy. Falling back to partitioning with the fast strategy.\n" 90 | ] 91 | }, 92 | { 93 | "name": "stdout", 94 | "output_type": "stream", 95 | "text": [ 96 | "You have a total of 917 chunks\n" 97 | ] 98 | } 99 | ], 100 | "source": [ 101 | "loader = UnstructuredPDFLoader(\"./docs/NET-Microservices-Architecture-for-Containerized-NET-Applications.pdf\")\n", 102 | "data = loader.load()\n", 103 | "\n", 104 | "text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)\n", 105 | "chunks = text_splitter.split_documents(data)\n", 106 | "\n", 107 | "print (f'You have a total of {len(chunks)} chunks')" 108 | ] 109 | }, 110 | { 111 | "attachments": {}, 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "### **4. Init Azure OpenAI and Pinecone clients**" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 4, 121 | "metadata": {}, 122 | "outputs": [], 123 | "source": [ 124 | "embeddings = OpenAIEmbeddings(\n", 125 | " openai_api_base=AZURE_OPENAI_API_BASE, \n", 126 | " openai_api_key=AZURE_OPENAI_API_KEY, \n", 127 | " openai_api_type=AZURE_OPENAI_API_TYPE,\n", 128 | " model=AZURE_OPENAI_EMBEDDINGS_MODEL_NAME, \n", 129 | " chunk_size=1)\n", 130 | "\n", 131 | "pinecone.init(\n", 132 | " api_key=PINECONE_API_KEY,\n", 133 | " environment=PINECONE_API_ENV \n", 134 | ")" 135 | ] 136 | }, 137 | { 138 | "attachments": {}, 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "### **5. Create and store embeddings into Pinecone**" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "execution_count": 6, 148 | "metadata": {}, 149 | "outputs": [], 150 | "source": [ 151 | "docsearch = Pinecone.from_texts([t.page_content for t in chunks], embeddings, index_name=PINECONE_INDEX_NAME)" 152 | ] 153 | }, 154 | { 155 | "attachments": {}, 156 | "cell_type": "markdown", 157 | "metadata": {}, 158 | "source": [ 159 | "### **6. Ask a question**" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": 10, 165 | "metadata": {}, 166 | "outputs": [ 167 | { 168 | "name": "stdout", 169 | "output_type": "stream", 170 | "text": [ 171 | "Answer: \n", 172 | "\n", 173 | " 1. Use asynchronous communication: Implement message-based communication across internal microservices to minimize ripple effects and enforce a higher level of microservice autonomy.\n", 174 | "\n", 175 | "2. Implement retries with exponential backoff: In case of transient faults, use the \"Retry pattern\" to retry the operation with increasing time intervals between attempts, allowing the system to recover.\n", 176 | "\n", 177 | "3. Use the Circuit Breaker pattern: Track the number of failed requests, and if the error rate exceeds a configured limit, trip the circuit breaker to prevent further attempts. After a timeout period, try again and close the circuit breaker if new requests are successful.\n" 178 | ] 179 | } 180 | ], 181 | "source": [ 182 | "llm = AzureChatOpenAI(\n", 183 | " temperature=0, \n", 184 | " openai_api_base=AZURE_OPENAI_API_BASE, \n", 185 | " openai_api_key=AZURE_OPENAI_API_KEY, \n", 186 | " openai_api_version=AZURE_OPENAI_API_VERSION, \n", 187 | " deployment_name=AZURE_OPENAI_GPT4_MODEL_NAME)\n", 188 | "\n", 189 | "chain = load_qa_chain(llm, chain_type=\"stuff\")\n", 190 | "\n", 191 | "query = \"Enumerate 3 strategies to handle partial failures?\"\n", 192 | "docs = docsearch.similarity_search(query, include_metadata=True)\n", 193 | "\n", 194 | "result = chain.run(input_documents=docs, question=query)\n", 195 | "\n", 196 | "print(f\"Answer: \\n\\n {result}\")" 197 | ] 198 | } 199 | ], 200 | "metadata": { 201 | "kernelspec": { 202 | "display_name": ".venv", 203 | "language": "python", 204 | "name": "python3" 205 | }, 206 | "language_info": { 207 | "codemirror_mode": { 208 | "name": "ipython", 209 | "version": 3 210 | }, 211 | "file_extension": ".py", 212 | "mimetype": "text/x-python", 213 | "name": "python", 214 | "nbconvert_exporter": "python", 215 | "pygments_lexer": "ipython3", 216 | "version": "3.10.11" 217 | }, 218 | "orig_nbformat": 4 219 | }, 220 | "nbformat": 4, 221 | "nbformat_minor": 2 222 | } 223 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This repository contains a practical example about how to build a GPT-4 Q&A app capable of answering questions related to your private documents in just a couple of hours. 4 | 5 | The app uses the following technologies: 6 | 7 | - [Azure OpenAI](https://azure.microsoft.com/en-us/products/cognitive-services/openai-service) 8 | - [Pinecone](https://www.pinecone.io/) 9 | - [Streamlit](https://streamlit.io/) 10 | 11 | # **Content** 12 | 13 | The repository contains the following applications. 14 | 15 | ![app-diagram](https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/main/imgs/qa-gpt-app-diagram.png) 16 | 17 | 18 | - A ``Jupyter Notebook``reads your private documents (for this example I'm using the dotnet microservices book) and stores the content in Pinecone. 19 | - A ``Streamlit`` app allow us to query the data stored in Pinecone using a GPT-4 LLM model. 20 | 21 | 22 | # **External Dependencies** 23 | - Azure OpenAI 24 | - Pinecone 25 | 26 | # **Prerequisites** 27 | 28 | You **MUST** have the following services running before trying to execute the app. 29 | 30 | - An ``Azure OpenAI`` instance with the following models deployed: 31 | - ``text-embedding-ada-002``. 32 | - ``gpt-4`` or ``gpt-4-32k``. 33 | 34 | _The models can be called whatever you like._ 35 | 36 | - A ``Pinecone`` database with an index with ``1536`` dimensions and ``cosine`` metric. 37 | 38 | _The index can be called whatever you like._ 39 | 40 | # **How to run the app** 41 | 42 | > Before trying to run the app, read the _Prerequisites_ section. 43 | 44 | ## **Step 1: Add your data into Pinecone** 45 | 46 | The repository contains a ``Jupyter Notebook`` that reads a PDF file from the ``docs`` folder, splits the content into multiple chunks and stores them into PineCone. 47 | 48 | You must set the following enviroment variables, before executing the ``Jupyter Notebook``: 49 | 50 | - ``PINECONE_API_KEY``: Pinecone ApiKey. 51 | - ``PINECONE_ENVIRONMENT``: Pinecone index environment. 52 | - ``PINECONE_INDEX_NAME``: Pinecone index name. 53 | - ``AZURE_OPENAI_APIKEY``: Azure OpenAI ApiKey. 54 | - ``AZURE_OPENAI_BASE_URI``: Azure OpenAI URI. 55 | - ``AZURE_OPENAI_EMBEDDINGS_MODEL_NAME``: The ``text-embedding-ada-002`` model deployment name. 56 | - ``AZURE_OPENAI_GPT4_MODEL_NAME``: The ``gpt-4`` model deployment name. 57 | 58 | _What's the model deployment name?_ 59 | - When you deploy a model on an ``Azure OpenAI`` instance you must give it a name. 60 | For this example to run properly you need to deploy at least a ``text-embedding-ada-002`` model and a ``gpt-4`` model. 61 | 62 | ![azure-openai-deployment-models](https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/main/imgs/qa-gpt-app-openai-deployments.png) 63 | 64 | ## **Step 2: Query your data** 65 | 66 | The ``app.py`` is a ``Streamlit`` app that does the following steps: 67 | 68 | - Converts your query into a vector. 69 | - Retrieves the information that is semantically related to our query from Pinecone. 70 | - Feeds the retrieved information into a LLM model which builds a response. 71 | 72 | **Run the app locally** : 73 | 74 | Restore dependencies: 75 | ```bash 76 | pip install -r requirements.txt 77 | ``` 78 | When you install ``Streamlit``, a command-line (CLI) tool gets installed as well. The purpose of this tool is to run ``Streamlit`` apps. 79 | ```bash 80 | streamlit run app.py 81 | ``` 82 | 83 | You MUST set the following environment variables on your local machine before executing the app: 84 | 85 | - ``PINECONE_API_KEY``: Pinecone ApiKey. 86 | - ``PINECONE_ENVIRONMENT``: Pinecone index environment. 87 | - ``PINECONE_INDEX_NAME``: Pinecone index name. 88 | - ``AZURE_OPENAI_APIKEY``: Azure OpenAI ApiKey. 89 | - ``AZURE_OPENAI_BASE_URI``: Azure OpenAI URI. 90 | - ``AZURE_OPENAI_EMBEDDINGS_MODEL_NAME``: The ``text-embedding-ada-002`` model deployment name. 91 | - ``AZURE_OPENAI_GPT4_MODEL_NAME``: The ``gpt-4`` model deployment name. 92 | 93 | **Run the app in a container**: 94 | 95 | This repository has a ``Dockerfile`` in case you prefer to execute the app on a container. 96 | 97 | Build the image: 98 | ```shell 99 | docker build -t qa-app . 100 | ``` 101 | 102 | Run it: 103 | ``` 104 | docker run -p 5050:5050 \ 105 | -e AZURE_OPENAI_APIKEY="" \ 106 | -e AZURE_OPENAI_BASE_URI="" \ 107 | -e AZURE_OPENAI_EMBEDDINGS_MODEL_NAME="" \ 108 | -e AZURE_OPENAI_GPT4_MODEL_NAME="" \ 109 | -e PINECONE_INDEX="" \ 110 | -e PINECONE_ENVIRONMENT="" \ 111 | -e PINECONE_API_KEY="" \ 112 | qa-app 113 | ``` 114 | 115 | # **Output** 116 | 117 | ![app-output](https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/main/imgs/qa-gpt-app-output.png) 118 | 119 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import openai 3 | import pinecone 4 | import os 5 | 6 | 7 | # Check if environment variables are present. If not, throw an error 8 | if os.getenv('PINECONE_API_KEY') is None: 9 | st.error("PINECONE_API_KEY not set. Please set this environment variable and restart the app.") 10 | if os.getenv('PINECONE_ENVIRONMENT') is None: 11 | st.error("PINECONE_ENVIRONMENT not set. Please set this environment variable and restart the app.") 12 | if os.getenv('PINECONE_INDEX') is None: 13 | st.error("PINECONE_INDEX not set. Please set this environment variable and restart the app.") 14 | if os.getenv('AZURE_OPENAI_APIKEY') is None: 15 | st.error("AZURE_OPENAI_APIKEY not set. Please set this environment variable and restart the app.") 16 | if os.getenv('AZURE_OPENAI_BASE_URI') is None: 17 | st.error("AZURE_OPENAI_BASE_URI not set. Please set this environment variable and restart the app.") 18 | if os.getenv('AZURE_OPENAI_EMBEDDINGS_MODEL_NAME') is None: 19 | st.error("AZURE_OPENAI_EMBEDDINGS_MODEL_NAME not set. Please set this environment variable and restart the app.") 20 | if os.getenv('AZURE_OPENAI_GPT4_MODEL_NAME') is None: 21 | st.error("AZURE_OPENAI_GPT4_MODEL_NAME not set. Please set this environment variable and restart the app.") 22 | 23 | 24 | st.title("Q&A App 🔎") 25 | query = st.text_input("What do you want to know?") 26 | 27 | if st.button("Search"): 28 | 29 | # # get Pinecone API environment variables 30 | pinecone_api = os.getenv('PINECONE_API_KEY') 31 | pinecone_env = os.getenv('PINECONE_ENVIRONMENT') 32 | pinecone_index = os.getenv('PINECONE_INDEX') 33 | 34 | # # get Azure OpenAI environment variables 35 | openai.api_key = os.getenv('AZURE_OPENAI_APIKEY') 36 | openai.api_base = os.getenv('AZURE_OPENAI_BASE_URI') 37 | openai.api_type = 'azure' 38 | openai.api_version = '2023-03-15-preview' 39 | embeddings_model_name = os.getenv('AZURE_OPENAI_EMBEDDINGS_MODEL_NAME') 40 | gpt4_model_name = os.getenv('AZURE_OPENAI_GPT4_MODEL_NAME') 41 | 42 | # Initialize Pinecone client and set index 43 | pinecone.init(api_key=pinecone_api, environment=pinecone_env) 44 | index = pinecone.Index(pinecone_index) 45 | 46 | # Convert your query into a vector using Azure OpenAI 47 | try: 48 | query_vector = openai.Embedding.create( 49 | input=query, 50 | engine=embeddings_model_name, 51 | )["data"][0]["embedding"] 52 | except Exception as e: 53 | st.error(f"Error calling OpenAI Embedding API: {e}") 54 | st.stop() 55 | 56 | # Search for the most similar vectors in Pinecone 57 | search_response = index.query( 58 | top_k=3, 59 | vector=query_vector, 60 | include_metadata=True) 61 | 62 | chunks = [item["metadata"]['text'] for item in search_response['matches']] 63 | 64 | # Combine texts into a single chunk to insert in the prompt 65 | joined_chunks = "\n".join(chunks) 66 | 67 | # Write the selected chunks into the UI 68 | with st.expander("Chunks"): 69 | for i, t in enumerate(chunks): 70 | t = t.replace("\n", " ") 71 | st.write("Chunk ", i, " - ", t) 72 | 73 | with st.spinner("Summarizing..."): 74 | try: 75 | # Build the prompt 76 | prompt = f""" 77 | Answer the following question based on the context below. 78 | If you don't know the answer, just say that you don't know. Don't try to make up an answer. Do not answer beyond this context. 79 | --- 80 | QUESTION: {query} 81 | --- 82 | CONTEXT: 83 | {joined_chunks} 84 | """ 85 | 86 | # Run chat completion using GPT-4 87 | response = openai.ChatCompletion.create( 88 | engine=gpt4_model_name, 89 | messages=[ 90 | { "role": "system", "content": "You are a Q&A assistant." }, 91 | { "role": "user", "content": prompt } 92 | ], 93 | temperature=0.7, 94 | max_tokens=1000 95 | ) 96 | 97 | # Write query answer 98 | st.markdown("### Answer:") 99 | st.write(response.choices[0]['message']['content']) 100 | 101 | 102 | except Exception as e: 103 | st.error(f"Error with OpenAI Chat Completion: {e}") -------------------------------------------------------------------------------- /docs/NET-Microservices-Architecture-for-Containerized-NET-Applications.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/34cd2afce5361b37a4221d93b85eedabf8b5e3c3/docs/NET-Microservices-Architecture-for-Containerized-NET-Applications.pdf -------------------------------------------------------------------------------- /imgs/qa-gpt-app-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/34cd2afce5361b37a4221d93b85eedabf8b5e3c3/imgs/qa-gpt-app-diagram.png -------------------------------------------------------------------------------- /imgs/qa-gpt-app-openai-deployments.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/34cd2afce5361b37a4221d93b85eedabf8b5e3c3/imgs/qa-gpt-app-openai-deployments.png -------------------------------------------------------------------------------- /imgs/qa-gpt-app-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karlospn/building-qa-app-with-openai-pinecone-and-streamlit/34cd2afce5361b37a4221d93b85eedabf8b5e3c3/imgs/qa-gpt-app-output.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | langchain 2 | pinecone-client 3 | openai 4 | unstructured 5 | streamlit --------------------------------------------------------------------------------