|
import gradio as gr |
|
from huggingface_hub import InferenceClient |
|
|
|
|
|
def respond( |
|
message, |
|
history: list[dict[str, str]], |
|
system_message, |
|
max_tokens, |
|
temperature, |
|
top_p, |
|
hf_token: gr.OAuthToken, |
|
): |
|
""" |
|
For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference |
|
""" |
|
client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b") |
|
|
|
messages = [{"role": "system", "content": system_message}] |
|
|
|
messages.extend(history) |
|
|
|
messages.append({"role": "user", "content": message}) |
|
|
|
response = "" |
|
|
|
for message in client.chat_completion( |
|
messages, |
|
max_tokens=max_tokens, |
|
stream=True, |
|
temperature=temperature, |
|
top_p=top_p, |
|
): |
|
choices = message.choices |
|
token = "" |
|
if len(choices) and choices[0].delta.content: |
|
token = choices[0].delta.content |
|
|
|
response += token |
|
yield response |
|
|
|
|
|
|
|
|
|
with gr.Blocks( |
|
title="π L.C.A.R.S - Local Computer Advanced Reasoning System", |
|
theme='Yntec/HaleyCH_Theme_Orange_Green' |
|
) as demo: |
|
|
|
|
|
history_state = gr.State([]) |
|
|
|
|
|
|
|
|
|
|
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Image( |
|
value="https://cdn-avatars.huggingface.co/v1/production/uploads/65d883893a52cd9bcd8ab7cf/tRsCJlHNZo1D02kBTmfy9.jpeg", |
|
elem_id="lcars_logo", |
|
height=200, show_download_button=False,container=False, |
|
width=200 |
|
) |
|
with gr.Column(scale=3): |
|
gr.HTML(f""" |
|
<div style='text-align: center; padding: 20px; font-size: 24px; font-weight: bold; margin-bottom: 20px; |
|
border-radius: 0px 0px 15px 15px;'> |
|
π₯οΈ L.C.A.R.S - Local Computer Advanced Reasoning System |
|
<br><small style='font-size: 14px;'>USS Enterprise β’ NCC-1701-D β’ Starfleet Command</small> |
|
</div> |
|
""") |
|
|
|
|
|
|
|
|
|
|
|
with gr.Tabs(): |
|
|
|
|
|
|
|
|
|
with gr.TabItem(label="π€ L.C.A.R.S Chat Intelligence", elem_id="lcars_main_tab"): |
|
|
|
with gr.Row(): |
|
|
|
with gr.Column(scale=2): |
|
gr.HTML(f"<div style=' padding: 10px; font-weight: bold;'>π§ REASONING PROCESS</div>") |
|
with gr.Accordion(label="π§ Current AI Reasoning", open=False): |
|
thinking_html = gr.HTML(label="AI Thought Process", show_label=True) |
|
|
|
|
|
message = gr.Textbox( |
|
show_copy_button=True, |
|
lines=6, |
|
label="π¬ Ask L.C.A.R.S", |
|
placeholder="Enter your message to the Local Computer Advanced Reasoning System..." |
|
) |
|
|
|
|
|
with gr.Row(): |
|
submit_btn = gr.Button("π Ask L.C.A.R.S", variant="huggingface", size="lg") |
|
clear_btn = gr.Button("ποΈ Clear", variant="huggingface") |
|
|
|
|
|
with gr.Row(): |
|
speak_response = gr.Checkbox(label="π Speak Response", value=False) |
|
speak_thoughts = gr.Checkbox(label="π§ Speak Reasoning", value=False) |
|
|
|
|
|
with gr.Accordion(label="β‘ Utilitys Quick Actions", open=False): |
|
with gr.Row(): |
|
artifact_id_input = gr.Textbox( |
|
label="Artifact ID", |
|
placeholder="Artifact ID (0, 1, 2)", |
|
scale=2 |
|
) |
|
execute_artifact_btn = gr.Button("βΆοΈ Execute Artifact", variant="huggingface") |
|
|
|
with gr.Row(): |
|
batch_artifact_ids = gr.Textbox( |
|
label="Batch Execute IDs", |
|
placeholder="e.g., 0,1 or 0-5", |
|
scale=2 |
|
) |
|
batch_execute_btn = gr.Button("β‘Batch Execute", variant="huggingface") |
|
|
|
|
|
with gr.Column(scale=2): |
|
gr.HTML(f"<div style=font-weight: bold;'>SYSTEM RESPONSE</div>") |
|
|
|
with gr.Accordion(label="π€ Library Computer Advanced Reasoning System", open=True): |
|
plain_text_output = gr.Markdown( |
|
container=True, |
|
show_copy_button=True, |
|
label="AI Response", |
|
height=400 |
|
) |
|
|
|
execution_output = gr.HTML(f"<div style=font-weight: bold;'>π§ Execution Results</div>") |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Current Session</div>") |
|
|
|
|
|
with gr.Accordion(label="π Session Chat History", open=False): |
|
chat_history_display = gr.HTML(label="Full Session History", show_label=True) |
|
|
|
with gr.Accordion(label="π Current Session Artifacts", open=False): |
|
artifacts_display = gr.HTML(label="Generated Artifacts Timeline", show_label=True) |
|
|
|
|
|
with gr.Column(scale=2): |
|
gr.HTML(f"<div style=font-weight: bold;'>π§± ENHANCED CODE ARTIFACTS WORKSHOP</div>") |
|
|
|
with gr.Accordion(label="π§± Code Artifacts Workshop", open=True): |
|
|
|
code_artifacts = gr.Code( |
|
language="python", |
|
label="Generated Code & Artifacts", |
|
lines=10, |
|
interactive=True, |
|
autocomplete=True, |
|
show_line_numbers=True, |
|
elem_id="code_editor" |
|
) |
|
|
|
|
|
with gr.Row(): |
|
artifact_description = gr.Textbox( |
|
label="Artifact Description", |
|
placeholder="Brief description of the code...", |
|
scale=2 |
|
) |
|
artifact_language = gr.Dropdown( |
|
choices=["python", "javascript", "html", "css", "bash", "sql", "json"], |
|
value="python", |
|
label="Language", |
|
scale=1 |
|
) |
|
|
|
with gr.Row(): |
|
ExecuteCodePad_btn = gr.Button("βΆοΈ Execute Code", variant="huggingface") |
|
CreateArtifact_btn = gr.Button("π§± Save Artifact", variant="huggingface") |
|
|
|
with gr.Row(): |
|
LoadArtifact_btn = gr.Button("π Load Artifact", variant="huggingface") |
|
Load_artifact_id_input = gr.Textbox( |
|
label="Artifact ID", |
|
placeholder="ID to Load", |
|
scale=1 |
|
) |
|
|
|
|
|
with gr.TabItem("π οΈ Task Enabled AI"): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>π οΈ Function Tools</div>") |
|
with gr.Row(): |
|
with gr.Column(): |
|
tool_model_name = gr.Textbox( |
|
label="Tool-Capable Model", |
|
value="leroydyer/lcars/qwen3-0.6b-q4_k_m.gguf" |
|
) |
|
tool_prompt = gr.Textbox( |
|
label="Tool Request", |
|
value="What is the result of 123 + 456? Use the add tool.", |
|
lines=4 |
|
) |
|
tool_call_btn = gr.Button("π οΈ Execute Tool Call", variant="huggingface") |
|
|
|
with gr.Column(): |
|
tool_output = gr.Textbox(label="Tool Execution Results", lines=15) |
|
|
|
with gr.TabItem("π» System Tools", elem_id="system_tab"): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>π» System Tools</div>") |
|
with gr.Tabs(): |
|
|
|
|
|
with gr.TabItem("π Code Fragment"): |
|
gr.Markdown("### Analyze a Python code snippet") |
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
code_input = gr.Code( |
|
language="python", |
|
label="Python Code", |
|
lines=15 |
|
) |
|
fragment_name = gr.Textbox( |
|
label="Fragment Name (optional)", |
|
placeholder="my_code_snippet", |
|
value="code_fragment" |
|
) |
|
analyze_fragment_btn = gr.Button("π Analyze Code Fragment", variant="huggingface") |
|
with gr.Column(scale=3): |
|
fragment_output = gr.Markdown(label="### π Analysis Results") |
|
code_output = gr.Markdown("Results will appear here") |
|
fragment_download = gr.File(label="π₯ Download Report") |
|
|
|
|
|
with gr.TabItem("π Single File"): |
|
gr.Markdown("### Analyze a single Python file") |
|
|
|
with gr.Row(): |
|
with gr.Column(): |
|
file_input = gr.File( |
|
label="Upload Python File", |
|
file_types=[".py"], |
|
type="filepath" |
|
) |
|
analyze_file_btn = gr.Button("π Analyze File", variant="huggingface") |
|
|
|
with gr.Column(scale=2): |
|
gr.Markdown("### π Analysis Results") |
|
single_file_output = gr.Markdown("Results will appear here") |
|
|
|
file_output = gr.Markdown(label="Analysis Results") |
|
file_download = gr.File(label="π₯ Download Report") |
|
|
|
|
|
with gr.TabItem("π Directory"): |
|
with gr.Row(): |
|
gr.HTML(f""" |
|
<div style='text-align: center; font-size: 24px; font-weight: bold; margin-bottom: 20px; |
|
border-radius: 0px 0px 15px 15px;'> |
|
π₯οΈ Analyze an entire directory/project |
|
|
|
</div> |
|
""") |
|
|
|
with gr.Column(): |
|
gr.HTML(f""" |
|
<div style='text-align: center; padding: 20px; background: linear-gradient(90deg,; font-size: 24px; font-weight: bold; margin-bottom: 20px; |
|
border-radius: 0px 0px 15px 15px;'> |
|
<br><small style='font-size: 14px;'>βΉοΈ Directory Scanning Tips |
|
|
|
- Default excluded dirs: `__pycache__`, `.git`, `.venv` |
|
</small></br> |
|
</div> |
|
""") |
|
dir_input = gr.Textbox( |
|
label="Directory Path", |
|
placeholder="/path/to/your/project", |
|
lines=1 |
|
) |
|
with gr.Row(): |
|
recurse_check = gr.Checkbox(label="Include subdirectories", value=True) |
|
analyze_dir_btn = gr.Button("π Analyze Directory", variant="huggingface") |
|
exclude_dirs_input = gr.Textbox( |
|
label="Directories to Exclude (comma separated)", |
|
placeholder="tests, docs, examples", |
|
lines=1 |
|
) |
|
with gr.Column(): |
|
gr.Markdown("### π Scan Summary") |
|
summary_output = gr.Markdown("Scan results will appear here") |
|
with gr.Column(): |
|
gr.Markdown("### π Detailed Results") |
|
detailed_output = gr.Markdown("Detailed errors and fixes will appear here") |
|
dir_output = gr.Markdown(label="Analysis Results") |
|
dir_download = gr.File(label="π₯ Download Report") |
|
|
|
|
|
with gr.TabItem(label="π Enhanced Session & Artifact Management"): |
|
with gr.Row(): |
|
|
|
with gr.Column(): |
|
gr.HTML(f"<div style= padding: 8px; font-weight: bold;'>π SESSION MANAGEMENT</div>") |
|
|
|
session_status = gr.Textbox(label="Session Status", value="Ready", interactive=False) |
|
|
|
with gr.Row(): |
|
session_name_input = gr.Textbox( |
|
label="Session Name", |
|
placeholder="Leave empty for auto-naming (NewSession1, NewSession2...)", |
|
scale=2 |
|
) |
|
merge_session_checkbox = gr.Checkbox( |
|
label="Merge Mode", |
|
value=False, |
|
info="Merge with current session instead of replacing" |
|
) |
|
|
|
with gr.Row(): |
|
save_session_btn = gr.Button("πΎ Save Session", variant="huggingface") |
|
load_session_btn = gr.Button("π Load Session", variant="huggingface") |
|
|
|
session_dropdown = gr.Dropdown( |
|
label="Available Sessions", |
|
choices=["none"], |
|
interactive=True, |
|
info="Select session to load" |
|
) |
|
|
|
with gr.Row(): |
|
load_all_sessions_btn = gr.Button("π Load All Sessions", variant="huggingface") |
|
refresh_sessions_btn = gr.Button("π Refresh Sessions", variant="huggingface") |
|
|
|
|
|
with gr.Column(): |
|
gr.HTML(f"<div style= padding: 8px; font-weight: bold;'>π§± ARTIFACT MANAGEMENT</div>") |
|
|
|
artifact_status = gr.Textbox(label="Artifact Status", value="Ready", interactive=False) |
|
|
|
with gr.Row(): |
|
artifact_session_input = gr.Textbox( |
|
label="Artifact Session Name", |
|
placeholder="Leave empty to load all artifacts", |
|
scale=2 |
|
) |
|
merge_artifacts_checkbox = gr.Checkbox( |
|
label="Merge Artifacts", |
|
value=True, |
|
info="Add to current artifacts instead of replacing" |
|
) |
|
|
|
with gr.Row(): |
|
load_artifacts_btn = gr.Button("π Load Artifacts", variant="huggingface") |
|
|
|
|
|
artifact_dropdown = gr.Dropdown( |
|
label="Available Artifact Files", |
|
choices=["none"], |
|
interactive=True, |
|
info="Select artifact file to load" |
|
) |
|
|
|
with gr.Row(): |
|
load_all_artifacts_btn = gr.Button("π Load All Artifacts", variant="huggingface") |
|
refresh_artifacts_btn = gr.Button("π Refresh Artifacts", variant="huggingface") |
|
|
|
|
|
with gr.TabItem(label="π Session & Artifact Browser"): |
|
with gr.Row(): |
|
session_info = gr.JSON(label="Session Details", value=[], elem_classes=["metadata-display"]) |
|
artifact_info = gr.JSON(label="Artifact Details", value=[], elem_classes=["metadata-display"]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Tab(label="π Directory to JSON Extractor", elem_id="directory_extractor_tab"): |
|
|
|
def ExtractDirectoryToJson(directory_path="dump", extension='.txt', json_file_path="_Data.json"): |
|
def extract_data_from_files(directory_path, Extension='.md', max_seq_length=2048): |
|
import os |
|
import json |
|
Json_list = [] |
|
|
|
|
|
if not os.path.exists(directory_path): |
|
return f"Error: Directory '{directory_path}' does not exist." |
|
|
|
|
|
if not os.listdir(directory_path): |
|
return f"Error: Directory '{directory_path}' is empty." |
|
|
|
|
|
for file_name in os.listdir(directory_path): |
|
if file_name.endswith(Extension): |
|
file_path = os.path.join(directory_path, file_name) |
|
try: |
|
with open(file_path, 'r', encoding='utf-8') as file: |
|
chunk = file.read() |
|
chunks = [chunk[i:i+max_seq_length] for i in range(0, len(chunk), max_seq_length)] |
|
for text_seg in chunks: |
|
Json_list.append({'DocumentTitle': file_name, 'Text': text_seg}) |
|
except Exception as e: |
|
return f"Error reading file {file_name}: {str(e)}" |
|
return Json_list |
|
|
|
def save_to_json(data, json_file): |
|
import os |
|
import json |
|
try: |
|
with open(json_file, 'w') as f: |
|
json.dump(data, f, indent=4) |
|
return True, None |
|
except Exception as e: |
|
return False, str(e) |
|
|
|
|
|
_data = extract_data_from_files(directory_path, Extension=extension) |
|
|
|
|
|
if isinstance(_data, str): |
|
return _data |
|
|
|
|
|
success, error = save_to_json(_data, json_file_path) |
|
if success: |
|
return f"File extraction completed. JSON file saved to: {json_file_path}" |
|
else: |
|
return f"Error saving JSON file: {error}" |
|
|
|
|
|
def process_directory(directory_path, extension, json_filename): |
|
|
|
if not directory_path: |
|
return "Please select a directory" |
|
if not extension: |
|
return "Please specify a file extension" |
|
if not json_filename: |
|
json_filename = "_Data.json" |
|
|
|
|
|
if not extension.startswith('.'): |
|
extension = '.' + extension |
|
|
|
|
|
result = ExtractDirectoryToJson( |
|
directory_path=directory_path, |
|
extension=extension, |
|
json_file_path=json_filename |
|
) |
|
return result |
|
|
|
|
|
|
|
FileTypes=['.txt','.md','.json','.py'] |
|
|
|
gr.Markdown("## Directory to JSON Extractor") |
|
gr.Markdown("Extract text from files in a directory and save as JSON") |
|
|
|
with gr.Row(): |
|
directory_input = gr.Textbox(label="Directory Path", placeholder="Path to directory containing files") |
|
directory_btn = gr.Button("Browse") |
|
|
|
with gr.Row(): |
|
extension_input = gr.Dropdown(label="File Extension",choices=FileTypes, interactive=True) |
|
json_output = gr.Textbox(label="Output JSON Filename", value="_Data.json") |
|
|
|
submitProcessDirectory_btn = gr.Button("Process Directory") |
|
output_text = gr.JSON(label="Output") |
|
|
|
|
|
|
|
|
|
with gr.Tab("π Crawl Repository"): |
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Markdown("## π― Source Configuration") |
|
|
|
source_type = gr.Dropdown( |
|
choices=["GitHub", "Local", "Hugging Face"], |
|
label="Source Type", |
|
value="GitHub" |
|
) |
|
|
|
|
|
with gr.Group(visible=True) as github_group: |
|
repo_url = gr.Textbox( |
|
label="GitHub Repository URL", |
|
placeholder="https://github.com/owner/repo", |
|
value="" |
|
) |
|
github_token = gr.Textbox( |
|
label="GitHub Token (optional)", |
|
type="password", |
|
placeholder="ghp_..." |
|
) |
|
|
|
|
|
with gr.Group(visible=False) as local_group: |
|
local_path = gr.Textbox( |
|
label="Local Directory Path", |
|
placeholder="/path/to/directory", |
|
value="" |
|
) |
|
|
|
|
|
with gr.Group(visible=False) as hf_group: |
|
hf_repo_id = gr.Textbox( |
|
label="Hugging Face Repository ID", |
|
placeholder="microsoft/DialoGPT-medium", |
|
value="" |
|
) |
|
hf_repo_type = gr.Dropdown( |
|
choices=["model", "dataset", "space"], |
|
label="Repository Type", |
|
value="model" |
|
) |
|
hf_token = gr.Textbox( |
|
label="Hugging Face Token (optional)", |
|
type="password", |
|
placeholder="hf_..." |
|
) |
|
|
|
gr.Markdown("## βοΈ Crawling Options") |
|
|
|
max_file_size = gr.Number( |
|
label="Max File Size (MB)", |
|
value=1, |
|
minimum=0.1, |
|
maximum=100 |
|
) |
|
|
|
include_patterns = gr.Textbox( |
|
label="Include Patterns (comma-separated)", |
|
placeholder="*.py, *.js, *.md", |
|
value="" |
|
) |
|
|
|
exclude_patterns = gr.Textbox( |
|
label="Exclude Patterns (comma-separated)", |
|
placeholder="*.pyc, __pycache__/*, .git/*", |
|
value="" |
|
) |
|
|
|
use_relative_paths = gr.Checkbox( |
|
label="Use Relative Paths", |
|
value=True |
|
) |
|
|
|
crawl_btn = gr.Button("π Start Crawling", variant="primary", size="lg") |
|
|
|
with gr.Column(scale=2): |
|
gr.Markdown("## π Results") |
|
|
|
results_summary = gr.Textbox( |
|
label="Crawling Summary", |
|
lines=8, |
|
interactive=False |
|
) |
|
|
|
file_list = gr.Dataframe( |
|
label="Files Found", |
|
headers=["File Path", "Size (chars)", "Type", "Lines"], |
|
interactive=False, |
|
wrap=True |
|
) |
|
|
|
|
|
with gr.Tab("π File Browser"): |
|
with gr.Row(): |
|
with gr.Column(scale=1): |
|
gr.Markdown("## π File Selection") |
|
|
|
selected_file = gr.Dropdown( |
|
label="Select File", |
|
choices=[], |
|
interactive=True, |
|
allow_custom_value=True |
|
) |
|
|
|
load_btn = gr.Button("π Load File", variant="secondary") |
|
save_btn = gr.Button("πΎ Save Changes", variant="primary") |
|
|
|
save_status = gr.Textbox( |
|
label="Status", |
|
lines=2, |
|
interactive=False |
|
) |
|
|
|
with gr.Column(scale=3): |
|
gr.Markdown("## βοΈ File Editor") |
|
|
|
file_content = gr.Textbox( |
|
label="File Content", |
|
lines=25, |
|
interactive=True, |
|
show_copy_button=True, |
|
placeholder="Select a file to view its content..." |
|
) |
|
|
|
|
|
with gr.Tab("π€ Export"): |
|
with gr.Row(): |
|
with gr.Column(): |
|
gr.Markdown("## πΎ Export Options") |
|
|
|
export_format = gr.Dropdown( |
|
choices=["JSON", "File List", "Summary Report"], |
|
label="Export Format", |
|
value="JSON" |
|
) |
|
|
|
export_btn = gr.Button("π Generate Export", variant="primary") |
|
|
|
export_output = gr.Textbox( |
|
label="Export Output", |
|
lines=20, |
|
show_copy_button=True, |
|
interactive=False |
|
) |
|
with gr.Tab("π§ Task Planning"): |
|
|
|
with gr.Column(scale = 1): |
|
|
|
with gr.Column(): |
|
with gr.Row(): |
|
sub_task_output = gr.Textbox(lines=4,show_label=True,container=False,label="Sub Tasks") |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Task Strategy and Planning</div>") |
|
with gr.Accordion("Task Graph", open=False): |
|
task_graph_img = gr.Image(label="Task Reasoning Graph") |
|
with gr.Row(): |
|
graph_btn = gr.Button("Visualize Task Graph",variant="huggingface") |
|
with gr.Row(): |
|
with gr.Column(): |
|
task_input = gr.Textbox(lines = 10,label="Enter Task Description",placeholder = "Write a BPE Tokenizer in VB.NET") |
|
|
|
|
|
with gr.Column(): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Generated Code</div>") |
|
|
|
with gr.Accordion("Generated Code", open=False): |
|
|
|
task_code_output = gr.Code(show_label=True,container=True,label="Task Code Generated",language='python') |
|
|
|
with gr.Row(): |
|
complexity_btn = gr.Button("Analyze Complexity", variant="huggingface") |
|
decompose_btn = gr.Button("Decompose Task", variant="huggingface") |
|
workflow_btn = gr.Button("Generate Workflow", variant="huggingface") |
|
with gr.Row(): |
|
GeneratePlan_btn = gr.Button("Generate plan", variant="huggingface") |
|
GenerateTaskCode_btn = gr.Button("Generate code", variant="huggingface") |
|
|
|
with gr.Row(): |
|
|
|
with gr.Tabs(): |
|
|
|
with gr.Tab("Complexity"): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Task Complexity</div>") |
|
|
|
complexity_output = gr.Markdown(show_label=True,max_height=600,container=True,show_copy_button = True,label="Task Complexity") |
|
|
|
with gr.Tab("Planning"): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Sub Task Planning</div>") |
|
|
|
decompose_output = gr.Markdown(show_label=True,container=True,show_copy_button = True,label="Task Analysis") |
|
|
|
with gr.Tab("WorkFlow"): |
|
gr.HTML(f"<div style= padding: 10px; font-weight: bold;'>Task Work-Flow</div>") |
|
|
|
workflow_output = gr.Markdown(show_label=True,container=True,label="Task WorkFlow") |
|
|
|
|
|
|
|
|
|
|
|
|
|
gr.HTML(f""" |
|
<div style='text-align: center; padding: 10px; margin-top: 20px; font-size: 12px; |
|
'> |
|
π L.C.A.R.S - Enhanced Local Computer Advanced Reasoning System v3.0 β’ Starfleet Command β’ Computer Core Online |
|
</div> |
|
""") |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch() |
|
|