From 9a80f840bf5e15e330b5f2c5746d8123ed2d5bbc Mon Sep 17 00:00:00 2001 From: manishshettym Date: Fri, 23 Feb 2024 00:35:40 +0000 Subject: [PATCH] fix UX during search --- codescholar/apps/app_decl.py | 19 ++- codescholar/apps/streamlit_app.py | 200 ++++++++++++++++-------------- 2 files changed, 124 insertions(+), 95 deletions(-) diff --git a/codescholar/apps/app_decl.py b/codescholar/apps/app_decl.py index 13a745d..3961a54 100644 --- a/codescholar/apps/app_decl.py +++ b/codescholar/apps/app_decl.py @@ -96,9 +96,22 @@ def search(): # search_main(args) return flask.jsonify( - { - "status": "CodeScholar is now growing idioms for this API. Please try again in ~2 mins." - } + {"status": "CodeScholar is now growing idioms for this API."} + ) + + +@scholarapp.route("/search_status", methods=["GET"]) +def search_status(): + api = flask.request.args.get("api") + # Check if the idioms for the API are ready + # This could involve checking a file, database, or cache status + idioms_dir = osp.join(api_cache_dir, api, "idioms", "progs") + idioms_ready = osp.exists(idioms_dir) and len(os.listdir(idioms_dir)) > 0 + if idioms_ready: + return flask.jsonify({"status": "ready"}) + else: + return flask.jsonify( + {"status": "CodeScholar is now growing idioms for this API."} ) diff --git a/codescholar/apps/streamlit_app.py b/codescholar/apps/streamlit_app.py index e4d15f5..1a4969a 100644 --- a/codescholar/apps/streamlit_app.py +++ b/codescholar/apps/streamlit_app.py @@ -1,3 +1,4 @@ +import os import re import math import json @@ -5,7 +6,7 @@ import numpy as np from collections import namedtuple import altair as alt - +import time import requests import streamlit as st import streamlit.components.v1 as components @@ -97,6 +98,18 @@ def search_selected(): st.session_state["input_type"] = "search" +def check_search_status(api): + response = requests.get(f"http://{endpoint}/search_status", params={"api": api}) + return response.json() + + +def get_idioms(api, size): + response = requests.post( + f"http://{endpoint}/search", json={"api": api, "size": size} + ) + return response.json() + + API = None """ @@ -105,12 +118,11 @@ def search_selected(): Further it also provides *LLM plugins* to automatically clean the idiom or generate some simple runnable code using it! """ -with open(f"{root}/codescholar/apps/app_bench.json") as f: - benchmarks = json.load(f) - +api_dirs = [d for d in os.listdir("cache") if os.path.isdir(f"./cache/{d}")] api_options = set() -for lib in benchmarks: - for api in benchmarks[lib]: +for api in api_dirs: + api_progs = os.path.join("cache", api, "idioms", "progs") + if os.path.exists(api_progs) and len(os.listdir(api_progs)) > 0: api_options.add(api) st.session_state.dropdown_api = st.selectbox( @@ -161,97 +173,101 @@ def search_selected(): size = st.slider("Choose the size of your idiom:", 4, 20, 4) +status_placeholder = st.empty() + with st.spinner("Growing your idioms ๐ŸŒฑ..."): - response = requests.post( - f"http://{endpoint}/search", json={"api": API, "size": size} - ) - idioms = response.json() + idioms = get_idioms(API, size) + status = check_search_status(API)["status"] + i = 0 + while status != "ready": + status_placeholder.info(f"[{i}] {API} API is new to CodeScholar! {status}") + time.sleep(5) + status = check_search_status(API)["status"] + i += 1 + + status_placeholder.empty() + idioms = get_idioms(API, size) + + +if len(idioms) == 0: + st.error("No idioms found for API: {} ๐Ÿซ™".format(API)) +else: + idioms = [ + v + for k, v in sorted( + idioms.items(), key=lambda item: int(item[1]["freq"]), reverse=True + ) + ] + tabs = st.tabs(["Idiom {}".format(i + 1) for i in range(len(idioms))]) + + for idiom, tab in zip(idioms, tabs): + with tab: + st.write("๐ŸŽ“: Found this idiom in {} programs!".format(idiom["freq"])) + highlighted_idiom_html = highlight_code_with_html(idiom["idiom"]) + maxh = max(100, min(30 * idiom["idiom"].count("\n"), 500)) + components.html(highlighted_idiom_html, height=maxh, scrolling=True) + + colbut1, colbut2 = st.columns([0.25, 0.8]) + with colbut1: + but1 = st.button("Clean this idiom?", key=f"clean_{tabs.index(tab)}") + with colbut2: + but2 = st.button( + "Code with this idiom?", key=f"write_{tabs.index(tab)}" + ) - if "status" in idioms: - st.info("{} API is new to CodeScholar! {}".format(API, idioms["status"])) - elif len(idioms) == 0: - st.error("No idioms found for API: {} ๐Ÿซ™".format(API)) - else: - idioms = [ - v - for k, v in sorted( - idioms.items(), key=lambda item: int(item[1]["freq"]), reverse=True - ) - ] - tabs = st.tabs(["Idiom {}".format(i + 1) for i in range(len(idioms))]) - - for idiom, tab in zip(idioms, tabs): - with tab: - st.write("๐ŸŽ“: Found this idiom in {} programs!".format(idiom["freq"])) - highlighted_idiom_html = highlight_code_with_html(idiom["idiom"]) - maxh = max(100, min(30 * idiom["idiom"].count("\n"), 500)) - components.html(highlighted_idiom_html, height=maxh, scrolling=True) - - colbut1, colbut2 = st.columns([0.25, 0.8]) - with colbut1: - but1 = st.button( - "Clean this idiom?", key=f"clean_{tabs.index(tab)}" + if but1: + with st.spinner("Cleaning your idioms ๐Ÿงน..."): + response = requests.post( + f"http://{endpoint}/clean", + json={"api": API, "idiom": idiom["idiom"]}, ) - with colbut2: - but2 = st.button( - "Code with this idiom?", key=f"write_{tabs.index(tab)}" + # st.error("This feature is not available yet! ๐Ÿซ™") + st.code(response.json()["idiom"], language="python") + if but2: + with st.spinner("Writing some code ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป..."): + response = requests.post( + f"http://{endpoint}/write", + json={"api": API, "idiom": idiom["idiom"]}, ) + # st.error("This feature is not available yet! ๐Ÿซ™") + st.code(response.json()["idiom"], language="python") - if but1: - with st.spinner("Cleaning your idioms ๐Ÿงน..."): - response = requests.post( - f"http://{endpoint}/clean", - json={"api": API, "idiom": idiom["idiom"]}, - ) - # st.error("This feature is not available yet! ๐Ÿซ™") - st.code(response.json()["idiom"], language="python") - if but2: - with st.spinner("Writing some code ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป..."): - response = requests.post( - f"http://{endpoint}/write", - json={"api": API, "idiom": idiom["idiom"]}, - ) - # st.error("This feature is not available yet! ๐Ÿซ™") - st.code(response.json()["idiom"], language="python") - - st.divider() - - """ - ##### CodeScholar Suggestions - """ - with st.spinner("Analyzing your idioms ๐Ÿ“Š..."): - response = requests.post(f"http://{endpoint}/plot", json={"api": API}) - - metrics = response.json() - metrics_df = pd.DataFrame( - { - "size": metrics["sizes"], - "cluster": metrics["clusters"], - "freq": metrics["freq"], - } - ) + st.divider() - x = metrics_df["size"].unique() - y1 = np.log(metrics_df.groupby("size")["cluster"].nunique()) - y2 = np.log(metrics_df.groupby("size")["freq"].mean()) + """ + ##### CodeScholar Suggestions + """ + with st.spinner("Analyzing your idioms ๐Ÿ“Š..."): + response = requests.post(f"http://{endpoint}/plot", json={"api": API}) + + metrics = response.json() + metrics_df = pd.DataFrame( + { + "size": metrics["sizes"], + "cluster": metrics["clusters"], + "freq": metrics["freq"], + } + ) - try: - ideal_size = np.where(y1 > y2)[0][0] + 3 - except IndexError: - pass - else: - chart_data = pd.DataFrame( - {"Size (Expressivity)": sorted(x), "Diversity": y1, "Reusability": y2} - ) - chart_data = chart_data[chart_data["Reusability"] > 0] + x = metrics_df["size"].unique() + y1 = np.log(metrics_df.groupby("size")["cluster"].nunique()) + y2 = np.log(metrics_df.groupby("size")["freq"].mean()) - col1, col2 = st.columns([2, 1]) - col1.line_chart( - chart_data, x="Size (Expressivity)", y=["Diversity", "Reusability"] - ) - col2.write( - "Ideal Idiom Size is **{} (ยฑ 1)** for {}".format(ideal_size, API) - ) - col2.write( - "At this size, reusability, diversity, and expressivity are at an equilibrium!!" - ) + try: + ideal_size = np.where(y1 > y2)[0][0] + 3 + except IndexError: + pass + else: + chart_data = pd.DataFrame( + {"Size (Expressivity)": sorted(x), "Diversity": y1, "Reusability": y2} + ) + chart_data = chart_data[chart_data["Reusability"] > 0] + + col1, col2 = st.columns([2, 1]) + col1.line_chart( + chart_data, x="Size (Expressivity)", y=["Diversity", "Reusability"] + ) + col2.write("Ideal Idiom Size is **{} (ยฑ 1)** for {}".format(ideal_size, API)) + col2.write( + "At this size, reusability, diversity, and expressivity are at an equilibrium!!" + )