alexanderHSG commited on
Commit
d927a2f
·
1 Parent(s): 16db7ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -28
app.py CHANGED
@@ -7,6 +7,10 @@ import pandas as pd
7
  import numpy as np
8
  from sklearn.metrics.pairwise import cosine_similarity
9
  from dotenv import load_dotenv
 
 
 
 
10
 
11
  load_dotenv()
12
 
@@ -21,6 +25,7 @@ driver = GraphDatabase.driver(neo4j_url, auth=AUTH)
21
 
22
 
23
 
 
24
 
25
 
26
 
@@ -57,6 +62,7 @@ def format_chat_prompt(message, chat_history, max_convo_length):
57
 
58
  #this is a simple prompt that takes a storyline prompt and formats an output in json to return a storyline of X slides.
59
  def slide_deck_storyline(storyline_prompt, nr_of_storypoints=5):
 
60
  nr_of_storypoints = str(nr_of_storypoints)
61
  system_prompt = f"""You are an AI particularly skilled at captivating storytelling for educational purposes.
62
  You know how tell a compelling, structure and exhaustive narrative around any given academic topic.
@@ -94,6 +100,7 @@ def slide_deck_storyline(storyline_prompt, nr_of_storypoints=5):
94
 
95
  return map, storypoint_name_nested
96
 
 
97
  #this is a prompt that takes a filter prompt and formats an output in json to return a filter cypress query.
98
  def custom_filtering(filter_prompt, current_cypher_query, neo4j_response):
99
 
@@ -132,12 +139,45 @@ def custom_filtering(filter_prompt, current_cypher_query, neo4j_response):
132
  )
133
  res = response.choices[0].message.content
134
  res = json.loads(res)
 
135
 
136
- html = construct_hmtl(query = res["cypherquery"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  print(res["cypherquery"])
 
139
 
140
- return html
141
 
142
 
143
 
@@ -218,6 +258,40 @@ def coordinate_simcalculation(storyline_output_storypoint_name_list):
218
 
219
  return HTMLoutput, highest_similarities, query
220
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  def get_neo4j_response(query):
222
  with driver.session() as session:
223
  result = session.run(query)
@@ -371,6 +445,11 @@ async () => {
371
  },
372
  SLIDE_DECK: {
373
  label: "title",
 
 
 
 
 
374
  [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
375
  static: {
376
  caption: "title",
@@ -566,7 +645,7 @@ css = """
566
  ## ---------------------------------------------------------------------------------------------------------------------
567
  graphVisual = gr.HTML()
568
  highest_similarities_gradio_list = gr.List(type="array", interactive=False, visible=False)
569
- nodeSelector = gr.Dropdown(label="Filter nodes", choices=["SLIDE_DECK", "SLIDE", "STORYPOINT"], value=["SLIDE_DECK", "SLIDE", "STORYPOINT"], multiselect=True, scale=1)
570
  filterBTN = gr.Button("Apply Filter")
571
 
572
  with gr.Blocks(title='Slide Inspo', js=scripts, head = js_call_draw, theme = gr.themes.Monochrome()).queue(default_concurrency_limit=1) as demo:
