harris1 commited on
Commit
408ec72
1 Parent(s): e4daf67

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -106
app.py CHANGED
@@ -285,11 +285,13 @@
285
 
286
  # if __name__ == "__main__":
287
  # iface.launch()
288
- import gradio as gr
289
  import os
290
  from mistralai.client import MistralClient
291
  from mistralai.models.chat_completion import ChatMessage
292
 
 
 
293
  # Mistral AI setup
294
  api_key = os.getenv("MISTRAL_API_KEY")
295
  if not api_key:
@@ -308,8 +310,6 @@ def generate_goals(input_var):
308
  except Exception as e:
309
  return f"An error occurred: {str(e)}"
310
 
311
-
312
- # HTML content with interactive visualization
313
  html_content = """
314
  <!DOCTYPE html>
315
  <html lang="en">
@@ -328,8 +328,9 @@ html_content = """
328
  <div id="visualization"></div>
329
  <div id="generatedGoals"></div>
330
  <script>
331
- // Define the goals and connections data
332
- const goals = [
 
333
  { id: 1, x: 100, y: 400, name: "Automate Data Import", description: "Develop scripts to automate exam data extraction from various sources (CSV, Excel, databases) using Pandas read_* functions." },
334
  { id: 2, x: 200, y: 300, name: "Data Cleaning", description: "Implement robust data cleaning processes to handle missing values, outliers, and inconsistencies in exam data using Pandas methods like dropna(), fillna(), and apply()." },
335
  { id: 3, x: 300, y: 200, name: "Data Transformation", description: "Utilize Pandas for complex data transformations such as pivoting exam results, melting question-wise scores, and creating derived features for analysis." },
@@ -404,61 +405,38 @@ html_content = """
404
  { source: 24, target: 17 },
405
  { source: 26, target: 29 }
406
  ];
407
- // Create the SVG container for the goals and connections
408
- const svg = d3.select("#goalSpace")
409
- .append("svg")
410
- .attr("width", width)
411
- .attr("height", height);
412
- // Draw connections between goals
413
- const links = svg.selectAll("line")
414
- .data(connections)
415
- .enter()
416
- .append("line")
417
- .attr("x1", d => goals.find(g => g.id === d.source).x)
418
- .attr("y1", d => goals.find(g => g.id === d.source).y)
419
- .attr("x2", d => goals.find(g => g.id === d.target).x)
420
- .attr("y2", d => goals.find(g => g.id === d.target).y)
421
- .attr("stroke", "#999")
422
- .attr("stroke-width", 1)
423
- .attr("stroke-opacity", 0.6);
424
- // Draw goal nodes
425
- const goalNodes = svg.selectAll("circle")
426
- .data(goals)
427
- .enter()
428
- .append("circle")
429
- .attr("cx", d => d.x)
430
- .attr("cy", d => d.y)
431
- .attr("r", 10)
432
- .attr("fill", d => {
433
- if (d.id <= 10) return "blue";
434
- if (d.id <= 20) return "green";
435
- return "orange";
436
- })
437
- .attr("class", "goal");
438
- // Add labels to the goals
439
- const goalLabels = svg.selectAll("text")
440
- .data(goals)
441
- .enter()
442
- .append("text")
443
- .attr("x", d => d.x + 15)
444
- .attr("y", d => d.y)
445
- .text(d => d.name)
446
- .attr("font-size", "12px");
447
- // Hover info box
448
- const hoverInfo = d3.select("#hoverInfo");
449
- // Add hover effects on goal nodes
450
- goalNodes.on("mouseover", function(event, d) {
451
- d3.select(this).attr("r", 15);
452
- hoverInfo.style("display", "block")
453
- .style("left", (event.pageX + 10) + "px")
454
- .style("top", (event.pageY - 10) + "px")
455
- .html(`<strong>${d.name}</strong><br>${d.description}`);
456
- }).on("mouseout", function() {
457
- d3.select(this).attr("r", 10);
458
- hoverInfo.style("display", "none");
459
- });
460
-
461
-
462
  node.on("click", async function(event, d) {
463
  const response = await fetch('/generate_goals', {
464
  method: 'POST',
@@ -468,55 +446,47 @@ html_content = """
468
  const data = await response.json();
469
  document.getElementById("generatedGoals").innerHTML = `<h2>Generated Goals for ${d.name}</h2><pre>${data.goals}</pre>`;
470
  });
471
-
472
- // Function to update selected goal information
473
- function updateSelectedGoalInfo(goal) {
474
- const selectedGoalDiv = d3.select("#selectedGoal");
475
- selectedGoalDiv.html(`
476
- <h3>${goal.name}</h3>
477
- <p>${goal.description}</p>
478
- `);
479
- }
480
- // Function to display the response from the server
481
- function displayResponse(content) {
482
- const responseBox = d3.select("#responseBox");
483
- responseBox.html(`
484
- <h2>Response</h2>
485
- <p>${content}</p>
486
- `);
487
- }
488
- // Handle mouse move event to highlight the closest goal
489
- svg.on("mousemove", function(event) {
490
- const [x, y] = d3.pointer(event);
491
- const closest = findClosestGoal(x, y);
492
- highlightClosestGoal(closest);
493
- });
494
- // Function to find the closest goal to the mouse pointer
495
- function findClosestGoal(x, y) {
496
- return goals.reduce((closest, goal) => {
497
- const distance = Math.sqrt(Math.pow(goal.x - x, 2) + Math.pow(goal.y - y, 2));
498
- return distance < closest.distance ? { goal, distance } : closest;
499
- }, { goal: null, distance: Infinity }).goal;
500
- }
501
- // Function to highlight the closest goal
502
- function highlightClosestGoal(goal) {
503
- d3.select("#info").html(`Closest goal: ${goal.name}`);
504
- }
505
-
506
  </script>
