Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,8 @@ from dotenv import load_dotenv
|
|
5 |
from art_explorer import ExplorationPathGenerator
|
6 |
from typing import Dict, Any, Optional, Union
|
7 |
from datetime import datetime
|
|
|
|
|
8 |
|
9 |
# Load environment variables
|
10 |
load_dotenv()
|
@@ -19,6 +21,57 @@ except Exception as e:
|
|
19 |
print(f"Error initializing ExplorationPathGenerator: {e}")
|
20 |
raise
|
21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
def format_output(result: Dict[str, Any]) -> str:
|
23 |
"""Format the exploration result for display with error handling"""
|
24 |
try:
|
@@ -31,13 +84,7 @@ def format_output(result: Dict[str, Any]) -> str:
|
|
31 |
}, indent=2)
|
32 |
|
33 |
def parse_json_input(json_str: str, default_value: Any) -> Any:
|
34 |
-
"""
|
35 |
-
Safely parse JSON input with detailed error handling
|
36 |
-
|
37 |
-
Args:
|
38 |
-
json_str: JSON string to parse
|
39 |
-
default_value: Fallback value if parsing fails
|
40 |
-
"""
|
41 |
if not json_str or json_str.strip() in ('', '{}', '[]'):
|
42 |
return default_value
|
43 |
try:
|
@@ -53,7 +100,7 @@ def validate_parameters(
|
|
53 |
) -> Dict[str, Any]:
|
54 |
"""Validate and merge exploration parameters"""
|
55 |
validated_params = {
|
56 |
-
"depth": max(1, min(10, depth)),
|
57 |
"domain": domain if domain.strip() else None,
|
58 |
"previous_explorations": []
|
59 |
}
|
@@ -67,48 +114,34 @@ def explore(
|
|
67 |
parameters: str = "{}",
|
68 |
depth: int = 5,
|
69 |
domain: str = ""
|
70 |
-
) -> str:
|
71 |
-
"""
|
72 |
-
Generate exploration path based on user input with comprehensive error handling
|
73 |
-
|
74 |
-
Args:
|
75 |
-
query (str): User's exploration query
|
76 |
-
path_history (str): JSON string of previous exploration path
|
77 |
-
parameters (str): JSON string of exploration parameters
|
78 |
-
depth (int): Exploration depth parameter (1-10)
|
79 |
-
domain (str): Specific domain context
|
80 |
-
|
81 |
-
Returns:
|
82 |
-
str: Formatted JSON string of exploration results or error message
|
83 |
-
"""
|
84 |
try:
|
85 |
-
# Input validation
|
86 |
if not query.strip():
|
87 |
raise ValueError("Query cannot be empty")
|
88 |
|
89 |
-
# Parse and validate inputs
|
90 |
selected_path = parse_json_input(path_history, [])
|
91 |
custom_parameters = parse_json_input(parameters, {})
|
92 |
-
|
93 |
-
# Validate and merge parameters
|
94 |
exploration_parameters = validate_parameters(depth, domain, custom_parameters)
|
95 |
|
96 |
-
# Debug logging
|
97 |
print(f"Processing query: {query}")
|
98 |
print(f"Parameters: {json.dumps(exploration_parameters, indent=2)}")
|
99 |
|
100 |
-
# Generate exploration path - FIXED HERE: changed user_query to query
|
101 |
result = generator.generate_exploration_path(
|
102 |
-
query=query,
|
103 |
selected_path=selected_path,
|
104 |
exploration_parameters=exploration_parameters
|
105 |
)
|
106 |
|
107 |
-
# Validate result
|
108 |
if not isinstance(result, dict):
|
109 |
raise ValueError("Invalid response format from generator")
|
110 |
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
112 |
|
113 |
except Exception as e:
|
114 |
error_response = {
|
@@ -122,101 +155,88 @@ def explore(
|
|
122 |
}
|
123 |
}
|
124 |
print(f"Error in explore function: {e}")
|
125 |
-
return format_output(error_response)
|
126 |
|
127 |
-
def create_interface() -> gr.
|
128 |
-
"""Create and configure the Gradio interface
|
129 |
|
130 |
-
|
131 |
-
gr.
|
132 |
-
label="Exploration Query",
|
133 |
-
placeholder="Enter your art history exploration query...",
|
134 |
-
lines=2
|
135 |
-
),
|
136 |
-
gr.Textbox(
|
137 |
-
label="Path History (JSON)",
|
138 |
-
placeholder="[]",
|
139 |
-
lines=3,
|
140 |
-
value="[]"
|
141 |
-
),
|
142 |
-
gr.Textbox(
|
143 |
-
label="Additional Parameters (JSON)",
|
144 |
-
placeholder="{}",
|
145 |
-
lines=3,
|
146 |
-
value="{}"
|
147 |
-
),
|
148 |
-
gr.Slider(
|
149 |
-
label="Exploration Depth",
|
150 |
-
minimum=1,
|
151 |
-
maximum=10,
|
152 |
-
value=5,
|
153 |
-
step=1
|
154 |
-
),
|
155 |
-
gr.Textbox(
|
156 |
-
label="Domain Context",
|
157 |
-
placeholder="Optional: Specify art history period or movement",
|
158 |
-
lines=1
|
159 |
-
)
|
160 |
-
]
|
161 |
-
|
162 |
-
output = gr.Textbox(
|
163 |
-
label="Exploration Result",
|
164 |
-
lines=20
|
165 |
-
)
|
166 |
-
|
167 |
-
examples = [
|
168 |
-
[
|
169 |
-
"Explore the evolution of Renaissance painting techniques",
|
170 |
-
"[]",
|
171 |
-
"{}",
|
172 |
-
5,
|
173 |
-
"Renaissance"
|
174 |
-
],
|
175 |
-
[
|
176 |
-
"Investigate the influence of Japanese art on Impressionism",
|
177 |
-
"[]",
|
178 |
-
"{}",
|
179 |
-
7,
|
180 |
-
"Impressionism"
|
181 |
-
],
|
182 |
-
[
|
183 |
-
"Analyze the development of Cubism through Picasso's work",
|
184 |
-
"[]",
|
185 |
-
"{}",
|
186 |
-
6,
|
187 |
-
"Cubism"
|
188 |
-
]
|
189 |
-
]
|
190 |
-
|
191 |
-
return gr.Interface(
|
192 |
-
fn=explore,
|
193 |
-
inputs=inputs,
|
194 |
-
outputs=output,
|
195 |
-
title="Art History Exploration Path Generator",
|
196 |
-
description="""Generate structured exploration paths for art history queries.
|
197 |
|
198 |
## Features:
|
199 |
- Dynamic exploration path generation
|
200 |
- Contextual understanding of art history
|
201 |
- Multi-dimensional analysis
|
202 |
- Customizable exploration depth
|
|
|
203 |
|
204 |
## Usage:
|
205 |
1. Enter your art history query
|
206 |
2. Adjust exploration depth (1-10)
|
207 |
3. Optionally specify domain context
|
208 |
-
4. View generated exploration path"""
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
|
214 |
if __name__ == "__main__":
|
215 |
try:
|
216 |
print(f"===== Application Startup at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} =====")
|
217 |
-
# Create interface
|
218 |
-
|
219 |
-
|
220 |
-
iface.launch()
|
221 |
except Exception as e:
|
222 |
print(f"Failed to launch interface: {e}")
|
|
|
5 |
from art_explorer import ExplorationPathGenerator
|
6 |
from typing import Dict, Any, Optional, Union
|
7 |
from datetime import datetime
|
8 |
+
import networkx as nx
|
9 |
+
import matplotlib.pyplot as plt
|
10 |
|
11 |
# Load environment variables
|
12 |
load_dotenv()
|
|
|
21 |
print(f"Error initializing ExplorationPathGenerator: {e}")
|
22 |
raise
|
23 |
|
24 |
+
def create_graph_visualization(nodes):
|
25 |
+
"""Create a graph visualization from exploration nodes"""
|
26 |
+
try:
|
27 |
+
# Create a new directed graph
|
28 |
+
G = nx.DiGraph()
|
29 |
+
|
30 |
+
# Add nodes to the graph
|
31 |
+
for node in nodes:
|
32 |
+
G.add_node(node['id'],
|
33 |
+
title=node['title'],
|
34 |
+
description=node['description'],
|
35 |
+
depth=node['depth'])
|
36 |
+
|
37 |
+
# Add edges based on connections
|
38 |
+
for node in nodes:
|
39 |
+
for conn in node['connections']:
|
40 |
+
G.add_edge(node['id'],
|
41 |
+
conn['target_id'],
|
42 |
+
weight=conn.get('relevance_score', 0))
|
43 |
+
|
44 |
+
# Create the plot
|
45 |
+
plt.figure(figsize=(12, 8))
|
46 |
+
|
47 |
+
# Use different colors for different depths
|
48 |
+
colors = ['#FF9999', '#99FF99', '#9999FF', '#FFFF99']
|
49 |
+
node_colors = [colors[G.nodes[node]['depth'] % len(colors)] for node in G.nodes()]
|
50 |
+
|
51 |
+
# Create layout
|
52 |
+
pos = nx.spring_layout(G, k=1, iterations=50)
|
53 |
+
|
54 |
+
# Draw the graph
|
55 |
+
nx.draw(G, pos,
|
56 |
+
node_color=node_colors,
|
57 |
+
with_labels=True,
|
58 |
+
labels={node: G.nodes[node]['title'] for node in G.nodes()},
|
59 |
+
node_size=2000,
|
60 |
+
font_size=8,
|
61 |
+
font_weight='bold',
|
62 |
+
arrows=True,
|
63 |
+
edge_color='gray',
|
64 |
+
width=1)
|
65 |
+
|
66 |
+
# Save to a temporary file
|
67 |
+
plt.savefig('temp_graph.png', format='png', dpi=300, bbox_inches='tight')
|
68 |
+
plt.close()
|
69 |
+
|
70 |
+
return 'temp_graph.png'
|
71 |
+
except Exception as e:
|
72 |
+
print(f"Error creating graph visualization: {e}")
|
73 |
+
return None
|
74 |
+
|
75 |
def format_output(result: Dict[str, Any]) -> str:
|
76 |
"""Format the exploration result for display with error handling"""
|
77 |
try:
|
|
|
84 |
}, indent=2)
|
85 |
|
86 |
def parse_json_input(json_str: str, default_value: Any) -> Any:
|
87 |
+
"""Safely parse JSON input with detailed error handling"""
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
if not json_str or json_str.strip() in ('', '{}', '[]'):
|
89 |
return default_value
|
90 |
try:
|
|
|
100 |
) -> Dict[str, Any]:
|
101 |
"""Validate and merge exploration parameters"""
|
102 |
validated_params = {
|
103 |
+
"depth": max(1, min(10, depth)),
|
104 |
"domain": domain if domain.strip() else None,
|
105 |
"previous_explorations": []
|
106 |
}
|
|
|
114 |
parameters: str = "{}",
|
115 |
depth: int = 5,
|
116 |
domain: str = ""
|
117 |
+
) -> tuple[str, Optional[str]]:
|
118 |
+
"""Generate exploration path and visualization"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
try:
|
|
|
120 |
if not query.strip():
|
121 |
raise ValueError("Query cannot be empty")
|
122 |
|
|
|
123 |
selected_path = parse_json_input(path_history, [])
|
124 |
custom_parameters = parse_json_input(parameters, {})
|
|
|
|
|
125 |
exploration_parameters = validate_parameters(depth, domain, custom_parameters)
|
126 |
|
|
|
127 |
print(f"Processing query: {query}")
|
128 |
print(f"Parameters: {json.dumps(exploration_parameters, indent=2)}")
|
129 |
|
|
|
130 |
result = generator.generate_exploration_path(
|
131 |
+
query=query,
|
132 |
selected_path=selected_path,
|
133 |
exploration_parameters=exploration_parameters
|
134 |
)
|
135 |
|
|
|
136 |
if not isinstance(result, dict):
|
137 |
raise ValueError("Invalid response format from generator")
|
138 |
|
139 |
+
# Create graph visualization if we have nodes
|
140 |
+
graph_path = None
|
141 |
+
if result.get("nodes"):
|
142 |
+
graph_path = create_graph_visualization(result["nodes"])
|
143 |
+
|
144 |
+
return format_output(result), graph_path
|
145 |
|
146 |
except Exception as e:
|
147 |
error_response = {
|
|
|
155 |
}
|
156 |
}
|
157 |
print(f"Error in explore function: {e}")
|
158 |
+
return format_output(error_response), None
|
159 |
|
160 |
+
def create_interface() -> gr.Blocks:
|
161 |
+
"""Create and configure the Gradio interface"""
|
162 |
|
163 |
+
with gr.Blocks(title="Art History Exploration Path Generator") as interface:
|
164 |
+
gr.Markdown("""# Art History Exploration Path Generator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
|
166 |
## Features:
|
167 |
- Dynamic exploration path generation
|
168 |
- Contextual understanding of art history
|
169 |
- Multi-dimensional analysis
|
170 |
- Customizable exploration depth
|
171 |
+
- Interactive visualization
|
172 |
|
173 |
## Usage:
|
174 |
1. Enter your art history query
|
175 |
2. Adjust exploration depth (1-10)
|
176 |
3. Optionally specify domain context
|
177 |
+
4. View generated exploration path and visualization""")
|
178 |
+
|
179 |
+
with gr.Row():
|
180 |
+
with gr.Column():
|
181 |
+
query_input = gr.Textbox(
|
182 |
+
label="Exploration Query",
|
183 |
+
placeholder="Enter your art history exploration query...",
|
184 |
+
lines=2
|
185 |
+
)
|
186 |
+
path_history = gr.Textbox(
|
187 |
+
label="Path History (JSON)",
|
188 |
+
placeholder="[]",
|
189 |
+
lines=3,
|
190 |
+
value="[]"
|
191 |
+
)
|
192 |
+
parameters = gr.Textbox(
|
193 |
+
label="Additional Parameters (JSON)",
|
194 |
+
placeholder="{}",
|
195 |
+
lines=3,
|
196 |
+
value="{}"
|
197 |
+
)
|
198 |
+
depth = gr.Slider(
|
199 |
+
label="Exploration Depth",
|
200 |
+
minimum=1,
|
201 |
+
maximum=10,
|
202 |
+
value=5,
|
203 |
+
step=1
|
204 |
+
)
|
205 |
+
domain = gr.Textbox(
|
206 |
+
label="Domain Context",
|
207 |
+
placeholder="Optional: Specify art history period or movement",
|
208 |
+
lines=1
|
209 |
+
)
|
210 |
+
generate_btn = gr.Button("Generate Exploration Path")
|
211 |
+
|
212 |
+
with gr.Column():
|
213 |
+
text_output = gr.JSON(label="Exploration Result")
|
214 |
+
graph_output = gr.Image(label="Exploration Graph")
|
215 |
+
|
216 |
+
examples = [
|
217 |
+
["Explore the evolution of Renaissance painting techniques", "[]", "{}", 5, "Renaissance"],
|
218 |
+
["Investigate the influence of Japanese art on Impressionism", "[]", "{}", 7, "Impressionism"],
|
219 |
+
["Analyze the development of Cubism through Picasso's work", "[]", "{}", 6, "Cubism"]
|
220 |
+
]
|
221 |
+
|
222 |
+
gr.Examples(
|
223 |
+
examples=examples,
|
224 |
+
inputs=[query_input, path_history, parameters, depth, domain]
|
225 |
+
)
|
226 |
+
|
227 |
+
generate_btn.click(
|
228 |
+
fn=explore,
|
229 |
+
inputs=[query_input, path_history, parameters, depth, domain],
|
230 |
+
outputs=[text_output, graph_output]
|
231 |
+
)
|
232 |
+
|
233 |
+
return interface
|
234 |
|
235 |
if __name__ == "__main__":
|
236 |
try:
|
237 |
print(f"===== Application Startup at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} =====")
|
238 |
+
# Create and launch interface
|
239 |
+
demo = create_interface()
|
240 |
+
demo.launch()
|
|
|
241 |
except Exception as e:
|
242 |
print(f"Failed to launch interface: {e}")
|