Spaces:
Running
Running
File size: 6,253 Bytes
05c2ac8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
import os
from datetime import datetime
from typing import List, Dict, Any, Optional
from fastapi import FastAPI, Request, BackgroundTasks
from fastapi.middleware.cors import CORSMiddleware
import gradio as gr
import uvicorn
from pydantic import BaseModel
from huggingface_hub.inference._mcp.agent import Agent
from dotenv import load_dotenv
load_dotenv()
# Configuration
WEBHOOK_SECRET = os.getenv("WEBHOOK_SECRET", "your-webhook-secret")
HF_TOKEN = os.getenv("HF_TOKEN")
HF_MODEL = os.getenv("HF_MODEL", "microsoft/DialoGPT-medium")
HF_PROVIDER = os.getenv("HF_PROVIDER", "huggingface")
# Simple storage for processed comments
comments_store: List[Dict[str, Any]] = []
# Agent instance
agent_instance: Optional[Agent] = None
class WebhookEvent(BaseModel):
event: Dict[str, str]
comment: Dict[str, Any]
discussion: Dict[str, Any]
repo: Dict[str, str]
app = FastAPI(title="HF Discussion Bot")
app.add_middleware(CORSMiddleware, allow_origins=["*"])
async def get_agent():
"""Get or create Agent instance"""
global agent_instance
if agent_instance is None and HF_TOKEN:
agent_instance = Agent(
model=HF_MODEL,
provider=HF_PROVIDER,
api_key=HF_TOKEN,
servers=[
{
"type": "stdio",
"config": {"command": "python", "args": ["mcp_server.py"]},
}
],
)
await agent_instance.load_tools()
return agent_instance
async def process_webhook_comment(webhook_data: Dict[str, Any]):
"""Process webhook using Agent with MCP tools"""
comment_content = webhook_data["comment"]["content"]
discussion_title = webhook_data["discussion"]["title"]
repo_name = webhook_data["repo"]["name"]
discussion_num = webhook_data["discussion"]["num"]
agent = await get_agent()
if not agent:
ai_response = "Error: Agent not configured (missing HF_TOKEN)"
else:
# Use Agent to respond to the discussion
prompt = f"""
Please respond to this HuggingFace discussion comment using the available tools.
Repository: {repo_name}
Discussion: {discussion_title} (#{discussion_num})
Comment: {comment_content}
First use generate_discussion_response to create a helpful response, then use post_discussion_comment to post it.
"""
try:
response_parts = []
async for item in agent.run(prompt):
# Collect the agent's response
if hasattr(item, "content") and item.content:
response_parts.append(item.content)
elif isinstance(item, str):
response_parts.append(item)
ai_response = (
" ".join(response_parts) if response_parts else "No response generated"
)
except Exception as e:
ai_response = f"Error using agent: {str(e)}"
# Store the interaction with reply link
discussion_url = f"https://huggingface.co/{repo_name}/discussions/{discussion_num}"
interaction = {
"timestamp": datetime.now().isoformat(),
"repo": repo_name,
"discussion_title": discussion_title,
"discussion_num": discussion_num,
"discussion_url": discussion_url,
"original_comment": comment_content,
"ai_response": ai_response,
"comment_author": webhook_data["comment"]["author"],
}
comments_store.append(interaction)
return ai_response
@app.post("/webhook")
async def webhook_handler(request: Request, background_tasks: BackgroundTasks):
"""Handle HF Hub webhooks"""
webhook_secret = request.headers.get("X-Webhook-Secret")
if webhook_secret != WEBHOOK_SECRET:
return {"error": "Invalid webhook secret"}
payload = await request.json()
event = payload.get("event", {})
if event.get("action") == "create" and event.get("scope") == "discussion.comment":
background_tasks.add_task(process_webhook_comment, payload)
return {"status": "processing"}
return {"status": "ignored"}
async def simulate_webhook(
repo_name: str, discussion_title: str, comment_content: str
) -> str:
"""Simulate webhook for testing"""
if not all([repo_name, discussion_title, comment_content]):
return "Please fill in all fields."
mock_payload = {
"event": {"action": "create", "scope": "discussion.comment"},
"comment": {
"content": comment_content,
"author": "test-user",
"created_at": datetime.now().isoformat(),
},
"discussion": {
"title": discussion_title,
"num": len(comments_store) + 1,
},
"repo": {"name": repo_name},
}
response = await process_webhook_comment(mock_payload)
return f"β
Processed! AI Response: {response}"
def create_gradio_app():
"""Create Gradio interface"""
with gr.Blocks(title="HF Discussion Bot", theme=gr.themes.Soft()) as demo:
gr.Markdown("# π€ HF Discussion Bot Dashboard")
gr.Markdown("*Powered by HuggingFace Tiny Agents + FastMCP*")
with gr.Column():
sim_repo = gr.Textbox(label="Repository", value="microsoft/DialoGPT-medium")
sim_title = gr.Textbox(label="Discussion Title", value="Test Discussion")
sim_comment = gr.Textbox(
label="Comment",
lines=3,
value="How do I use this model?",
)
sim_btn = gr.Button("π€ Test Webhook")
with gr.Column():
sim_result = gr.Textbox(label="Result", lines=8)
sim_btn.click(
fn=simulate_webhook,
inputs=[sim_repo, sim_title, sim_comment],
outputs=[sim_result],
)
return demo
# Mount Gradio app
gradio_app = create_gradio_app()
app = gr.mount_gradio_app(app, gradio_app, path="/gradio")
if __name__ == "__main__":
print("π Starting HF Discussion Bot with Tiny Agents...")
print("π Dashboard: http://localhost:8001/gradio")
print("π Webhook: http://localhost:8001/webhook")
uvicorn.run("server:app", host="0.0.0.0", port=8001, reload=True)
|