Skip to content

Commit da79a48

Browse files
authored
Merge pull request #11 from severian42/dev
Dev
2 parents 308375d + da381be commit da79a48

File tree

353 files changed

+129
-60
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

353 files changed

+129
-60
lines changed

.DS_Store

0 Bytes
Binary file not shown.

README.md

Lines changed: 1 addition & 0 deletions

app.py

Lines changed: 126 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,47 @@ def run_command(command):
8787
except subprocess.CalledProcessError as e:
8888
return f"Error: {e.stderr}"
8989

90-
def index_graph(root_dir):
90+
def index_graph(root_dir, progress=gr.Progress()):
9191
command = f"python -m graphrag.index --root {root_dir}"
9292
logging.info(f"Running indexing command: {command}")
93-
result = run_command(command)
93+
94+
# Create a queue to store the output
95+
output_queue = queue.Queue()
96+
97+
def run_command_with_output():
98+
process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
99+
for line in iter(process.stdout.readline, ''):
100+
output_queue.put(line)
101+
process.stdout.close()
102+
process.wait()
103+
104+
# Start the command in a separate thread
105+
thread = threading.Thread(target=run_command_with_output)
106+
thread.start()
107+
108+
# Initialize progress
109+
progress(0, desc="Starting indexing...")
110+
111+
# Process the output and update progress
112+
full_output = []
113+
while thread.is_alive() or not output_queue.empty():
114+
try:
115+
line = output_queue.get_nowait()
116+
full_output.append(line)
117+
118+
# Update progress based on the output
119+
if "Processing file" in line:
120+
progress((0.5, None), desc="Processing files...")
121+
elif "Indexing completed" in line:
122+
progress(1, desc="Indexing completed")
123+
124+
yield "\n".join(full_output), update_logs()
125+
except queue.Empty:
126+
time.sleep(0.1)
127+
128+
thread.join()
94129
logging.info("Indexing completed")
95-
return result, update_logs()
130+
return "\n".join(full_output), update_logs()
96131

97132
def run_query(root_dir, method, query, history):
98133
command = f"python -m graphrag.query --root {root_dir} --method {method} \"{query}\""
@@ -121,7 +156,7 @@ def upload_file(file):
121156
# Get the updated file list
122157
updated_file_list = [f["path"] for f in list_input_files()]
123158

124-
return status, gr.Dropdown.update(choices=updated_file_list), update_logs()
159+
return status, gr.update(choices=updated_file_list), update_logs()
125160

126161
def list_input_files():
127162
input_dir = os.path.join("ragtest", "input")
@@ -140,7 +175,7 @@ def delete_file(file_path):
140175
# Get the updated file list
141176
updated_file_list = [f["path"] for f in list_input_files()]
142177

143-
return status, gr.Dropdown.update(choices=updated_file_list), update_logs()
178+
return status, gr.update(choices=updated_file_list), update_logs()
144179

145180
def read_file_content(file_path):
146181
try:
@@ -208,7 +243,7 @@ def find_latest_graph_file(root_dir):
208243
def update_visualization(root_dir, folder_name, file_name):
209244
if not folder_name or not file_name:
210245
return None, "Please select a folder and a GraphML file."
211-
file_name = file_name.split("] ")[1] # Remove file type prefix
246+
file_name = file_name.split("] ")[1] if "]" in file_name else file_name # Remove file type prefix
212247
graph_path = os.path.join(root_dir, "output", folder_name, "artifacts", file_name)
213248
if not graph_path.endswith('.graphml'):
214249
return None, "Please select a GraphML file for visualization."
@@ -275,9 +310,9 @@ def update_visualization(root_dir, folder_name, file_name):
275310
title=f'3D Graph Visualization: {os.path.basename(graph_path)}',
276311
showlegend=False,
277312
scene=dict(
278-
xaxis=dict(showbackground=False),
279-
yaxis=dict(showbackground=False),
280-
zaxis=dict(showbackground=False)
313+
xaxis=dict(showbackground=False, showticklabels=False, title=''),
314+
yaxis=dict(showbackground=False, showticklabels=False, title=''),
315+
zaxis=dict(showbackground=False, showticklabels=False, title='')
281316
),
282317
margin=dict(l=0, r=0, b=0, t=40),
283318
annotations=[
@@ -289,11 +324,14 @@ def update_visualization(root_dir, folder_name, file_name):
289324
x=0,
290325
y=0
291326
)
292-
]
327+
],
328+
autosize=True
293329
)
294330

