Initial commit
@@ -0,0 +1,5 @@
|
||||
.venv
|
||||
.env
|
||||
tweets.json
|
||||
fewertweets.json
|
||||
__pycache__
|
||||
@@ -0,0 +1,26 @@
|
||||
## This script imports the tinytweets.json file into your Cosmos database
|
||||
## It will work for any json file containing a single array of objects
|
||||
## There's nothing specific to llamaindex going on here
|
||||
## You can get your data into mongo any way you like.
|
||||
|
||||
json_file = 'tweets.json'
|
||||
|
||||
# Load environment variables from local .env file
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
import os
|
||||
import json
|
||||
from pymongo.mongo_client import MongoClient
|
||||
|
||||
# Load the tweets from a local file
|
||||
with open(json_file, 'r') as f:
|
||||
tweets = json.load(f)
|
||||
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv('MONGODB_URI'))
|
||||
db = client[os.getenv("MONGODB_DATABASE")]
|
||||
collection = db[os.getenv("MONGODB_COLLECTION")]
|
||||
|
||||
# Insert the tweets into mongo
|
||||
collection.insert_many(tweets)
|
||||
@@ -0,0 +1,53 @@
|
||||
## This script loads data from a mongo database into an index
|
||||
## This will convert all the documents in the database into vectors
|
||||
## which requires a call to OpenAI for each one, so it can take some time.
|
||||
## Once the data is indexed, it will be stored as a new collection in mongodb
|
||||
## and you can query it without having to re-index every time.
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
# This will turn on really noisy logging if you want it, but it will slow things down
|
||||
# import logging
|
||||
# import sys
|
||||
# logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
||||
# logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
||||
|
||||
import os
|
||||
from llama_index.readers.mongo import SimpleMongoReader
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from llama_index.vector_stores.azurecosmosmongo import AzureCosmosDBMongoDBVectorSearch
|
||||
from llama_index.indices.vector_store.base import VectorStoreIndex
|
||||
from llama_index.storage.storage_context import StorageContext
|
||||
|
||||
# load objects from mongo and convert them into LlamaIndex Document objects
|
||||
# llamaindex has a special class that does this for you
|
||||
# it pulls every object in a given collection
|
||||
query_dict = {}
|
||||
reader = SimpleMongoReader(uri=os.getenv("MONGODB_URI"))
|
||||
documents = reader.load_data(
|
||||
os.getenv("MONGODB_DATABASE"),
|
||||
os.getenv("MONGODB_COLLECTION"), # this is the collection where the objects you loaded in 1_import got stored
|
||||
field_names=["full_text"], # these is a list of the top-level fields in your objects that will be indexed
|
||||
# make sure your objects have a field called "full_text" or that you change this value
|
||||
query_dict=query_dict # this is a mongo query dict that will filter your data if you don't want to index everything
|
||||
)
|
||||
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv("MONGODB_URI"))
|
||||
|
||||
# create Atlas as a vector store
|
||||
store = AzureCosmosDBMongoDBVectorSearch(
|
||||
client,
|
||||
db_name=os.getenv('MONGODB_DATABASE'),
|
||||
collection_name=os.getenv('MONGODB_VECTORS'), # this is where your embeddings will be stored
|
||||
index_name=os.getenv('MONGODB_VECTOR_INDEX') # this is the name of the index you will need to create
|
||||
)
|
||||
|
||||
# now create an index from all the Documents and store them in Atlas
|
||||
storage_context = StorageContext.from_defaults(vector_store=store)
|
||||
index = VectorStoreIndex.from_documents(
|
||||
documents, storage_context=storage_context,
|
||||
show_progress=True, # this will show you a progress bar as the embeddings are created
|
||||
)
|
||||
|
||||
# you can't query your index yet because you need to create a vector search index in mongodb's UI now
|
||||
@@ -0,0 +1,35 @@
|
||||
## This shows how to load your pre-indexed data from mongo and query it
|
||||
## Note that you MUST manually create a vector search index before this will work
|
||||
## and you must pass in the name of that index when connecting to Mongodb below
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
# Turns on really noisy logging
|
||||
import logging
|
||||
import sys
|
||||
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
||||
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
||||
|
||||
import os
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from llama_index.vector_stores.azurecosmosmongo import AzureCosmosDBMongoDBVectorSearch
|
||||
from llama_index.indices.vector_store.base import VectorStoreIndex
|
||||
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv("MONGODB_URI"))
|
||||
|
||||
# connect to Atlas as a vector store
|
||||
store = AzureCosmosDBMongoDBVectorSearch(
|
||||
client,
|
||||
db_name=os.getenv('MONGODB_DATABASE'), # this is the database where you stored your embeddings
|
||||
collection_name=os.getenv('MONGODB_VECTORS'), # this is where your embeddings were stored in 2_load_and_index.py
|
||||
index_name=os.getenv('MONGODB_VECTOR_INDEX') # this is the name of the index you created after loading your data
|
||||
)
|
||||
index = VectorStoreIndex.from_vector_store(store)
|
||||
|
||||
# query your data!
|
||||
# here we have customized the number of documents returned per query to 20, because tweets are really short
|
||||
query_engine = index.as_query_engine(similarity_top_k=20)
|
||||
response = query_engine.query("What does the author think of web frameworks?")
|
||||
print(response)
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
# LlamaIndex retrieval augmented generation
|
||||
## with MongoDB, Flask and Next.js
|
||||
|
||||
See this demo [in action](https://mongodb-demo-frontend.onrender.com/)!
|
||||
|
||||
## What is this?
|
||||
|
||||
LlamaIndex is an open-source framework that lets you build AI applications powered by large language models (LLMs) like OpenAI's GPT-4. This application is a demonstration of how to do that, starting from scratch to a fully deployed web application. We'll show you how to run everything in this repo and then start customizing it for your own needs.
|
||||
|
||||
In this example, we'll be using MongoDB as a data store and a vector store. Our back end will be a Python API powered by Flask, and our front end will be a JavaScript web app written in Next.js.
|
||||
|
||||
The app will load a series of tweets (loaded from a Twitter archive export) and then index them to answer questions about the author and their opinions.
|
||||
|
||||
## What we'll be doing
|
||||
|
||||
The basic steps of this demo are:
|
||||
* Get data from a JSON file into a Mongo database (this step is optional if you already have data in Mongo)
|
||||
* Index the data using LlamaIndex. This will use OpenAI's gpt-3.5-turbo under the hood and convert your text into [vector embeddings](https://docs.llamaindex.ai/en/stable/understanding/indexing/indexing.html#what-is-an-embedding), so you'll need an OpenAI API key, and it can take some time depending how much data you have
|
||||
* Store the embedded data back into MongoDB. LlamaIndex will do this for you automatically.
|
||||
* Create a Vector Search Index in MongoDB. This is a manual step you'll need to perform in the MongoDB UI.
|
||||
* Query the data! This will demonstrate that the data is now queryable. Then you'll want to build an app on top of it.
|
||||
* Set up a Flask API in Python to answer questions about the data, hosted on [Render](https://render.com).
|
||||
* Set up a Next.js front-end in JavaScript, also hosted on Render. This will accept user questions, pass them to the API, and display the results.
|
||||
|
||||
## Instructions
|
||||
|
||||
You can either use these instructions as a tutorial and rebuild the application from scratch, or clone the repo and use it as a template.
|
||||
|
||||
### Before you begin
|
||||
|
||||
We'll assume you have the current version of Python installed (3.11.6 or better), as well as Node.js for the front-end (version 20 or better) and git for source control.
|
||||
|
||||
### Get the code
|
||||
|
||||
First clone this repo
|
||||
|
||||
```
|
||||
git clone git@github.com:run-llama/mongodb-demo.git
|
||||
```
|
||||
|
||||
### Sign up for MongoDB Atlas
|
||||
|
||||
We'll be using MongoDB's hosted database service, [MongoDB Atlas](https://www.mongodb.com/cloud/atlas/register). You can sign up for free and get a small hosted cluster for free:
|
||||
|
||||

|
||||
|
||||
The signup process will walk you through the process of creating your cluster and ensuring it's configured for you to access. Once the cluster is created, choose "Connect" and then "Connect to your application". Choose Python, and you'll be presented with a connection string that looks like this:
|
||||
|
||||

|
||||
|
||||
### Set up environment variables
|
||||
|
||||
Copy the connection string (make sure you include your password) and put it into a file called `.env` in the root of this repo. It should look like this:
|
||||
|
||||
```
|
||||
MONGODB_URI=mongodb+srv://seldo:xxxxxxxxxxx@llamaindexdemocluster.xfrdhpz.mongodb.net/?retryWrites=true&w=majority
|
||||
```
|
||||
|
||||
You will also need to choose a name for your database, and the collection where we will store the tweets, and also include them in .env. They can be any string, but this is what we used:
|
||||
|
||||
```
|
||||
MONGODB_DATABASE=tiny_tweets_db
|
||||
MONGODB_COLLECTION=tiny_tweets_collection
|
||||
```
|
||||
|
||||
### Set up a python virtual environment and install dependencies
|
||||
|
||||
To avoid colliding with other Python dependencies, it's a good idea to create a python virtual environment to work in. There are lots of ways to do this, but the way we did it is to run this in the root of the repo:
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
```
|
||||
|
||||
Now we'll install all the dependencies we need in one go with pip:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
This installs the MongoDB drivers, LlamaIndex itself, and some utility libraries.
|
||||
|
||||
### Import tweets into MongoDB
|
||||
|
||||
You are now ready to import our ready-made data set into Mongo. This is the file `tinytweets.json`, a selection of approximately 1000 tweets from @seldo on Twitter in mid-2019. With your environment set up you can do this by running
|
||||
|
||||
```
|
||||
python 1_import.py
|
||||
```
|
||||
|
||||
If you're curious, the code is below. If you don't want to use tweets, you can replace `json_file` with any other array of JSON objects, but you will need to modify some code later to make sure the correct field gets indexed. There is no LlamaIndex-specific code here; you can load your data into Mongo any way you want to.
|
||||
|
||||
```python
|
||||
json_file = 'tinytweets.json'
|
||||
|
||||
# Load environment variables from local .env file
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
import os
|
||||
import json
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.server_api import ServerApi
|
||||
|
||||
# Load the tweets from a local file
|
||||
with open(json_file, 'r') as f:
|
||||
tweets = json.load(f)
|
||||
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv('MONGODB_URI'), server_api=ServerApi('1'))
|
||||
db = client[os.getenv("MONGODB_DATABASE")]
|
||||
collection = db[os.getenv("MONGODB_COLLECTION")]
|
||||
|
||||
# Insert the tweets into mongo
|
||||
collection.insert_many(tweets)
|
||||
```
|
||||
|
||||
### Load and index your data
|
||||
|
||||
Now we're ready to index our data. To do this, LlamaIndex will pull your text out of Mongo, split it into chunks, and then send those chunks to OpenAI to be turned into [vector embeddings](https://docs.llamaindex.ai/en/stable/understanding/indexing/indexing.html#what-is-an-embedding). The embeddings will then be stored in a new collection in Mongo. This will take a while depending how much text you have, but the good news is that once it's done you will be able to query quickly without needing to re-index.
|
||||
|
||||
We'll be using OpenAI to do the embedding, so now is when you need to [generate an OpenAI API key](https://platform.openai.com/account/api-keys) if you haven't already and add it to your `.env` file like this:
|
||||
|
||||
```
|
||||
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
You'll also need to pick a name for the new collection where the embeddings will be stored, and add it to `.env`, along with the name of a vector search index (we'll be creating this in the next step, after you've indexed your data):
|
||||
|
||||
```
|
||||
MONGODB_VECTORS=tiny_tweets_vectors
|
||||
MONGODB_VECTOR_INDEX=tiny_tweets_vector_index
|
||||
```
|
||||
|
||||
If the data you're indexing is the tweets we gave you, you're ready to go:
|
||||
|
||||
```bash
|
||||
python 2_load_and_index.py
|
||||
```
|
||||
|
||||
You can view the full source code of this script, but let's highlight a few important parts:
|
||||
|
||||
```python
|
||||
query_dict = {}
|
||||
reader = SimpleMongoReader(uri=os.getenv("MONGODB_URI"))
|
||||
documents = reader.load_data(
|
||||
os.getenv("MONGODB_DATABASE"),
|
||||
os.getenv("MONGODB_COLLECTION"),
|
||||
field_names=["full_text"],
|
||||
query_dict=query_dict
|
||||
)
|
||||
```
|
||||
|
||||
What you're doing here is creating a Reader which loads the data out of Mongo in the collection and database specified. It looks for text in a set of specific keys in each object. In this case we've given it just one key, "full_text". The final parameter is a mongo [query document](https://www.mongodb.com/docs/manual/tutorial/query-documents/), a JSON object you can use to filter your objects down to a subset. We're leaving it empty because we want all the tweets in the collection.
|
||||
|
||||
```python
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv("MONGODB_URI"), server_api=ServerApi('1'))
|
||||
|
||||
# create Atlas as a vector store
|
||||
store = MongoDBAtlasVectorSearch(
|
||||
client,
|
||||
db_name=os.getenv('MONGODB_DATABASE'),
|
||||
collection_name=os.getenv('MONGODB_VECTORS'),
|
||||
index_name=os.getenv('MONGODB_VECTOR_INDEX')
|
||||
)
|
||||
```
|
||||
|
||||
Now you're creating a vector search client for Mongo. In addition to a MongoDB client object, you again tell it what database everything is in. This time you give it the name of the collection where you'll store the vector embeddings, and the name of the vector search index you'll create in the next step.
|
||||
|
||||
This process can take a while, so when we kick it off we set the `show_progress` parameter to `True`, which prints a convenient little progress bar:
|
||||
|
||||
```python
|
||||
storage_context = StorageContext.from_defaults(vector_store=store)
|
||||
index = VectorStoreIndex.from_documents(
|
||||
documents, storage_context=storage_context,
|
||||
show_progress=True
|
||||
)
|
||||
```
|
||||
|
||||
### Create a vector search index
|
||||
|
||||
Now if all has gone well you should be able to log in to the Mongo Atlas UI and see two collections in your database: the original data in `tiny_tweets_collection`, and the vector embeddings in `tiny_tweets_vectors`.
|
||||
|
||||

|
||||
|
||||
Now it's time to create the vector search index so that you can query the data. First, click the Search tab, and then click "Create Search Index":
|
||||
|
||||

|
||||
|
||||
It's not yet possible to create a vector search index using the Visual Editor, so select JSON editor:
|
||||
|
||||

|
||||
|
||||
Now under "database and collection" select `tiny_tweets_db` and within that select `tiny_tweets_vectors`. Then under "Index name" enter `tiny_tweets_vector_index` (or whatever value you put for MONGODB_VECTOR_INDEX in `.env`). Under that, you'll want to enter this JSON object:
|
||||
|
||||
```json
|
||||
{
|
||||
"mappings": {
|
||||
"dynamic": true,
|
||||
"fields": {
|
||||
"embedding": {
|
||||
"dimensions": 1536,
|
||||
"similarity": "cosine",
|
||||
"type": "knnVector"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This tells Mongo that the `embedding` field in each document (in the `tiny_tweets_vectors` collection) is a vector of 1536 dimensions (this is the size of embeddings used by OpenAI), and that we want to use cosine similarity to compare vectors. You don't need to worry too much about these values unless you want to use a different LLM to OpenAI entirely.
|
||||
|
||||
The UI will ask you to review and confirm your choices, then you need to wait a minute or two while it generates the index. If all goes well, you should see something like this screen:
|
||||
|
||||

|
||||
|
||||
Now you're ready to query your data!
|
||||
|
||||
### Run a test query
|
||||
|
||||
You can do this by running
|
||||
|
||||
```bash
|
||||
python 3_query.py
|
||||
```
|
||||
|
||||
This sets up a connection to Atlas just like `2_load_and_index.py` did, then it creates a [query engine](https://docs.llamaindex.ai/en/stable/understanding/querying/querying.html#getting-started) and runs a query against it:
|
||||
|
||||
```python
|
||||
query_engine = index.as_query_engine(similarity_top_k=20)
|
||||
response = query_engine.query("What does the author think of web frameworks?")
|
||||
print(response)
|
||||
```
|
||||
|
||||
If all is well, you should get a nuanced opinion about web frameworks.
|
||||
|
||||
### Set up a new repo
|
||||
|
||||
Now we have a way to quickly query our data using an LLM. But we want an app! To do that, we're going to set up a Python Flash API as a backend and a JavaScript Next.js app as a front-end. We're going to deploy both of them to [Render](https://render.com), and to do that we need them to be in a GitHub repo. So let's do that:
|
||||
|
||||
1. Create a new public GitHub repository
|
||||
2. Clone it to your local machine
|
||||
3. Copy all the files from this repo to the new repo (make sure you don't include the `.git` folder)
|
||||
4. Commit and push the files to GitHub
|
||||
|
||||
For the rest of this tutorial we're going to assume you're working in the folder you just created, attached to a repo you control.
|
||||
|
||||
### Run the Flask API
|
||||
|
||||
The details of creating a Flask app are out of scope for this tutorial, but you can find one already set up for you in `flask_app` in the repo. It sets up a Mongo Atlas client just like we did in `3_query.py`, and it has one real method, `process_form`, which accepts a `query` parameter:
|
||||
|
||||
```python
|
||||
@app.route('/process_form', methods=['POST'])
|
||||
@cross_origin()
|
||||
def process_form():
|
||||
query = request.form.get('query')
|
||||
if query is not None:
|
||||
# here we have customized the number of documents returned per query to 20, because tweets are really short
|
||||
query_engine = index.as_query_engine(similarity_top_k=20)
|
||||
response = query_engine.query(query)
|
||||
return jsonify({"response": str(response)})
|
||||
else:
|
||||
return jsonify({"error": "query field is missing"}), 400
|
||||
```
|
||||
|
||||
(The `@cross_origin()` decorator is necessary to allow the front-end to make requests to the API.)
|
||||
|
||||
You can run it locally by running
|
||||
|
||||
```bash
|
||||
flask run
|
||||
```
|
||||
|
||||
And you can check it's running by going to [http://127.0.0.1:5000](http://127.0.0.1:5000) in your browser. You should get a "Hello, world!" response.
|
||||
|
||||
### Deploy the Flask API to Render
|
||||
|
||||
Set up a Render account (we recommend logging in with your GitHub account, to simplify things) and create a new web service:
|
||||
|
||||
1. Select "build and deploy from a github repository" then select the repo you created above.
|
||||
2. Give the service a unique name
|
||||
3. Set the root directory to `flask_app`
|
||||
4. Set the runtime to Python 3
|
||||
5. Select the Free tier
|
||||
|
||||
**Important: set `PYTHON_VERSION`**. Your first deploy will fail because some packages will not be found, to fix this, set your python version to the same one you're using locally:
|
||||
|
||||
1. Go to "Environment"
|
||||
2. Select "Add environment variable"
|
||||
3. Set the `key` to `PYTHON_VERSION` and the value to `3.11.6` (or whatever version you're using locally)
|
||||
4. Click "save changes"
|
||||
5. Go to the "Deploy" button in the top right and select "deploy latest commit". It should now deploy successfully.
|
||||
|
||||
### Add your `.env` environment variables to Render
|
||||
|
||||
In the same way that you set `PYTHON_VERSION` you should now set all the other environment variables from your `.env` file in your Render environment. Your code needs to know where to connect to Mongo, etc.. So it should eventually look like this:
|
||||
|
||||

|
||||
|
||||
### Add your app IPs to MongoDB Atlas
|
||||
|
||||
To allow your API to connect to MongoDB, you need to add its IP addresses to the list of IPs allowed to connect by Mongo. You can find the IPs in the "Connect" button in the top right of Render.
|
||||
|
||||

|
||||
|
||||
Go to MongoDB's UI and select "Network Access" from under "Security" in the menu on the left. Click "Add IP address" three times and add one of the IPs supplied by Render each time.
|
||||
|
||||
With all this done, your API should now be up and running and able to connect to MongoDB. Time to build a frontend!
|
||||
|
||||
### Run the Next.js app
|
||||
|
||||
Just like the Flask app, we've already done the heavy lifting for you and you can find the app in `next_app`. To get it going locally, run these in the root of the Next app:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
This will give you a local server on [http://127.0.0.1:3000](http://127.0.0.1:3000). If you're already running the Flask API, you should be able to run queries!
|
||||
|
||||
### Deploy the Next.js app to Render
|
||||
|
||||
Just like the Flask app, we're going to deploy the Next.js app to Render on the free plan. The steps are very similar:
|
||||
|
||||
1. Select "build and deploy from a github repository" then select the repo you created above.
|
||||
2. Give the service a unique name
|
||||
3. Set the root directory to `next_app`
|
||||
4. Set the runtime to Node.js
|
||||
5. Select the Free tier
|
||||
|
||||
### Set environment variables for Next.js
|
||||
|
||||
Just as with Python, you're going to need to set an environment variable called `NODE_VERSION` to `20` and rebuild your first deploy.
|
||||
|
||||
You're also going to need to tell it where to find the Flask API. To do this, create an environment variable called `NEXT_PUBLIC_API_HOST` and set it to the hostname on Render of your Flask API (in our case, that was `https://mongodb-demo-zpxu.onrender.com/`).
|
||||
|
||||
You don't need to set any of the other environment variables, only your Flask API needs to know how to connect to Mongo.
|
||||
|
||||
Redeploy your Next.js application.
|
||||
|
||||
### Celebrate!
|
||||
|
||||
If all is well, you should now have a demo app just like ours! You can begin customizing it to your use-case.
|
||||
|
After Width: | Height: | Size: 96 KiB |
|
After Width: | Height: | Size: 372 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 252 KiB |
@@ -0,0 +1,48 @@
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
from flask import Flask, request, jsonify
|
||||
from flask_cors import CORS, cross_origin
|
||||
import os
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from llama_index.vector_stores.azurecosmosmongo import AzureCosmosDBMongoDBVectorSearch
|
||||
from llama_index.indices.vector_store.base import VectorStoreIndex
|
||||
|
||||
import logging
|
||||
import sys
|
||||
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
|
||||
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))
|
||||
|
||||
# Create a new client and connect to the server
|
||||
client = MongoClient(os.getenv("MONGODB_URI"))
|
||||
|
||||
# connect to Atlas as a vector store
|
||||
store = AzureCosmosDBMongoDBVectorSearch(
|
||||
client,
|
||||
db_name=os.getenv('MONGODB_DATABASE'), # this is the database where you stored your embeddings
|
||||
collection_name=os.getenv('MONGODB_VECTORS'), # this is where your embeddings were stored in 2_load_and_index.py
|
||||
index_name=os.getenv('MONGODB_VECTOR_INDEX') # this is the name of the index you created after loading your data
|
||||
)
|
||||
index = VectorStoreIndex.from_vector_store(store)
|
||||
|
||||
app = Flask(__name__)
|
||||
cors = CORS(app)
|
||||
app.config['CORS_HEADERS'] = 'Content-Type'
|
||||
|
||||
# This is just so you can easily tell the app is running
|
||||
@app.route('/')
|
||||
def hello_world():
|
||||
return 'Hello, World!'
|
||||
|
||||
@app.route('/process_form', methods=['POST'])
|
||||
@cross_origin()
|
||||
def process_form():
|
||||
query = request.form.get('query')
|
||||
if query is not None:
|
||||
# query your data!
|
||||
# here we have customized the number of documents returned per query to 20, because tweets are really short
|
||||
query_engine = index.as_query_engine(similarity_top_k=20)
|
||||
response = query_engine.query(query)
|
||||
return jsonify({"response": str(response)})
|
||||
else:
|
||||
return jsonify({"error": "query field is missing"}), 400
|
||||
@@ -0,0 +1,60 @@
|
||||
aiohttp==3.8.6
|
||||
aiosignal==1.3.1
|
||||
aiostream==0.5.2
|
||||
annotated-types==0.6.0
|
||||
anyio==3.7.1
|
||||
async-timeout==4.0.3
|
||||
attrs==23.1.0
|
||||
certifi==2023.7.22
|
||||
charset-normalizer==3.3.1
|
||||
click==8.1.7
|
||||
dataclasses-json==0.5.14
|
||||
Deprecated==1.2.14
|
||||
dnspython==2.4.2
|
||||
Flask==2.2.5
|
||||
Flask-Cors==4.0.0
|
||||
frozenlist==1.4.0
|
||||
fsspec==2023.10.0
|
||||
greenlet==3.0.1
|
||||
gunicorn==21.2.0
|
||||
idna==3.4
|
||||
itsdangerous==2.1.2
|
||||
Jinja2==3.1.2
|
||||
joblib==1.3.2
|
||||
jsonpatch==1.33
|
||||
jsonpointer==2.4
|
||||
langchain==0.0.325
|
||||
langsmith==0.0.53
|
||||
llama-index==0.8.55
|
||||
MarkupSafe==2.1.3
|
||||
marshmallow==3.20.1
|
||||
multidict==6.0.4
|
||||
mypy-extensions==1.0.0
|
||||
nest-asyncio==1.5.8
|
||||
nltk==3.8.1
|
||||
numpy==1.26.1
|
||||
openai==0.28.1
|
||||
packaging==23.2
|
||||
pandas==2.1.2
|
||||
pydantic==2.4.2
|
||||
pydantic_core==2.10.1
|
||||
pymongo==4.5.0
|
||||
python-dateutil==2.8.2
|
||||
python-dotenv==1.0.0
|
||||
pytz==2023.3.post1
|
||||
PyYAML==6.0.1
|
||||
regex==2023.10.3
|
||||
requests==2.31.0
|
||||
six==1.16.0
|
||||
sniffio==1.3.0
|
||||
SQLAlchemy==2.0.22
|
||||
tenacity==8.2.3
|
||||
tiktoken==0.5.1
|
||||
tqdm==4.66.1
|
||||
typing-inspect==0.9.0
|
||||
typing_extensions==4.8.0
|
||||
tzdata==2023.3
|
||||
urllib3==1.26.18
|
||||
Werkzeug==2.2.3
|
||||
wrapt==1.15.0
|
||||
yarl==1.9.2
|
||||
@@ -0,0 +1,36 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
.yarn/install-state.gz
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
@@ -0,0 +1,36 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,107 @@
|
||||
:root {
|
||||
--max-width: 1100px;
|
||||
--border-radius: 12px;
|
||||
--font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
|
||||
'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
|
||||
'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
|
||||
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
|
||||
--primary-glow: conic-gradient(
|
||||
from 180deg at 50% 50%,
|
||||
#16abff33 0deg,
|
||||
#0885ff33 55deg,
|
||||
#54d6ff33 120deg,
|
||||
#0071ff33 160deg,
|
||||
transparent 360deg
|
||||
);
|
||||
--secondary-glow: radial-gradient(
|
||||
rgba(255, 255, 255, 1),
|
||||
rgba(255, 255, 255, 0)
|
||||
);
|
||||
|
||||
--tile-start-rgb: 239, 245, 249;
|
||||
--tile-end-rgb: 228, 232, 233;
|
||||
--tile-border: conic-gradient(
|
||||
#00000080,
|
||||
#00000040,
|
||||
#00000030,
|
||||
#00000020,
|
||||
#00000010,
|
||||
#00000010,
|
||||
#00000080
|
||||
);
|
||||
|
||||
--callout-rgb: 238, 240, 241;
|
||||
--callout-border-rgb: 172, 175, 176;
|
||||
--card-rgb: 180, 185, 188;
|
||||
--card-border-rgb: 131, 134, 135;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
|
||||
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
|
||||
--secondary-glow: linear-gradient(
|
||||
to bottom right,
|
||||
rgba(1, 65, 255, 0),
|
||||
rgba(1, 65, 255, 0),
|
||||
rgba(1, 65, 255, 0.3)
|
||||
);
|
||||
|
||||
--tile-start-rgb: 2, 13, 46;
|
||||
--tile-end-rgb: 2, 5, 19;
|
||||
--tile-border: conic-gradient(
|
||||
#ffffff80,
|
||||
#ffffff40,
|
||||
#ffffff30,
|
||||
#ffffff20,
|
||||
#ffffff10,
|
||||
#ffffff10,
|
||||
#ffffff80
|
||||
);
|
||||
|
||||
--callout-rgb: 20, 20, 20;
|
||||
--callout-border-rgb: 108, 108, 108;
|
||||
--card-rgb: 100, 100, 100;
|
||||
--card-border-rgb: 200, 200, 200;
|
||||
}
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
max-width: 100vw;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
html {
|
||||
color-scheme: dark;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Inter } from 'next/font/google'
|
||||
import './globals.css'
|
||||
|
||||
const inter = Inter({ subsets: ['latin'] })
|
||||
|
||||
export const metadata = {
|
||||
title: 'MongoDB LlamaIndex demo',
|
||||
description: '',
|
||||
}
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>{children}</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
'use client'
|
||||
|
||||
import styles from './page.module.css'
|
||||
import React, { useState } from 'react';
|
||||
|
||||
export default function Home() {
|
||||
const [query, setQuery] = useState('');
|
||||
const [responseText, setResponseText] = useState('');
|
||||
|
||||
const handleSubmit = async (event) => {
|
||||
event.preventDefault();
|
||||
setResponseText('Thinking...')
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('query', query);
|
||||
|
||||
const response = await fetch(process.env.NEXT_PUBLIC_API_HOST + '/process_form', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const responseData = await response.json();
|
||||
console.log(responseData);
|
||||
setResponseText(responseData.response)
|
||||
} else {
|
||||
console.error('Failed to submit:', response.statusText);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<main className={styles.main}>
|
||||
<div>
|
||||
<h1>Query my tweets</h1>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
name="query"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
/>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
<div className={styles.response}>
|
||||
{responseText}
|
||||
</div>
|
||||
<div className={styles.examples}>
|
||||
<h2>Try some sample questions like...</h2>
|
||||
<ul>
|
||||
<li>What television shows does the author watch?</li>
|
||||
<li>Does the author like dogs?</li>
|
||||
<li>How does the author feel about web frameworks?</li>
|
||||
</ul>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content:center;
|
||||
align-items: center;
|
||||
padding: 6rem;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.main form input {
|
||||
padding: 10px;
|
||||
margin-right: 10px;
|
||||
width: 30em;
|
||||
}
|
||||
|
||||
.main form button {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.response {
|
||||
margin-top: 2rem;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
background-color: #000;
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.examples {
|
||||
margin-top: 2em;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {}
|
||||
|
||||
module.exports = nextConfig
|
||||
@@ -0,0 +1,406 @@
|
||||
{
|
||||
"name": "next_app",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "next_app",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"next": "14.0.0",
|
||||
"react": "^18",
|
||||
"react-dom": "^18"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.0.tgz",
|
||||
"integrity": "sha512-cIKhxkfVELB6hFjYsbtEeTus2mwrTC+JissfZYM0n+8Fv+g8ucUfOlm3VEDtwtwydZ0Nuauv3bl0qF82nnCAqA=="
|
||||
},
|
||||
"node_modules/@next/swc-darwin-arm64": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.0.tgz",
|
||||
"integrity": "sha512-HQKi159jCz4SRsPesVCiNN6tPSAFUkOuSkpJsqYTIlbHLKr1mD6be/J0TvWV6fwJekj81bZV9V/Tgx3C2HO9lA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-darwin-x64": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.0.tgz",
|
||||
"integrity": "sha512-4YyQLMSaCgX/kgC1jjF3s3xSoBnwHuDhnF6WA1DWNEYRsbOOPWjcYhv8TKhRe2ApdOam+VfQSffC4ZD+X4u1Cg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-gnu": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.0.tgz",
|
||||
"integrity": "sha512-io7fMkJ28Glj7SH8yvnlD6naIhRDnDxeE55CmpQkj3+uaA2Hko6WGY2pT5SzpQLTnGGnviK85cy8EJ2qsETj/g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-arm64-musl": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.0.tgz",
|
||||
"integrity": "sha512-nC2h0l1Jt8LEzyQeSs/BKpXAMe0mnHIMykYALWaeddTqCv5UEN8nGO3BG8JAqW/Y8iutqJsaMe2A9itS0d/r8w==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-gnu": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.0.tgz",
|
||||
"integrity": "sha512-Wf+WjXibJQ7hHXOdNOmSMW5bxeJHVf46Pwb3eLSD2L76NrytQlif9NH7JpHuFlYKCQGfKfgSYYre5rIfmnSwQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-linux-x64-musl": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.0.tgz",
|
||||
"integrity": "sha512-WTZb2G7B+CTsdigcJVkRxfcAIQj7Lf0ipPNRJ3vlSadU8f0CFGv/ST+sJwF5eSwIe6dxKoX0DG6OljDBaad+rg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-arm64-msvc": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.0.tgz",
|
||||
"integrity": "sha512-7R8/x6oQODmNpnWVW00rlWX90sIlwluJwcvMT6GXNIBOvEf01t3fBg0AGURNKdTJg2xNuP7TyLchCL7Lh2DTiw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-ia32-msvc": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.0.tgz",
|
||||
"integrity": "sha512-RLK1nELvhCnxaWPF07jGU4x3tjbyx2319q43loZELqF0+iJtKutZ+Lk8SVmf/KiJkYBc7Cragadz7hb3uQvz4g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/swc-win32-x64-msvc": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.0.tgz",
|
||||
"integrity": "sha512-g6hLf1SUko+hnnaywQQZzzb3BRecQsoKkF3o/C+F+dOA4w/noVAJngUVkfwF0+2/8FzNznM7ofM6TGZO9svn7w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
|
||||
"integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
|
||||
"dependencies": {
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/busboy": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||
"dependencies": {
|
||||
"streamsearch": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001558",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz",
|
||||
"integrity": "sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/browserslist"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/client-only": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
|
||||
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
|
||||
},
|
||||
"node_modules/glob-to-regexp": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dependencies": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"loose-envify": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-14.0.0.tgz",
|
||||
"integrity": "sha512-J0jHKBJpB9zd4+c153sair0sz44mbaCHxggs8ryVXSFBuBqJ8XdE9/ozoV85xGh2VnSjahwntBZZgsihL9QznA==",
|
||||
"dependencies": {
|
||||
"@next/env": "14.0.0",
|
||||
"@swc/helpers": "0.5.2",
|
||||
"busboy": "1.6.0",
|
||||
"caniuse-lite": "^1.0.30001406",
|
||||
"postcss": "8.4.31",
|
||||
"styled-jsx": "5.1.1",
|
||||
"watchpack": "2.4.0"
|
||||
},
|
||||
"bin": {
|
||||
"next": "dist/bin/next"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.17.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@next/swc-darwin-arm64": "14.0.0",
|
||||
"@next/swc-darwin-x64": "14.0.0",
|
||||
"@next/swc-linux-arm64-gnu": "14.0.0",
|
||||
"@next/swc-linux-arm64-musl": "14.0.0",
|
||||
"@next/swc-linux-x64-gnu": "14.0.0",
|
||||
"@next/swc-linux-x64-musl": "14.0.0",
|
||||
"@next/swc-win32-arm64-msvc": "14.0.0",
|
||||
"@next/swc-win32-ia32-msvc": "14.0.0",
|
||||
"@next/swc-win32-x64-msvc": "14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": "^1.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"sass": "^1.3.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@opentelemetry/api": {
|
||||
"optional": true
|
||||
},
|
||||
"sass": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.31",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/postcss/"
|
||||
},
|
||||
{
|
||||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/postcss"
|
||||
},
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.6",
|
||||
"picocolors": "^1.0.0",
|
||||
"source-map-js": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/react": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
|
||||
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-dom": {
|
||||
"version": "18.2.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
|
||||
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^18.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/scheduler": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
|
||||
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map-js": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/styled-jsx": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
|
||||
"integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
|
||||
"dependencies": {
|
||||
"client-only": "0.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@babel/core": {
|
||||
"optional": true
|
||||
},
|
||||
"babel-plugin-macros": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.6.2",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||
},
|
||||
"node_modules/watchpack": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
|
||||
"integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
|
||||
"dependencies": {
|
||||
"glob-to-regexp": "^0.4.1",
|
||||
"graceful-fs": "^4.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "next_app",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"next": "14.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
|
||||
|
After Width: | Height: | Size: 629 B |
@@ -0,0 +1,19 @@
|
||||
[tool.poetry]
|
||||
name = "cosmosdb"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
authors = ["Laurie Voss <github@seldo.com>"]
|
||||
readme = "README.md"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.11"
|
||||
llama-index = "^0.9.25.post1"
|
||||
python-dotenv = "^1.0.0"
|
||||
pymongo = "^4.6.1"
|
||||
flask = "^3.0.0"
|
||||
flask-cors = "^4.0.0"
|
||||
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||