Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| from pathlib import Path | |
| import gradio as gr | |
| from typing import Any, Callable | |
| import contextvars | |
| from uw_programmatic.uw_machine import UWMachine | |
| from uw_programmatic.csv_to_markdown import convert_csv_to_markdown | |
| import pandas as pd | |
| from dotenv import load_dotenv | |
| import os | |
| # Used to ensure that EventBus works across Gradio and the StateMachine. | |
| def run_with_context(func: Callable) -> Callable: | |
| ctx = contextvars.copy_context() | |
| def wrapper(*args, **kwargs) -> Any: | |
| return ctx.run(func, *args, **kwargs) | |
| return wrapper | |
| # Runs the state machine - sends the parameters over and kicks off the whole process. | |
| def generate_questions( | |
| page_lower, page_higher, question_number, taxonomy | |
| ) -> tuple[str, gr.DownloadButton, gr.DownloadButton]: | |
| if machine.value and machine.value.current_state_value == "start": | |
| machine.value.start_machine() # Start the machine! | |
| if not question_number or question_number <= 0: | |
| msg = "Choose a valid question number." | |
| raise gr.Error(msg) | |
| if not page_lower or not page_higher or page_higher < page_lower: | |
| msg = "Choose a valid page range." | |
| raise gr.Error(msg) | |
| if page_higher - page_lower <= 6: | |
| msg = "Page range must be >6." | |
| raise gr.Error(msg) | |
| if not taxonomy or len(taxonomy) == 0: | |
| msg = "Choose at least one taxonomy." | |
| raise gr.Error(msg) | |
| try: | |
| machine.value.send( | |
| "process_event", | |
| event_={ | |
| "type": "user_input", | |
| "value": { | |
| "page_range": (page_lower, page_higher), | |
| "question_number": question_number, | |
| "taxonomy": taxonomy, | |
| }, | |
| }, | |
| ) | |
| except AttributeError: | |
| create_statemachine() | |
| machine.value.start_machine() | |
| machine.value.send( | |
| "process_event", | |
| event_={ | |
| "type": "user_input", | |
| "value": { | |
| "page_range": (page_lower, page_higher), | |
| "question_number": question_number, | |
| "taxonomy": taxonomy, | |
| }, | |
| }, | |
| ) | |
| button = gr.DownloadButton( | |
| label="Download Questions", | |
| visible=True, | |
| scale=1, | |
| value=f"{Path.cwd().joinpath('outputs/professor_guide.csv')}", | |
| ) | |
| button_2 = gr.DownloadButton( | |
| visible=True, | |
| value=f"{Path.cwd().joinpath('outputs/rejected_list.csv')}", | |
| scale=1, | |
| label="Download Rejected Questions", | |
| ) | |
| markdown = "## Questions Ready for Download Below" | |
| if machine.value.errored: | |
| button = gr.update(visible=False) | |
| button_2 = gr.update(visible=False) | |
| markdown = "## Questions Not Ready for Download" | |
| exception = "Bad Page Range Selected" | |
| raise gr.Error(exception) | |
| # After questions are generated, read the CSV file | |
| csv_path = Path.cwd().joinpath("outputs/professor_guide.csv") | |
| if csv_path.exists(): | |
| checkFrame = pd.read_csv(csv_path, usecols=[0], header=None) | |
| checkFrame.columns = ["Check"] | |
| if checkFrame.iloc[0]["Check"] != "Failed to generate more questions." and checkFrame.iloc[0]["Check"] != "Too many rejected questions.": | |
| # Generate markdown content | |
| markdown_content = convert_csv_to_markdown(csv_path) | |
| return ( | |
| markdown, | |
| button, | |
| button_2, | |
| gr.update(value=markdown_content, visible=True) | |
| ) | |
| else: | |
| return (markdown, button, button_2, gr.update(visible=False)) | |
| else: | |
| return (markdown, button, button_2, gr.update(visible=False)) | |
| def create_statemachine() -> None: | |
| # Creates UWMachine from the config.yaml in current directory | |
| cwd_path = Path.cwd() / "uw_programmatic" | |
| config_path = cwd_path.joinpath(Path("config.yaml")) | |
| try: | |
| machine.value = UWMachine.from_config_file(config_path) | |
| except Exception as e: | |
| raise gr.Error(str(e)) from e | |
| def questions_downloaded() -> dict[str, Any]: | |
| return gr.update(visible=False) | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# UW Quiz Generator") | |
| machine = gr.State(value=None) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| taxonomy = gr.CheckboxGroup( | |
| choices=["Knowledge", "Comprehension", "Application"], | |
| label="Taxonomy", | |
| value="Knowledge", | |
| ) | |
| question_number = gr.Number( | |
| minimum=1, maximum=25, label="Number of Questions", value=3 | |
| ) | |
| gr.Markdown("For Textbook - Pages 1-348") | |
| with gr.Row(): | |
| page_lower = gr.Number( | |
| label="First Page", minimum=1, value=1, maximum=348 | |
| ) | |
| page_higher = gr.Number( | |
| label="Last Page", minimum=1, value=348, maximum=348 | |
| ) | |
| start_button = gr.Button(value="Generate Questions", scale=1) | |
| with gr.Column(scale=1): | |
| output = gr.Markdown("## Questions Not Ready for Download", visible=True) | |
| download_professor = gr.DownloadButton( | |
| label="Download Questions", visible=False, scale=1 | |
| ) | |
| download_failures = gr.DownloadButton( | |
| label="Download Failed Questions", visible=False, scale=1 | |
| ) | |
| with gr.Row(): | |
| #Markdown component to display generated questions as an ordered list | |
| question_output = gr.Markdown(visible=False) | |
| # State machine must be initialized in gr.Blocks for the context wrapper to work. | |
| create_statemachine() | |
| start_button.click( | |
| fn=run_with_context(generate_questions), | |
| inputs=[page_lower, page_higher, question_number, taxonomy], | |
| outputs=[output, download_professor, download_failures, question_output], | |
| ) | |
| download_professor.click( | |
| fn=run_with_context(questions_downloaded), outputs=[download_professor] | |
| ) | |
| download_failures.click( | |
| fn=run_with_context(questions_downloaded), outputs=[download_failures] | |
| ) | |
| load_dotenv() | |
| demo.launch( | |
| share=True, | |
| ssr_mode=False, | |
| auth=(os.environ.get("HF_USERNAME", ""), os.environ.get("HF_PASSWORD", "")), | |
| ) | |
| #demo.launch() | |