commit
Browse files- app.py +20 -5
- realtime_server.py +2 -1
- requirements.txt +1 -1
app.py
CHANGED
|
@@ -2,7 +2,11 @@
|
|
| 2 |
# Version 26.11 – ohne Modi, stabil für Text + Voice
|
| 3 |
|
| 4 |
import gradio as gr
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
from huggingface_hub import hf_hub_download
|
| 7 |
|
| 8 |
from load_documents import load_documents, DATASET, PDF_FILE, HTML_FILE
|
|
@@ -13,6 +17,8 @@ from llm import load_llm
|
|
| 13 |
from rag_pipeline import answer, PDF_BASE_URL, LAW_URL
|
| 14 |
|
| 15 |
from speech_io import transcribe_audio, synthesize_speech
|
|
|
|
|
|
|
| 16 |
import sys
|
| 17 |
sys.dont_write_bytecode = True
|
| 18 |
|
|
@@ -202,9 +208,9 @@ with gr.Blocks(title="Prüfungsrechts-Chatbot (RAG + Sprache)") as demo:
|
|
| 202 |
)
|
| 203 |
|
| 204 |
gr.Markdown("### ⚡ Voice (Realtime) – thử nghiệm")
|
| 205 |
-
gr.Markdown("Sử dụng OpenAI Realtime API cho hội thoại nói.
|
| 206 |
gr.HTML("""
|
| 207 |
-
<iframe src="
|
| 208 |
""")
|
| 209 |
|
| 210 |
clear_btn = gr.Button("Chat zurücksetzen")
|
|
@@ -216,12 +222,21 @@ with gr.Blocks(title="Prüfungsrechts-Chatbot (RAG + Sprache)") as demo:
|
|
| 216 |
|
| 217 |
with gr.Column(scale=1):
|
| 218 |
gr.Markdown("### 📄 Prüfungsordnung (PDF)")
|
| 219 |
-
|
|
|
|
|
|
|
|
|
|
| 220 |
|
| 221 |
gr.Markdown("### 📘 Hochschulgesetz NRW (Website)")
|
| 222 |
gr.HTML(
|
| 223 |
f'<iframe src="{LAW_URL}" style="width:100%;height:350px;border:none;"></iframe>'
|
| 224 |
)
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
if __name__ == "__main__":
|
| 227 |
-
|
|
|
|
|
|
| 2 |
# Version 26.11 – ohne Modi, stabil für Text + Voice
|
| 3 |
|
| 4 |
import gradio as gr
|
| 5 |
+
try:
|
| 6 |
+
from gradio_pdf import PDF
|
| 7 |
+
_HAS_PDF = True
|
| 8 |
+
except ImportError:
|
| 9 |
+
_HAS_PDF = False
|
| 10 |
from huggingface_hub import hf_hub_download
|
| 11 |
|
| 12 |
from load_documents import load_documents, DATASET, PDF_FILE, HTML_FILE
|
|
|
|
| 17 |
from rag_pipeline import answer, PDF_BASE_URL, LAW_URL
|
| 18 |
|
| 19 |
from speech_io import transcribe_audio, synthesize_speech
|
| 20 |
+
from fastapi import FastAPI
|
| 21 |
+
import realtime_server as rt
|
| 22 |
import sys
|
| 23 |
sys.dont_write_bytecode = True
|
| 24 |
|
|
|
|
| 208 |
)
|
| 209 |
|
| 210 |
gr.Markdown("### ⚡ Voice (Realtime) – thử nghiệm")
|
| 211 |
+
gr.Markdown("Sử dụng OpenAI Realtime API cho hội thoại nói. Trang test chạy cùng máy chủ này.")
|
| 212 |
gr.HTML("""
|
| 213 |
+
<iframe src="/realtime/" style="width:100%;height:300px;border:1px solid #ccc"></iframe>
|
| 214 |
""")
|
| 215 |
|
| 216 |
clear_btn = gr.Button("Chat zurücksetzen")
|
|
|
|
| 222 |
|
| 223 |
with gr.Column(scale=1):
|
| 224 |
gr.Markdown("### 📄 Prüfungsordnung (PDF)")
|
| 225 |
+
if _HAS_PDF:
|
| 226 |
+
PDF(_pdf_path, height=350)
|
| 227 |
+
else:
|
| 228 |
+
gr.HTML(f'<iframe src="{PDF_BASE_URL}" style="width:100%;height:350px;border:none;"></iframe>')
|
| 229 |
|
| 230 |
gr.Markdown("### 📘 Hochschulgesetz NRW (Website)")
|
| 231 |
gr.HTML(
|
| 232 |
f'<iframe src="{LAW_URL}" style="width:100%;height:350px;border:none;"></iframe>'
|
| 233 |
)
|
| 234 |
|
| 235 |
+
# FastAPI app: mount Gradio + realtime server cùng một host
|
| 236 |
+
app = FastAPI()
|
| 237 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
| 238 |
+
app.mount("/realtime", rt.app)
|
| 239 |
+
|
| 240 |
if __name__ == "__main__":
|
| 241 |
+
import uvicorn
|
| 242 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|
realtime_server.py
CHANGED
|
@@ -42,7 +42,8 @@ html = """
|
|
| 42 |
|
| 43 |
function ensureWS() {
|
| 44 |
if (ws && ws.readyState === WebSocket.OPEN) return ws;
|
| 45 |
-
|
|
|
|
| 46 |
ws.onopen = () => {
|
| 47 |
document.getElementById('status').textContent = 'Status: WS connected';
|
| 48 |
};
|
|
|
|
| 42 |
|
| 43 |
function ensureWS() {
|
| 44 |
if (ws && ws.readyState === WebSocket.OPEN) return ws;
|
| 45 |
+
const basePath = (location.pathname.endsWith('/') ? location.pathname.slice(0,-1) : location.pathname);
|
| 46 |
+
ws = new WebSocket((location.protocol === 'https:' ? 'wss://' : 'ws://') + location.host + basePath + '/ws');
|
| 47 |
ws.onopen = () => {
|
| 48 |
document.getElementById('status').textContent = 'Status: WS connected';
|
| 49 |
};
|
requirements.txt
CHANGED
|
@@ -16,7 +16,7 @@ langchain-openai
|
|
| 16 |
huggingface-hub
|
| 17 |
fastapi
|
| 18 |
uvicorn
|
| 19 |
-
websockets
|
| 20 |
|
| 21 |
# === VectorStore ===
|
| 22 |
faiss-cpu
|
|
|
|
| 16 |
huggingface-hub
|
| 17 |
fastapi
|
| 18 |
uvicorn
|
| 19 |
+
websockets>=12.0
|
| 20 |
|
| 21 |
# === VectorStore ===
|
| 22 |
faiss-cpu
|