@@ -577,61 +656,79 @@ with gr.Blocks(title='Slide Inspo', js=scripts, head = js_call_draw, theme = gr.
577
  with gr.Row():
578
  queryPlaceholder = gr.Textbox(visible=False)
579
  responsePlaceholder = gr.Textbox(visible=False)
 
 
580
  with gr.Column(scale=1):
581
  gr.Markdown("""## 1. Input: 🔍
582
 
583
  **Define Your Workshop Objective.**
584
  Choose a topic that is timely and fills a skill gap relevant to your consulting firm’s strategic goals.
585
  Define learning goals that focus on acquiring skills applicable in real-world consulting scenarios.
586
- Consider how mastering these skills can innovate and enhance your firm’s service offerings, aligning with emerging market needs and providing a competitive edge.
 
 
 
587
  """)
588
- storyline_prompt = gr.Textbox(placeholder = 'Give us a topic and we will provide a storyline for you! For example: "SCRUM in Software Development"',
 
 
 
 
 
 
 
 
589
  label = 'Topic to build:',
590
  lines=5,
591
  scale = 3)
592
- nr_storypoints_to_build = gr.Number(value=5,
593
  label="How many story points?",
594
  scale =1)
595
  storyline_output_JSON = gr.JSON(visible=False)
596
 
597
- btn = gr.Button("Build Storyline 🦄")
598
 
599
  with gr.Column(scale=1):
600
  gr.Markdown("""## 2. Storyline: 🦄
601
 
602
- **Content Requirements and Story Points.**
603
- Develop content that supports your workshop’s learning goals, using theories, case studies, and real-world applications.
604
- **Story Points Explained.**
605
- Story points are key milestones in your presentation that underline important learning outcomes. Adapt them to emphasize skills and insights crucial for your firm’s services.
606
- **Evaluating Story Points.**
607
- Effective story points are clear, engaging, and directly tied to your objectives. They should advance understanding and skill acquisition.
608
- **Optimal Number.**
609
- Choose 5 to 10 story points based on the topic's complexity. Fewer, detailed points suit in-depth topics, while more points work for broader overviews.
610
  """)
611
- storyline_output_storypoint_name_list = gr.List(visible=True, type="array", interactive=True, label="Adapt and add Story points, if needed: 📝", scale=1, wrap=True, col_count=[2, "fixed"], elem_id="SPList", headers=["#SP", "Description"])
 
612
  #storyline_output_pretty = gr.Textbox(label="Your Storyline:", lines=13, scale=3, interactive=False)
613
  submit_button = gr.Button("⚡ Find Slides ⚡", elem_id="visGraph")
614
- submit_button.click(fn= coordinate_simcalculation, inputs=[storyline_output_storypoint_name_list], outputs=[graphVisual, highest_similarities_gradio_list, queryPlaceholder]).then(js = js_call_draw).then(get_neo4j_response, inputs=[queryPlaceholder], outputs=[responsePlaceholder])
 
 
615
 
616
 
617
 
618
- btn.click(slide_deck_storyline,
619
  inputs = [storyline_prompt, nr_storypoints_to_build],
620
- outputs = [storyline_output_JSON, storyline_output_storypoint_name_list])
 
 
 
621
 
622
  storyline_prompt.submit(slide_deck_storyline,
623
  inputs = [storyline_prompt, nr_storypoints_to_build],
624
- outputs = [storyline_output_JSON, storyline_output_storypoint_name_list])
 
 
 
625
 
626
  gr.Markdown("""## 3. Visualize and Filter: 🔍
627
 
628
- Utilize the graph database to align the retrieved data with the objectives and story points defined in Steps 1 and 2:
629
- **Filtering the Graph.**
630
  Apply filters to better understand the retrieved slides and content that directly correspond to the established learning goals and story points.
631
  **Exploring the Graph.**
632
- Explore relationships and connections within the graph to ensure comprehensive coverage and to identify potential enhancements for your narrative.
633
  **Refinements.**
634
- Should gaps or misalignments be discovered during exploration, revisit Steps 1 and 2 to adjust the learning goals or story points. Then, reapply these refined criteria to filter and explore the graph again, ensuring the presentation content is optimally tailored and coherent.
635
  """)
636
 
637
 
@@ -639,11 +736,16 @@ Choose 5 to 10 story points based on the topic's complexity. Fewer, detailed poi
639
  with gr.Column(scale=2):
640
  nodeSelector.render()
641
  filterBTN.render()
642
- filterBTN.click(fn= construct_hmtl, inputs=[highest_similarities_gradio_list, nodeSelector], outputs=[graphVisual]).then(js = js_call_draw)
 
 
643
  with gr.Column(scale=2):
644
- custom_filtering_output = gr.Textbox( lines=10, scale=3, interactive=False, label = "Describe what you would like to filter for?", placeholder = "For example: 'Show me all slides of the slide decks of the second story point.'")
645
  customfilter_btn = gr.Button("Apply custom filter")
646
- customfilter_btn.click(custom_filtering, inputs=[custom_filtering_output, queryPlaceholder, responsePlaceholder], outputs=[graphVisual]).then(js = js_call_draw)
 
 
 
647
  with gr.Group():
648
  with gr.Row():
649
  graphVisual.render()
@@ -654,4 +756,4 @@ Choose 5 to 10 story points based on the topic's complexity. Fewer, detailed poi
654
 
655
 
656
  gr.close_all()
657
- demo.launch()
 
7
  import numpy as np
8
  from sklearn.metrics.pairwise import cosine_similarity
9
  from dotenv import load_dotenv
10
+ import sqlite3
11
+ from datetime import datetime
12
+ import re
13
+
14
 
15
  load_dotenv()
16
 
 
25
 
26
 
27
 
28
+ user_id = None
29
 
30
 
31
 
 
62
 
63
  #this is a simple prompt that takes a storyline prompt and formats an output in json to return a storyline of X slides.
64
  def slide_deck_storyline(storyline_prompt, nr_of_storypoints=5):
65
+ print("hi")
66
  nr_of_storypoints = str(nr_of_storypoints)
67
  system_prompt = f"""You are an AI particularly skilled at captivating storytelling for educational purposes.
68
  You know how tell a compelling, structure and exhaustive narrative around any given academic topic.
 
100
 
101
  return map, storypoint_name_nested
102
 
103
+
104
  #this is a prompt that takes a filter prompt and formats an output in json to return a filter cypress query.
105
  def custom_filtering(filter_prompt, current_cypher_query, neo4j_response):
106
 
 
139
  )
140
  res = response.choices[0].message.content
141
  res = json.loads(res)
142
+ cypher_query = res["cypherquery"]
143
 
144
+ # Enhanced pattern to catch variations including potential spaces, newlines, and mixed cases
145
+ pattern = r"(?i)\b(CREATE|SET|DELETE|REMOVE|MERGE)\s*(\(|\[|\{)?"
146
+
147
+ # Split the query into individual statements based on semicolons
148
+ statements = cypher_query.split(';')
149
+
150
+ # Further process each statement to check for conditional or nested writes
151
+ def is_write_statement(statement):
152
+ # Check if the statement includes write operations
153
+ if re.search(pattern, statement):
154
+ return True
155
+ # Check for potentially hidden write operations within sub-queries or function calls
156
+ nested_patterns = [
157
+ r"FOREACH\s*\(([^)]+)\)", # Looking inside FOREACH loops
158
+ r"CASE\s+WHEN\s+[^:]+:\s+[^:]+ELSE\s+[^:]+END", # Checking CASE statements
159
+ r"CALL\s+[^()]+(\(.*\))?YIELD\s+[^()]+", # Checking CALL statements
160
+ ]
161
+ for nested_pattern in nested_patterns:
162
+ if re.search(nested_pattern, statement, re.IGNORECASE | re.DOTALL):
163
+ # Recursively check inside the nested statement
164
+ match = re.search(nested_pattern, statement, re.IGNORECASE | re.DOTALL)
165
+ if match and is_write_statement(match.group(1)):
166
+ return True
167
+ return False
168
+
169
+ # Filter statements that contain write operations
170
+ filtered_statements = [stmt for stmt in statements if not is_write_statement(stmt)]
171
+
172
+ # Join the filtered statements back into a single query string
173
+ filtered_query = '; '.join(filtered_statements)
174
+
175
+ html = construct_hmtl(query = filtered_query)
176
 
177
  print(res["cypherquery"])
178
+ print(filtered_query)
179
 
180
+ return html, filtered_query
181
 
182
 
183
 
 
258
 
259
  return HTMLoutput, highest_similarities, query
260
 
261
+ def track_user_interaction(user_input, action):
262
+ global user_id
263
+
264
+ user_id = str(user_id)
265
+ connection = sqlite3.connect('user_interactions.db')
266
+ cursor = connection.cursor()
267
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
268
+ user_input_str = str(user_input)
269
+ action_str = str(action)
270
+ # Escape single quotes by replacing them with two single quotes
271
+ user_input_str = user_input_str.replace("'", "''")
272
+ action_str = action_str.replace("'", "''")
273
+ cursor.execute('''
274
+ CREATE TABLE IF NOT EXISTS user_interactions (
275
+ user_input TEXT NOT NULL,
276
+ action TEXT NOT NULL,
277
+ timestamp TEXT NOT NULL,
278
+ user_id TEXT NOT NULL
279
+ );
280
+ ''')
281
+ insert_query = "INSERT INTO user_interactions (user_input, action, timestamp, user_id) VALUES ('" + user_input_str + "', '" + action_str + "', '" + timestamp + "', '" + user_id + "')"
282
+
283
+ cursor.execute(insert_query)
284
+ connection.commit()
285
+ connection.close()
286
+
287
+ def profile_user(username, password):
288
+ global user_id
289
+ user_id = username
290
+ track_user_interaction("", "login")
291
+ return True
292
+
293
+
294
+
295
  def get_neo4j_response(query):
296
  with driver.session() as session:
297
  result = session.run(query)
 
445
  },
446
  SLIDE_DECK: {
447
  label: "title",
448
+
449
+ title: function(node) {
450
+ // This function returns HTML content that will be shown as tooltip
451
+ return `<b>Name:</b> ${node.properties.title}<br/>;
452
+ }
453
  [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
454
  static: {
455
  caption: "title",
 
645
  ## ---------------------------------------------------------------------------------------------------------------------
646
  graphVisual = gr.HTML()
647
  highest_similarities_gradio_list = gr.List(type="array", interactive=False, visible=False)
648
+ nodeSelector = gr.Dropdown(scale = 3, label="Filter nodes", choices=["SLIDE_DECK", "SLIDE", "STORYPOINT"], value=["SLIDE_DECK", "SLIDE", "STORYPOINT"], multiselect=True)
649
  filterBTN = gr.Button("Apply Filter")
650
 
651
  with gr.Blocks(title='Slide Inspo', js=scripts, head = js_call_draw, theme = gr.themes.Monochrome()).queue(default_concurrency_limit=1) as demo:
 
656
  with gr.Row():
657
  queryPlaceholder = gr.Textbox(visible=False)
658
  responsePlaceholder = gr.Textbox(visible=False)
659
+ user_id = gr.Textbox(visible=False)
660
+ customFilterQuery = gr.Textbox(visible=False)
661
  with gr.Column(scale=1):
662
  gr.Markdown("""## 1. Input: 🔍
663
 
664
  **Define Your Workshop Objective.**
665
  Choose a topic that is timely and fills a skill gap relevant to your consulting firm’s strategic goals.
666
  Define learning goals that focus on acquiring skills applicable in real-world consulting scenarios.
667
+ Consider how mastering these skills can innovate and enhance your firm’s service offerings, aligning with emerging market needs and providing a competitive edge.
668
+ *Our AI takes care to draft story points based on your input.*
669
+ **What are Story Points?**
670
+ Story points are key milestones in your presentation that underline important learning outcomes. You can adapt them in the next step to cover skills and insights crucial for your firm’s services.
671
  """)
672
+ storyline_prompt = gr.Textbox(placeholder = """Give us a topic and we will provide a storyline for you! For example:
673
+
674
+ Topic: AI enhancements for decision-making and process automation across multiple sectors such as finance, healthcare, and retail.
675
+
676
+ Goals: Equip participants with the ability to apply AI techniques practically to solve industry-specific challenges.
677
+
678
+ Implementation: Explore and integrate AI-driven solutions tailored to each sector, enhancing the firm’s service offerings.
679
+
680
+ Outcome: Fellow consultant will develop a comprehensive understanding of AI's potential and capabilities. This knowledge will enable consultants to effectively identify and propose AI-driven solutions.""",
681
  label = 'Topic to build:',
682
  lines=5,
683
  scale = 3)
