Clément Simon commited on
Commit
ca2bbd4
1 Parent(s): d9846ba

switch to docker

Browse files
Files changed (5) hide show
  1. .gitignore +1 -0
  2. Dockerfile +20 -0
  3. app.py +0 -137
  4. main.py +238 -0
  5. user_profile.json +7 -0
.gitignore CHANGED
@@ -1,3 +1,4 @@
1
  .env
2
  .venv
3
  __pycache__
 
 
1
  .env
2
  .venv
3
  __pycache__
4
+ static/map.html
Dockerfile ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ WORKDIR /code
4
+
5
+ COPY ./requirements.txt /code/requirements.txt
6
+
7
+ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
8
+
9
+ RUN useradd -m -u 1000 user
10
+
11
+ USER user
12
+
13
+ ENV HOME=/home/user \
14
+ PATH=/home/user/.local/bin:$PATH
15
+
16
+ WORKDIR $HOME/app
17
+
18
+ COPY --chown=user . $HOME/app
19
+
20
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
app.py DELETED
@@ -1,137 +0,0 @@
1
- import os
2
- import sys
3
- from datetime import datetime
4
- from pathlib import Path
5
-
6
- import gradio as gr
7
- import plotly.graph_objects as go
8
- import uvicorn
9
- from dotenv import load_dotenv
10
- from fastapi import FastAPI
11
- from fastapi.staticfiles import StaticFiles
12
- from mistralai.client import ChatMessage, MistralClient
13
-
14
- # create a FastAPI app
15
- app = FastAPI()
16
-
17
- # create a static directory to store the static files
18
- static_dir = Path('./static')
19
- static_dir.mkdir(parents=True, exist_ok=True)
20
-
21
- # mount FastAPI StaticFiles server
22
- app.mount("/static", StaticFiles(directory=static_dir), name="static")
23
-
24
- # Gradio stuff
25
-
26
-
27
- # def predict(text_input):
28
- # file_name = f"{datetime.utcnow().strftime('%s')}.html"
29
- # file_path = static_dir / file_name
30
- # print(file_path)
31
- # with open(file_path, "w") as f:
32
- # f.write(f"""
33
- # <script src="https://cdn.tailwindcss.com"></script>
34
- # <body class="bg-gray-200 dark:text-white dark:bg-gray-900">
35
- # <h1 class="text-3xl font-bold">
36
- # Hello <i>{text_input}</i> From Gradio Iframe
37
- # </h1>
38
- # <h3>Filename: {file_name}</h3>
39
- # """)
40
- # iframe = f"""<iframe src="/static/{file_name}" width="100%" height="500px"></iframe>"""
41
- # link = f'<a href="/static/{file_name}" target="_blank">{file_name}</a>'
42
- # return link, iframe
43
-
44
-
45
- # with gr.Blocks() as block:
46
- # gr.Markdown("""
47
- # ## Gradio + FastAPI + Static Server
48
- # This is a demo of how to use Gradio with FastAPI and a static server.
49
- # The Gradio app generates dynamic HTML files and stores them in a static directory. FastAPI serves the static files.
50
- # """)
51
- # with gr.Row():
52
- # with gr.Column():
53
- # text_input = gr.Textbox(label="Name")
54
- # markdown = gr.Markdown(label="Output Box")
55
- # new_btn = gr.Button("New")
56
- # with gr.Column():
57
- # html = gr.HTML(label="HTML preview", show_label=True)
58
-
59
- # new_btn.click(fn=predict, inputs=[text_input], outputs=[markdown, html])
60
-
61
-
62
-
63
- # Load environment variables
64
- load_dotenv()
65
- api_key = os.getenv('API_KEY')
66
- client = MistralClient(api_key=api_key)
67
- model = 'mistral-small'
68
-
69
-
70
- title = "Gaia Mistral Chat Demo"
71
- description = "Example of simple chatbot with Gradio and Mistral AI via its API"
72
- placeholder = "Posez moi une question sur l'agriculture"
73
- examples = ["Comment fait on pour produire du maïs ?", "Rédige moi une lettre pour faire un stage dans une exploitation agricole", "Comment reprendre une exploitation agricole ?"]
74
-
75
-
76
- def chat_with_mistral(user_input):
77
- messages = [ChatMessage(role="user", content=user_input)]
78
-
79
- chat_response = client.chat(model=model, messages=messages)
80
- return chat_response.choices[0].message.content
81
-
82
- def create_world_map(
83
- lat=45.5017,
84
- lon=-73.5673,
85
- ):
86
- fig = go.Figure(go.Scattermapbox
87
- (
88
- lat=[lat],
89
- lon=[lon],
90
- mode='markers',
91
- marker=go.scattermapbox.Marker(size=14),
92
- text=['Montreal'],
93
- ))
94
-
95
- fig.update_layout(
96
- mapbox_style="open-street-map",
97
- hovermode='closest',
98
- mapbox=dict(
99
- bearing=0,
100
- center=go.layout.mapbox.Center(
101
- lat=lat,
102
- lon=lon,
103
- ),
104
- pitch=0,
105
- zoom=5
106
- ),
107
- )
108
-
109
- return fig
110
-
111
- with gr.Blocks() as demo:
112
- with gr.Column():
113
- with gr.Row():
114
- user_input = gr.Textbox(lines=2, placeholder=placeholder)
115
- send_chat_btn = gr.Button(value="Send")
116
- lat = gr.Number(value=45.5017, label="Latitude")
117
- lon = gr.Number(value=-73.5673, label="Longitude")
118
- update_map_btn = gr.Button(value="Update Map")
119
-
120
- chat_output = gr.Textbox(lines=2, placeholder="Réponse")
121
-
122
- # map:
123
- map = gr.Plot()
124
- demo.load(chat_with_mistral, user_input, chat_output)
125
- send_chat_btn.click(chat_with_mistral, user_input, chat_output)
126
- # map:
127
- demo.load(create_world_map, [lat, lon], map)
128
- update_map_btn.click(create_world_map, [lat, lon], map)
129
-
130
-
131
-
132
- # mount Gradio app to FastAPI app
133
- app = gr.mount_gradio_app(app, demo, path="/")
134
-
135
- # serve the app
136
- if __name__ == "__main__":
137
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
main.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+
6
+ import gradio as gr
7
+ import plotly.graph_objects as go
8
+ import uvicorn
9
+ from dotenv import load_dotenv
10
+ from fastapi import FastAPI
11
+ from fastapi.staticfiles import StaticFiles
12
+ from mistralai.client import ChatMessage, MistralClient
13
+ from pydantic import BaseModel
14
+ from fastapi import Depends
15
+ import json
16
+ from fastapi.responses import HTMLResponse
17
+
18
+
19
+ # Load environment variables
20
+ load_dotenv()
21
+ api_key = os.getenv('API_KEY')
22
+ client = MistralClient(api_key=api_key)
23
+ model = 'mistral-small'
24
+
25
+ title = "Gaia Mistral Chat Demo"
26
+ description = "Example of simple chatbot with Gradio and Mistral AI via its API"
27
+ placeholder = "Posez moi une question sur l'agriculture"
28
+ examples = ["Comment fait on pour produire du maïs ?",
29
+ "Rédige moi une lettre pour faire un stage dans une exploitation agricole", "Comment reprendre une exploitation agricole ?"]
30
+
31
+
32
+ # create a FastAPI app
33
+ app = FastAPI()
34
+
35
+ # create a static directory to store the static files
36
+ static_dir = Path('./static')
37
+ static_dir.mkdir(parents=True, exist_ok=True)
38
+
39
+ # mount FastAPI StaticFiles server
40
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
41
+
42
+
43
+ # Gradio stuff
44
+
45
+ def predict(text_input):
46
+ file_name = f"{datetime.utcnow().strftime('%s')}.html"
47
+ file_path = static_dir / file_name
48
+ print(file_path)
49
+ with open(file_path, "w") as f:
50
+ f.write(f"""
51
+ <script src="https://cdn.tailwindcss.com"></script>
52
+ <body class="bg-gray-200 dark:text-white dark:bg-gray-900">
53
+ <h1 class="text-3xl font-bold">
54
+ Hello <i>{text_input}</i> From Gradio Iframe
55
+ </h1>
56
+ <h3>Filename: {file_name}</h3>
57
+ """)
58
+ iframe = f"""<iframe src="/static/{file_name}" width="100%" height="500px"></iframe>"""
59
+ link = f'<a href="/static/{file_name}" target="_blank">{file_name}</a>'
60
+ return link, iframe
61
+
62
+
63
+ with gr.Blocks() as block:
64
+ gr.Markdown("""
65
+ ## Gradio + FastAPI + Static Server
66
+ This is a demo of how to use Gradio with FastAPI and a static server.
67
+ The Gradio app generates dynamic HTML files and stores them in a static directory. FastAPI serves the static files.
68
+ """)
69
+ with gr.Row():
70
+ with gr.Column():
71
+ text_input = gr.Textbox(label="Name")
72
+ markdown = gr.Markdown(label="Output Box")
73
+ new_btn = gr.Button("New")
74
+ with gr.Column():
75
+ html = gr.HTML(label="HTML preview", show_label=True)
76
+
77
+ new_btn.click(fn=predict, inputs=[text_input], outputs=[markdown, html])
78
+
79
+
80
+ def create_world_map(lat, lon):
81
+
82
+ fig = go.Figure(go.Scattermapbox(
83
+ lat=[lat],
84
+ lon=[lon],
85
+ mode='markers',
86
+ marker=go.scattermapbox.Marker(size=14),
87
+ text=['Location'],
88
+ ))
89
+
90
+ fig.update_layout(
91
+ mapbox_style="open-street-map",
92
+ hovermode='closest',
93
+ mapbox=dict(
94
+ bearing=0,
95
+ center=go.layout.mapbox.Center(
96
+ lat=lat,
97
+ lon=lon,
98
+ ),
99
+ pitch=0,
100
+ zoom=5
101
+ ),
102
+ )
103
+
104
+ return fig
105
+
106
+
107
+ # # Fake JSON data for the user profile
108
+ # user_profile_data = {
109
+ # "name": "John Doe",
110
+ # "age": 30,
111
+ # "location": "Montreal",
112
+ # "lat": 45.5017,
113
+ # "lon": -73.5673
114
+ # }
115
+
116
+ # #as a JSON:
117
+ # with open('user_profile.json', 'w') as f:
118
+ # json.dump(user_profile_data, f)
119
+
120
+ # Mistral AI Chat
121
+
122
+ def chat_with_mistral(user_input):
123
+ messages = [ChatMessage(role="user", content=user_input)]
124
+
125
+ chat_response = client.chat(model=model, messages=messages)
126
+ return chat_response.choices[0].message.content
127
+
128
+
129
+ ### FRONTEND ###
130
+ def create_gradio_dashboard():
131
+ with gr.Blocks() as demo:
132
+ # Mistral AI Chat
133
+ with gr.Column():
134
+ with gr.Row():
135
+ user_input = gr.Textbox (lines=2, placeholder=placeholder)
136
+ send_chat_btn = gr.Button(value="Send")
137
+ update_map_btn = gr.Button(value="Update Map")
138
+ chat_output = gr.Textbox(lines=2, placeholder="Réponse")
139
+
140
+ # Profile
141
+ with gr.Row():
142
+ name = gr.Textbox(label="Name")
143
+ age = gr.Number(label="Age")
144
+ location = gr.Textbox(label="Location")
145
+ lat = gr.Number(value=45.5017, label="Latitude")
146
+ lon = gr.Number(value=-73.5673, label="Longitude")
147
+ load_user_profile_btn = gr.Button(value="Load User Profile")
148
+ save_user_profile_btn = gr.Button(value="Save User Profile")
149
+
150
+ # Map
151
+ with gr.Row():
152
+ map = gr.Plot()
153
+
154
+ # Mistral AI Chat
155
+ demo.load(chat_with_mistral, user_input, chat_output)
156
+ send_chat_btn.click(chat_with_mistral, user_input, chat_output)
157
+
158
+ return demo
159
+
160
+
161
+ # Profile stuff
162
+ class UserProfile(BaseModel):
163
+ name: str
164
+ age: int
165
+ location: str
166
+ lat: float
167
+ lon: float
168
+
169
+ @app.post("/user_profile")
170
+ def save_user_profile(user_profile: UserProfile):
171
+ with open('user_profile.json', 'w') as f:
172
+ json.dump(user_profile.dict(), f)
173
+ return user_profile.dict()
174
+
175
+ @app.get("/user_profile")
176
+ def load_user_profile():
177
+ with open('user_profile.json', 'r') as f:
178
+ user_profile = json.load(f)
179
+ return UserProfile(**user_profile)
180
+
181
+ @app.put("/user_profile")
182
+ def update_user_profile(user_profile: UserProfile):
183
+ with open('user_profile.json', 'w') as f:
184
+ json.dump(user_profile.dict(), f)
185
+ return user_profile
186
+
187
+ # load user profile on startup
188
+ user_profile = load_user_profile()
189
+
190
+
191
+ ### BACKEND ###
192
+ @app.get("/meteo")
193
+ async def read_meteo(location: str, date: str):
194
+ # API call to get the weather
195
+ pass
196
+
197
+ # Home page : using the user profile, display the weather and chat with Mistral AI
198
+ @app.get("/", response_class=HTMLResponse)
199
+ async def home(user_profile: UserProfile = Depends(load_user_profile)):
200
+
201
+ #1st : display as background the map of the user location:
202
+ # get the user location
203
+ lat = user_profile.lat
204
+ lon = user_profile.lon
205
+ # create the map
206
+ fig = create_world_map(lat, lon)
207
+ # save the map as a file
208
+ map_file = static_dir / "map.html"
209
+ fig.write_html(str(map_file))
210
+ # display the map
211
+ map_html = f'<iframe src="/static/map.html" width="100%" height="500px"></iframe>'
212
+
213
+ #2nd : gradio dashboard on top of the map to toggle the user profile and display chat with Mistral AI
214
+ # create the gradio dashboard
215
+ # gradio_dashboard = create_gradio_dashboard()
216
+ # save the dashboard as a file
217
+ # dashboard_file = static_dir / "dashboard.html"
218
+ # gradio_dashboard.save(dashboard_file)
219
+ # # display the dashboard
220
+ # dashboard_html = f'<iframe src="/static/dashboard.html" width="100%" height="500px"></iframe>'
221
+
222
+ return f"""
223
+ <h1>Welcome to the home page</h1>
224
+ <h2>User Profile</h2>
225
+ <p>Name: {user_profile.name}</p>
226
+ <p>Age: {user_profile.age}</p>
227
+ <p>Location: {user_profile.location}</p>
228
+ <p>Latitude: {user_profile.lat}</p>
229
+ <p>Longitude: {user_profile.lon}</p>
230
+ <h2>Map</h2>
231
+ {map_html}
232
+ """
233
+ # <h2>Gradio Dashboard</h2>
234
+ # {dashboard_html}
235
+
236
+ # serve the app
237
+ if __name__ == "__main__":
238
+ uvicorn.run(app, host="0.0.0.0", port=7860)
user_profile.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "John Doe",
3
+ "age": 30,
4
+ "location": "Montreal",
5
+ "lat": 45.5017,
6
+ "lon": -73.5673
7
+ }