507
  </body>
508
  </html>
509
  """
510
 
511
- # Gradio interface
512
- iface = gr.Interface(
513
- fn=generate_goals,
514
- inputs="text",
515
- outputs="text",
516
- title="Exam Data Analysis Goals Generator",
517
- description="Click on a goal in the visualization to generate related goals.",
518
- article=html_content
519
- )
520
 
521
- # Launch the Gradio app
522
- iface.launch()
 
285
 
286
  # if __name__ == "__main__":
287
  # iface.launch()
288
+ from flask import Flask, request, jsonify, render_template_string
289
  import os
290
  from mistralai.client import MistralClient
291
  from mistralai.models.chat_completion import ChatMessage
292
 
293
+ app = Flask(__name__)
294
+
295
  # Mistral AI setup
296
  api_key = os.getenv("MISTRAL_API_KEY")
297
  if not api_key:
 
310
  except Exception as e:
311
  return f"An error occurred: {str(e)}"
312
 
 
 
313
  html_content = """
314
  <!DOCTYPE html>
315
  <html lang="en">
 
328
  <div id="visualization"></div>
329
  <div id="generatedGoals"></div>
330
  <script>
331
+ const width = 1200;
332
+ const height = 800;
333
+ const goals = [
334
  { id: 1, x: 100, y: 400, name: "Automate Data Import", description: "Develop scripts to automate exam data extraction from various sources (CSV, Excel, databases) using Pandas read_* functions." },
335
  { id: 2, x: 200, y: 300, name: "Data Cleaning", description: "Implement robust data cleaning processes to handle missing values, outliers, and inconsistencies in exam data using Pandas methods like dropna(), fillna(), and apply()." },
336
  { id: 3, x: 300, y: 200, name: "Data Transformation", description: "Utilize Pandas for complex data transformations such as pivoting exam results, melting question-wise scores, and creating derived features for analysis." },
 
405
  { source: 24, target: 17 },
406
  { source: 26, target: 29 }
407
  ];
408
+ const svg = d3.select("#visualization")
409
+ .append("svg")
410
+ .attr("width", width)
411
+ .attr("height", height);
412
+ const simulation = d3.forceSimulation(goals)
413
+ .force("link", d3.forceLink(connections).id(d => d.id))
414
+ .force("charge", d3.forceManyBody().strength(-400))
415
+ .force("center", d3.forceCenter(width / 2, height / 2));
416
+ const link = svg.append("g")
417
+ .selectAll("line")
418
+ .data(connections)
419
+ .enter().append("line")
420
+ .attr("stroke", "#999")
421
+ .attr("stroke-opacity", 0.6);
422
+ const node = svg.append("g")
423
+ .selectAll("circle")
424
+ .data(goals)
425
+ .enter().append("circle")
426
+ .attr("r", 10)
427
+ .attr("fill", d => d.color)
428
+ .call(d3.drag()
429
+ .on("start", dragstarted)
430
+ .on("drag", dragged)
431
+ .on("end", dragended));
432
+ const text = svg.append("g")
433
+ .selectAll("text")
434
+ .data(goals)
435
+ .enter().append("text")
436
+ .text(d => d.name)
437
+ .attr("font-size", "12px")
438
+ .attr("dx", 12)
439
+ .attr("dy", 4);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
440
  node.on("click", async function(event, d) {
441
  const response = await fetch('/generate_goals', {
442
  method: 'POST',
 
446
  const data = await response.json();
447
  document.getElementById("generatedGoals").innerHTML = `<h2>Generated Goals for ${d.name}</h2><pre>${data.goals}</pre>`;
448
  });
449
+ simulation.on("tick", () => {
450
+ link
451
+ .attr("x1", d => d.source.x)
452
+ .attr("y1", d => d.source.y)
453
+ .attr("x2", d => d.target.x)
454
+ .attr("y2", d => d.target.y);
455
+ node
456
+ .attr("cx", d => d.x)
457
+ .attr("cy", d => d.y);
458
+ text
459
+ .attr("x", d => d.x)
460
+ .attr("y", d => d.y);
461
+ });
462
+ function dragstarted(event) {
463
+ if (!event.active) simulation.alphaTarget(0.3).restart();
464
+ event.subject.fx = event.subject.x;
465
+ event.subject.fy = event.subject.y;
466
+ }
467
+ function dragged(event) {
468
+ event.subject.fx = event.x;
469
+ event.subject.fy = event.y;
470
+ }
471
+ function dragended(event) {
472
+ if (!event.active) simulation.alphaTarget(0);
473
+ event.subject.fx = null;
474
+ event.subject.fy = null;
475
+ }
 
 
 
 
 
 
 
 
476
  </script>
477
  </body>
478
  </html>
479
  """
480
 
481
+ @app.route('/')
482
+ def index():
483
+ return render_template_string(html_content)
484
+
485
+ @app.route('/generate_goals', methods=['POST'])
486
+ def generate_goals_api():
487
+ input_var = request.json['input_var']
488
+ goals = generate_goals(input_var)
489
+ return jsonify({'goals': goals})
490
 
491
+ if __name__ == "__main__":
492
+ app.run(host='0.0.0.0', port=7860)