Spaces:
Running
Running
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,329 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import requests
|
| 3 |
+
import json
|
| 4 |
+
from typing import List, Dict, Generator
|
| 5 |
+
import asyncio
|
| 6 |
+
import aiohttp
|
| 7 |
+
import time
|
| 8 |
+
import logging
|
| 9 |
+
|
| 10 |
+
# Configure logging
|
| 11 |
+
logging.basicConfig(level=logging.INFO)
|
| 12 |
+
logger = logging.getLogger(__name__)
|
| 13 |
+
|
| 14 |
+
# Configuration
|
| 15 |
+
POLLINATIONS_API_URL = "https://text.pollinations.ai/openai"
|
| 16 |
+
API_KEY = "wPGHlU-7pPYlOetQ"
|
| 17 |
+
MAX_CONTEXT_MESSAGES = 15
|
| 18 |
+
DEFAULT_MODEL = "openai"
|
| 19 |
+
|
| 20 |
+
class AIAssistant:
|
| 21 |
+
def __init__(self):
|
| 22 |
+
self.conversation_history = []
|
| 23 |
+
|
| 24 |
+
async def generate_streaming_response(self, prompt: str, history: List[List[str]]) -> Generator[str, None, None]:
|
| 25 |
+
"""Generate streaming response from Pollinations API"""
|
| 26 |
+
|
| 27 |
+
# Convert Gradio history to conversation format
|
| 28 |
+
messages = [{
|
| 29 |
+
'role': 'system',
|
| 30 |
+
'content': 'आप एक helpful AI assistant हैं। User को Hindi और English दोनों languages में helpful और accurate answers देते हैं। आप friendly, conversational और natural tone में बात करते हैं। Code माँगने पर proper formatting के साथ दें। हमेशा relevant और उपयोगी जवाब दें।'
|
| 31 |
+
}]
|
| 32 |
+
|
| 33 |
+
# Add conversation history
|
| 34 |
+
for user_msg, assistant_msg in history[-MAX_CONTEXT_MESSAGES:]:
|
| 35 |
+
if user_msg:
|
| 36 |
+
messages.append({"role": "user", "content": user_msg})
|
| 37 |
+
if assistant_msg:
|
| 38 |
+
messages.append({"role": "assistant", "content": assistant_msg})
|
| 39 |
+
|
| 40 |
+
# Add current prompt
|
| 41 |
+
messages.append({"role": "user", "content": prompt})
|
| 42 |
+
|
| 43 |
+
payload = {
|
| 44 |
+
'model': DEFAULT_MODEL,
|
| 45 |
+
'messages': messages,
|
| 46 |
+
'temperature': 0.7,
|
| 47 |
+
'max_tokens': 2000,
|
| 48 |
+
'top_p': 0.9,
|
| 49 |
+
'stream': True,
|
| 50 |
+
'private': True,
|
| 51 |
+
'referrer': API_KEY,
|
| 52 |
+
'seed': int(time.time()) % 1000000
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
try:
|
| 56 |
+
async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=120)) as session:
|
| 57 |
+
async with session.post(
|
| 58 |
+
POLLINATIONS_API_URL,
|
| 59 |
+
json=payload,
|
| 60 |
+
headers={
|
| 61 |
+
'Content-Type': 'application/json',
|
| 62 |
+
'Accept': 'text/event-stream',
|
| 63 |
+
'User-Agent': 'AI-Assistant-HF/1.0'
|
| 64 |
+
}
|
| 65 |
+
) as response:
|
| 66 |
+
|
| 67 |
+
if response.status != 200:
|
| 68 |
+
error_text = await response.text()
|
| 69 |
+
yield f"❌ API Error: {response.status} - {error_text}"
|
| 70 |
+
return
|
| 71 |
+
|
| 72 |
+
full_response = ""
|
| 73 |
+
buffer = ""
|
| 74 |
+
|
| 75 |
+
async for chunk in response.content.iter_chunked(1024):
|
| 76 |
+
buffer += chunk.decode('utf-8', errors='ignore')
|
| 77 |
+
lines = buffer.split('\n')
|
| 78 |
+
buffer = lines[-1] # Keep incomplete line in buffer
|
| 79 |
+
|
| 80 |
+
for line in lines[:-1]:
|
| 81 |
+
line = line.strip()
|
| 82 |
+
if line.startswith('data: '):
|
| 83 |
+
data = line[6:]
|
| 84 |
+
|
| 85 |
+
if data == '[DONE]':
|
| 86 |
+
return
|
| 87 |
+
|
| 88 |
+
try:
|
| 89 |
+
parsed = json.loads(data)
|
| 90 |
+
content = parsed.get('choices', [{}])[0].get('delta', {}).get('content', '')
|
| 91 |
+
if content:
|
| 92 |
+
full_response += content
|
| 93 |
+
yield full_response
|
| 94 |
+
except json.JSONDecodeError:
|
| 95 |
+
continue
|
| 96 |
+
|
| 97 |
+
except asyncio.TimeoutError:
|
| 98 |
+
yield "⏰ Request timeout - कृपया दोबारा कोशिश करें"
|
| 99 |
+
except Exception as e:
|
| 100 |
+
logger.error(f"API Error: {str(e)}")
|
| 101 |
+
yield f"❌ Connection Error: {str(e)}"
|
| 102 |
+
|
| 103 |
+
def chat_response(self, message: str, history: List[List[str]]):
|
| 104 |
+
"""Main chat response function for Gradio"""
|
| 105 |
+
if not message or not message.strip():
|
| 106 |
+
return history, ""
|
| 107 |
+
|
| 108 |
+
# Run async function in sync context
|
| 109 |
+
try:
|
| 110 |
+
loop = asyncio.new_event_loop()
|
| 111 |
+
asyncio.set_event_loop(loop)
|
| 112 |
+
|
| 113 |
+
# Get final response
|
| 114 |
+
full_response = ""
|
| 115 |
+
async def get_response():
|
| 116 |
+
nonlocal full_response
|
| 117 |
+
async for response in self.generate_streaming_response(message, history):
|
| 118 |
+
full_response = response
|
| 119 |
+
|
| 120 |
+
loop.run_until_complete(get_response())
|
| 121 |
+
loop.close()
|
| 122 |
+
|
| 123 |
+
if not full_response:
|
| 124 |
+
full_response = "माफ करें, मैं आपका सवाल समझ नहीं पाया। कृपया दोबारा कोशिश करें।"
|
| 125 |
+
|
| 126 |
+
# Add to history
|
| 127 |
+
history.append([message, full_response])
|
| 128 |
+
return history, ""
|
| 129 |
+
|
| 130 |
+
except Exception as e:
|
| 131 |
+
logger.error(f"Chat error: {str(e)}")
|
| 132 |
+
error_message = f"❌ तकनीकी समस्या: {str(e)}"
|
| 133 |
+
history.append([message, error_message])
|
| 134 |
+
return history, ""
|
| 135 |
+
|
| 136 |
+
# Initialize AI Assistant
|
| 137 |
+
ai_assistant = AIAssistant()
|
| 138 |
+
|
| 139 |
+
# Custom CSS
|
| 140 |
+
custom_css = """
|
| 141 |
+
/* Main container styling */
|
| 142 |
+
.gradio-container {
|
| 143 |
+
font-family: 'Inter', sans-serif !important;
|
| 144 |
+
background: linear-gradient(135deg, #FBF9F6 0%, #F7F5F2 100%) !important;
|
| 145 |
+
min-height: 100vh;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/* Header styling */
|
| 149 |
+
.main-header {
|
| 150 |
+
text-align: center;
|
| 151 |
+
padding: 2rem 0;
|
| 152 |
+
background: rgba(255, 255, 255, 0.8);
|
| 153 |
+
border-radius: 1rem;
|
| 154 |
+
margin-bottom: 2rem;
|
| 155 |
+
backdrop-filter: blur(10px);
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
/* Chat interface styling */
|
| 159 |
+
.chat-interface {
|
| 160 |
+
max-width: 800px;
|
| 161 |
+
margin: 0 auto;
|
| 162 |
+
}
|
| 163 |
+
|
| 164 |
+
/* Chatbot messages */
|
| 165 |
+
.message.user {
|
| 166 |
+
background: linear-gradient(135deg, #EAE4DE 0%, #D9CFC7 100%) !important;
|
| 167 |
+
border-radius: 1rem 1rem 0.5rem 1rem !important;
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
.message.bot {
|
| 171 |
+
background: linear-gradient(135deg, #F7F5F2 0%, #EFEBE7 100%) !important;
|
| 172 |
+
border-radius: 1rem 1rem 1rem 0.5rem !important;
|
| 173 |
+
border-left: 4px solid #D97757 !important;
|
| 174 |
+
}
|
| 175 |
+
|
| 176 |
+
/* Input styling */
|
| 177 |
+
.input-container {
|
| 178 |
+
background: rgba(255, 255, 255, 0.9) !important;
|
| 179 |
+
border-radius: 1rem !important;
|
| 180 |
+
border: 2px solid #EAE8E5 !important;
|
| 181 |
+
backdrop-filter: blur(10px);
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
/* Button styling */
|
| 185 |
+
.submit-btn {
|
| 186 |
+
background: linear-gradient(135deg, #D97757 0%, #B85C42 100%) !important;
|
| 187 |
+
color: white !important;
|
| 188 |
+
border: none !important;
|
| 189 |
+
border-radius: 0.75rem !important;
|
| 190 |
+
font-weight: 600 !important;
|
| 191 |
+
}
|
| 192 |
+
|
| 193 |
+
.submit-btn:hover {
|
| 194 |
+
transform: translateY(-2px) !important;
|
| 195 |
+
box-shadow: 0 8px 25px rgba(217, 119, 87, 0.3) !important;
|
| 196 |
+
}
|
| 197 |
+
|
| 198 |
+
/* Examples styling */
|
| 199 |
+
.examples-container {
|
| 200 |
+
display: flex;
|
| 201 |
+
flex-wrap: wrap;
|
| 202 |
+
gap: 0.5rem;
|
| 203 |
+
justify-content: center;
|
| 204 |
+
margin-top: 1rem;
|
| 205 |
+
}
|
| 206 |
+
|
| 207 |
+
.example-btn {
|
| 208 |
+
background: rgba(247, 245, 242, 0.8) !important;
|
| 209 |
+
border: 1px solid #EAE8E5 !important;
|
| 210 |
+
border-radius: 2rem !important;
|
| 211 |
+
padding: 0.5rem 1rem !important;
|
| 212 |
+
font-size: 0.875rem !important;
|
| 213 |
+
color: #5A524C !important;
|
| 214 |
+
transition: all 0.2s ease !important;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
.example-btn:hover {
|
| 218 |
+
background: rgba(217, 119, 87, 0.1) !important;
|
| 219 |
+
border-color: #D97757 !important;
|
| 220 |
+
transform: translateY(-1px) !important;
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
/* Footer */
|
| 224 |
+
.footer-info {
|
| 225 |
+
text-align: center;
|
| 226 |
+
padding: 1rem;
|
| 227 |
+
color: #8B7355;
|
| 228 |
+
font-size: 0.875rem;
|
| 229 |
+
border-top: 1px solid #EAE8E5;
|
| 230 |
+
background: rgba(255, 255, 255, 0.5);
|
| 231 |
+
}
|
| 232 |
+
"""
|
| 233 |
+
|
| 234 |
+
# Create Gradio Interface
|
| 235 |
+
with gr.Blocks(
|
| 236 |
+
theme=gr.themes.Soft(
|
| 237 |
+
primary_hue="orange",
|
| 238 |
+
secondary_hue="amber",
|
| 239 |
+
neutral_hue="stone"
|
| 240 |
+
),
|
| 241 |
+
css=custom_css,
|
| 242 |
+
title="AI Assistant - Powered by Pollinations"
|
| 243 |
+
) as demo:
|
| 244 |
+
|
| 245 |
+
# Header
|
| 246 |
+
with gr.Row(elem_classes="main-header"):
|
| 247 |
+
with gr.Column():
|
| 248 |
+
gr.HTML("""
|
| 249 |
+
<div style="display: flex; align-items: center; justify-content: center; gap: 1rem;">
|
| 250 |
+
<svg width="48" height="48" viewBox="0 0 100 100">
|
| 251 |
+
<path d="M50 0 L61.8 38.2 L100 38.2 L69.1 61.8 L80.9 100 L50 76.4 L19.1 100 L30.9 61.8 L0 38.2 L38.2 38.2 Z" fill="#D97757"/>
|
| 252 |
+
</svg>
|
| 253 |
+
<h1 style="font-size: 2.5rem; font-weight: 600; color: #3D3D3D; margin: 0; font-family: 'Playfair Display', serif;">
|
| 254 |
+
Hi, कैसे मदद कर सकता हूँ?
|
| 255 |
+
</h1>
|
| 256 |
+
</div>
|
| 257 |
+
<p style="color: #8B7355; margin-top: 0.5rem; font-size: 1.1rem;">
|
| 258 |
+
आपका AI Assistant - Hindi और English में बातचीत के लिए तैयार
|
| 259 |
+
</p>
|
| 260 |
+
""")
|
| 261 |
+
|
| 262 |
+
# Main Chat Interface
|
| 263 |
+
with gr.Row(elem_classes="chat-interface"):
|
| 264 |
+
with gr.Column(scale=1):
|
| 265 |
+
chatbot = gr.Chatbot(
|
| 266 |
+
[],
|
| 267 |
+
height=500,
|
| 268 |
+
show_label=False,
|
| 269 |
+
avatar_images=("👤", "🤖"),
|
| 270 |
+
bubble_full_width=False,
|
| 271 |
+
show_share_button=False,
|
| 272 |
+
show_copy_button=True
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
with gr.Row():
|
| 276 |
+
with gr.Column(scale=8):
|
| 277 |
+
msg = gr.Textbox(
|
| 278 |
+
placeholder="मुझसे कुछ भी पूछें... (Hindi या English में)",
|
| 279 |
+
show_label=False,
|
| 280 |
+
container=False,
|
| 281 |
+
lines=1,
|
| 282 |
+
max_lines=5
|
| 283 |
+
)
|
| 284 |
+
with gr.Column(scale=1, min_width=80):
|
| 285 |
+
submit = gr.Button(
|
| 286 |
+
"भेजें ➤",
|
| 287 |
+
variant="primary",
|
| 288 |
+
elem_classes="submit-btn"
|
| 289 |
+
)
|
| 290 |
+
|
| 291 |
+
# Example prompts
|
| 292 |
+
with gr.Row():
|
| 293 |
+
gr.Examples(
|
| 294 |
+
examples=[
|
| 295 |
+
["एक कविता लिखकर दो"],
|
| 296 |
+
["Python में calculator बनाना सिखाएं"],
|
| 297 |
+
["मुझसे बात करिए"],
|
| 298 |
+
["What is machine learning?"],
|
| 299 |
+
["भारत का इतिहास बताएं"],
|
| 300 |
+
["कोई मजेदार fact बताएं"]
|
| 301 |
+
],
|
| 302 |
+
inputs=msg,
|
| 303 |
+
elem_classes="examples-container"
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
# Footer
|
| 307 |
+
gr.HTML("""
|
| 308 |
+
<div class="footer-info">
|
| 309 |
+
<p>🔒 Powered by <strong>Pollinations AI</strong> | 🌟 Built with Gradio on Hugging Face Spaces</p>
|
| 310 |
+
<p style="font-size: 0.75rem; margin-top: 0.5rem;">
|
| 311 |
+
यह AI assistant आपकी बातचीत को याद रखता है और context के साथ जवाब देता है
|
| 312 |
+
</p>
|
| 313 |
+
</div>
|
| 314 |
+
""")
|
| 315 |
+
|
| 316 |
+
# Event handlers
|
| 317 |
+
msg.submit(ai_assistant.chat_response, [msg, chatbot], [chatbot, msg])
|
| 318 |
+
submit.click(ai_assistant.chat_response, [msg, chatbot], [chatbot, msg])
|
| 319 |
+
|
| 320 |
+
# Launch configuration
|
| 321 |
+
if __name__ == "__main__":
|
| 322 |
+
demo.launch(
|
| 323 |
+
server_name="0.0.0.0",
|
| 324 |
+
server_port=7860,
|
| 325 |
+
share=False,
|
| 326 |
+
debug=False,
|
| 327 |
+
show_error=True,
|
| 328 |
+
quiet=False
|
| 329 |
+
)
|