DeepGit-lite / app.py
zamalali
Refine DeepGit Lite description and improve error handling for GitHub API key and document embeddings
1796763
raw
history blame
7.55 kB
import gradio as gr
import time
import threading
import logging
from src.deepgit_lite import run_deepgit_lite
# ---------------------------
# 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
# ---------------------------
# Title, Favicon & Description
# ---------------------------
favicon_html = """
<head>
<link rel="icon" type="image/x-icon" href="file/assets/deepgit.ico">
<title>DeepGit Lite Research Agent</title>
</head>
"""
title = """
<div style="text-align: center; margin-top: 20px;">
<h1 style="font-size: 36px; display: inline-flex; align-items: center; gap: 16px;">
<img src="https://img.icons8.com/?size=100&id=118557&format=png&color=000000" width="64" />
<span>DeepGit Lite</span>
</h1>
<p style="font-size: 18px; color: #555; margin-top: 10px;">
⚙️ A lightweight GitHub research agent for deep semantic search and ranking.
</p>
</div>
"""
description = """<p align="center">
DeepGit Lite is a streamlined version of DeepGit designed for fast semantic search on GitHub repositories. It enhances your query, retrieves repositories using dense retrieval via FAISS, filters by star count, combines scores based on semantic similarity and popularity, and then provides a concise justification for the top results.
</p>"""
consent_text = """
<div style="padding: 10px; text-align: center;">
<p>
By using DeepGit Lite, you consent to temporary processing of your query for semantic search and ranking purposes.
</p>
<p>
⭐ Star us on GitHub if you find this tool useful!<br/>
<a href="https://github.com/zamalali/DeepGit" target="_blank">GitHub</a>
</p>
</div>
"""
footer = """
<div style="text-align: center; margin-top: 40px; font-size: 13px; color: #888;">
Made with <span style="color: crimson;">❤️</span> by <b>Zamal</b>
</div>
"""
# ---------------------------
# HTML Table Renderer for DeepGit Lite
# ---------------------------
def format_percent(value):
try:
return f"{float(value) * 100:.1f}%"
except:
return value
def parse_result_to_html(raw_result: str) -> str:
entries = raw_result.strip().split("Final Rank:")
html = """
<style>
table {
width: 100%;
border-collapse: collapse;
margin: 1em 0;
font-size: 14px;
}
th, td {
padding: 12px 15px;
border: 1px solid #ddd;
text-align: left;
vertical-align: top;
}
th {
background-color: #f4f4f4;
}
tr:hover { background-color: #f9f9f9; }
</style>
<table>
<thead>
<tr>
<th>Rank</th>
<th>Title</th>
<th>Link</th>
<th>Semantic Similarity</th>
<th>Final Score</th>
</tr>
</thead>
<tbody>
"""
for entry in entries[1:]:
lines = entry.strip().split("\n")
data = {}
data["Final Rank"] = lines[0].strip()
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>{format_percent(data.get('Semantic Similarity', ''))}</td>
<td>{format_percent(data.get('Final Score', ''))}</td>
</tr>
"""
html += "</tbody></table>"
return html
# ---------------------------
# Background Workflow Runner for DeepGit Lite
# ---------------------------
def run_lite_workflow(topic, result_container):
result = run_deepgit_lite(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[:]
filtered_final = filter_logs(final_logs)
raw_result = result_container.get("raw_result", "No results returned.")
html_result = parse_result_to_html(raw_result)
yield "", html_result
# ---------------------------
# App UI Setup for DeepGit Lite
# ---------------------------
with gr.Blocks(
theme="gstaff/sketch",
css="""
#main_container { margin: auto; max-width: 900px; }
footer, footer * { display: none !important; }
"""
) as demo:
gr.HTML(favicon_html)
gr.HTML(title)
gr.HTML(description)
with gr.Column(elem_id="user_consent_container") as consent_block:
gr.HTML(consent_text)
agree_button = gr.Button("I Agree", variant="primary")
with gr.Column(elem_id="main_container", visible=False) as main_block:
research_input = gr.Textbox(
label="Research Topic",
placeholder="Enter your research topic here, e.g., 'Instruction-based fine-tuning for LLaMA 2 using chain-of-thought prompting in Python.'",
lines=3
)
run_button = gr.Button("Run DeepGit Lite", variant="primary")
status_display = gr.Markdown("")
detail_display = gr.HTML("")
output_html = gr.HTML("")
state = gr.State([])
def enable_main():
return gr.update(visible=False), gr.update(visible=True)
agree_button.click(fn=enable_main, inputs=[], outputs=[consent_block, main_block], queue=False)
def lite_runner(topic):
for status, details in stream_lite_workflow(topic):
yield status, details
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(footer)
demo.queue(max_size=10).launch()