seanfaheymedia's picture
Update deep_research.py
cc1ea0b verified
# deep_research.py
import gradio as gr
from dotenv import load_dotenv
from clarifier_agent import clarifier_agent
from research_manager import ResearchManagerAgent
from agents import Runner
from collections import defaultdict
from datetime import datetime
import time
import logging
load_dotenv(override=True)
# --- Rate Limiter ---
class RateLimiter:
# Rate limit to 2 requests per minute, 10 requests per day
def __init__(self, max_requests=2, time_window=60, daily_quota=10):
self.max_requests = max_requests
self.time_window = time_window # seconds
self.request_history = defaultdict(list)
self.daily_quota = daily_quota
self.daily_counts = defaultdict(lambda: {'date': self._today(), 'count': 0})
def _today(self):
return datetime.utcnow().strftime('%Y-%m-%d')
def is_rate_limited(self, user_id):
now = time.time()
self.request_history[user_id] = [
t for t in self.request_history[user_id] if now - t < self.time_window
]
if len(self.request_history[user_id]) >= self.max_requests:
return True
self.request_history[user_id].append(now)
return False
def is_quota_exceeded(self, user_id):
today = self._today()
user_quota = self.daily_counts[user_id]
if user_quota['date'] != today:
user_quota['date'] = today
user_quota['count'] = 0
if user_quota['count'] >= self.daily_quota:
return True
user_quota['count'] += 1
self.daily_counts[user_id] = user_quota
return False
rate_limiter = RateLimiter()
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
async def get_user_id(request: gr.Request = None):
user_id = "default_user"
if request is not None:
try:
forwarded = request.headers.get("X-Forwarded-For")
if forwarded:
user_id = forwarded.split(",")[0].strip()
else:
user_id = getattr(request.client, 'host', 'default_user')
except Exception:
pass
logger.debug(f"[RateLimiter] user_id={user_id}")
return user_id
# Step 1 β€” Generate clarifying questions
async def get_clarifying_questions(query, request: gr.Request = None):
user_id = await get_user_id(request)
if rate_limiter.is_rate_limited(user_id):
return ["Rate limit exceeded. Please wait a minute."], "", "", ""
if rate_limiter.is_quota_exceeded(user_id):
return ["Daily quota exceeded. Try again tomorrow."], "", "", ""
result = await Runner.run(clarifier_agent, input=query)
return result.final_output.questions
# Step 2 β€” Run full research pipeline via coordinator agent (handoff style)
async def run_with_handoff(query, q1, q2, q3, a1, a2, a3, request: gr.Request = None):
user_id = await get_user_id(request)
if rate_limiter.is_rate_limited(user_id):
yield "Rate limit exceeded. Please wait a minute."
return
if rate_limiter.is_quota_exceeded(user_id):
yield "You have reached your daily quota. Try again tomorrow."
return
questions = [q1, q2, q3]
answers = [a1, a2, a3]
async for chunk in ResearchManagerAgent().run(
query,
questions,
answers,
):
yield chunk
with gr.Blocks(theme=gr.themes.Default(primary_hue="sky")) as ui:
gr.Markdown("# πŸ” Deep Research Agent (Clarify ➑️ Research ➑️ Email)")
query = gr.Textbox(label="πŸ”Ž What would you like to research?")
get_questions_btn = gr.Button("Generate Clarifying Questions", variant="primary")
clar_q1 = gr.Textbox(label="Clarifying Question 1", interactive=False)
clar_q2 = gr.Textbox(label="Clarifying Question 2", interactive=False)
clar_q3 = gr.Textbox(label="Clarifying Question 3", interactive=False)
answer_1 = gr.Textbox(label="Your Answer to Q1")
answer_2 = gr.Textbox(label="Your Answer to Q2")
answer_3 = gr.Textbox(label="Your Answer to Q3")
submit_answers_btn = gr.Button("Submit & Run Full Research")
report = gr.Markdown(label="πŸ“„ Research Report")
# Step 1
query.submit(
fn=get_clarifying_questions,
inputs=query,
outputs=[clar_q1, clar_q2, clar_q3]
).then(lambda *_: "", outputs=report)
get_questions_btn.click(
fn=get_clarifying_questions,
inputs=query,
outputs=[clar_q1, clar_q2, clar_q3]
).then(lambda *_: "", outputs=report)
# Step 2
submit_answers_btn.click(
fn=run_with_handoff,
inputs=[query, clar_q1, clar_q2, clar_q3, answer_1, answer_2, answer_3],
outputs=report
)
ui.launch(inbrowser=True)