Kfjjdjdjdhdhd commited on
Commit
5b4adb6
·
verified ·
1 Parent(s): 9cd71e4

Update api.py

Browse files
Files changed (1) hide show
  1. api.py +509 -347
api.py CHANGED
@@ -1,347 +1,509 @@
1
- from main import *
2
- from tts_api import *
3
- from stt_api import *
4
- from sentiment_api import *
5
- from imagegen_api import *
6
- from musicgen_api import *
7
- from translation_api import *
8
- from codegen_api import *
9
- from text_to_video_api import *
10
- from summarization_api import *
11
- from image_to_3d_api import *
12
- from flask import Flask, request, jsonify, Response, send_file, stream_with_context
13
- from flask_cors import CORS
14
- import torch
15
- import torch.nn.functional as F
16
- import torchaudio
17
- import numpy as np
18
- from PIL import Image
19
- import io
20
- import tempfile
21
- import queue
22
- import json
23
- import base64
24
- from markupsafe import Markup
25
- from markupsafe import escape
26
-
27
- app = Flask(__name__)
28
- CORS(app)
29
-
30
- html_code = """<!DOCTYPE html>
31
- <html lang="en">
32
- <head>
33
- <meta charset="UTF-8">
34
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
35
- <title>AI Text Generation</title>
36
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
37
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" integrity="sha512-9usAa10IRO0HhonpyAIVpjrylPvoDwiPUiKdWk5t3PyolY1cOd4DSE0Ga+ri4AuTroPR5aQvXU9xC6qOPnzFeg==" crossorigin="anonymous" referrerpolicy="no-referrer" />
38
- <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
39
- <style>
40
- body {
41
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
42
- background: #f0f0f0;
43
- color: #333;
44
- margin: 0;
45
- padding: 0;
46
- display: flex;
47
- flex-direction: column;
48
- align-items: center;
49
- min-height: 100vh;
50
- }
51
- .container {
52
- width: 95%;
53
- max-width: 900px;
54
- padding: 20px;
55
- background-color: #fff;
56
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
57
- border-radius: 8px;
58
- margin-top: 20px;
59
- margin-bottom: 20px;
60
- display: flex;
61
- flex-direction: column;
62
- }
63
- .header {
64
- text-align: center;
65
- margin-bottom: 20px;
66
- }
67
- .header h1 {
68
- font-size: 2em;
69
- color: #333;
70
- }
71
- .form-group {
72
- margin-bottom: 15px;
73
- }
74
- .form-group textarea {
75
- width: 100%;
76
- padding: 10px;
77
- border: 1px solid #ccc;
78
- border-radius: 5px;
79
- font-size: 16px;
80
- box-sizing: border-box;
81
- resize: vertical;
82
- }
83
- button {
84
- padding: 10px 15px;
85
- border: none;
86
- border-radius: 5px;
87
- background-color: #007bff;
88
- color: white;
89
- font-size: 18px;
90
- cursor: pointer;
91
- transition: background-color 0.3s ease;
92
- }
93
- button:hover {
94
- background-color: #0056b3;
95
- }
96
- #output {
97
- margin-top: 20px;
98
- padding: 15px;
99
- border: 1px solid #ddd;
100
- border-radius: 5px;
101
- background-color: #f9f9f9;
102
- white-space: pre-wrap;
103
- word-break: break-word;
104
- overflow-y: auto;
105
- max-height: 100vh;
106
- }
107
- #output strong {
108
- font-weight: bold;
109
- }
110
- .animated-text {
111
- position: fixed;
112
- top: 20px;
113
- left: 20px;
114
- font-size: 1.5em;
115
- color: rgba(0, 0, 0, 0.1);
116
- pointer-events: none;
117
- z-index: -1;
118
- }
119
- @media (max-width: 768px) {
120
- .container {
121
- width: 98%;
122
- margin-top: 10px;
123
- margin-bottom: 10px;
124
- padding: 15px;
125
- }
126
- .header h1 {
127
- font-size: 1.8em;
128
- }
129
- .form-group textarea, .form-group input[type="text"] {
130
- font-size: 14px;
131
- padding: 8px;
132
- }
133
- button {
134
- font-size: 16px;
135
- padding: 8px 12px;
136
- }
137
- #output {
138
- font-size: 14px;
139
- padding: 10px;
140
- margin-top: 15px;
141
- }
142
- }
143
- </style>
144
- </head>
145
- <body>
146
- <div class="animated-text animate__animated animate__fadeIn animate__infinite infinite">AI POWERED</div>
147
- <div class="container">
148
- <div class="header animate__animated animate__fadeInDown">
149
- </div>
150
- <div class="form-group animate__animated animate__fadeInLeft">
151
- <textarea id="text" rows="5" placeholder="Enter text"></textarea>
152
- </div>
153
- <button onclick="generateText()" class="animate__animated animate__fadeInUp">Generate Reasoning</button>
154
- <div id="output" class="animate__animated">
155
- <strong>Response:</strong><br>
156
- <span id="generatedText"></span>
157
- </div>
158
- </div>
159
- <script>
160
- let eventSource = null;
161
- let accumulatedText = "";
162
- let lastResponse = "";
163
- async function generateText() {
164
- const inputText = document.getElementById("text").value;
165
- document.getElementById("generatedText").innerText = "";
166
- accumulatedText = "";
167
- if (eventSource) {
168
- eventSource.close();
169
- }
170
- const temp = 0.7;
171
- const top_k_val = 40;
172
- const top_p_val = 0.0;
173
- const repetition_penalty_val = 1.2;
174
- const requestData = {
175
- text: inputText,
176
- temp: temp,
177
- top_k: top_k_val,
178
- top_p: top_p_val,
179
- reppenalty: repetition_penalty_val
180
- };
181
- const params = new URLSearchParams(requestData).toString();
182
- eventSource = new EventSource('/api/v1/generate_stream?' + params);
183
- eventSource.onmessage = function(event) {
184
- if (event.data === "<END_STREAM>") {
185
- eventSource.close();
186
- const currentResponse = accumulatedText.replace("<|endoftext|>", "").replace(/\s+(?=[.,,。])/g, '').trim();
187
- if (currentResponse === lastResponse.trim()) {
188
- accumulatedText = "**Response is repetitive. Please try again or rephrase your query.**";
189
- } else {
190
- lastResponse = currentResponse;
191
- }
192
- document.getElementById("generatedText").innerHTML = marked.parse(accumulatedText);
193
- return;
194
- }
195
- accumulatedText += event.data;
196
- let partialText = accumulatedText.replace("<|endoftext|>", "").replace(/\s+(?=[.,,。])/g, '').trim();
197
- document.getElementById("generatedText").innerHTML = marked.parse(partialText);
198
- };
199
- eventSource.onerror = function(error) {
200
- console.error("SSE error", error);
201
- eventSource.close();
202
- };
203
- const outputDiv = document.getElementById("output");
204
- outputDiv.classList.add("show");
205
- }
206
- function base64ToBlob(base64Data, contentType) {
207
- contentType = contentType || '';
208
- const sliceSize = 1024;
209
- const byteCharacters = atob(base64Data);
210
- const bytesLength = byteCharacters.length;
211
- const slicesCount = Math.ceil(bytesLength / sliceSize);
212
- const byteArrays = new Array(slicesCount);
213
- for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
214
- const begin = sliceIndex * sliceSize;
215
- const end = Math.min(begin + sliceSize, bytesLength);
216
- const bytes = new Array(end - begin);
217
- for (let offset = begin, i = 0; offset < end; ++i, ++offset) {
218
- bytes[i] = byteCharacters[offset].charCodeAt(0);
219
- }
220
- byteArrays[sliceIndex] = new Uint8Array(bytes);
221
- }
222
- return new Blob(byteArrays, { type: contentType });
223
- }
224
- </script>
225
- </body>
226
- </html>
227
- """
228
- feedback_queue = queue.Queue()
229
-
230
-
231
- @app.route("/")
232
- def index():
233
- return html_code
234
-
235
- @app.route("/api/v1/generate_stream", methods=["GET"])
236
- def generate_stream():
237
- text = request.args.get("text", "")
238
- temp = float(request.args.get("temp", 0.7))
239
- top_k = int(request.args.get("top_k", 40))
240
- top_p = float(request.args.get("top_p", 0.0))
241
- reppenalty = float(request.args.get("reppenalty", 1.2))
242
- response_queue = queue.Queue()
243
- reasoning_queue.put({
244
- 'text_input': text,
245
- 'temperature': temp,
246
- 'top_k': top_k,
247
- 'top_p': top_p,
248
- 'repetition_penalty': reppenalty,
249
- 'response_queue': response_queue
250
- })
251
- @stream_with_context
252
- def event_stream():
253
- while True:
254
- output = response_queue.get()
255
- if "error" in output:
256
- yield "data: <ERROR>\n\n"
257
- break
258
- text_chunk = output.get("text")
259
- if text_chunk:
260
- for word in text_chunk.split(' '):
261
- clean_word = word.strip()
262
- if clean_word:
263
- yield "data: " + clean_word + "\n\n"
264
- yield "data: <END_STREAM>\n\n"
265
- break
266
- return Response(event_stream(), mimetype="text/event-stream")
267
-
268
- @app.route("/api/v1/generate", methods=["POST"])
269
- def generate():
270
- data = request.get_json()
271
- text = data.get("text", "")
272
- temp = float(data.get("temp", 0.7))
273
- top_k = int(data.get("top_k", 40))
274
- top_p = float(data.get("top_p", 0.0))
275
- reppenalty = float(data.get("reppenalty", 1.2))
276
- response_queue = queue.Queue()
277
- reasoning_queue.put({
278
- 'text_input': text,
279
- 'temperature': temp,
280
- 'top_k': top_k,
281
- 'top_p': top_p,
282
- 'repetition_penalty': reppenalty,
283
- 'response_queue': response_queue
284
- })
285
- output = response_queue.get()
286
- if "error" in output:
287
- return jsonify({"error": output["error"]}), 500
288
- result_text = output.get("text", "").strip()
289
- return jsonify({"response": result_text})
290
-
291
- @app.route("/api/v1/feedback", methods=["POST"])
292
- def feedback():
293
- data = request.get_json()
294
- feedback_text = data.get("feedback_text")
295
- correct_category = data.get("correct_category")
296
- if feedback_text and correct_category:
297
- feedback_queue.put((feedback_text, correct_category))
298
- return jsonify({"status": "feedback received"})
299
- return jsonify({"status": "feedback failed"}), 400
300
-
301
- @app.route("/api/v1/tts", methods=["POST"])
302
- def tts_api():
303
- return tts_route()
304
-
305
- @app.route("/api/v1/stt", methods=["POST"])
306
- def stt_api():
307
- return stt_route()
308
-
309
- @app.route("/api/v1/sentiment", methods=["POST"])
310
- def sentiment_api():
311
- return sentiment_route()
312
-
313
- @app.route("/api/v1/imagegen", methods=["POST"])
314
- def imagegen_api():
315
- return imagegen_route()
316
-
317
- @app.route("/api/v1/musicgen", methods=["POST"])
318
- def musicgen_api():
319
- return musicgen_route()
320
-
321
- @app.route("/api/v1/translation", methods=["POST"])
322
- def translation_api():
323
- return translation_route()
324
-
325
- @app.route("/api/v1/codegen", methods=["POST"])
326
- def codegen_api():
327
- return codegen_route()
328
-
329
- @app.route("/api/v1/text_to_video", methods=["POST"])
330
- def text_to_video_api():
331
- return text_to_video_route()
332
-
333
- @app.route("/api/v1/summarization", methods=["POST"])
334
- def summarization_api():
335
- return summarization_route()
336
-
337
- @app.route("/api/v1/image_to_3d", methods=["POST"])
338
- def image_to_3d_api():
339
- return image_to_3d_route()
340
-
341
- @app.route("/api/v1/sadtalker", methods=["POST"])
342
- def sadtalker():
343
- from sadtalker_api import router as sadtalker_router
344
- return sadtalker_router.create_video()
345
-
346
- if __name__ == "__main__":
347
- app.run(host="0.0.0.0", port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from main import *
2
+ from tts_api import *
3
+ from stt_api import *
4
+ from sentiment_api import *
5
+ from imagegen_api import *
6
+ from musicgen_api import *
7
+ from translation_api import *
8
+ from codegen_api import *
9
+ from text_to_video_api import *
10
+ from summarization_api import *
11
+ from image_to_3d_api import *
12
+ from flask import Flask, request, jsonify, Response, send_file, stream_with_context
13
+ from flask_cors import CORS
14
+ import torch
15
+ import torch.nn.functional as F
16
+ import torchaudio
17
+ import numpy as np
18
+ from PIL import Image
19
+ import io
20
+ import tempfile
21
+ import queue
22
+ import json
23
+ import base64
24
+ from markupsafe import Markup
25
+ from markupsafe import escape
26
+
27
+ app = Flask(__name__)
28
+ CORS(app)
29
+
30
+ html_code = """<!DOCTYPE html>
31
+ <html lang="en">
32
+ <head>
33
+ <meta charset="UTF-8">
34
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
35
+ <title>AI Conversational Avatar</title>
36
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
37
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"/>
38
+ <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
39
+ <style>
40
+ body {
41
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
42
+ background: #f0f0f0;
43
+ color: #333;
44
+ margin: 0;
45
+ padding: 0;
46
+ display: flex;
47
+ flex-direction: column;
48
+ align-items: center;
49
+ min-height: 100vh;
50
+ }
51
+ .container {
52
+ width: 95%;
53
+ max-width: 900px;
54
+ padding: 20px;
55
+ background-color: #fff;
56
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
57
+ border-radius: 8px;
58
+ margin-top: 20px;
59
+ margin-bottom: 20px;
60
+ display: flex;
61
+ flex-direction: column;
62
+ }
63
+ .header {
64
+ text-align: center;
65
+ margin-bottom: 20px;
66
+ }
67
+ .header h1 {
68
+ font-size: 2em;
69
+ color: #333;
70
+ }
71
+ .form-group {
72
+ margin-bottom: 15px;
73
+ }
74
+ .form-group textarea, .form-group input[type="text"] {
75
+ width: 100%;
76
+ padding: 10px;
77
+ border: 1px solid #ccc;
78
+ border-radius: 5px;
79
+ font-size: 16px;
80
+ box-sizing: border-box;
81
+ }
82
+ button, #recordButton, #stopButton {
83
+ padding: 10px 15px;
84
+ border: none;
85
+ border-radius: 5px;
86
+ background-color: #007bff;
87
+ color: white;
88
+ font-size: 18px;
89
+ cursor: pointer;
90
+ transition: background-color 0.3s ease;
91
+ margin-right: 5px;
92
+ }
93
+ button:hover, #recordButton:hover, #stopButton:hover {
94
+ background-color: #0056b3;
95
+ }
96
+ #output {
97
+ margin-top: 20px;
98
+ padding: 15px;
99
+ border: 1px solid #ddd;
100
+ border-radius: 5px;
101
+ background-color: #f9f9f9;
102
+ white-space: pre-wrap;
103
+ word-break: break-word;
104
+ overflow-y: auto;
105
+ max-height: 300px;
106
+ }
107
+ #videoOutput {
108
+ margin-top: 20px;
109
+ border: 1px solid #ddd;
110
+ border-radius: 5px;
111
+ overflow: hidden;
112
+ }
113
+ #videoOutput video {
114
+ width: 100%;
115
+ display: block;
116
+ }
117
+ #animatedText {
118
+ position: fixed;
119
+ top: 20px;
120
+ left: 20px;
121
+ font-size: 1.5em;
122
+ color: rgba(0, 0, 0, 0.1);
123
+ pointer-events: none;
124
+ z-index: -1;
125
+ }
126
+ #transcriptionOutput {
127
+ margin-top: 10px;
128
+ padding: 10px;
129
+ border: 1px solid #ddd;
130
+ border-radius: 5px;
131
+ background-color: #f9f9f9;
132
+ font-size: 14px;
133
+ word-break: break-word;
134
+ }
135
+ @media (max-width: 768px) {
136
+ .container {
137
+ width: 98%;
138
+ margin-top: 10px;
139
+ margin-bottom: 10px;
140
+ padding: 15px;
141
+ }
142
+ .header h1 {
143
+ font-size: 1.8em;
144
+ }
145
+ .form-group textarea, .form-group input[type="text"] {
146
+ font-size: 14px;
147
+ padding: 8px;
148
+ }
149
+ button, #recordButton, #stopButton {
150
+ font-size: 16px;
151
+ padding: 8px 12px;
152
+ }
153
+ #output, #transcriptionOutput {
154
+ font-size: 14px;
155
+ padding: 10px;
156
+ margin-top: 15px;
157
+ }
158
+ }
159
+ </style>
160
+ </head>
161
+ <body>
162
+ <div id="animatedText" class="animated-text animate__animated animate__fadeIn animate__infinite infinite">AI POWERED</div>
163
+ <div class="container">
164
+ <div class="header animate__animated animate__fadeInDown">
165
+ <h1>Conversational Avatar</h1>
166
+ </div>
167
+ <div class="form-group animate__animated animate__fadeInLeft">
168
+ <textarea id="textInput" rows="3" placeholder="Or type your request here"></textarea>
169
+ </div>
170
+ <div class="form-group animate__animated animate__fadeInRight" style="text-align: center;">
171
+ <button onclick="generateResponse()" class="animate__animated animate__fadeInUp">Generate Avatar Response</button>
172
+ </div>
173
+
174
+ <div style="text-align: center; margin-bottom: 15px;">
175
+ <button id="recordButton" class="animate__animated animate__fadeInUp"><i class="fas fa-microphone"></i> Start Recording</button>
176
+ <button id="stopButton" class="animate__animated animate__fadeInUp" disabled><i class="fas fa-stop-circle"></i> Stop Recording</button>
177
+ </div>
178
+
179
+ <div id="transcriptionOutput" class="animate__animated animate__fadeIn">
180
+ <strong>Transcription:</strong>
181
+ <span id="transcriptionText"></span>
182
+ </div>
183
+
184
+ <div id="output" class="animate__animated animate__fadeIn">
185
+ <strong>Response:</strong><br>
186
+ <span id="responseText"></span>
187
+ </div>
188
+
189
+ <div id="videoOutput" class="animate__animated animate__fadeIn">
190
+ <video id="avatarVideo" controls></video>
191
+ </div>
192
+ </div>
193
+
194
+ <script>
195
+ let mediaRecorder;
196
+ let audioChunks = [];
197
+ let lastResponse = "";
198
+ let accumulatedText = "";
199
+ let eventSource = null;
200
+ let audioURL;
201
+
202
+ const recordButton = document.getElementById('recordButton');
203
+ const stopButton = document.getElementById('stopButton');
204
+ const transcriptionTextSpan = document.getElementById('transcriptionText');
205
+ const responseTextSpan = document.getElementById('responseText');
206
+ const avatarVideoPlayer = document.getElementById('avatarVideo');
207
+ const textInputField = document.getElementById('textInput');
208
+
209
+ recordButton.onclick = async () => {
210
+ try {
211
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
212
+ mediaRecorder = new MediaRecorder(stream);
213
+ audioChunks = [];
214
+
215
+ mediaRecorder.ondataavailable = event => {
216
+ audioChunks.push(event.data);
217
+ };
218
+
219
+ mediaRecorder.onstop = async () => {
220
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
221
+ const formData = new FormData();
222
+ formData.append('audio', audioBlob, 'recording.wav');
223
+
224
+ transcriptionTextSpan.innerText = "Transcribing...";
225
+ responseTextSpan.innerText = "";
226
+ avatarVideoPlayer.src = "";
227
+
228
+ try {
229
+ const sttResponse = await fetch('/api/v1/stt', {
230
+ method: 'POST',
231
+ body: formData
232
+ });
233
+
234
+ if (!sttResponse.ok) {
235
+ throw new Error(\`HTTP error! status: ${sttResponse.status}\`);
236
+ }
237
+
238
+ const sttData = await sttResponse.json();
239
+ const transcribedText = sttData.text;
240
+ transcriptionTextSpan.innerText = transcribedText || "Transcription failed.";
241
+
242
+ if (transcribedText) {
243
+ await generateAvatarVideoResponse(transcribedText);
244
+ }
245
+
246
+ } catch (error) {
247
+ console.error("STT or subsequent error:", error);
248
+ transcriptionTextSpan.innerText = "Transcription error.";
249
+ responseTextSpan.innerText = "Error processing audio.";
250
+ } finally {
251
+ recordButton.disabled = false;
252
+ stopButton.disabled = true;
253
+ }
254
+ };
255
+
256
+ recordButton.disabled = true;
257
+ stopButton.disabled = false;
258
+ transcriptionTextSpan.innerText = "Recording...";
259
+ mediaRecorder.start();
260
+
261
+ } catch (error) {
262
+ console.error("Error accessing microphone:", error);
263
+ transcriptionTextSpan.innerText = "Microphone access denied or error.";
264
+ recordButton.disabled = false;
265
+ stopButton.disabled = true;
266
+ }
267
+ };
268
+
269
+ stopButton.onclick = () => {
270
+ if (mediaRecorder && mediaRecorder.state === "recording") {
271
+ transcriptionTextSpan.innerText = "Processing...";
272
+ mediaRecorder.stop();
273
+ recordButton.disabled = true;
274
+ stopButton.disabled = true;
275
+ }
276
+ };
277
+
278
+ async function generateResponse() {
279
+ const inputText = textInputField.value;
280
+ if (!inputText.trim()) {
281
+ alert("Please enter text or record audio.");
282
+ return;
283
+ }
284
+ transcriptionTextSpan.innerText = inputText;
285
+ await generateAvatarVideoResponse(inputText);
286
+ }
287
+
288
+
289
+ async function generateAvatarVideoResponse(inputText) {
290
+ responseTextSpan.innerText = "Generating response...";
291
+ avatarVideoPlayer.src = "";
292
+ accumulatedText = "";
293
+ lastResponse = "";
294
+
295
+ const temp = 0.7;
296
+ const top_k_val = 40;
297
+ const top_p_val = 0.0;
298
+ const repetition_penalty_val = 1.2;
299
+
300
+ const requestData = {
301
+ text: inputText,
302
+ temp: temp,
303
+ top_k: top_k_val,
304
+ top_p: top_p_val,
305
+ reppenalty: repetition_penalty_val
306
+ };
307
+
308
+ if (eventSource) {
309
+ eventSource.close();
310
+ }
311
+
312
+ eventSource = new EventSource('/api/v1/generate_stream?' + new URLSearchParams(requestData).toString());
313
+
314
+ eventSource.onmessage = async function(event) {
315
+ if (event.data === "<END_STREAM>") {
316
+ eventSource.close();
317
+ const currentResponse = accumulatedText.replace("<|endoftext|>", "").replace(/\s+(?=[.,,。])/g, '').trim();
318
+ if (currentResponse === lastResponse.trim()) {
319
+ accumulatedText = "**Response is repetitive. Please try again or rephrase your query.**";
320
+ } else {
321
+ lastResponse = currentResponse;
322
+ }
323
+ responseTextSpan.innerHTML = marked.parse(accumulatedText);
324
+
325
+ try {
326
+ const ttsResponse = await fetch('/api/v1/tts', {
327
+ method: 'POST',
328
+ headers: {
329
+ 'Content-Type': 'application/json'
330
+ },
331
+ body: JSON.stringify({ text: currentResponse })
332
+ });
333
+
334
+ if (!ttsResponse.ok) {
335
+ throw new Error(\`TTS HTTP error! status: ${ttsResponse.status}\`);
336
+ }
337
+
338
+ const ttsBlob = await ttsResponse.blob();
339
+ audioURL = URL.createObjectURL(ttsBlob);
340
+
341
+
342
+ const sadTalkerResponse = await fetch('/api/v1/sadtalker', {
343
+ method: 'POST',
344
+ body: new URLSearchParams({
345
+ 'source_image': './examples/source_image/full_body_female.png',
346
+ 'driven_audio': audioURL,
347
+ 'preprocess': 'full',
348
+ 'still_mode': false,
349
+ 'use_enhancer': true
350
+ })
351
+ });
352
+
353
+ if (!sadTalkerResponse.ok) {
354
+ throw new Error(\`SadTalker HTTP error! status: ${sadTalkerResponse.status}\`);
355
+ }
356
+
357
+ const sadTalkerData = await sadTalkerResponse.json();
358
+ const videoURL = sadTalkerData.video_url;
359
+ avatarVideoPlayer.src = videoURL;
360
+
361
+
362
+ } catch (ttsError) {
363
+ console.error("TTS or SadTalker error:", ttsError);
364
+ responseTextSpan.innerHTML += "<br><br>Error generating audio or video avatar.";
365
+ }
366
+
367
+ return;
368
+ }
369
+ accumulatedText += event.data;
370
+ let partialText = accumulatedText.replace("<|endoftext|>", "").replace(/\s+(?=[.,,。])/g, '').trim();
371
+ responseTextSpan.innerHTML = marked.parse(partialText);
372
+ };
373
+
374
+ eventSource.onerror = function(error) {
375
+ console.error("SSE error", error);
376
+ eventSource.close();
377
+ responseTextSpan.innerText = "Error generating response stream.";
378
+ };
379
+
380
+ const outputDiv = document.getElementById("output");
381
+ outputDiv.classList.add("show");
382
+ }
383
+
384
+
385
+ </script>
386
+ </body>
387
+ </html>
388
+ """
389
+
390
+ feedback_queue = queue.Queue()
391
+
392
+
393
+ @app.route("/")
394
+ def index():
395
+ return html_code
396
+
397
+ @app.route("/api/v1/generate_stream", methods=["GET"])
398
+ def generate_stream():
399
+ text = request.args.get("text", "")
400
+ temp = float(request.args.get("temp", 0.7))
401
+ top_k = int(request.args.get("top_k", 40))
402
+ top_p = float(request.args.get("top_p", 0.0))
403
+ reppenalty = float(request.args.get("reppenalty", 1.2))
404
+ response_queue = queue.Queue()
405
+ reasoning_queue.put({
406
+ 'text_input': text,
407
+ 'temperature': temp,
408
+ 'top_k': top_k,
409
+ 'top_p': top_p,
410
+ 'repetition_penalty': reppenalty,
411
+ 'response_queue': response_queue
412
+ })
413
+ @stream_with_context
414
+ def event_stream():
415
+ while True:
416
+ output = response_queue.get()
417
+ if "error" in output:
418
+ yield "data: <ERROR>\n\n"
419
+ break
420
+ text_chunk = output.get("text")
421
+ if text_chunk:
422
+ for word in text_chunk.split(' '):
423
+ clean_word = word.strip()
424
+ if clean_word:
425
+ yield "data: " + clean_word + "\n\n"
426
+ yield "data: <END_STREAM>\n\n"
427
+ break
428
+ return Response(event_stream(), mimetype="text/event-stream")
429
+
430
+ @app.route("/api/v1/generate", methods=["POST"])
431
+ def generate():
432
+ data = request.get_json()
433
+ text = data.get("text", "")
434
+ temp = float(data.get("temp", 0.7))
435
+ top_k = int(data.get("top_k", 40))
436
+ top_p = float(data.get("top_p", 0.0))
437
+ reppenalty = float(data.get("reppenalty", 1.2))
438
+ response_queue = queue.Queue()
439
+ reasoning_queue.put({
440
+ 'text_input': text,
441
+ 'temperature': temp,
442
+ 'top_k': top_k,
443
+ 'top_p': top_p,
444
+ 'repetition_penalty': reppenalty,
445
+ 'response_queue': response_queue
446
+ })
447
+ output = response_queue.get()
448
+ if "error" in output:
449
+ return jsonify({"error": output["error"]}), 500
450
+ result_text = output.get("text", "").strip()
451
+ return jsonify({"response": result_text})
452
+
453
+ @app.route("/api/v1/feedback", methods=["POST"])
454
+ def feedback():
455
+ data = request.get_json()
456
+ feedback_text = data.get("feedback_text")
457
+ correct_category = data.get("correct_category")
458
+ if feedback_text and correct_category:
459
+ feedback_queue.put((feedback_text, correct_category))
460
+ return jsonify({"status": "feedback received"})
461
+ return jsonify({"status": "feedback failed"}), 400
462
+
463
+ @app.route("/api/v1/tts", methods=["POST"])
464
+ def tts_api():
465
+ return tts_route()
466
+
467
+ @app.route("/api/v1/stt", methods=["POST"])
468
+ def stt_api():
469
+ return stt_route()
470
+
471
+ @app.route("/api/v1/sentiment", methods=["POST"])
472
+ def sentiment_api():
473
+ return sentiment_route()
474
+
475
+ @app.route("/api/v1/imagegen", methods=["POST"])
476
+ def imagegen_api():
477
+ return imagegen_route()
478
+
479
+ @app.route("/api/v1/musicgen", methods=["POST"])
480
+ def musicgen_api():
481
+ return musicgen_route()
482
+
483
+ @app.route("/api/v1/translation", methods=["POST"])
484
+ def translation_api():
485
+ return translation_route()
486
+
487
+ @app.route("/api/v1/codegen", methods=["POST"])
488
+ def codegen_api():
489
+ return codegen_route()
490
+
491
+ @app.route("/api/v1/text_to_video", methods=["POST"])
492
+ def text_to_video_api():
493
+ return text_to_video_route()
494
+
495
+ @app.route("/api/v1/summarization", methods=["POST"])
496
+ def summarization_api():
497
+ return summarization_route()
498
+
499
+ @app.route("/api/v1/image_to_3d", methods=["POST"])
500
+ def image_to_3d_api():
501
+ return image_to_3d_route()
502
+
503
+ @app.route("/api/v1/sadtalker", methods=["POST"])
504
+ def sadtalker():
505
+ from sadtalker_api import router as sadtalker_router
506
+ return sadtalker_router.create_video()
507
+
508
+ if __name__ == "__main__":
509
+ app.run(host="0.0.0.0", port=7860)