JatsTheAIGen commited on
Commit
2945a34
·
1 Parent(s): 18dd400

api endpoints for UI migration v10

Browse files
Files changed (4) hide show
  1. FLASK_API_SETUP.md +368 -0
  2. express_flask_integration.js +145 -0
  3. flask_api.py +182 -0
  4. requirements.txt +4 -0
FLASK_API_SETUP.md ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Flask API Setup Guide
2
+
3
+ ## Overview
4
+
5
+ The Flask API (`flask_api.py`) provides a simple REST API interface to the Research AI Assistant orchestrator. It runs on port 5001, separate from Gradio (port 7860).
6
+
7
+ ## Architecture
8
+
9
+ ```
10
+ ┌─────────────────┐
11
+ │ Express.js UI │ Port 3000
12
+ │ (or other │ - User interface
13
+ │ frontend) │ - Session management
14
+ └────────┬────────┘
15
+ │ HTTP POST /api/chat
16
+
17
+ ┌─────────────────┐
18
+ │ Flask API │ Port 5001
19
+ │ flask_api.py │ - REST endpoints
20
+ │ │ - Imports from app.py
21
+ └────────┬────────┘ - Direct Python access
22
+
23
+ ┌─────────────────┐
24
+ │ Orchestrator │ Python
25
+ │ (from app.py) │ - AI agents
26
+ │ │ - Context management
27
+ └─────────────────┘
28
+
29
+ ┌─────────────────┐
30
+ │ Gradio UI │ Port 7860
31
+ │ (optional) │ - Alternative UI
32
+ │ app.py │ - Can run alongside
33
+ └─────────────────┘
34
+ ```
35
+
36
+ ## Quick Start
37
+
38
+ ### Step 1: Install Dependencies
39
+
40
+ ```bash
41
+ pip install flask flask-cors
42
+ ```
43
+
44
+ Or install all requirements:
45
+ ```bash
46
+ pip install -r requirements.txt
47
+ ```
48
+
49
+ ### Step 2: Start Flask API
50
+
51
+ ```bash
52
+ # Default port 5001
53
+ python flask_api.py
54
+
55
+ # Or specify custom port
56
+ FLASK_PORT=5001 python flask_api.py
57
+ ```
58
+
59
+ You should see:
60
+ ```
61
+ STARTING FLASK API
62
+ INITIALIZING AI ORCHESTRATOR
63
+ ✓ AI ORCHESTRATOR READY
64
+ Starting Flask API on port 5001
65
+ ```
66
+
67
+ ### Step 3: Test the API
68
+
69
+ ```bash
70
+ # Health check
71
+ curl http://localhost:5001/health
72
+
73
+ # Chat endpoint
74
+ curl -X POST http://localhost:5001/api/chat \
75
+ -H "Content-Type: application/json" \
76
+ -d '{
77
+ "message": "Hello, how are you?",
78
+ "session_id": "test-session-123",
79
+ "user_id": "test-user"
80
+ }'
81
+ ```
82
+
83
+ ## API Endpoints
84
+
85
+ ### `GET /health`
86
+
87
+ Health check endpoint.
88
+
89
+ **Response:**
90
+ ```json
91
+ {
92
+ "status": "ok",
93
+ "orchestrator_available": true,
94
+ "service": "flask_api"
95
+ }
96
+ ```
97
+
98
+ ### `POST /api/chat`
99
+
100
+ Main chat endpoint for processing user messages.
101
+
102
+ **Request:**
103
+ ```json
104
+ {
105
+ "message": "What is machine learning?",
106
+ "history": [], // optional
107
+ "session_id": "session-123", // optional, auto-generated if not provided
108
+ "user_id": "user-123" // optional, defaults to "Admin_J"
109
+ }
110
+ ```
111
+
112
+ **Response:**
113
+ ```json
114
+ {
115
+ "response": "Machine learning is...",
116
+ "history": [
117
+ {"role": "user", "content": "What is machine learning?"},
118
+ {"role": "assistant", "content": "Machine learning is..."}
119
+ ],
120
+ "reasoning": {
121
+ "chain_of_thought": {...},
122
+ "confidence_calibration": {...}
123
+ },
124
+ "performance": {
125
+ "processing_time": 1.23,
126
+ "tokens_used": 456
127
+ },
128
+ "context": {
129
+ "session_context": "...",
130
+ "relevant_interactions": [...]
131
+ },
132
+ "session_id": "session-123",
133
+ "skills": "<div>...</div>" // HTML for skills display
134
+ }
135
+ ```
136
+
137
+ ### `GET /api/orchestrator/status`
138
+
139
+ Check if orchestrator is available.
140
+
141
+ **Response:**
142
+ ```json
143
+ {
144
+ "orchestrator_available": true,
145
+ "orchestrator_type": "MVPOrchestrator"
146
+ }
147
+ ```
148
+
149
+ ## Configuration
150
+
151
+ ### Environment Variables
152
+
153
+ ```bash
154
+ # Flask configuration
155
+ FLASK_PORT=5001 # Port for Flask API (default: 5001)
156
+ FLASK_HOST=0.0.0.0 # Host to bind to (default: 0.0.0.0)
157
+
158
+ # AI configuration (used by orchestrator)
159
+ HF_TOKEN=your_token_here # Hugging Face token for API access
160
+ ```
161
+
162
+ ### Ports
163
+
164
+ - **Flask API**: 5001 (configurable via `FLASK_PORT`)
165
+ - **Gradio UI**: 7860 (separate, can run alongside)
166
+ - **Express.js** (external): 3000 (your frontend)
167
+
168
+ ## Running with Gradio
169
+
170
+ You can run Flask API alongside Gradio:
171
+
172
+ **Terminal 1: Flask API**
173
+ ```bash
174
+ python flask_api.py
175
+ ```
176
+
177
+ **Terminal 2: Gradio UI (optional)**
178
+ ```bash
179
+ python app.py
180
+ ```
181
+
182
+ Both can run simultaneously on different ports.
183
+
184
+ ## Integration Examples
185
+
186
+ ### Express.js Integration
187
+
188
+ See `EXPRESS_FLASK_INTEGRATION.md` for Express.js setup.
189
+
190
+ ### Python Client
191
+
192
+ ```python
193
+ import requests
194
+
195
+ def chat_with_flask(message, session_id=None):
196
+ url = "http://localhost:5001/api/chat"
197
+ data = {
198
+ "message": message,
199
+ "session_id": session_id or "python-client-session"
200
+ }
201
+ response = requests.post(url, json=data)
202
+ return response.json()
203
+
204
+ # Usage
205
+ result = chat_with_flask("Hello, how are you?")
206
+ print(result["response"])
207
+ ```
208
+
209
+ ### JavaScript/Node.js Client
210
+
211
+ ```javascript
212
+ const axios = require('axios');
213
+
214
+ async function chatWithFlask(message, sessionId = null) {
215
+ const response = await axios.post('http://localhost:5001/api/chat', {
216
+ message: message,
217
+ session_id: sessionId || `node-client-session-${Date.now()}`
218
+ });
219
+ return response.data;
220
+ }
221
+
222
+ // Usage
223
+ chatWithFlask("Hello, how are you?")
224
+ .then(result => console.log(result.response))
225
+ .catch(error => console.error(error));
226
+ ```
227
+
228
+ ## Troubleshooting
229
+
230
+ ### Issue: "Orchestrator not available"
231
+
232
+ **Check:**
233
+ 1. Flask API logs show initialization errors
234
+ 2. `HF_TOKEN` environment variable is set
235
+ 3. All dependencies are installed
236
+
237
+ **Solution:**
238
+ ```bash
239
+ # Check logs
240
+ # Look for "INITIALIZING AI ORCHESTRATOR" section
241
+
242
+ # Verify HF token
243
+ echo $HF_TOKEN
244
+
245
+ # Reinstall dependencies
246
+ pip install -r requirements.txt
247
+ ```
248
+
249
+ ### Issue: "Port already in use"
250
+
251
+ **Solution:**
252
+ ```bash
253
+ # Use different port
254
+ FLASK_PORT=5002 python flask_api.py
255
+ ```
256
+
257
+ ### Issue: "Module not found"
258
+
259
+ **Check:**
260
+ 1. You're in the correct directory (same as `app.py`)
261
+ 2. All imports are available
262
+
263
+ **Solution:**
264
+ ```bash
265
+ # Make sure you're in the project root
266
+ cd /path/to/Research_AI_Assistant
267
+
268
+ # Verify Python path
269
+ python -c "import app; print('✓ app.py importable')"
270
+ ```
271
+
272
+ ### Issue: "CORS errors"
273
+
274
+ **Solution:** Flask-CORS is enabled by default. If issues persist:
275
+
276
+ ```python
277
+ # In flask_api.py, customize CORS:
278
+ from flask_cors import CORS
279
+ CORS(app, resources={r"/api/*": {"origins": "*"}})
280
+ ```
281
+
282
+ ## Advantages Over Gradio API
283
+
284
+ | Feature | Flask API | Gradio HTTP |
285
+ |---------|-----------|-------------|
286
+ | **Simplicity** | ✅ Simple JSON | ⚠️ Gradio-specific format |
287
+ | **Control** | ✅ Full control | ⚠️ Limited by Gradio |
288
+ | **Path issues** | ✅ None | ⚠️ Can have path problems |
289
+ | **Dependencies** | ✅ Just Flask | ⚠️ Requires Gradio client |
290
+ | **API design** | ✅ You design it | ⚠️ Gradio's design |
291
+ | **Startup** | ✅ Fast | ⚠️ Slower (Gradio overhead) |
292
+
293
+ ## Production Deployment
294
+
295
+ ### Using PM2 (Process Manager)
296
+
297
+ ```bash
298
+ # Install PM2
299
+ npm install -g pm2
300
+
301
+ # Start Flask API
302
+ pm2 start flask_api.py --interpreter python3 --name flask-api
303
+
304
+ # Start Express (if using)
305
+ pm2 start server.js --name express
306
+
307
+ # View status
308
+ pm2 status
309
+ ```
310
+
311
+ ### Using systemd (Linux)
312
+
313
+ Create `/etc/systemd/system/flask-api.service`:
314
+ ```ini
315
+ [Unit]
316
+ Description=Research AI Assistant Flask API
317
+ After=network.target
318
+
319
+ [Service]
320
+ Type=simple
321
+ User=your-user
322
+ WorkingDirectory=/path/to/Research_AI_Assistant
323
+ Environment="FLASK_PORT=5001"
324
+ Environment="HF_TOKEN=your-token"
325
+ ExecStart=/usr/bin/python3 flask_api.py
326
+ Restart=always
327
+
328
+ [Install]
329
+ WantedBy=multi-user.target
330
+ ```
331
+
332
+ Then:
333
+ ```bash
334
+ sudo systemctl enable flask-api
335
+ sudo systemctl start flask-api
336
+ ```
337
+
338
+ ## Security Considerations
339
+
340
+ 1. **CORS**: Currently allows all origins (`*`). In production, restrict to your frontend domain:
341
+ ```python
342
+ CORS(app, origins=["https://your-frontend.com"])
343
+ ```
344
+
345
+ 2. **Rate Limiting**: Consider adding rate limiting:
346
+ ```bash
347
+ pip install flask-limiter
348
+ ```
349
+
350
+ 3. **Authentication**: Add API keys or tokens for production:
351
+ ```python
352
+ @app.before_request
353
+ def check_api_key():
354
+ api_key = request.headers.get('X-API-Key')
355
+ if api_key != os.getenv('API_KEY'):
356
+ return jsonify({'error': 'Unauthorized'}), 401
357
+ ```
358
+
359
+ ## Summary
360
+
361
+ ✅ **Simple**: Just Flask, no complex wrappers
362
+ ✅ **Flexible**: Your API design, your control
363
+ ✅ **Compatible**: Works alongside Gradio
364
+ ✅ **Standard**: Standard REST API pattern
365
+ ✅ **Fast**: Direct Python imports, no overhead
366
+
367
+ Start Flask, integrate your frontend, done! 🚀
368
+
express_flask_integration.js ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Express.js Integration with Flask API
3
+ *
4
+ * This module provides Express routes that proxy requests to the Flask API.
5
+ * Use this if you have an Express.js frontend that needs to communicate with
6
+ * the Python Flask API backend.
7
+ *
8
+ * Usage in server.js:
9
+ * const { setupFlaskRoutes, initializeFlask } = require('./express_flask_integration');
10
+ * setupFlaskRoutes(app);
11
+ * await initializeFlask();
12
+ */
13
+
14
+ const axios = require('axios');
15
+
16
+ // Flask API configuration
17
+ const FLASK_API_URL = process.env.FLASK_API_URL || 'http://localhost:5001';
18
+ const FLASK_HEALTH_ENDPOINT = `${FLASK_API_URL}/health`;
19
+ const FLASK_CHAT_ENDPOINT = `${FLASK_API_URL}/api/chat`;
20
+
21
+ /**
22
+ * Initialize Flask API connection
23
+ * Checks if Flask API is running and orchestrator is available
24
+ */
25
+ async function initializeFlask() {
26
+ console.log('Checking Flask API connection...');
27
+
28
+ try {
29
+ const response = await axios.get(FLASK_HEALTH_ENDPOINT, {
30
+ timeout: 5000
31
+ });
32
+
33
+ if (response.data.status === 'ok') {
34
+ console.log('✓ Flask API connected');
35
+
36
+ if (response.data.orchestrator_available) {
37
+ console.log('✓ AI Orchestrator available');
38
+ } else {
39
+ console.warn('⚠ AI Orchestrator not available - some features may be limited');
40
+ }
41
+
42
+ return true;
43
+ } else {
44
+ console.error('✗ Flask API health check failed');
45
+ return false;
46
+ }
47
+ } catch (error) {
48
+ console.error('✗ Cannot connect to Flask API:', error.message);
49
+ console.error(` Make sure Flask API is running on ${FLASK_API_URL}`);
50
+ console.error(' Start it with: python flask_api.py');
51
+ return false;
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Setup Flask routes on Express app
57
+ * Adds /api/flask/* routes that proxy to Flask API
58
+ */
59
+ function setupFlaskRoutes(app) {
60
+ // Health check route (proxies to Flask)
61
+ app.get('/api/flask/health', async (req, res) => {
62
+ try {
63
+ const response = await axios.get(FLASK_HEALTH_ENDPOINT);
64
+ res.json(response.data);
65
+ } catch (error) {
66
+ res.status(503).json({
67
+ error: 'Flask API unavailable',
68
+ message: error.message
69
+ });
70
+ }
71
+ });
72
+
73
+ // Main chat endpoint (proxies to Flask)
74
+ app.post('/api/chat', async (req, res) => {
75
+ try {
76
+ const { message, history, session_id, user_id } = req.body;
77
+
78
+ if (!message || !message.trim()) {
79
+ return res.status(400).json({
80
+ error: 'Message is required'
81
+ });
82
+ }
83
+
84
+ // Forward request to Flask API
85
+ const response = await axios.post(FLASK_CHAT_ENDPOINT, {
86
+ message: message.trim(),
87
+ history: history || [],
88
+ session_id: session_id || `express-session-${Date.now()}`,
89
+ user_id: user_id || 'Express_User'
90
+ }, {
91
+ timeout: 60000 // 60 second timeout for AI processing
92
+ });
93
+
94
+ // Return Flask response
95
+ res.json(response.data);
96
+
97
+ } catch (error) {
98
+ console.error('Error in Flask chat endpoint:', error);
99
+
100
+ if (error.code === 'ECONNREFUSED') {
101
+ return res.status(503).json({
102
+ error: 'Flask API unavailable',
103
+ message: 'The AI backend is not running. Please start Flask API.',
104
+ response: 'I apologize, but the AI service is temporarily unavailable. Please try again later.'
105
+ });
106
+ }
107
+
108
+ if (error.response) {
109
+ // Flask API returned an error
110
+ return res.status(error.response.status).json(error.response.data);
111
+ }
112
+
113
+ // Other errors
114
+ res.status(500).json({
115
+ error: 'Internal server error',
116
+ message: error.message,
117
+ response: 'I apologize, but I encountered an error processing your request. Please try again.'
118
+ });
119
+ }
120
+ });
121
+
122
+ // Orchestrator status route
123
+ app.get('/api/flask/orchestrator/status', async (req, res) => {
124
+ try {
125
+ const response = await axios.get(`${FLASK_API_URL}/api/orchestrator/status`);
126
+ res.json(response.data);
127
+ } catch (error) {
128
+ res.status(503).json({
129
+ error: 'Flask API unavailable',
130
+ message: error.message
131
+ });
132
+ }
133
+ });
134
+
135
+ console.log('✓ Flask routes configured');
136
+ console.log(` POST /api/chat -> ${FLASK_CHAT_ENDPOINT}`);
137
+ console.log(` GET /api/flask/health -> ${FLASK_HEALTH_ENDPOINT}`);
138
+ }
139
+
140
+ module.exports = {
141
+ setupFlaskRoutes,
142
+ initializeFlask,
143
+ FLASK_API_URL
144
+ };
145
+
flask_api.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Flask API for Research AI Assistant
3
+ Provides REST API endpoints for external integrations (e.g., Express.js frontend)
4
+
5
+ Run separately from Gradio on port 5001 (Gradio runs on 7860)
6
+ Usage: python flask_api.py
7
+ """
8
+
9
+ import os
10
+ import sys
11
+ import logging
12
+ import asyncio
13
+ from flask import Flask, request, jsonify
14
+ from flask_cors import CORS
15
+ from typing import Dict, Any, Optional
16
+
17
+ # Configure logging
18
+ logging.basicConfig(
19
+ level=logging.INFO,
20
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
21
+ )
22
+ logger = logging.getLogger(__name__)
23
+
24
+ # Create Flask app
25
+ app = Flask(__name__)
26
+ CORS(app) # Enable CORS for Express.js and other frontends
27
+
28
+ # Import orchestrator and handlers from app.py
29
+ # This imports without triggering Gradio launch
30
+ _orchestrator = None
31
+ _process_message_async = None
32
+
33
+ def initialize_orchestrator():
34
+ """Initialize the orchestrator from app.py"""
35
+ global _orchestrator, _process_message_async
36
+
37
+ try:
38
+ logger.info("=" * 60)
39
+ logger.info("STARTING FLASK API")
40
+ logger.info("=" * 60)
41
+ logger.info("INITIALIZING AI ORCHESTRATOR")
42
+ logger.info("=" * 60)
43
+
44
+ # Import from app.py (this won't trigger app.py's launch code)
45
+ from app import orchestrator, process_message_async
46
+
47
+ _orchestrator = orchestrator
48
+ _process_message_async = process_message_async
49
+
50
+ if _orchestrator is not None:
51
+ logger.info("✓ AI ORCHESTRATOR READY")
52
+ else:
53
+ logger.warning("⚠ Orchestrator not available - some features may be limited")
54
+
55
+ logger.info("=" * 60)
56
+
57
+ except Exception as e:
58
+ logger.error(f"Failed to initialize orchestrator: {e}", exc_info=True)
59
+ _orchestrator = None
60
+ _process_message_async = None
61
+
62
+ # Initialize on startup
63
+ initialize_orchestrator()
64
+
65
+ @app.route('/health', methods=['GET'])
66
+ def health_check():
67
+ """Health check endpoint"""
68
+ return jsonify({
69
+ 'status': 'ok',
70
+ 'orchestrator_available': _orchestrator is not None,
71
+ 'service': 'flask_api'
72
+ })
73
+
74
+ @app.route('/api/chat', methods=['POST'])
75
+ def chat():
76
+ """
77
+ Main chat endpoint
78
+ Receives JSON:
79
+ {
80
+ "message": "user message",
81
+ "history": [], // optional, chat history
82
+ "session_id": "session-123", // optional
83
+ "user_id": "user-123" // optional, defaults to "Admin_J"
84
+ }
85
+
86
+ Returns JSON:
87
+ {
88
+ "response": "assistant response",
89
+ "history": [...], // updated chat history
90
+ "reasoning": {...}, // reasoning data
91
+ "performance": {...}, // performance metrics
92
+ "context": {...}, // context data
93
+ "session_id": "session-123",
94
+ "skills": "..." // skills HTML
95
+ }
96
+ """
97
+ try:
98
+ data = request.get_json()
99
+
100
+ if not data:
101
+ return jsonify({'error': 'No JSON data provided'}), 400
102
+
103
+ message = data.get('message', '')
104
+ if not message or not message.strip():
105
+ return jsonify({'error': 'Message is required'}), 400
106
+
107
+ # Extract optional parameters
108
+ history = data.get('history', [])
109
+ session_id = data.get('session_id', f"flask-session-{os.urandom(4).hex()}")
110
+ user_id = data.get('user_id', 'Admin_J')
111
+
112
+ logger.info(f"Chat request: message={message[:50]}..., session_id={session_id}, user_id={user_id}")
113
+
114
+ # Process message using the async handler from app.py
115
+ if _process_message_async is None:
116
+ return jsonify({
117
+ 'error': 'Orchestrator not available',
118
+ 'response': 'I apologize, but the AI system is not available. Please try again later.'
119
+ }), 503
120
+
121
+ # Run async function in sync context
122
+ loop = asyncio.new_event_loop()
123
+ asyncio.set_event_loop(loop)
124
+ try:
125
+ result = loop.run_until_complete(
126
+ _process_message_async(
127
+ message=message.strip(),
128
+ history=history,
129
+ session_id=session_id,
130
+ user_id=user_id
131
+ )
132
+ )
133
+ finally:
134
+ loop.close()
135
+
136
+ # result is a tuple: (updated_history, empty_string, reasoning_data, performance_data, context_data, session_id, skills_html)
137
+ updated_history, _, reasoning_data, performance_data, context_data, returned_session_id, skills_html = result
138
+
139
+ # Extract assistant response from history (last message)
140
+ response = ""
141
+ if updated_history and len(updated_history) > 0:
142
+ last_entry = updated_history[-1]
143
+ if isinstance(last_entry, dict):
144
+ response = last_entry.get('content', '')
145
+ elif isinstance(last_entry, tuple) and len(last_entry) >= 2:
146
+ response = last_entry[1] # (user, assistant) format
147
+
148
+ return jsonify({
149
+ 'response': response,
150
+ 'history': updated_history,
151
+ 'reasoning': reasoning_data or {},
152
+ 'performance': performance_data or {},
153
+ 'context': context_data or {},
154
+ 'session_id': returned_session_id or session_id,
155
+ 'skills': skills_html or ''
156
+ })
157
+
158
+ except Exception as e:
159
+ logger.error(f"Error in chat endpoint: {e}", exc_info=True)
160
+ return jsonify({
161
+ 'error': str(e),
162
+ 'response': 'I apologize, but I encountered an error processing your request. Please try again.'
163
+ }), 500
164
+
165
+ @app.route('/api/orchestrator/status', methods=['GET'])
166
+ def orchestrator_status():
167
+ """Check orchestrator status"""
168
+ return jsonify({
169
+ 'orchestrator_available': _orchestrator is not None,
170
+ 'orchestrator_type': type(_orchestrator).__name__ if _orchestrator else None
171
+ })
172
+
173
+ if __name__ == '__main__':
174
+ port = int(os.getenv('FLASK_PORT', 5001))
175
+ host = os.getenv('FLASK_HOST', '0.0.0.0')
176
+
177
+ logger.info(f"Starting Flask API on port {port}")
178
+ logger.info(f"Health check: http://{host}:{port}/health")
179
+ logger.info(f"Chat endpoint: http://{host}:{port}/api/chat")
180
+
181
+ app.run(host=host, port=port, debug=False)
182
+
requirements.txt CHANGED
@@ -66,6 +66,10 @@ tzdata>=2023.3
66
  ujson>=5.8.0
67
  orjson>=3.9.0
68
 
 
 
 
 
69
  # HF Spaces Specific Dependencies
70
  # Note: huggingface-cli is part of huggingface-hub (installed by SDK)
71
  gradio-client>=0.8.0
 
66
  ujson>=5.8.0
67
  orjson>=3.9.0
68
 
69
+ # Flask API for external integrations
70
+ flask>=3.0.0
71
+ flask-cors>=4.0.0
72
+
73
  # HF Spaces Specific Dependencies
74
  # Note: huggingface-cli is part of huggingface-hub (installed by SDK)
75
  gradio-client>=0.8.0