DeepGit-lite / app.py
zamal's picture
Update app.py
29c5e0f verified
import spaces
import gradio as gr
import time
import threading
import logging
from gradio.themes.utils import sizes
from main import run_repository_ranking # Import the repository ranking function
# ---------------------------
# Global Logging Buffer Setup
# ---------------------------
LOG_BUFFER = []
LOG_BUFFER_LOCK = threading.Lock()
class BufferLogHandler(logging.Handler):
def emit(self, record):
log_entry = self.format(record)
with LOG_BUFFER_LOCK:
LOG_BUFFER.append(log_entry)
root_logger = logging.getLogger()
if not any(isinstance(h, BufferLogHandler) for h in root_logger.handlers):
handler = BufferLogHandler()
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
root_logger.addHandler(handler)
def filter_logs(logs):
filtered = []
last_was_fetching = False
for log in logs:
if "HTTP Request:" in log:
if not last_was_fetching:
filtered.append("Fetching repositories...")
last_was_fetching = True
else:
filtered.append(log)
last_was_fetching = False
return filtered
def parse_result_to_html(raw_result: str) -> str:
"""
Parses the raw string output from run_repository_ranking to an HTML table.
Only the top 10 results are displayed.
"""
entries = raw_result.strip().split("Final Rank:")
entries = entries[1:11] # Use only the first 10 entries
if not entries:
return "<p>No repositories found for your query.</p>"
html = """
<table border="1" style="width:80%; margin: auto; border-collapse: collapse;">
<thead>
<tr>
<th>Rank</th>
<th>Title</th>
<th>Link</th>
<th>Combined Score</th>
</tr>
</thead>
<tbody>
"""
for entry in entries:
lines = entry.strip().split("\n")
data = {}
data["Final Rank"] = lines[0].strip() if lines else ""
for line in lines[1:]:
if ": " in line:
key, val = line.split(": ", 1)
data[key.strip()] = val.strip()
html += f"""
<tr>
<td>{data.get('Final Rank', '')}</td>
<td>{data.get('Title', '')}</td>
<td><a href="{data.get('Link', '#')}" target="_blank">GitHub</a></td>
<td>{data.get('Combined Score', '')}</td>
</tr>
"""
html += "</tbody></table>"
return html
# ---------------------------
# GPU-enabled Wrapper for Repository Ranking
# ---------------------------
@spaces.GPU(duration=180)
def gpu_run_repo(topic: str):
return run_repository_ranking(topic)
def run_lite_workflow(topic, result_container):
result = gpu_run_repo(topic)
result_container["raw_result"] = result
def stream_lite_workflow(topic):
with LOG_BUFFER_LOCK:
LOG_BUFFER.clear()
result_container = {}
workflow_thread = threading.Thread(target=run_lite_workflow, args=(topic, result_container))
workflow_thread.start()
last_index = 0
while workflow_thread.is_alive() or (last_index < len(LOG_BUFFER)):
with LOG_BUFFER_LOCK:
new_logs = LOG_BUFFER[last_index:]
last_index = len(LOG_BUFFER)
if new_logs:
filtered_logs = filter_logs(new_logs)
status_msg = filtered_logs[-1]
detail_msg = "<br/>".join(filtered_logs)
yield status_msg, detail_msg
time.sleep(0.5)
workflow_thread.join()
with LOG_BUFFER_LOCK:
final_logs = LOG_BUFFER[:]
raw_result = result_container.get("raw_result", "No results returned.")
html_result = parse_result_to_html(raw_result)
yield "", html_result
def lite_runner(topic):
# Provide immediate feedback upon button press.
yield "Workflow started", "<p>Processing your request. Please wait...</p>"
for status, details in stream_lite_workflow(topic):
yield status, details
# ---------------------------
# App UI Setup Using Gradio Soft Theme with Centered Layout
# ---------------------------
with gr.Blocks(
theme=gr.themes.Soft(text_size=sizes.text_md),
title="DeepGit Lite",
css="""
/* Center header and footer */
#header { text-align: center; margin-bottom: 20px; }
#main-container { max-width: 800px; margin: auto; }
#footer { text-align: center; margin-top: 20px; }
"""
) as demo:
gr.Markdown(
"""
<div style="padding-top: 60px;">
<div style="display: flex; align-items: center; justify-content: center;">
<img src="https://img.icons8.com/?size=100&id=118557&format=png&color=000000"
style="width: 60px; height: 60px; margin-right: 12px;">
<h1 style="margin: 0; font-size: 2.5em; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
DeepGit Lite
</h1>
</div>
<div style="text-align: center; margin-top: 20px; font-size: 1.1em; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;">
<p>
✨ DeepGit Lite is the lightweight pro version of <strong>DeepGit</strong>.<br>
It harnesses advanced deep semantic search to explore GitHub repositories and deliver curated results.<br>
Under the hood, it leverages a hybrid ranking approach combining dense retrieval, BM25 scoring, and cross-encoder re-ranking for optimal discovery.<br>
If the agent returns no repositories found, it means no chain was invoked due to GPU unavailability. Please duplicate the space and re-run.
</p>
<p>
🚀 Check out the full DeepGit version on
<a href="https://github.com/zamalali/DeepGit" target="_blank">GitHub</a> and ⭐
<strong>Star DeepGit</strong> on GitHub!
</p>
</div>
</div>
""",
elem_id="header"
)
with gr.Column(elem_id="main-container"):
research_input = gr.Textbox(
label="Research Query",
placeholder="Enter your research topic here, e.g., 'data augmentation pipelines for LLM fine-tuning'",
lines=3
)
run_button = gr.Button("Run DeepGit Lite", variant="primary")
status_display = gr.Markdown(label="Status")
detail_display = gr.HTML(label="Results")
run_button.click(
fn=lite_runner,
inputs=[research_input],
outputs=[status_display, detail_display],
api_name="deepgit_lite",
show_progress=True
)
research_input.submit(
fn=lite_runner,
inputs=[research_input],
outputs=[status_display, detail_display],
api_name="deepgit_lite_submit",
show_progress=True
)
gr.HTML(
"""
<div id="footer">
Made with ❤️ by <b>Zamal</b>
</div>
"""
)
demo.queue(max_size=10).launch()