295-
# Return the Plotly figure instead of converting to image
296-
return fig, f"Graph visualization generated successfully. Using file: {graph_path}"
331+
fig.update_layout(autosize=True)
332+
fig.update_layout(height=600) # Set a fixed height
333+
config = {'responsive': True}
334+
return fig, f"Graph visualization generated successfully. Using file: {graph_path}", config
297335
except Exception as e:
298336
return None, f"Error visualizing graph: {str(e)}"
299337

@@ -335,7 +373,7 @@ def send_message(root_dir, query_type, query, history, system_message, temperatu
335373
else: # Direct chat
336374
result = chat_with_llm(query, history, system_message, temperature, max_tokens, model)
337375
history.append((query, result))
338-
return history, gr.Textbox.update(value=""), update_logs()
376+
return history, gr.update(value=""), update_logs()
339377

340378
def fetch_ollama_models():
341379
try:
@@ -350,7 +388,7 @@ def fetch_ollama_models():
350388

351389
def update_model_choices():
352390
models = fetch_ollama_models()
353-
return gr.Dropdown.update(choices=models, value=models[0] if models else None)
391+
return gr.update(choices=models, value=models[0] if models else None)
354392

355393
custom_css = """
356394
html, body {
@@ -415,34 +453,26 @@ def update_model_choices():
415453
margin-top: 10px;
416454
}
417455
418-
#visualization-container {
419-
height: 30%;
420-
min-height: 200px;
421-
display: flex;
422-
flex-direction: column;
423-
border: 2px solid var(--color-accent);
424-
border-radius: 8px;
425-
margin-top: 20px;
426-
overflow: hidden;
427-
}
428-
429456
#visualization-plot {
430-
flex: 1;
431-
min-height: 0;
457+
width: 100%;
458+
aspect-ratio: 1 / 1;
459+
max-height: 600px; /* Adjust this value as needed */
432460
}
433461
434-
#vis-controls {
435-
padding: 10px;
436-
background-color: var(--color-foreground);
437-
border-top: 1px solid var(--color-accent);
462+
#vis-controls-row {
463+
display: flex;
464+
justify-content: space-between;
465+
align-items: center;
466+
margin-top: 10px;
438467
}
439468
440-
#vis-controls .gr-button {
441-
margin-bottom: 10px;
469+
#vis-controls-row > * {
470+
flex: 1;
471+
margin: 0 5px;
442472
}
443473
444474
#vis-status {
445-
margin-top: 5px;
475+
margin-top: 10px;
446476
}
447477
448478
/* Chat input styling */
@@ -540,10 +570,35 @@ def update_model_choices():
540570
}
541571
542572
#visualization-container {
573+
display: flex;
574+
flex-direction: column;
543575
border: 2px solid var(--color-accent);
544576
border-radius: 8px;
545-
padding: 10px;
546577
margin-top: 20px;
578+
padding: 10px;
579+
background-color: var(--color-foreground);
580+
height: calc(100vh - 300px); /* Adjust this value as needed */
581+
}
582+
583+
#visualization-plot {
584+
width: 100%;
585+
height: 100%;
586+
}
587+
588+
#vis-controls-row {
589+
display: flex;
590+
justify-content: space-between;
591+
align-items: center;
592+
margin-top: 10px;
593+
}
594+
595+
#vis-controls-row > * {
596+
flex: 1;
597+
margin: 0 5px;
598+
}
599+
600+
#vis-status {
601+
margin-top: 10px;
547602
}
548603
549604
#log-container {
@@ -590,7 +645,7 @@ def list_output_files(root_dir):
590645

591646
def update_file_list():
592647
files = list_input_files()
593-
return gr.Dropdown.update(choices=[f["path"] for f in files])
648+
return gr.update(choices=[f["path"] for f in files])
594649

595650
def update_file_content(file_path):
596651
if not file_path:
@@ -605,36 +660,41 @@ def update_file_content(file_path):
605660

606661
def update_output_folder_list():
607662
folders = list_output_folders(root_dir.value)
608-
return gr.Dropdown.update(choices=folders, value=folders[0] if folders else None)
663+
return gr.update(choices=folders, value=folders[0] if folders else None)
609664

610665
def update_folder_content_list(root_dir, folder_name):
611666
if not folder_name:
612-
return gr.Dropdown.update(choices=[])
667+
return gr.update(choices=[])
613668
contents = list_folder_contents(os.path.join(root_dir, "output", folder_name))
614-
return gr.Dropdown.update(choices=contents)
669+
return gr.update(choices=contents)
615670

616671
def handle_content_selection(root_dir, folder_name, selected_item):
617-
if selected_item.startswith("[DIR]"):
672+
if isinstance(selected_item, list) and selected_item:
673+
selected_item = selected_item[0] # Take the first item if it's a list
674+
675+
if isinstance(selected_item, str) and selected_item.startswith("[DIR]"):
618676
dir_name = selected_item[6:] # Remove "[DIR] " prefix
619677
sub_contents = list_folder_contents(os.path.join(root_dir, "output", folder_name, dir_name))
620-
return gr.Dropdown.update(choices=sub_contents), "", ""
621-
else:
622-
file_name = selected_item.split("] ")[1] # Remove file type prefix
678+
return gr.update(choices=sub_contents), "", ""
679+
elif isinstance(selected_item, str):
680+
file_name = selected_item.split("] ")[1] if "]" in selected_item else selected_item # Remove file type prefix if present
623681
file_path = os.path.join(root_dir, "output", folder_name, "artifacts", file_name)
624682
file_size = os.path.getsize(file_path)
625683
file_type = os.path.splitext(file_name)[1]
626684
file_info = f"File: {file_name}\nSize: {file_size} bytes\nType: {file_type}"
627685
content = read_file_content(file_path)
628-
return gr.Dropdown.update(), file_info, content
686+
return gr.update(), file_info, content
687+
else:
688+
return gr.update(), "", ""
629689

630690
def initialize_selected_folder(root_dir, folder_name):
631691
if not folder_name:
632-
return "Please select a folder first.", gr.Dropdown.update(choices=[])
692+
return "Please select a folder first.", gr.update(choices=[])
633693
folder_path = os.path.join(root_dir, "output", folder_name, "artifacts")
634694
if not os.path.exists(folder_path):
635-
return f"Artifacts folder not found in '{folder_name}'.", gr.Dropdown.update(choices=[])
695+
return f"Artifacts folder not found in '{folder_name}'.", gr.update(choices=[])
636696
contents = list_folder_contents(folder_path)
637-
return f"Folder '{folder_name}/artifacts' initialized with {len(contents)} items.", gr.Dropdown.update(choices=contents)
697+
return f"Folder '{folder_name}/artifacts' initialized with {len(contents)} items.", gr.update(choices=contents)
638698

639699
def list_output_folders(root_dir):
640700
output_dir = os.path.join(root_dir, "output")
@@ -656,13 +716,13 @@ def list_folder_contents(folder_path):
656716
default_model = settings['llm']['model']
657717

658718
with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo:
659-
gr.Markdown("# GraphRAG UI", elem_id="title")
719+
gr.Markdown("# GraphRAG Local UI", elem_id="title")
660720

661721
with gr.Row(elem_id="main-container"):
662722
with gr.Column(scale=1, elem_id="left-column"):
663723
with gr.Tabs():
664724
with gr.TabItem("Data Management"):
665-
with gr.Accordion("File Operations", open=False):
725+
with gr.Accordion("File Upload (.txt)", open=True):
666726
file_upload = gr.File(label="Upload .txt File", file_types=[".txt"])
667727
upload_btn = gr.Button("Upload File", variant="primary")
668728
upload_output = gr.Textbox(label="Upload Status", visible=False)
@@ -680,10 +740,11 @@ def list_folder_contents(folder_path):
680740
operation_status = gr.Textbox(label="Operation Status", visible=False)
681741

682742

683-
with gr.Accordion("Indexing", open=False):
684-
root_dir = gr.Textbox(label="Root Directory", value="./ragtest")
743+
with gr.Accordion("Indexing", open=True):
744+
root_dir = gr.Textbox(label="Root Directory", value=os.path.abspath("./ragtest"))
685745
index_btn = gr.Button("Run Indexing", variant="primary")
686-
index_output = gr.Textbox(label="Indexing Output", lines=5, visible=False)
746+
index_output = gr.Textbox(label="Indexing Output", lines=10, visible=True)
747+
index_progress = gr.Textbox(label="Indexing Progress", visible=True)
687748

688749
with gr.TabItem("Indexing Outputs"):
689750
output_folder_list = gr.Dropdown(label="Select Output Folder", choices=[], interactive=True)
@@ -696,15 +757,15 @@ def list_folder_contents(folder_path):
696757

697758
with gr.TabItem("Settings"):
698759
settings = load_settings()
699-
with gr.Box():
760+
with gr.Group():
700761
for key, value in settings.items():
701762
create_setting_component(key, value)
702763

703-
with gr.Box(elem_id="log-container"):
764+
with gr.Group(elem_id="log-container"):
704765
log_output = gr.TextArea(label="Logs", elem_id="log-output")
705766

706767
with gr.Column(scale=2, elem_id="right-column"):
707-
with gr.Box(elem_id="chat-container"):
768+
with gr.Group(elem_id="chat-container"):
708769
chatbot = gr.Chatbot(label="Chat History", elem_id="chatbot")
709770
with gr.Row(elem_id="chat-input-row"):
710771
query_type = gr.Radio(["global", "local", "direct"], label="Query Type", value="global")
@@ -724,11 +785,11 @@ def list_folder_contents(folder_path):
724785
refresh_models_btn = gr.Button("Refresh Models", variant="secondary")
725786

726787

727-
with gr.Row(elem_id="visualization-container"):
788+
with gr.Group(elem_id="visualization-container"):
728789
vis_output = gr.Plot(label="Graph Visualization", elem_id="visualization-plot")
729-
with gr.Column(elem_id="vis-controls", scale=1):
790+
with gr.Row(elem_id="vis-controls-row"):
730791
vis_btn = gr.Button("Visualize Graph", variant="secondary")
731-
vis_status = gr.Textbox(label="Visualization Status", elem_id="vis-status", show_label=False)
792+
vis_status = gr.Textbox(label="Visualization Status", elem_id="vis-status", show_label=False)
732793

733794
# Event handlers
734795
upload_btn.click(fn=upload_file, inputs=[file_upload], outputs=[upload_output, file_list, log_output])
@@ -742,7 +803,12 @@ def list_folder_contents(folder_path):
742803
)
743804
delete_btn.click(fn=delete_file, inputs=[file_list], outputs=[operation_status, file_list, log_output])
744805
save_btn.click(fn=save_file_content, inputs=[file_list, file_content], outputs=[operation_status, log_output])
745-
index_btn.click(fn=index_graph, inputs=[root_dir], outputs=[index_output, log_output])
806+
index_btn.click(
807+
fn=index_graph,
808+
inputs=[root_dir],
809+
outputs=[index_output, log_output],
810+
show_progress=True
811+
)
746812
refresh_folder_btn.click(fn=update_output_folder_list, outputs=[output_folder_list]).then(
747813
fn=update_logs,
748814
outputs=[log_output]
@@ -801,4 +867,4 @@ def list_folder_contents(folder_path):
801867
""")
802868

803869
if __name__ == "__main__":
804-
demo.launch(enable_queue=False)
870+
demo.launch()

graphrag/.DS_Store

0 Bytes
Binary file not shown.
-3 Bytes
Binary file not shown.

graphrag/config/.DS_Store

0 Bytes
Binary file not shown.
-3 Bytes
Binary file not shown.
-3 Bytes
Binary file not shown.
-3 Bytes
Binary file not shown.
-3 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)