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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +245 -26
app.py CHANGED
@@ -4,6 +4,138 @@ import gradio as gr
4
  import json
5
  import plotly.graph_objects as go
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  class ArtExplorer:
8
  def __init__(self):
9
  self.client = openai.OpenAI(
@@ -38,32 +170,119 @@ class ArtExplorer:
38
  return fig
39
 
40
  def get_llm_response(self, query: str, zoom_context: dict = None) -> dict:
41
- system_prompt = """You are an art history expert. Generate a structured JSON configuration for an interactive art exploration interface."""
42
-
43
- user_prompt = f"""
44
- Query: {query}
45
- Zoom Level: {self.current_state['zoom_level']}
46
- Current Selections: {json.dumps(zoom_context) if zoom_context else 'None'}
47
-
48
- Return a JSON object with configurations for temporal, geographical, and style axes.
49
- Include exact coordinates for geographical locations in this format:
50
- "locations": [
51
- {{"name": "Paris", "lat": 48.8566, "lon": 2.3522, "description": "Center of French art"}},
52
- {{"name": "Florence", "lat": 43.7696, "lon": 11.2558, "description": "Renaissance art hub"}}
53
- ]
54
- """
55
-
56
- response = self.client.chat.completions.create(
57
- model="mixtral-8x7b-32768",
58
- messages=[
59
- {"role": "system", "content": system_prompt},
60
- {"role": "user", "content": user_prompt}
61
- ],
62
- temperature=0.1,
63
- max_tokens=1024
64
- )
65
-
66
- return json.loads(response.choices[0].message.content)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  def create_interface(self):
69
  with gr.Blocks() as demo:
 
4
  import json
5
  import plotly.graph_objects as go
6
 
7
+
8
+ CONTEXTUAL_ZOOM_PROMPT = """
9
+ You are an expert art historian specializing in interactive exploration. Analyze the query and generate contextually aware zoom configurations with explanations.
10
+
11
+ ###Input###
12
+ User Query: {user_query}
13
+ Current Zoom States: {
14
+ "temporal": {"level": "", "selection": ""},
15
+ "geographical": {"level": "", "selection": ""},
16
+ "style": {"level": "", "selection": ""},
17
+ "subject": {"level": "", "selection": ""}
18
+ }
19
+
20
+ ###Output Format###
21
+ {
22
+ "analysis": {
23
+ "query_focus": "main subject",
24
+ "historical_context": "brief explanation"
25
+ },
26
+ "axis_configurations": {
27
+ "temporal": {
28
+ "component": "st.slider",
29
+ "current_zoom": {
30
+ "level": "century/decade/year",
31
+ "range": [start, end],
32
+ "explanation": "Why this time range is relevant"
33
+ },
34
+ "available_zooms": {
35
+ "in": {
36
+ "range": [narrower_start, narrower_end],
37
+ "explanation": "What focusing here reveals"
38
+ },
39
+ "out": {
40
+ "range": [broader_start, broader_end],
41
+ "explanation": "Broader historical context"
42
+ }
43
+ },
44
+ "impacted_by": {
45
+ "geographical": "how location affects timeframe",
46
+ "style": "how style affects timeframe"
47
+ }
48
+ },
49
+ "geographical": {
50
+ "component": "st.map",
51
+ "current_zoom": {
52
+ "level": "continent/country/city",
53
+ "locations": [
54
+ {
55
+ "name": "",
56
+ "lat": 0,
57
+ "lon": 0,
58
+ "relevance": "why this location matters"
59
+ }
60
+ ]
61
+ },
62
+ "available_zooms": {
63
+ "in": {
64
+ "locations": ["more specific locations"],
65
+ "explanation": "What focusing here reveals"
66
+ },
67
+ "out": {
68
+ "locations": ["broader regions"],
69
+ "explanation": "Broader geographical context"
70
+ }
71
+ },
72
+ "impacted_by": {
73
+ "temporal": "how time period affects locations",
74
+ "style": "how style affects locations"
75
+ }
76
+ },
77
+ "style": {
78
+ "component": "st.multiselect" if current_zoom == "broad" else "st.selectbox",
79
+ "current_zoom": {
80
+ "level": "movement/sub_movement/specific",
81
+ "options": ["list of styles"],
82
+ "explanation": "Style context for this period/location"
83
+ }
84
+ }
85
+ },
86
+ "streamlit_adaptations": {
87
+ "recommended_components": {
88
+ "component_name": "reason for recommendation based on zoom level",
89
+ "configuration": {}
90
+ }
91
+ }
92
+ }
93
+
94
+ ###Example for "paint during napoleon war"###
95
+ {
96
+ "temporal": {
97
+ "component": "st.slider",
98
+ "current_zoom": {
99
+ "level": "period",
100
+ "range": [1799, 1815],
101
+ "explanation": "Napoleon's reign as First Consul and Emperor"[1]
102
+ },
103
+ "available_zooms": {
104
+ "in": {
105
+ "range": [1812, 1815],
106
+ "explanation": "Focus on final campaigns and artistic responses"[1]
107
+ }
108
+ }
109
+ },
110
+ "geographical": {
111
+ "component": "st.map",
112
+ "current_zoom": {
113
+ "level": "continent",
114
+ "locations": [
115
+ {
116
+ "name": "France",
117
+ "relevance": "Center of Napoleonic art production"[2]
118
+ },
119
+ {
120
+ "name": "Spain",
121
+ "relevance": "Goya's war paintings perspective"[1]
122
+ }
123
+ ]
124
+ }
125
+ }
126
+ }
127
+
128
+ ###Requirements###
129
+ 1. Explain zoom level changes and their historical significance
130
+ 2. Adapt Streamlit components based on zoom level
131
+ 3. Show relationships between different axes
132
+ 4. Provide historical context for available selections
133
+ 5. Consider how selections affect other axes
134
+ 6. Include relevant historical explanations for each zoom level
135
+
136
+ Generate only the JSON response, maintaining strict JSON format."""
137
+
138
+
139
  class ArtExplorer:
140
  def __init__(self):
141
  self.client = openai.OpenAI(
 
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: