ryanyyc commited on
Commit
640b9e7
·
verified ·
1 Parent(s): a541591

Upload folder using huggingface_hub

Browse files
.gitignore ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .openai
3
+ .dockerignore
4
+ chat_history.pkl
5
+ embeddings.json
6
+ new_uploads/*
7
+ prev_uploads/*
8
+
9
+
10
+ # Work in Progress
11
+ app.py
12
+ index.html
13
+ index.js
14
+ index.css
2024-08-06T15:30:18.239414.json ADDED
@@ -0,0 +1 @@
 
 
1
+ [{"timestamp": "2024-08-06T15:30:18.239414"}, {"role": "user", "content": "Tell me about a lease"}, {"role": "assistant", "content": "A lease is a legal agreement between a landlord (or lessor) and a tenant (or lessee) that outlines the terms and conditions under which a property is rented. It typically includes details such as the duration of the lease (term), the amount of rent to be paid, any security deposits required, maintenance responsibilities, and other provisions related to the use of the property. Leases can vary in length, with some being short-term (e.g., month-to-month) and others lasting several years. A lease provides both parties with rights and obligations regarding the property being rented for the specified period."}, {"full_prompt": [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Context:\nTERM\n\na) The term of the Lease shall be for sixteen (16) years, commencing on the first day of May, 1998, and ending on the last day of April, 2014.\n\nPOSSESSION\n\na) Lessee shall be entitled to possession on or about May 1, 1998 or upon completion of Tenant Improvement work.\n\nb) In the event the Lessor shall permit the Lessee to occupy the Premises prior to the commencement date of the term of this Lease, such occupancy shall be subject to all the provisions of this Lease. Early possession shall not advance the termination date of this Lease, and Lessor shall not be responsible for equipment installed by the Lessee.\n\nRENT\n\na) This Lease is the type commonly referred to as a \u201cgross lease\u201d. Lessee shall pay\nQUIET ENJOYMENT\n\nLessor warrants that Lessee, upon discharge of all of Lessee\u2019s obligations hereunder, shall and may be peaceably and quietly hold and enjoy the premises for the term of the Lease.\n\nLSEKENN.DOC 7\n\n26. GROUND LEASE The Lessee acknowledges that the Lessor has entered into a Ground Lease for the property described in Exhibit A, and has constructed an office building on said property. All rights of Lessor are subject to that Ground Lease, and in the event of any dispute between the terms of this Lease and that of the Ground Lease, the Ground Lease shall control.\n\nDATED this__/ S* day of RornQ , 1998,\n\nLESSOR:\n\nHIGHLINE PROFESSIONAL BUILDING ASSOCIATES LIMITED PARTNERSHIP 10900 N.E. Fourth, Suite 1550\n\nBellevue, WA 98004\n\nBy: Lf (A vl I) hid!\n\nGeneral Pa\n\nLESSEE: Surgery Associates Michael Kennelly, M.D.\n\n16122 Eighth Street SW Suite D-1 Seattle, WA 98166\n\nLESSEE\n\nLESSEE:\n\nSurgery Associates\n\nWilliam L. White, M.D.\n\n16122 Eighth Street SW Suite D-1 Seattle, WA 98166\nWu-Hsun Yang and Geoffrey Bender\n\nFirst Amendment to Lease\n\nHighline Professional Building\n\nThe parties to this First Amendment to Lease dated the December ___, 2023 are Highline Professional Building Associates, Limited Partnership (\u201cLandlord\u201d) and Wu-Hsun Yang and Geoffrey Bender (\u201cTenant\u201d).\t\n\nWHEREAS, Landlord and Tenant have a binding Lease Agreement dated June 10, 2021, together the lease in and to the premises described in Exhibit A Legal Description of the Property more commonly known as Highline Professional Building, 16122 8th, Avenue SW, Suite D3, City of Burien, County of King, State of Washington.\n\nThe parties do hereby mutually agree to modify certain particulars of the Lease Agreement as follow:\n\n1.\tSection 4 Term\n\nSection 4 shall be modified as follows:\n\n\u201cThe term of the Lease shall be extended ten (10) years commencing August 1, 2024 and ending July 31, 2034.\u201d\n\n2.\tSection 5 Rent.\n\n\tMonthly rent for the extended term of the Lease shall be as follows:\nSouth Seattle Nephrology Associates, LLC.\n\nFirst Amendment to Lease\n\nHighline Professional Building\n\nThe parties to this First Amendment to Lease dated the December ___, 2023 are Highline Professional Building Associates, Limited Partnership (\u201cLandlord\u201d) and South Seattle Nephrology Associates, LLC. a Washington Limited Liability Company (\u201cTenant\u201d).\t\n\nWHEREAS, Landlord and Tenant have a binding Lease Agreement dated October 1, 2018, together the lease in and to the premises described in Exhibit A Legal Description of the Property more commonly known as Highline Professional Building, 16122 8th, Avenue SW, Suite E-2, City of Burien, County of King, State of Washington.\n\nThe parties do hereby mutually agree to modify certain particulars of the Lease Agreement as follow:\n\n1.\tSection 4 Term\n\nSection 4 shall be modified as follows:\n\n\u201cThe term of the Lease shall be extended three (3) years commencing January 1, 2024 and ending December 31, 2026.\u201d\n\n2.\tSection 5 Rent.\nSteven McClean MD, PC\n\nFirst Amendment to Lease\n\nHighline Professional Building\n\nThe parties to this First Amendment to Lease dated the September 15, 2022, are Highline Professional Building Associates, Limited Partnership (\u201cLandlord\u201d) and Steven P. McClean MD, PC. an individual (\u201cTenant\u201d).\t\n\nWHEREAS, Landlord and Tenant have a binding Lease Agreement dated July 5, 2012, together the lease in and to the premises described in Exhibit A Legal Description of the Property more commonly known as Highline Professional Building, 16122 8th, Avenue SW, Suite E-3, City of Burien, County of King, State of Washington.\n\nThe parties do hereby mutually agree to modify certain particulars of the Lease Agreement as follow:\n\n1.\tSection 4 Term\n\nSection 4 shall be modified as follows:\n\n\u201cThe term of the Lease shall be extended five (5) years commencing October 1, 2022 and ending September 30, 2027.\u201d\n\n2.\tSection 5 Rent.\n\n\tMonthly rent for the extended term of the Lease shall be as follows:\n\n\nQuestion: Tell me about a lease\nAnswer:"}]}]
Dockerfile ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # syntax=docker/dockerfile:1
2
+
3
+ # Comments are provided throughout this file to help you get started.
4
+ # If you need more help, visit the Dockerfile reference guide at
5
+ # https://docs.docker.com/go/dockerfile-reference/
6
+
7
+ # Want to help us make this template better? Share your feedback here: https://forms.gle/ybq9Krt8jtBL3iCk7
8
+
9
+ ARG PYTHON_VERSION=3.12.4
10
+ FROM python:${PYTHON_VERSION}-slim as base
11
+
12
+ # Prevents Python from writing pyc files.
13
+ ENV PYTHONDONTWRITEBYTECODE=1
14
+
15
+ # Keeps Python from buffering stdout and stderr to avoid situations where
16
+ # the application crashes without emitting any logs due to buffering.
17
+ ENV PYTHONUNBUFFERED=1
18
+
19
+ WORKDIR /app
20
+
21
+ # Create a non-privileged user that the app will run under.
22
+ # See https://docs.docker.com/go/dockerfile-user-best-practices/
23
+ ARG UID=10001
24
+ RUN adduser \
25
+ --disabled-password \
26
+ --gecos "" \
27
+ --home "/nonexistent" \
28
+ --shell "/sbin/nologin" \
29
+ --no-create-home \
30
+ --uid "${UID}" \
31
+ appuser
32
+
33
+ # Install system dependencies.
34
+ RUN apt-get update && apt-get install -y \
35
+ build-essential \
36
+ meson \
37
+ ninja-build \
38
+ pkg-config \
39
+ libpoppler-cpp-dev \
40
+ && rm -rf /var/lib/apt/lists/*
41
+
42
+ # Download dependencies as a separate step to take advantage of Docker's caching.
43
+ # Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
44
+ # Leverage a bind mount to requirements.txt to avoid having to copy them into
45
+ # into this layer.
46
+ RUN --mount=type=cache,target=/root/.cache/pip \
47
+ --mount=type=bind,source=requirements.txt,target=requirements.txt \
48
+ python -m pip install -r requirements.txt
49
+
50
+ # Switch to the non-privileged user to run the application.
51
+ USER appuser
52
+
53
+ # Copy the source code into the container.
54
+ COPY . .
55
+
56
+ # Expose the port that the application listens on.
57
+ EXPOSE 7860
58
+
59
+ # Ensure Gradio listens on all network interfaces
60
+ ENV GRADIO_SERVER_NAME="0.0.0.0"
61
+
62
+ # Run the application.
63
+ CMD ["python", "OpenAIChat.py"]
EmbedUpsert.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import dotenv
4
+ from openai import OpenAI
5
+ from langchain.text_splitter import CharacterTextSplitter
6
+ from langchain_community.document_loaders import DirectoryLoader
7
+ from utils import DOC_CHUNK_SIZE, DOC_CHUNK_OVERLAP, DOC_DIRECTORY, EMBEDDING_FILE
8
+
9
+ '''
10
+ This file handles the loading and embedding of documents.
11
+ Saves the embeddings to a json file specified by EMBEDDING_FILE.
12
+ Uses OpenAI's text-embedding-3-small model for embeddings.
13
+
14
+ Supported formats: pdf
15
+
16
+ Format of saved json file:
17
+ List of dictionaries with keys:
18
+ 'doc_id': {filename}_{chunk number}
19
+ 'embeddings': List of embeddings for the chunk, one embedding for each character in chunk
20
+
21
+ Specifications:
22
+ OpenAI embeds with a dimension of 1536 per character
23
+ '''
24
+
25
+ # Load environment variables
26
+ dotenv.load_dotenv()
27
+
28
+ def load_documents():
29
+ '''
30
+ Load documents from a specified directory into a list
31
+
32
+ Returns:
33
+ documents: List of documents loaded from the directory, split by chunks
34
+ '''
35
+ # Create document loaders
36
+ pdf_loader = DirectoryLoader(DOC_DIRECTORY, glob='*.pdf')
37
+ docx_loader = DirectoryLoader(DOC_DIRECTORY, glob='*.docx')
38
+ txt_loader = DirectoryLoader(DOC_DIRECTORY, glob='*.txt')
39
+ loaders = [pdf_loader]
40
+
41
+ # Load documents
42
+ print("Loading documents...")
43
+ documents = []
44
+ for loader in loaders:
45
+ try:
46
+ documents.extend(loader.load())
47
+ except Exception as e:
48
+ print(f"Error loading documents: {e}")
49
+
50
+ if (len(documents) == 0):
51
+ print("No documents loaded.")
52
+ return []
53
+
54
+ # Split documents into chunks
55
+ text_splitter = CharacterTextSplitter(chunk_size=DOC_CHUNK_SIZE, chunk_overlap=DOC_CHUNK_OVERLAP)
56
+ documents = text_splitter.split_documents(documents)
57
+
58
+ # Iterate to edit metadata to include chunk number
59
+ # format = {filename}_{chunk number}
60
+ chunk_num = 1
61
+ prev_doc_id = documents[0].metadata['source']
62
+ for chunk in documents:
63
+ print(chunk.metadata)
64
+ if chunk.metadata['source'] != prev_doc_id:
65
+ chunk_num = 1
66
+ prev_doc_id = chunk.metadata['source']
67
+ chunk.metadata['source'] = f"{prev_doc_id}_{chunk_num}"
68
+ chunk_num += 1
69
+
70
+ return documents
71
+
72
+ def embed_documents(documents):
73
+ '''
74
+ Embed documents using OpenAIEmbeddings
75
+
76
+ Args:
77
+ documents: List of documents to embed
78
+
79
+ Returns:
80
+ List of JSON objects {doc_id, embeddings, metadata}
81
+ '''
82
+ # Use OpenAI to embed documents
83
+ client = OpenAI(
84
+ api_key=os.getenv("OPENAI_API_KEY")
85
+ )
86
+ embeddings = []
87
+ print("Embedding documents...")
88
+
89
+ # Embed each chunk
90
+ for chunk in documents:
91
+ chunk_embeddings = client.embeddings.create(
92
+ model="text-embedding-3-small",
93
+ input=chunk.page_content
94
+ )
95
+ # Extract embeddings from response
96
+ chunk_embedding = [record.embedding for record in chunk_embeddings.data]
97
+ embeddings.append({
98
+ 'doc_id': chunk.metadata['source'],
99
+ 'embeddings': chunk_embedding[0],
100
+ 'metadata': {'source': chunk.metadata['source'], 'text': chunk.page_content}
101
+ })
102
+ return embeddings
103
+
104
+ def save_embeddings(embeddings, filename):
105
+ '''
106
+ Save generated embedding to a json file
107
+
108
+ Args:
109
+ embeddings: List of embeddings to save
110
+ filename: Name of the file to save the embeddings
111
+ '''
112
+ print("Saving embedding...")
113
+ with open(filename, 'w') as file:
114
+ json.dump(embeddings, file)
115
+
116
+ ### Main code
117
+ documents = load_documents()
118
+ if (len(documents) == 0):
119
+ exit()
120
+ embeddings = embed_documents(documents)
121
+ save_embeddings(embeddings, EMBEDDING_FILE)
OpenAIChat.py ADDED
@@ -0,0 +1,525 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio
3
+ import shutil
4
+ import json
5
+ import dotenv
6
+ import pickle
7
+ import itertools
8
+ from collections import Counter
9
+ from datetime import datetime
10
+ from huggingface_hub import HfApi, HfFolder
11
+ from openai import OpenAI as OpenAIClient
12
+ from pinecone import ServerlessSpec
13
+ from pinecone.grpc import PineconeGRPC as Pinecone
14
+ from transformers import BertTokenizerFast
15
+ from langchain.text_splitter import CharacterTextSplitter
16
+ from langchain_community.document_loaders import DirectoryLoader
17
+
18
+ '''
19
+ This file contains the code for user prompting of the language model.
20
+ The language model used is gpt 3.5 turbo and uses documents stored in Pinecone.
21
+ '''
22
+
23
+ # Load environment variables
24
+ dotenv.load_dotenv()
25
+ assert os.getenv("OPENAI_API_KEY") is not None, "Please set the OPENAI_API_KEY environment variable."
26
+ assert os.getenv("PINECONE_API_KEY") is not None, "Please set the PINECONE_API_KEY environment variable."
27
+ assert os.getenv("HUGGINGFACE_API_KEY") is not None, "Please set the HUGGINGFACE_API_KEY environment variable."
28
+
29
+ HfFolder.save_token(os.getenv("HUGGINGFACE_API_KEY"))
30
+
31
+ CHAT_HISTORY_FILE = "chat_history.pkl"
32
+ NEW_UPLOAD_DIRECTORY = "new_uploads/"
33
+ PREV_UPLOAD_DIRECTORY = "prev_uploads/"
34
+ DOC_CHUNK_SIZE = 1000
35
+ DOC_CHUNK_OVERLAP = 40
36
+ EMBEDDING_FILE = 'embeddings.json'
37
+ INDEX_NAME = "hybrid"
38
+ BATCH_SIZE = 100
39
+ INTERACTIONS_DATASET = "ryanRocks/FalconOpenAIInteractions"
40
+ FILES_DATASET = "ryanRocks/FalconOpenAIFiles"
41
+
42
+ # Ensure uploads directory exists
43
+ os.makedirs(NEW_UPLOAD_DIRECTORY, exist_ok=True)
44
+ os.makedirs(PREV_UPLOAD_DIRECTORY, exist_ok=True)
45
+
46
+ chat_history = []
47
+ chatbot_history = []
48
+
49
+ # Initialize Pinecone database
50
+ try:
51
+ pc = Pinecone(
52
+ api_key=os.getenv("PINECONE_API_KEY"),
53
+ pool_threads=30,
54
+ spec=ServerlessSpec(
55
+ cloud="aws",
56
+ region="us-east-1",
57
+ ),
58
+ )
59
+ print("Connected to Pinecone")
60
+ except Exception as e:
61
+ print(f"Error initializing Pinecone: {e}")
62
+ exit()
63
+
64
+ # Initialize index if it does not exist
65
+ existing_indexes = [index.name for index in pc.list_indexes().indexes]
66
+ if INDEX_NAME not in existing_indexes:
67
+ pc.create_index(
68
+ name=INDEX_NAME,
69
+ dimension=1536,
70
+ metric="dotproduct",
71
+ spec=ServerlessSpec(
72
+ cloud="aws",
73
+ region="us-east-1",
74
+ ),
75
+ )
76
+ print(f"Created index {INDEX_NAME}")
77
+ else:
78
+ print(f"Index {INDEX_NAME} already exists")
79
+
80
+
81
+ def initialize_chat_history():
82
+ '''
83
+ Initialize the chat history using the chat history pickle file.
84
+ '''
85
+ global chatbot_history
86
+ loaded_chat_history = []
87
+ if (os.path.exists(CHAT_HISTORY_FILE)):
88
+ with open(CHAT_HISTORY_FILE, "rb") as f:
89
+ loaded_chat_history = pickle.load(f)
90
+ else:
91
+ loaded_chat_history = []
92
+
93
+ for i in range(0, len(loaded_chat_history), 2):
94
+ chatbot_history.append((
95
+ loaded_chat_history[i]['content'],
96
+ loaded_chat_history[i+1]['content']
97
+ ))
98
+
99
+ async def upload_file(files):
100
+ '''
101
+ Upload files to Pinecone
102
+
103
+ Args:
104
+ files: List of file paths to process
105
+ '''
106
+ # Copy files to uploads directory for easier processing
107
+ for file in files:
108
+ file_path = os.path.join(NEW_UPLOAD_DIRECTORY, file.name.split('/')[-1])
109
+ shutil.move(file.name, file_path)
110
+
111
+ # Load documents
112
+ documents = read_documents()
113
+ dense_embeddings = dense_embed(documents)
114
+ sparse_embeddings = sparse_embed(documents)
115
+
116
+ #save_embeddings(dense_embeddings, EMBEDDING_FILE)
117
+
118
+ # Upsert embeddings into Pinecone
119
+ await upsert(dense_embeddings, sparse_embeddings)
120
+
121
+ # Move newly uploaded files to previous uploads directory
122
+ move_files()
123
+
124
+ return get_uploaded_files()
125
+
126
+ def read_documents():
127
+ '''
128
+ Load documents from a specified directory into a list
129
+
130
+ Args:
131
+ file_paths: List of file paths to load documents from
132
+ Returns:
133
+ documents: List of documents loaded from the directory, split by chunks
134
+ '''
135
+ # Load documents
136
+ print("Loading documents...")
137
+ documents = []
138
+
139
+ # Declare loaders for different file types
140
+ pdf_loader = DirectoryLoader(NEW_UPLOAD_DIRECTORY, glob="*.pdf")
141
+ docx_loader = DirectoryLoader(NEW_UPLOAD_DIRECTORY, glob="*.docx")
142
+ txt_loader = DirectoryLoader(NEW_UPLOAD_DIRECTORY, glob="*.txt")
143
+
144
+ for loader in [pdf_loader, docx_loader, txt_loader]:
145
+ # Load document
146
+ try:
147
+ # Error loading documents: Expected directory, got file: '/private/var/folders/sc/_5mj781j5315nzv10s8kvs1w0000gn/T/gradio/33a9766ee3f05c368d3c7fe56f6f2356e88a4348/YuYouChen Resume.pdf'
148
+ documents.extend(loader.load())
149
+ except Exception as e:
150
+ print(f"Error loading documents: {e}")
151
+
152
+ if (len(documents) == 0):
153
+ print("No documents loaded.")
154
+ return []
155
+
156
+ # Split documents into chunks
157
+ text_splitter = CharacterTextSplitter(chunk_size=DOC_CHUNK_SIZE, chunk_overlap=DOC_CHUNK_OVERLAP)
158
+ documents = text_splitter.split_documents(documents)
159
+
160
+ # Iterate to edit metadata to include chunk number
161
+ # format = {filename}_{chunk number}
162
+ chunk_num = 1
163
+ prev_doc_id = documents[0].metadata['source']
164
+ for chunk in documents:
165
+ if chunk.metadata['source'] != prev_doc_id:
166
+ chunk_num = 1
167
+ prev_doc_id = chunk.metadata['source']
168
+ chunk.metadata['source'] = f"{prev_doc_id}_{chunk_num}"
169
+ chunk_num += 1
170
+
171
+ print("Documents loaded")
172
+ return documents
173
+
174
+ def dense_embed(documents):
175
+ '''
176
+ Embed documents using OpenAIEmbeddings
177
+
178
+ Args:
179
+ documents: List of documents to embed
180
+
181
+ Returns:
182
+ List of JSON objects {doc_id, embeddings, metadata}
183
+ '''
184
+ print("Generating dense embeddings...")
185
+ # Use OpenAI to embed documents
186
+ client = OpenAIClient(
187
+ api_key=os.getenv("OPENAI_API_KEY")
188
+ )
189
+ embeddings = []
190
+
191
+ # Embed each chunk
192
+ for chunk in documents:
193
+ chunk_embeddings = client.embeddings.create(
194
+ model="text-embedding-3-small",
195
+ input=chunk.page_content
196
+ )
197
+ # Extract embeddings from response
198
+ chunk_embedding = [record.embedding for record in chunk_embeddings.data]
199
+ embeddings.append({
200
+ 'doc_id': chunk.metadata['source'].split('/')[-1],
201
+ 'embeddings': chunk_embedding[0],
202
+ 'metadata': {'source': chunk.metadata['source'], 'text': chunk.page_content}
203
+ })
204
+
205
+ print("Complete")
206
+ return embeddings
207
+
208
+ def sparse_embed(documents):
209
+ '''
210
+ Generate sparse embeddings for a list of documents
211
+
212
+ Args:
213
+ documents: List of documents to generate sparse embeddings for
214
+
215
+ Returns:
216
+ List of sparse embeddings in dictionary format
217
+ '''
218
+ print("Generating sparse embeddings...")
219
+ tokenizer = BertTokenizerFast.from_pretrained('bert-base-uncased')
220
+ sparse_embeds = []
221
+
222
+ for chunk in documents:
223
+ # Create batch of input_ids
224
+ inputs = tokenizer(
225
+ chunk.page_content,
226
+ padding=True,
227
+ truncation=True,
228
+ max_length=512,
229
+ add_special_tokens=False,
230
+ )['input_ids']
231
+
232
+ # Create sparse dictionaries
233
+ sparse_embed = build_dict(inputs)
234
+ sparse_embeds.append(sparse_embed)
235
+
236
+ print("Complete")
237
+ return sparse_embeds
238
+
239
+ def build_dict(input_batch):
240
+ '''
241
+ Build a dictionary for sparse embeddings
242
+
243
+ Args:
244
+ input_batch: List of embeddings to convert to a dictionary
245
+
246
+ Returns:
247
+ List of sparse embeddings in dictionary format
248
+ '''
249
+ sparse_emb = []
250
+
251
+ # Iterate through input batch
252
+ indices = []
253
+ values = []
254
+
255
+ # Convert the input_batch list to a dictionary of key to frequency values
256
+ freqs = dict(Counter(input_batch))
257
+ for idx in freqs:
258
+ indices.append(idx)
259
+ values.append(float(freqs[idx]))
260
+ sparse_emb.append({'indices': indices, 'values': values})
261
+
262
+ return sparse_emb
263
+
264
+ def save_embeddings(embeddings, filename):
265
+ '''
266
+ Save generated embedding to a json file
267
+
268
+ Args:
269
+ embeddings: List of embeddings to save
270
+ filename: Name of the file to save the embeddings
271
+ '''
272
+ print("Saving embedding...")
273
+ with open(filename, 'w') as file:
274
+ json.dump(embeddings, file)
275
+ print("Complete")
276
+
277
+ def chunks(iterable):
278
+ '''
279
+ Breaks vector list into chunks of BATCH_SIZE for parallel upserts
280
+
281
+ Args:
282
+ iterable: List of vectors to chunk
283
+ '''
284
+ print("Chunking")
285
+ it = iter(iterable)
286
+ chunk = tuple(itertools.islice(it, BATCH_SIZE))
287
+ while chunk:
288
+ yield chunk
289
+ chunk = tuple(itertools.islice(it, BATCH_SIZE))
290
+ print("Complete")
291
+
292
+ def vectorize(dense_embeddings, sparse_embeddings):
293
+ '''
294
+ Vectorize embeddings with document ids to prepare for insertion into Pinecone
295
+
296
+ Args:
297
+ embeddings: List of embeddings to vectorize
298
+
299
+ Returns:
300
+ List of vectors with tuples (chunk ids, embeddings)
301
+ '''
302
+ print("Vectorizing...")
303
+ vectors = []
304
+ for dense, sparse in zip(dense_embeddings, sparse_embeddings):
305
+ vectors.append({
306
+ 'id': dense['doc_id'],
307
+ 'values': dense['embeddings'],
308
+ 'sparse_values': sparse[0],
309
+ 'metadata': dense['metadata'],
310
+ })
311
+ print("Vectorized")
312
+ return vectors
313
+
314
+ async def upsert(dense_embeddings, sparse_embeddings):
315
+ '''
316
+ Upsert embeddings into pinecone
317
+ '''
318
+ index = pc.Index(INDEX_NAME)
319
+ vectors = vectorize(dense_embeddings, sparse_embeddings)
320
+
321
+ # Insert vectors into database in chunks
322
+ print("Upserting embeddings...")
323
+ vector_chunks = chunks(vectors)
324
+ for chunk in vector_chunks:
325
+ index.upsert(chunk)
326
+
327
+ print("Complete")
328
+
329
+ def move_files():
330
+ '''
331
+ Move uploaded files to the previous uploads directory
332
+ '''
333
+ print("Moving files...")
334
+ api = HfApi()
335
+ for file in os.listdir(NEW_UPLOAD_DIRECTORY):
336
+ file_path = os.path.join(NEW_UPLOAD_DIRECTORY, file)
337
+ if (os.path.isfile(file_path)):
338
+ # Upload file to HuggingFace Datasets
339
+ api.upload_file(
340
+ path_or_fileobj = file_path,
341
+ path_in_repo = file,
342
+ repo_id = "ryanRocks/FalconOpenAIFiles",
343
+ repo_type = "dataset",
344
+ )
345
+ # Move file to previous uploads directory
346
+ new_file_path = os.path.join(PREV_UPLOAD_DIRECTORY, file)
347
+ shutil.move(file_path, new_file_path)
348
+
349
+ def hybrid_scale(dense, sparse, alpha):
350
+ print("Hybrid scaling...")
351
+ # Check alpha value in range 0 to 1
352
+ if alpha < 0 or alpha > 1:
353
+ raise ValueError("Alpha must be between 0 and 1")
354
+
355
+ # Scale dense and sparse vectors to create hybrid search vectors
356
+ hdense = [v * alpha for v in dense]
357
+ hsparse = {
358
+ 'indices': sparse['indices'],
359
+ 'values': [v * (1 - alpha) for v in sparse['values']],
360
+ }
361
+ print("Complete")
362
+ return hdense, hsparse
363
+
364
+ def hybrid_query(question, top_k, alpha):
365
+ try:
366
+ print("Hybrid querying...")
367
+
368
+ # Convert the question into a dense vector
369
+ print("Converting question to dense vector...")
370
+ client = OpenAIClient(
371
+ api_key=os.getenv("OPENAI_API_KEY")
372
+ )
373
+ query_embedding = client.embeddings.create(
374
+ model="text-embedding-3-small",
375
+ input=question,
376
+ )
377
+ dense_vec = [record.embedding for record in query_embedding.data][0]
378
+ print("Complete")
379
+
380
+ # Convert the question into a sparse vector
381
+ print("Converting question to sparse vector...")
382
+ tokenizer = BertTokenizerFast.from_pretrained('bert-base-uncased')
383
+ inputs = tokenizer(
384
+ question,
385
+ padding=True,
386
+ truncation=True,
387
+ max_length=512,
388
+ add_special_tokens=False,
389
+ )['input_ids']
390
+ sparse_vec = build_dict(inputs)[0]
391
+ print("Complete")
392
+
393
+ # Scale alpha with hybrid_scale
394
+ dense_vec, sparse_vec = hybrid_scale(
395
+ dense_vec, sparse_vec, alpha
396
+ )
397
+
398
+ # Query pinecone with the query parameters
399
+ print("Querying Pinecone...")
400
+ index = pc.Index(INDEX_NAME)
401
+ result = index.query(
402
+ vector=dense_vec,
403
+ sparse_vector=sparse_vec,
404
+ top_k=top_k,
405
+ include_values=True,
406
+ include_metadata=True,
407
+ )
408
+ print("Complete")
409
+
410
+ # Return search results as json
411
+ return result
412
+ except Exception as e:
413
+ print(f"Error querying Pinecone: {e}")
414
+
415
+ def prompt(question, history):
416
+ '''
417
+ Prompt the language model with user input
418
+
419
+ Args:
420
+ question: User string input to prompt the language model
421
+ Returns:
422
+ Language model response to the user
423
+ '''
424
+
425
+ global chatbot_history
426
+ global chat_history
427
+
428
+ # Handle clearing history
429
+ if len(history) == 0:
430
+ chatbot_history = []
431
+ chat_history = []
432
+ with open(CHAT_HISTORY_FILE, "wb") as f:
433
+ pickle.dump(chat_history, f)
434
+
435
+ # Check for API key
436
+ if (os.getenv("OPENAI_API_KEY") is None):
437
+ return "Please set the OPENAI_API_KEY environment variable."
438
+
439
+ # Query database and prompt the language model with results
440
+ try:
441
+ # Query database for context
442
+ results = hybrid_query(question, top_k=5, alpha=0.4)
443
+ context = ""
444
+ for match in results['matches']:
445
+ context += match['metadata']['text'] + "\n"
446
+
447
+ client = OpenAIClient()
448
+
449
+ # Prepare prompt with chat history
450
+ prompt = f"Context:\n{context}\n\nQuestion: {question}\nAnswer:"
451
+ messages = [{"role": "system", "content": "You are a helpful assistant."}]
452
+ messages.extend(chat_history)
453
+ messages.append({"role": "user", "content": prompt})
454
+
455
+ time = datetime.now().isoformat()
456
+ print("Prompting language model...")
457
+ response = client.chat.completions.create(
458
+ messages=messages,
459
+ model="gpt-3.5-turbo",
460
+ )
461
+
462
+ # Extract answer from response
463
+ answer = response.choices[0].message.content.strip()
464
+
465
+ interaction = [
466
+ {"timestamp": time},
467
+ {"role": "user", "content": question},
468
+ {"role": "assistant", "content": answer},
469
+ {"full_prompt": messages},
470
+ ]
471
+
472
+ with open(f"{time}.json", "w") as f:
473
+ json.dump(interaction, f)
474
+
475
+ # Upload interaction to HuggingFace Datasets
476
+ api = HfApi()
477
+ api.upload_file(
478
+ path_or_fileobj = f"{time}.json",
479
+ path_in_repo = f"{time}.json",
480
+ repo_id = INTERACTIONS_DATASET,
481
+ repo_type = "dataset",
482
+ )
483
+
484
+ # Save chat history
485
+ chat_history.extend([
486
+ {"role": "user", "content": question},
487
+ {"role": "assistant", "content": answer},
488
+ ])
489
+
490
+ with open(CHAT_HISTORY_FILE, "wb") as f:
491
+ pickle.dump(chat_history, f)
492
+
493
+ return answer
494
+
495
+ # Handle exceptions
496
+ except Exception as e:
497
+ return "Error: " + str(e)
498
+
499
+ def get_uploaded_files():
500
+ '''
501
+ Get uploaded files in prev_uploads directory
502
+ '''
503
+ uploaded_files = []
504
+
505
+ for file in os.listdir(PREV_UPLOAD_DIRECTORY):
506
+ file_path = os.path.join(PREV_UPLOAD_DIRECTORY, file)
507
+ if (os.path.isfile(file_path)):
508
+ uploaded_files.append(file_path)
509
+ return uploaded_files
510
+
511
+ # Create a Gradio interface
512
+ with gradio.Blocks() as demo:
513
+ # Load chat history
514
+ initialize_chat_history()
515
+
516
+ # Create chatbot interface
517
+ chatbot = gradio.Chatbot(value=chat_history, placeholder="What would you like to know?")
518
+ gradio.ChatInterface(fn=prompt, chatbot=chatbot)
519
+
520
+ # Create file upload interface
521
+ file_output = gradio.File(value=get_uploaded_files())
522
+ upload_button = gradio.UploadButton("Click to upload a file", file_types=["pdf, docx, txt"], file_count="multiple")
523
+ upload_button.upload(upload_file, upload_button, file_output)
524
+
525
+ demo.launch()
README.Docker.md ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ### Building and running your application
2
+
3
+ When you're ready, start your application by running:
4
+ `docker compose up --build`.
5
+
6
+ Your application will be available at http://localhost:8000.
7
+
8
+ ### Deploying your application to the cloud
9
+
10
+ First, build your image, e.g.: `docker build -t myapp .`.
11
+ If your cloud uses a different CPU architecture than your development
12
+ machine (e.g., you are on a Mac M1 and your cloud provider is amd64),
13
+ you'll want to build the image for that platform, e.g.:
14
+ `docker build --platform=linux/amd64 -t myapp .`.
15
+
16
+ Then, push it to your registry, e.g. `docker push myregistry.com/myapp`.
17
+
18
+ Consult Docker's [getting started](https://docs.docker.com/go/get-started-sharing/)
19
+ docs for more detail on building and pushing.
20
+
21
+ ### References
22
+ * [Docker's Python guide](https://docs.docker.com/language/python/)
README.md CHANGED
@@ -1,12 +1,6 @@
1
  ---
2
  title: FalconOpenAI
3
- emoji: 👀
4
- colorFrom: red
5
- colorTo: blue
6
  sdk: gradio
7
- sdk_version: 4.40.0
8
- app_file: app.py
9
- pinned: false
10
  ---
11
-
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
  title: FalconOpenAI
3
+ app_file: OpenAIChat.py
 
 
4
  sdk: gradio
5
+ sdk_version: 4.38.1
 
 
6
  ---
 
 
__pycache__/OpenAIUpsert.cpython-312.pyc ADDED
Binary file (3.1 kB). View file
 
__pycache__/utils.cpython-311.pyc ADDED
Binary file (1.08 kB). View file
 
__pycache__/utils.cpython-312.pyc ADDED
Binary file (946 Bytes). View file
 
compose.yaml ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Comments are provided throughout this file to help you get started.
2
+ # If you need more help, visit the Docker Compose reference guide at
3
+ # https://docs.docker.com/go/compose-spec-reference/
4
+
5
+ # Here the instructions define your application as a service called "server".
6
+ # This service is built from the Dockerfile in the current directory.
7
+ # You can add other services your application may depend on here, such as a
8
+ # database or a cache. For examples, see the Awesome Compose repository:
9
+ # https://github.com/docker/awesome-compose
10
+ services:
11
+ server:
12
+ build:
13
+ context: .
14
+ ports:
15
+ - 7860:7860
16
+ env_file:
17
+ - .env
18
+ image: ryanyyc/project-falcon:openai
19
+
20
+ # The commented out section below is an example of how to define a PostgreSQL
21
+ # database that your application can use. `depends_on` tells Docker Compose to
22
+ # start the database before your application. The `db-data` volume persists the
23
+ # database data between container restarts. The `db-password` secret is used
24
+ # to set the database password. You must create `db/password.txt` and add
25
+ # a password of your choosing to it before running `docker compose up`.
26
+ # depends_on:
27
+ # db:
28
+ # condition: service_healthy
29
+ # db:
30
+ # image: postgres
31
+ # restart: always
32
+ # user: postgres
33
+ # secrets:
34
+ # - db-password
35
+ # volumes:
36
+ # - db-data:/var/lib/postgresql/data
37
+ # environment:
38
+ # - POSTGRES_DB=example
39
+ # - POSTGRES_PASSWORD_FILE=/run/secrets/db-password
40
+ # expose:
41
+ # - 5432
42
+ # healthcheck:
43
+ # test: [ "CMD", "pg_isready" ]
44
+ # interval: 10s
45
+ # timeout: 5s
46
+ # retries: 5
47
+ # volumes:
48
+ # db-data:
49
+ # secrets:
50
+ # db-password:
51
+ # file: db/password.txt
52
+
requirements.txt ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ aiohttp==3.9.5
3
+ aiosignal==1.3.1
4
+ altair==5.3.0
5
+ annotated-types==0.7.0
6
+ antlr4-python3-runtime==4.9.3
7
+ anyio==4.4.0
8
+ attrs==23.2.0
9
+ backoff==2.2.1
10
+ beautifulsoup4==4.12.3
11
+ blinker==1.8.2
12
+ cachetools==5.4.0
13
+ certifi==2024.7.4
14
+ cffi==1.16.0
15
+ chardet==5.2.0
16
+ charset-normalizer==3.3.2
17
+ click==8.1.7
18
+ coloredlogs==15.0.1
19
+ contourpy==1.2.1
20
+ cryptography==43.0.0
21
+ cycler==0.12.1
22
+ dataclasses-json==0.6.7
23
+ datasets==2.20.0
24
+ deepdiff==7.0.1
25
+ Deprecated==1.2.14
26
+ dill==0.3.8
27
+ distro==1.9.0
28
+ dnspython==2.6.1
29
+ effdet==0.4.1
30
+ email_validator==2.2.0
31
+ emoji==2.12.1
32
+ et-xmlfile==1.1.0
33
+ fastapi==0.111.0
34
+ fastapi-cli==0.0.4
35
+ ffmpy==0.3.2
36
+ filelock==3.15.4
37
+ filetype==1.2.0
38
+ Flask==3.0.3
39
+ flatbuffers==24.3.25
40
+ fonttools==4.53.1
41
+ frozenlist==1.4.1
42
+ fsspec==2024.5.0
43
+ google-api-core==2.19.1
44
+ google-auth==2.32.0
45
+ google-cloud-vision==3.7.3
46
+ googleapis-common-protos==1.63.2
47
+ gradio==4.38.1
48
+ gradio_client==1.1.0
49
+ grpc-gateway-protoc-gen-openapiv2==0.1.0
50
+ grpcio==1.65.1
51
+ h11==0.14.0
52
+ httpcore==1.0.5
53
+ httptools==0.6.1
54
+ httpx==0.27.0
55
+ huggingface-hub==0.23.4
56
+ humanfriendly==10.0
57
+ idna==3.7
58
+ importlib_resources==6.4.0
59
+ iopath==0.1.10
60
+ itsdangerous==2.2.0
61
+ Jinja2==3.1.4
62
+ joblib==1.4.2
63
+ jsonpatch==1.33
64
+ jsonpath-python==1.0.6
65
+ jsonpointer==3.0.0
66
+ jsonschema==4.23.0
67
+ jsonschema-specifications==2023.12.1
68
+ kiwisolver==1.4.5
69
+ langchain==0.2.7
70
+ langchain-community==0.2.7
71
+ langchain-core==0.2.17
72
+ langchain-openai==0.1.16
73
+ langchain-pinecone==0.1.1
74
+ langchain-text-splitters==0.2.2
75
+ langdetect==1.0.9
76
+ langsmith==0.1.85
77
+ layoutparser==0.3.4
78
+ libmagic==1.0
79
+ lxml==5.2.2
80
+ lz4==4.3.3
81
+ Markdown==3.6
82
+ markdown-it-py==3.0.0
83
+ MarkupSafe==2.1.5
84
+ marshmallow==3.21.3
85
+ matplotlib==3.9.1
86
+ mdurl==0.1.2
87
+ mpmath==1.3.0
88
+ multidict==6.0.5
89
+ multiprocess==0.70.16
90
+ mypy-extensions==1.0.0
91
+ nest-asyncio==1.6.0
92
+ networkx==3.3
93
+ nltk==3.8.1
94
+ numpy==1.26.4
95
+ olefile==0.47
96
+ omegaconf==2.3.0
97
+ onnx==1.16.1
98
+ onnxruntime==1.18.1
99
+ openai==1.35.13
100
+ opencv-python==4.10.0.84
101
+ openpyxl==3.1.5
102
+ ordered-set==4.1.0
103
+ orjson==3.10.6
104
+ packaging==24.1
105
+ pandas==2.2.2
106
+ pdf2image==1.17.0
107
+ pdfminer.six==20231228
108
+ pdfplumber==0.11.2
109
+ pikepdf==9.0.0
110
+ pillow==10.4.0
111
+ pillow_heif==0.17.0
112
+ pinecone==4.0.0
113
+ pinecone-client==3.2.2
114
+ portalocker==2.10.1
115
+ proto-plus==1.24.0
116
+ protobuf==3.20.3
117
+ psutil==6.0.0
118
+ pyarrow==17.0.0
119
+ pyarrow-hotfix==0.6
120
+ pyasn1==0.6.0
121
+ pyasn1_modules==0.4.0
122
+ pycocotools==2.0.8
123
+ pycparser==2.22
124
+ pydantic==2.8.2
125
+ pydantic_core==2.20.1
126
+ pydub==0.25.1
127
+ Pygments==2.18.0
128
+ pypandoc==1.13
129
+ pyparsing==3.1.2
130
+ pypdf==4.3.1
131
+ pypdfium2==4.30.0
132
+ pytesseract==0.3.10
133
+ python-dateutil==2.9.0.post0
134
+ python-docx==1.1.2
135
+ python-dotenv==1.0.1
136
+ python-iso639==2024.4.27
137
+ python-magic==0.4.27
138
+ python-multipart==0.0.9
139
+ python-oxmsg==0.0.1
140
+ python-pptx==0.6.23
141
+ pytz==2024.1
142
+ PyYAML==6.0.1
143
+ rapidfuzz==3.9.4
144
+ referencing==0.35.1
145
+ regex==2024.5.15
146
+ requests==2.32.3
147
+ requests-toolbelt==1.0.0
148
+ rich==13.7.1
149
+ rpds-py==0.19.0
150
+ rsa==4.9
151
+ ruff==0.5.1
152
+ safetensors==0.4.3
153
+ scipy==1.14.0
154
+ semantic-version==2.10.0
155
+ shellingham==1.5.4
156
+ six==1.16.0
157
+ sniffio==1.3.1
158
+ soupsieve==2.5
159
+ SQLAlchemy==2.0.31
160
+ starlette==0.37.2
161
+ sympy==1.13.1
162
+ tabulate==0.9.0
163
+ tenacity==8.5.0
164
+ tesseract==0.1.3
165
+ tiktoken==0.7.0
166
+ timm==1.0.7
167
+ tokenizers==0.19.1
168
+ tomlkit==0.12.0
169
+ toolz==0.12.1
170
+ torch==2.3.1
171
+ torchvision==0.18.1
172
+ tqdm==4.66.4
173
+ transformers==4.42.4
174
+ typer==0.12.3
175
+ typing-inspect==0.9.0
176
+ typing_extensions==4.12.2
177
+ tzdata==2024.1
178
+ ujson==5.10.0
179
+ unstructured==0.15.0
180
+ unstructured-client==0.24.1
181
+ unstructured-inference==0.7.36
182
+ unstructured.pytesseract==0.3.12
183
+ urllib3==2.2.2
184
+ uvicorn==0.30.1
185
+ uvloop==0.19.0
186
+ watchfiles==0.22.0
187
+ websockets==11.0.3
188
+ Werkzeug==3.0.3
189
+ wrapt==1.16.0
190
+ xlrd==2.0.1
191
+ XlsxWriter==3.2.0
192
+ xxhash==3.4.1
193
+ yarl==1.9.4
utils.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ def load_embeddings(filename):
4
+ '''
5
+ Load embeddings from specified json file
6
+
7
+ Args:
8
+ filename: Name of the json file to load embeddings from
9
+
10
+ Returns:
11
+ List of embeddings loaded from the file
12
+ '''
13
+ print("Loading embeddings...")
14
+ with open(filename, 'r') as file:
15
+ embeddings = json.load(file)
16
+ return embeddings
17
+
18
+ DOC_CHUNK_SIZE = 1000
19
+ DOC_CHUNK_OVERLAP = 40
20
+ DOC_DIRECTORY = './'
21
+ EMBEDDING_FILE = 'embeddings.json'
22
+ BATCH_SIZE = 100
23
+ INDEX_NAME = "project-falcon"