legends810 commited on
Commit
dde3f74
·
verified ·
1 Parent(s): 3bad7c7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +218 -246
app.py CHANGED
@@ -1,11 +1,14 @@
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)
@@ -15,261 +18,230 @@ logger = logging.getLogger(__name__)
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
- /* Chat interface styling */
149
- .chat-interface {
150
- max-width: 800px;
151
- margin: 0 auto;
152
- }
 
153
 
154
- /* Button styling */
155
- .submit-btn {
156
- background: linear-gradient(135deg, #D97757 0%, #B85C42 100%) !important;
157
- color: white !important;
158
- border: none !important;
159
- border-radius: 0.75rem !important;
160
- font-weight: 600 !important;
161
- }
162
 
163
- .submit-btn:hover {
164
- transform: translateY(-2px) !important;
165
- box-shadow: 0 8px 25px rgba(217, 119, 87, 0.3) !important;
166
- }
167
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
 
169
- # Create Gradio Interface
170
- with gr.Blocks(
171
- theme=gr.themes.Soft(
172
- primary_hue="orange",
173
- secondary_hue="amber",
174
- neutral_hue="stone"
175
- ),
176
- css=custom_css,
177
- title="AI Assistant - Powered by Pollinations"
178
- ) as demo:
179
 
180
- # Header
181
- gr.HTML("""
182
- <div style="text-align: center; padding: 2rem 0; background: rgba(255, 255, 255, 0.8); border-radius: 1rem; margin-bottom: 2rem; backdrop-filter: blur(10px);">
183
- <div style="display: flex; align-items: center; justify-content: center; gap: 1rem;">
184
- <svg width="48" height="48" viewBox="0 0 100 100">
185
- <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"/>
186
- </svg>
187
- <h1 style="font-size: 2.5rem; font-weight: 600; color: #3D3D3D; margin: 0; font-family: 'Playfair Display', serif;">
188
- Hi, कैसे मदद कर सकता हूँ?
189
- </h1>
190
- </div>
191
- <p style="color: #8B7355; margin-top: 0.5rem; font-size: 1.1rem;">
192
- आपका AI Assistant - Hindi और English में बातचीत के लिए तैयार
193
- </p>
194
- </div>
195
- """)
196
 
197
- # Main Chat Interface
198
- with gr.Column():
199
- # Fixed Chatbot with proper parameters
200
- chatbot = gr.Chatbot(
201
- value=[],
202
- height=500,
203
- show_label=False,
204
- avatar_images=("👤", "🤖"),
205
- show_share_button=False,
206
- show_copy_button=True,
207
- type="tuples" # Explicitly set type to avoid warning
208
- )
209
-
210
- with gr.Row():
211
- with gr.Column(scale=8):
212
- msg = gr.Textbox(
213
- placeholder="मुझसे कुछ भी पूछें... (Hindi या English में)",
214
- show_label=False,
215
- container=False,
216
- lines=1,
217
- max_lines=5
218
- )
219
- with gr.Column(scale=1, min_width=80):
220
- submit = gr.Button(
221
- "भेजें ➤",
222
- variant="primary"
223
- )
224
-
225
- # Example prompts - Fixed without elem_classes
226
- with gr.Row():
227
- with gr.Column():
228
- gr.Markdown("**कुछ सुझाव:**")
229
- example_buttons = []
230
- examples = [
231
- "एक कविता लिखकर दो",
232
- "Python में calculator बनाना सिखाएं",
233
- "मुझसे बात करिए",
234
- "What is machine learning?",
235
- "भारत का इतिहास बताएं",
236
- "कोई मजेदार fact बताएं"
237
- ]
 
 
 
 
238
 
239
- # Create example buttons manually
240
- with gr.Row():
241
- for i, example in enumerate(examples[:3]):
242
- btn = gr.Button(example, size="sm", variant="secondary")
243
- example_buttons.append(btn)
244
- btn.click(lambda x=example: x, outputs=msg)
245
 
246
- with gr.Row():
247
- for i, example in enumerate(examples[3:]):
248
- btn = gr.Button(example, size="sm", variant="secondary")
249
- example_buttons.append(btn)
250
- btn.click(lambda x=example: x, outputs=msg)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
 
252
- # Footer
253
- gr.HTML("""
254
- <div style="text-align: center; padding: 1rem; color: #8B7355; font-size: 0.875rem; border-top: 1px solid #EAE8E5; background: rgba(255, 255, 255, 0.5);">
255
- <p>🔒 Powered by <strong>Pollinations AI</strong> | 🌟 Built with Gradio on Hugging Face Spaces</p>
256
- <p style="font-size: 0.75rem; margin-top: 0.5rem;">
257
- यह AI assistant आपकी बातचीत को याद रखता है और context के साथ जवाब देता है
258
- </p>
259
- </div>
260
- """)
 
 
261
 
262
- # Event handlers
263
- msg.submit(ai_assistant.chat_response, [msg, chatbot], [chatbot, msg])
264
- submit.click(ai_assistant.chat_response, [msg, chatbot], [chatbot, msg])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
- # Launch configuration
267
  if __name__ == "__main__":
268
- demo.launch(
269
- server_name="0.0.0.0",
270
- server_port=7860,
271
- share=False,
272
- debug=False,
273
- show_error=True,
274
- quiet=False
275
- )
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from pydantic import BaseModel
4
+ from typing import List, Dict, Optional
5
  import asyncio
6
  import aiohttp
7
+ import json
8
  import time
9
  import logging
10
+ from fastapi.responses import StreamingResponse
11
+ import uvicorn
12
 
13
  # Configure logging
14
  logging.basicConfig(level=logging.INFO)
 
18
  POLLINATIONS_API_URL = "https://text.pollinations.ai/openai"
19
  API_KEY = "wPGHlU-7pPYlOetQ"
20
  MAX_CONTEXT_MESSAGES = 15
 
21
 
22
+ # FastAPI app
23
+ app = FastAPI(
24
+ title="AI Assistant API",
25
+ description="Server API for AI Assistant powered by Pollinations",
26
+ version="1.0.0"
27
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ # CORS middleware - आपके frontend के लिए जरूरी
30
+ app.add_middleware(
31
+ CORSMiddleware,
32
+ allow_origins=["*"], # Production में specific domains add करें
33
+ allow_credentials=True,
34
+ allow_methods=["*"],
35
+ allow_headers=["*"],
36
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ # Request models
39
+ class ChatMessage(BaseModel):
40
+ role: str
41
+ content: str
42
 
43
+ class ChatRequest(BaseModel):
44
+ type: str
45
+ prompt: str
46
+ model: Optional[str] = "openai"
47
+ conversation: Optional[List[ChatMessage]] = []
48
+ stream: Optional[bool] = True
49
+ private: Optional[bool] = True
50
+ referrer: Optional[str] = API_KEY
51
 
52
+ class ChatResponse(BaseModel):
53
+ success: bool
54
+ choices: Optional[List[Dict]] = None
55
+ error: Optional[str] = None
56
+ model: Optional[str] = None
57
+ timestamp: Optional[int] = None
58
 
59
+ @app.get("/")
60
+ async def root():
61
+ """Health check endpoint"""
62
+ return {
63
+ "status": "running",
64
+ "message": "AI Assistant API Server",
65
+ "timestamp": int(time.time())
66
+ }
67
 
68
+ @app.post("/api/chat")
69
+ async def chat_endpoint(request: ChatRequest):
70
+ """Main chat endpoint - exactly like your server.php"""
71
+
72
+ if not request.prompt or not request.prompt.strip():
73
+ raise HTTPException(status_code=400, detail="Prompt cannot be empty")
74
+
75
+ try:
76
+ if request.stream:
77
+ return StreamingResponse(
78
+ generate_streaming_response(request),
79
+ media_type="text/event-stream",
80
+ headers={
81
+ "Cache-Control": "no-cache",
82
+ "Connection": "keep-alive",
83
+ "Access-Control-Allow-Origin": "*",
84
+ "Access-Control-Allow-Methods": "POST, GET, OPTIONS",
85
+ "Access-Control-Allow-Headers": "Content-Type"
86
+ }
87
+ )
88
+ else:
89
+ response = await generate_non_streaming_response(request)
90
+ return response
91
+
92
+ except Exception as e:
93
+ logger.error(f"Chat error: {str(e)}")
94
+ raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")
95
 
96
+ async def generate_streaming_response(request: ChatRequest):
97
+ """Generate streaming response - exactly like your PHP version"""
 
 
 
 
 
 
 
 
98
 
99
+ # System message
100
+ system_message = {
101
+ 'role': 'system',
102
+ 'content': 'आप एक helpful AI assistant हैं। User को Hindi और English दोनों languages में helpful और accurate answers देते हैं। आप friendly, conversational और natural tone में बात करते हैं। Code माँगने पर proper formatting के साथ दें। हमेशा relevant और उपयोगी जवाब दें।'
103
+ }
 
 
 
 
 
 
 
 
 
 
 
104
 
105
+ messages = [system_message]
106
+
107
+ # Add conversation history
108
+ for msg in request.conversation[-MAX_CONTEXT_MESSAGES:]:
109
+ if msg.role in ['user', 'assistant'] and msg.content.strip():
110
+ content = msg.content[:2000] # Limit content length
111
+ messages.append({
112
+ 'role': msg.role,
113
+ 'content': content
114
+ })
115
+
116
+ # Add current prompt
117
+ messages.append({
118
+ 'role': 'user',
119
+ 'content': request.prompt
120
+ })
121
+
122
+ payload = {
123
+ 'model': request.model,
124
+ 'messages': messages,
125
+ 'temperature': 0.7,
126
+ 'max_tokens': 1000,
127
+ 'top_p': 0.9,
128
+ 'stream': True,
129
+ 'private': request.private,
130
+ 'referrer': request.referrer,
131
+ 'seed': int(time.time()) % 1000000
132
+ }
133
+
134
+ try:
135
+ async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=60)) as session:
136
+ async with session.post(
137
+ POLLINATIONS_API_URL,
138
+ json=payload,
139
+ headers={
140
+ 'Content-Type': 'application/json',
141
+ 'Accept': 'text/event-stream',
142
+ 'User-Agent': 'AI-Assistant-API/1.0'
143
+ }
144
+ ) as response:
145
+
146
+ if response.status != 200:
147
+ error_text = await response.text()
148
+ yield f"data: {json.dumps({'error': f'API returned HTTP {response.status}: {error_text}'})}\n\n"
149
+ return
150
 
151
+ async for line in response.content:
152
+ line_text = line.decode('utf-8')
153
+ yield line_text
 
 
 
154
 
155
+ yield "data: [DONE]\n\n"
156
+
157
+ except asyncio.TimeoutError:
158
+ yield f"data: {json.dumps({'error': 'Request timeout - कृपया दो���ारा कोशिश करें'})}\n\n"
159
+ except Exception as e:
160
+ yield f"data: {json.dumps({'error': f'Network error: {str(e)}'})}\n\n"
161
+
162
+ async def generate_non_streaming_response(request: ChatRequest):
163
+ """Generate non-streaming response"""
164
+
165
+ system_message = {
166
+ 'role': 'system',
167
+ 'content': 'आप एक helpful AI assistant हैं। User को Hindi और English दोनों languages में helpful और accurate answers देते हैं। आप friendly, conversational और natural tone में बात करते हैं। Code माँगने पर proper formatting के साथ दें। हमेशा relevant और उपयोगी जवाब दें।'
168
+ }
169
+
170
+ messages = [system_message]
171
+
172
+ for msg in request.conversation[-MAX_CONTEXT_MESSAGES:]:
173
+ if msg.role in ['user', 'assistant'] and msg.content.strip():
174
+ content = msg.content[:2000]
175
+ messages.append({
176
+ 'role': msg.role,
177
+ 'content': content
178
+ })
179
+
180
+ messages.append({
181
+ 'role': 'user',
182
+ 'content': request.prompt
183
+ })
184
 
185
+ payload = {
186
+ 'model': request.model,
187
+ 'messages': messages,
188
+ 'temperature': 0.7,
189
+ 'max_tokens': 1000,
190
+ 'top_p': 0.9,
191
+ 'stream': False,
192
+ 'private': request.private,
193
+ 'referrer': request.referrer,
194
+ 'seed': int(time.time()) % 1000000
195
+ }
196
 
197
+ try:
198
+ async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30)) as session:
199
+ async with session.post(
200
+ POLLINATIONS_API_URL,
201
+ json=payload,
202
+ headers={
203
+ 'Content-Type': 'application/json',
204
+ 'User-Agent': 'AI-Assistant-API/1.0'
205
+ }
206
+ ) as response:
207
+
208
+ if response.status != 200:
209
+ error_text = await response.text()
210
+ return ChatResponse(
211
+ success=False,
212
+ error=f"API returned HTTP {response.status}: {error_text}"
213
+ )
214
+
215
+ data = await response.json()
216
+
217
+ return ChatResponse(
218
+ success=True,
219
+ choices=data.get('choices', []),
220
+ model=request.model,
221
+ timestamp=int(time.time())
222
+ )
223
+
224
+ except Exception as e:
225
+ logger.error(f"API Error: {str(e)}")
226
+ return ChatResponse(
227
+ success=False,
228
+ error=f"Network error: {str(e)}"
229
+ )
230
+
231
+ # Health check endpoints
232
+ @app.get("/health")
233
+ async def health_check():
234
+ return {"status": "healthy", "timestamp": int(time.time())}
235
+
236
+ @app.get("/api/status")
237
+ async def api_status():
238
+ return {
239
+ "api_version": "1.0.0",
240
+ "pollinations_endpoint": POLLINATIONS_API_URL,
241
+ "max_context_messages": MAX_CONTEXT_MESSAGES,
242
+ "supported_models": ["openai"],
243
+ "timestamp": int(time.time())
244
+ }
245
 
 
246
  if __name__ == "__main__":
247
+ uvicorn.run(app, host="0.0.0.0", port=7860)