baconnier commited on
Commit
c38a10f
·
verified ·
1 Parent(s): 70f3228

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -126
app.py CHANGED
@@ -136,6 +136,7 @@ Current Zoom States: {
136
  Generate only the JSON response, maintaining strict JSON format."""
137
 
138
 
 
139
  class ArtExplorer:
140
  def __init__(self):
141
  self.client = openai.OpenAI(
@@ -149,140 +150,108 @@ class ArtExplorer:
149
 
150
  def create_map(self, locations):
151
  """Create a Plotly map figure from location data"""
 
 
 
152
  fig = go.Figure(go.Scattermapbox(
153
  lat=[loc.get('lat') for loc in locations],
154
  lon=[loc.get('lon') for loc in locations],
155
  mode='markers',
156
  marker=go.scattermapbox.Marker(size=10),
157
- text=[loc.get('name') for loc in locations],
158
- hovertemplate='<b>%{text}</b><extra></extra>'
159
  ))
160
 
161
  fig.update_layout(
162
  mapbox_style="open-street-map",
163
  mapbox=dict(
164
- center=dict(lat=48.8566, lon=2.3522), # Default to Paris
165
  zoom=4
166
  ),
167
- margin=dict(r=0, t=0, l=0, b=0),
168
- showlegend=False
169
  )
170
  return fig
171
 
172
  def get_llm_response(self, query: str, zoom_context: dict = None) -> dict:
173
  try:
174
- # Format the CONTEXTUAL_ZOOM_PROMPT with current values
175
- formatted_prompt = CONTEXTUAL_ZOOM_PROMPT.format(
176
- user_query=query,
177
- current_zoom_states={
178
- "temporal": {
179
- "level": self.current_state.get("zoom_level", ""),
180
- "selection": zoom_context.get("temporal") if zoom_context else ""
181
- },
182
- "geographical": {
183
- "level": self.current_state.get("zoom_level", ""),
184
- "selection": zoom_context.get("geographical") if zoom_context else ""
185
- },
186
- "style": {
187
- "level": self.current_state.get("zoom_level", ""),
188
- "selection": zoom_context.get("style") if zoom_context else ""
189
- },
190
- "subject": {
191
- "level": self.current_state.get("zoom_level", ""),
192
- "selection": zoom_context.get("subject") if zoom_context else ""
193
- }
194
- }
195
- )
196
-
197
  response = self.client.chat.completions.create(
198
  model="mixtral-8x7b-32768",
199
  messages=[
200
- {
201
- "role": "system",
202
- "content": "You are an expert art historian specializing in interactive exploration."
203
- },
204
- {
205
- "role": "user",
206
- "content": formatted_prompt
207
- }
208
  ],
209
  temperature=0.1,
210
  max_tokens=2048
211
  )
212
 
213
  result = json.loads(response.choices[0].message.content)
214
-
215
- # Validate response structure
216
- if "axis_configurations" not in result:
217
- raise KeyError("Missing axis_configurations in LLM response")
218
-
219
  return result
220
 
221
  except Exception as e:
222
  print(f"Error in LLM response: {str(e)}")
223
- # Return default structure following the same format as the prompt
224
- return {
225
- "analysis": {
226
- "query_focus": "Default focus",
227
- "historical_context": "Default historical context"
228
- },
229
- "axis_configurations": {
230
- "temporal": {
231
- "component": "st.slider",
232
- "current_zoom": {
233
- "level": "century",
234
- "range": [1700, 2000],
235
- "explanation": "Default time range"
236
- },
237
- "available_zooms": {
238
- "in": {
239
- "range": [1800, 1900],
240
- "explanation": "Zoom in to see more detail"
241
- },
242
- "out": {
243
- "range": [1500, 2024],
244
- "explanation": "Broader historical context"
245
- }
246
- },
247
- "impacted_by": {
248
- "geographical": "Location affects time period",
249
- "style": "Style affects time period"
250
- }
251
  },
252
- "geographical": {
253
- "component": "st.map",
254
- "current_zoom": {
255
- "level": "continent",
256
- "locations": [
257
- {
258
- "name": "Paris",
259
- "lat": 48.8566,
260
- "lon": 2.3522,
261
- "relevance": "Default location"
262
- }
263
- ]
264
  },
265
- "available_zooms": {
266
- "in": {
267
- "locations": ["Paris", "London", "Rome"],
268
- "explanation": "Major art centers"
269
- },
270
- "out": {
271
- "locations": ["Europe", "Americas", "Asia"],
272
- "explanation": "Global art movements"
273
- }
274
- }
275
- },
276
- "style": {
277
- "component": "st.multiselect",
278
- "current_zoom": {
279
- "level": "movement",
280
- "options": ["Classical", "Modern"],
281
- "explanation": "Default art movements"
282
  }
283
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  }
285
  }
 
286
 
287
  def create_interface(self):
288
  with gr.Blocks() as demo:
@@ -323,55 +292,62 @@ class ArtExplorer:
323
 
324
  def initial_search(query):
325
  config = self.get_llm_response(query)
326
- self.current_state["selections"] = {}
327
- self.current_state["zoom_level"] = 0
328
 
329
- # Create map figure from locations
330
- map_fig = self.create_map(config["geographical"]["locations"])
 
 
 
 
 
331
 
332
  return {
333
- time_slider: config["temporal"]["range"],
334
  map_plot: map_fig,
335
- style_select: gr.Dropdown(choices=config["style"]["options"]),
336
- time_explanation: config["temporal"]["explanation"],
337
- geo_explanation: config["geographical"]["explanation"],
338
- style_explanation: config["style"]["explanation"]
339
  }
340
 
341
  def zoom_axis(query, axis_name, current_value):
342
  self.current_state["zoom_level"] += 1
343
- self.current_state["selections"][axis_name] = current_value
344
-
345
  config = self.get_llm_response(
346
  query,
347
  zoom_context={axis_name: current_value}
348
  )
349
 
350
- updates = {}
 
351
  if axis_name == "temporal":
352
- updates.update({
353
- time_slider: config["temporal"]["range"],
354
- time_explanation: config["temporal"]["explanation"]
355
- })
356
  elif axis_name == "geographical":
357
- map_fig = self.create_map(config["geographical"]["locations"])
358
- updates.update({
359
  map_plot: map_fig,
360
- geo_explanation: config["geographical"]["explanation"]
361
- })
362
- elif axis_name == "style":
363
- updates.update({
364
- style_select: gr.Dropdown(choices=config["style"]["options"]),
365
- style_explanation: config["style"]["explanation"]
366
- })
367
- return updates
368
 
369
  # Connect event handlers
370
  search_btn.click(
371
  fn=initial_search,
372
  inputs=[query],
373
- outputs=[time_slider, map_plot, style_select,
374
- time_explanation, geo_explanation, style_explanation]
 
 
 
 
 
 
375
  )
376
 
377
  time_zoom.click(
 
136
  Generate only the JSON response, maintaining strict JSON format."""
137
 
138
 
139
+
140
  class ArtExplorer:
141
  def __init__(self):
142
  self.client = openai.OpenAI(
 
150
 
151
  def create_map(self, locations):
152
  """Create a Plotly map figure from location data"""
153
+ if not locations:
154
+ locations = [{"name": "Paris", "lat": 48.8566, "lon": 2.3522}]
155
+
156
  fig = go.Figure(go.Scattermapbox(
157
  lat=[loc.get('lat') for loc in locations],
158
  lon=[loc.get('lon') for loc in locations],
159
  mode='markers',
160
  marker=go.scattermapbox.Marker(size=10),
161
+ text=[loc.get('name') for loc in locations]
 
162
  ))
163
 
164
  fig.update_layout(
165
  mapbox_style="open-street-map",
166
  mapbox=dict(
167
+ center=dict(lat=48.8566, lon=2.3522),
168
  zoom=4
169
  ),
170
+ margin=dict(r=0, t=0, l=0, b=0)
 
171
  )
172
  return fig
173
 
174
  def get_llm_response(self, query: str, zoom_context: dict = None) -> dict:
175
  try:
176
+ current_zoom_states = {
177
+ "temporal": {"level": self.current_state["zoom_level"], "selection": ""},
178
+ "geographical": {"level": self.current_state["zoom_level"], "selection": ""},
179
+ "style": {"level": self.current_state["zoom_level"], "selection": ""},
180
+ "subject": {"level": self.current_state["zoom_level"], "selection": ""}
181
+ }
182
+
183
+ if zoom_context:
184
+ for key, value in zoom_context.items():
185
+ if key in current_zoom_states:
186
+ current_zoom_states[key]["selection"] = value
187
+
 
 
 
 
 
 
 
 
 
 
 
188
  response = self.client.chat.completions.create(
189
  model="mixtral-8x7b-32768",
190
  messages=[
191
+ {"role": "system", "content": "You are an expert art historian specializing in interactive exploration."},
192
+ {"role": "user", "content": CONTEXTUAL_ZOOM_PROMPT.format(
193
+ user_query=query,
194
+ current_zoom_states=json.dumps(current_zoom_states, indent=2)
195
+ )}
 
 
 
196
  ],
197
  temperature=0.1,
198
  max_tokens=2048
199
  )
200
 
201
  result = json.loads(response.choices[0].message.content)
 
 
 
 
 
202
  return result
203
 
204
  except Exception as e:
205
  print(f"Error in LLM response: {str(e)}")
206
+ return self.get_default_response()
207
+
208
+ def get_default_response(self):
209
+ return {
210
+ "analysis": {
211
+ "query_focus": "Default focus",
212
+ "historical_context": "Default historical context"
213
+ },
214
+ "axis_configurations": {
215
+ "temporal": {
216
+ "component": "st.slider",
217
+ "current_zoom": {
218
+ "level": "century",
219
+ "range": [1700, 2000],
220
+ "explanation": "Default time range"
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  },
222
+ "available_zooms": {
223
+ "in": {
224
+ "range": [1800, 1900],
225
+ "explanation": "Zoom in to see more detail"
 
 
 
 
 
 
 
 
226
  },
227
+ "out": {
228
+ "range": [1500, 2024],
229
+ "explanation": "Broader historical context"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
231
  }
232
+ },
233
+ "geographical": {
234
+ "current_zoom": {
235
+ "level": "continent",
236
+ "locations": [
237
+ {
238
+ "name": "Paris",
239
+ "lat": 48.8566,
240
+ "lon": 2.3522,
241
+ "relevance": "Default location"
242
+ }
243
+ ]
244
+ }
245
+ },
246
+ "style": {
247
+ "current_zoom": {
248
+ "level": "movement",
249
+ "options": ["Classical", "Modern"],
250
+ "explanation": "Default art movements"
251
+ }
252
  }
253
  }
254
+ }
255
 
256
  def create_interface(self):
257
  with gr.Blocks() as demo:
 
292
 
293
  def initial_search(query):
294
  config = self.get_llm_response(query)
 
 
295
 
296
+ # Access the correct nested structure
297
+ temporal_config = config["axis_configurations"]["temporal"]["current_zoom"]
298
+ geographical_config = config["axis_configurations"]["geographical"]["current_zoom"]
299
+ style_config = config["axis_configurations"]["style"]["current_zoom"]
300
+
301
+ # Create map figure
302
+ map_fig = self.create_map(geographical_config["locations"])
303
 
304
  return {
305
+ time_slider: temporal_config["range"],
306
  map_plot: map_fig,
307
+ style_select: gr.Dropdown(choices=style_config["options"]),
308
+ time_explanation: temporal_config["explanation"],
309
+ geo_explanation: geographical_config.get("explanation", ""),
310
+ style_explanation: style_config["explanation"]
311
  }
312
 
313
  def zoom_axis(query, axis_name, current_value):
314
  self.current_state["zoom_level"] += 1
 
 
315
  config = self.get_llm_response(
316
  query,
317
  zoom_context={axis_name: current_value}
318
  )
319
 
320
+ axis_config = config["axis_configurations"][axis_name]["current_zoom"]
321
+
322
  if axis_name == "temporal":
323
+ return {
324
+ time_slider: axis_config["range"],
325
+ time_explanation: axis_config["explanation"]
326
+ }
327
  elif axis_name == "geographical":
328
+ map_fig = self.create_map(axis_config["locations"])
329
+ return {
330
  map_plot: map_fig,
331
+ geo_explanation: axis_config.get("explanation", "")
332
+ }
333
+ else: # style
334
+ return {
335
+ style_select: gr.Dropdown(choices=axis_config["options"]),
336
+ style_explanation: axis_config["explanation"]
337
+ }
 
338
 
339
  # Connect event handlers
340
  search_btn.click(
341
  fn=initial_search,
342
  inputs=[query],
343
+ outputs=[
344
+ time_slider,
345
+ map_plot,
346
+ style_select,
347
+ time_explanation,
348
+ geo_explanation,
349
+ style_explanation
350
+ ]
351
  )
352
 
353
  time_zoom.click(