684
+ nr_storypoints_to_build = gr.Number(value=3,
685
  label="How many story points?",
686
  scale =1)
687
  storyline_output_JSON = gr.JSON(visible=False)
688
 
689
+ btn_buildstoryline = gr.Button("Build Storyline 🦄")
690
 
691
  with gr.Column(scale=1):
692
  gr.Markdown("""## 2. Storyline: 🦄
693
 
694
+ **Content Requirements and Story Points.**
695
+ Develop content that supports your workshop’s learning goals, using theories, case studies, and real-world applications.
696
+ **Evaluating Story Points.**
697
+ Effective story points are clear, engaging, and directly tied to your objectives. They should advance understanding and skill acquisition.
 
 
 
 
698
  """)
699
+ storyline_output_storypoint_name_list = gr.List(visible=True, type="array", interactive=True, label="Adapt and add Story points, if needed: 📝",
700
+ scale=1, wrap=True, col_count=[2, "fixed"], elem_id="SPList", headers=["#SP", "Description"])
701
  #storyline_output_pretty = gr.Textbox(label="Your Storyline:", lines=13, scale=3, interactive=False)
702
  submit_button = gr.Button("⚡ Find Slides ⚡", elem_id="visGraph")
703
+ submit_button.click(fn= coordinate_simcalculation, inputs=[storyline_output_storypoint_name_list], outputs=[graphVisual, highest_similarities_gradio_list, queryPlaceholder]
704
+ ).then(track_user_interaction, inputs=[storyline_output_storypoint_name_list, gr.Textbox("find slides", visible=False)]
705
+ ).then(js = js_call_draw).then(get_neo4j_response, inputs=[queryPlaceholder], outputs=[responsePlaceholder])
706
 
