Pash1986 commited on
Commit
6822c70
·
verified ·
1 Parent(s): 2c86990

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -0
app.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from time import sleep
3
+ import json
4
+ from pymongo import MongoClient
5
+ from bson import ObjectId
6
+ from openai import OpenAI
7
+ openai_client = OpenAI()
8
+ import os
9
+
10
+ # Get the restaurants based on the search and location
11
+ def get_restaurants(search, location, meters):
12
+ try:
13
+ uri = os.environ.get('MONGODB_ATLAS_URI')
14
+ client = MongoClient(uri)
15
+ db_name = 'whatscooking'
16
+ collection_name = 'restaurants'
17
+ restaurants_collection = client[db_name][collection_name]
18
+ trips_collection = client[db_name]['smart_trips']
19
+ except:
20
+ st.error("Error Connecting to the MongoDB Atlas Cluster")
21
+ return None, None, None, None
22
+
23
+ try:
24
+ newTrip, pre_agg = pre_aggregate_meters(restaurants_collection, location, meters)
25
+
26
+ response = openai_client.embeddings.create(
27
+ input=search,
28
+ model="text-embedding-3-small",
29
+ dimensions=256
30
+ )
31
+
32
+ vectorQuery = {
33
+ "$vectorSearch": {
34
+ "index": "vector_index",
35
+ "queryVector": response.data[0].embedding,
36
+ "path": "embedding",
37
+ "numCandidates": 10,
38
+ "limit": 3,
39
+ "filter": {"searchTrip": newTrip}
40
+ }
41
+ }
42
+
43
+ restaurant_docs = list(trips_collection.aggregate([vectorQuery, {"$project": {"_id": 0, "embedding": 0}}]))
44
+
45
+ chat_response = openai_client.chat.completions.create(
46
+ model="gpt-4o",
47
+ messages=[
48
+ {"role": "system", "content": "You are a helpful restaurant assistant. Answer shortly and quickly. You will get a context if the context is not relevant to the user query please address that and not provide by default the restaurants as is."},
49
+ {"role": "user", "content": f"Find me the 2 best restaurant and why based on {search} and {restaurant_docs}. Shortly explain trades offs and why I should go to each one. You can mention the third option as a possible alternative in one sentence."}
50
+ ]
51
+ )
52
+
53
+ trips_collection.delete_many({"searchTrip": newTrip})
54
+
55
+ if len(restaurant_docs) == 0:
56
+ return "No restaurants found", '<iframe style="background: #FFFFFF;border: none;border-radius: 2px;box-shadow: 0 2px 10px 0 rgba(70, 76, 79, .2);" width="640" height="480" src="https://charts.mongodb.com/charts-paveldev-wiumf/embed/charts?id=65c24b0c-2215-4e6f-829c-f484dfd8a90c&filter={\'restaurant_id\':\'\'}&maxDataAge=3600&theme=light&autoRefresh=true"></iframe>', str(pre_agg), str(vectorQuery)
57
+
58
+ first_restaurant = restaurant_docs[0]['restaurant_id']
59
+ second_restaurant = restaurant_docs[1]['restaurant_id']
60
+ third_restaurant = restaurant_docs[2]['restaurant_id']
61
+ restaurant_string = f"'{first_restaurant}', '{second_restaurant}', '{third_restaurant}'"
62
+
63
+ iframe = '<iframe style="background: #FFFFFF;border: none;border-radius: 2px;box-shadow: 0 2px 10px 0 rgba(70, 76, 79, .2);" width="640" height="480" src="https://charts.mongodb.com/charts-paveldev-wiumf/embed/charts?id=65c24b0c-2215-4e6f-829c-f484dfd8a90c&filter={\'restaurant_id\':{$in:[' + restaurant_string + ']}}&maxDataAge=3600&theme=light&autoRefresh=true"></iframe>'
64
+ client.close()
65
+ return chat_response.choices[0].message.content, iframe, str(pre_agg), str(vectorQuery)
66
+ except Exception as e:
67
+ st.error(f"Your query caused an error: {e}")
68
+ return "Your query caused an error, please retry with allowed input only ...", '<iframe style="background: #FFFFFF;border: none;border-radius: 2px;box-shadow: 0 2px 10px 0 rgba(70, 76, 79, .2);" width="640" height="480" src="https://charts.mongodb.com/charts-paveldev-wiumf/embed/charts?id=65c24b0c-2215-4e6f-829c-f484dfd8a90c&filter={\'restaurant_id\':\'\'}&maxDataAge=3600&theme=light&autoRefresh=true"></iframe>', str(pre_agg), str(vectorQuery)
69
+
70
+ def pre_aggregate_meters(restaurants_collection, location, meters):
71
+ tripId = ObjectId()
72
+ pre_aggregate_pipeline = [{
73
+ "$geoNear": {
74
+ "near": location,
75
+ "distanceField": "distance",
76
+ "maxDistance": meters,
77
+ "spherical": True,
78
+ },
79
+ }, {
80
+ "$addFields": {
81
+ "searchTrip": tripId,
82
+ "date": tripId.generation_time
83
+ }
84
+ }, {
85
+ "$merge": {
86
+ "into": "smart_trips"
87
+ }
88
+ }]
89
+
90
+ result = restaurants_collection.aggregate(pre_aggregate_pipeline)
91
+ sleep(3)
92
+ return tripId, pre_aggregate_pipeline
93
+
94
+ st.markdown(
95
+ """
96
+ # MongoDB's Vector Restaurant Planner
97
+ Start typing below to see the results. You can search a specific cuisine for you and choose 3 predefined locations.
98
+
99
+ The radius specifies the distance from the start search location. This space uses the dataset called [whatscooking.restaurants](https://huggingface.co/datasets/AIatMongoDB/whatscooking.restaurants)
100
+ """
101
+ )
102
+
103
+ search = st.text_input("What type of dinner are you looking for?")
104
+ location = st.radio("Location", options=[
105
+ {"label": "Timesquare Manhattan", "value": {"type": "Point", "coordinates": [-73.98527039999999, 40.7589099]}},
106
+ {"label": "Westside Manhattan", "value": {"type": "Point", "coordinates": [-74.013686, 40.701975]}},
107
+ {"label": "Downtown Manhattan", "value": {"type": "Point", "coordinates": [-74.000468, 40.720777]}}
108
+ ], format_func=lambda x: x['label'])
109
+ meters = st.slider("Radius in meters", min_value=500, max_value=10000, step=5)
110
+
111
+ if st.button("Get Restaurants"):
112
+ location_value = location['value']
113
+ result, iframe, pre_agg, vectorQuery = get_restaurants(search, location_value, meters)
114
+ if result:
115
+ st.markdown(result)
116
+ st.markdown(iframe, unsafe_allow_html=True)
117
+ st.json(pre_agg)
118
+ st.json(vectorQuery)