import os
import json
import gradio as gr
from datetime import datetime
from dotenv import load_dotenv
from openai import OpenAI
from prompts import SYSTEM_PROMPT, format_exploration_prompt
# Load environment variables
load_dotenv()
class ExplorationPathGenerator:
def __init__(self, api_key: str):
self.client = OpenAI(
api_key=api_key,
base_url="https://api.groq.com/openai/v1"
)
def generate_exploration_path(self, query: str, selected_path=None, exploration_parameters=None):
try:
if selected_path is None:
selected_path = []
if exploration_parameters is None:
exploration_parameters = {}
# Use the prompt from prompt.py
formatted_prompt = format_exploration_prompt(
user_query=query,
selected_path=selected_path,
exploration_parameters=exploration_parameters
)
response = self.client.chat.completions.create(
model="mixtral-8x7b-32768",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": formatted_prompt}
],
temperature=0.7,
max_tokens=4000
)
result = json.loads(response.choices[0].message.content)
# Convert exploration response to graph format
nodes = []
node_id_counter = 0
# Add meta insights as central node
node_id_counter += 1
meta_node = {
"id": f"meta_{node_id_counter}",
"title": "Exploration Summary",
"description": result["exploration_summary"]["current_context"],
"depth": 0,
"connections": []
}
nodes.append(meta_node)
# Create nodes from standard axes
for axis in result["knowledge_axes"]["standard_axes"]:
node_id_counter += 1
axis_node = {
"id": f"std_{node_id_counter}",
"title": axis["name"],
"description": f"Current values: {', '.join(axis['current_values'])}",
"depth": 1,
"connections": []
}
# Connect to meta node
meta_node["connections"].append({
"target_id": axis_node["id"],
"relevance_score": 0.8
})
# Add potential values as nodes
for value in axis["potential_values"]:
node_id_counter += 1
value_node = {
"id": f"val_{node_id_counter}",
"title": value["value"],
"description": value["contextual_rationale"],
"depth": 2,
"connections": []
}
nodes.append(value_node)
axis_node["connections"].append({
"target_id": value_node["id"],
"relevance_score": value["relevance_score"] / 100
})
nodes.append(axis_node)
# Create nodes from emergent axes
for axis in result["knowledge_axes"]["emergent_axes"]:
node_id_counter += 1
emergent_node = {
"id": f"emg_{node_id_counter}",
"title": f"{axis['name']} (Emergent)",
"description": f"Parent axis: {axis['parent_axis']}",
"depth": 2,
"connections": []
}
# Connect to meta node
meta_node["connections"].append({
"target_id": emergent_node["id"],
"relevance_score": 0.6
})
# Add innovative values
for value in axis["innovative_values"]:
node_id_counter += 1
value_node = {
"id": f"inv_{node_id_counter}",
"title": value["value"],
"description": value["discovery_potential"],
"depth": 3,
"connections": []
}
nodes.append(value_node)
emergent_node["connections"].append({
"target_id": value_node["id"],
"relevance_score": value["innovation_score"] / 100
})
nodes.append(emergent_node)
return {"nodes": nodes}
except Exception as e:
print(f"Error generating exploration path: {e}")
return {"error": str(e)}
def create_visualization_html(self, nodes):
"""Create a simple HTML visualization"""
html_content = "
"
# Create a style for the nodes
html_content += """
"""
# Create nodes visualization
for node in nodes:
depth_color = ['#FF9999', '#99FF99', '#9999FF'][node['depth'] % 3]
html_content += f"""
Depth: {node['depth']}
{node['title']}
{node['description']}
"""
# Add connections
if node.get('connections'):
html_content += "
Connections:"
for conn in node['connections']:
html_content += f"- Connected to: {conn['target_id']}"
if 'relevance_score' in conn:
html_content += f" (Relevance: {conn['relevance_score']:.2f})"
html_content += "
"
html_content += "
"
html_content += "
"
html_content += "
"
return html_content
def explore(query: str, path_history: str = "[]", parameters: str = "{}", depth: int = 5, domain: str = "") -> tuple:
"""Generate exploration path and visualization"""
try:
# Initialize generator
api_key = os.getenv("GROQ_API_KEY")
if not api_key:
raise ValueError("GROQ_API_KEY not found in environment variables")
generator = ExplorationPathGenerator(api_key=api_key)
# Parse inputs
try:
selected_path = json.loads(path_history)
exploration_parameters = json.loads(parameters)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON input: {str(e)}")
# Add parameters
exploration_parameters.update({
"domain": domain,
"depth": depth
})
# Generate result
result = generator.generate_exploration_path(
query=query,
selected_path=selected_path,
exploration_parameters=exploration_parameters
)
# Create visualization
graph_html = generator.create_visualization_html(result.get('nodes', []))
summary = f"Exploration path generated with {len(result.get('nodes', []))} nodes"
return json.dumps(result), graph_html, summary
except Exception as e:
error_response = {
"error": str(e),
"status": "failed",
"timestamp": datetime.now().isoformat(),
"query": query
}
return json.dumps(error_response), "Error generating visualization
", f"Error: {str(e)}"
def create_interface() -> gr.Blocks:
"""Create and configure the Gradio interface"""
with gr.Blocks(
title="Art History Exploration Path Generator",
theme=gr.themes.Soft()
) as interface:
gr.Markdown("""
# Knowledge Exploration Path Generator
Generate interactive exploration paths through complex topics.
""")
with gr.Row():
with gr.Column(scale=1):
query_input = gr.Textbox(
label="Exploration Query",
placeholder="Enter your exploration query...",
lines=2
)
depth = gr.Slider(
label="Exploration Depth",
minimum=1,
maximum=10,
value=5,
step=1
)
domain = gr.Textbox(
label="Domain Context",
placeholder="Optional: Specify domain context",
lines=1
)
generate_btn = gr.Button("Generate Exploration Path", variant="primary")
with gr.Column(scale=2):
text_output = gr.JSON(label="Raw Result")
graph_output = gr.HTML(label="Visualization")
summary_output = gr.Textbox(label="Summary", lines=2)
generate_btn.click(
fn=explore,
inputs=[
query_input,
gr.Textbox(value="[]", visible=False),
gr.Textbox(value="{}", visible=False),
depth,
domain
],
outputs=[text_output, graph_output, summary_output]
)
return interface
if __name__ == "__main__":
try:
print(f"===== Application Startup at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} =====")
demo = create_interface()
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=True
)
except Exception as e:
print(f"Failed to launch interface: {e}")