707
 
708
 
709
+ btn_buildstoryline.click(slide_deck_storyline,
710
  inputs = [storyline_prompt, nr_storypoints_to_build],
711
+ outputs = [storyline_output_JSON, storyline_output_storypoint_name_list]
712
+ ).then(track_user_interaction, inputs=[storyline_prompt, gr.Textbox("build storyline prompt", visible=False)]
713
+ ).then(track_user_interaction, inputs=[storyline_output_storypoint_name_list, gr.Textbox("build storyline gpt output", visible=False)]
714
+ ).then(track_user_interaction, inputs=[nr_storypoints_to_build, gr.Textbox("build storyline number of points", visible=False)])
715
 
716
  storyline_prompt.submit(slide_deck_storyline,
717
  inputs = [storyline_prompt, nr_storypoints_to_build],
718
+ outputs = [storyline_output_JSON, storyline_output_storypoint_name_list]
719
+ ).then(track_user_interaction, inputs=[storyline_prompt, gr.Textbox("build storyline prompt", visible=False)]
720
+ ).then(track_user_interaction, inputs=[storyline_output_storypoint_name_list, gr.Textbox("build storyline gpt output", visible=False)]
721
+ ).then(track_user_interaction, inputs=[nr_storypoints_to_build, gr.Textbox("build storyline number of points", visible=False)])
722
 
723
  gr.Markdown("""## 3. Visualize and Filter: 🔍
724
 
725
+ Utilize the visualization to align the retrieved slides and storypoints with the objectives and story points defined in Steps 1 and 2:
726
+ **Filtering the Visualization.**
727
  Apply filters to better understand the retrieved slides and content that directly correspond to the established learning goals and story points.
728
  **Exploring the Graph.**
729
+ Explore relationships within the slide decks, slides, and story points to ensure comprehensive coverage and to identify potential inspiration for your narrative.
730
  **Refinements.**
731
+ Should gaps or misalignments be discovered during exploration, revisit Steps 1 and 2 to adjust the learning goals or story points. Then, reapply these refined criteria to filter and explore the visualization again, ensuring the presentation content is tailored and coherent.
732
  """)
733
 
734
 
 
736
  with gr.Column(scale=2):
737
  nodeSelector.render()
738
  filterBTN.render()
739
+ filterBTN.click(fn= construct_hmtl, inputs=[highest_similarities_gradio_list, nodeSelector], outputs=[graphVisual]).then(track_user_interaction, inputs=[nodeSelector, gr.Textbox("filterDropdown", visible=False)]
740
+ ).then(js = js_call_draw)
741
+
742
  with gr.Column(scale=2):
743
+ custom_filtering_output = gr.Textbox(lines=2, scale=3, interactive=True, label = "Describe what you would like to filter for?", placeholder = """For example: """)
744
  customfilter_btn = gr.Button("Apply custom filter")
745
+ customfilter_btn.click(custom_filtering, inputs=[custom_filtering_output, queryPlaceholder, responsePlaceholder], outputs=[graphVisual, customFilterQuery]
746
+ ).then(track_user_interaction, inputs=[custom_filtering_output, gr.Textbox("customFilterPrompt", visible=False)]
747
+ ).then(track_user_interaction, inputs=[customFilterQuery, gr.Textbox("customFilterQuery", visible=False)]).then(js = js_call_draw)
748
+
749
  with gr.Group():
750
  with gr.Row():
751
  graphVisual.render()
 
756
 
757
 
758
  gr.close_all()
759
+ demo.launch(show_api=False, auth_message = "Hello there! Please log in to access the NarrativeNet Weaver using your Prolific ID as username. The password can be blank.", auth=profile_user)