Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| # gradio_timer_buffer_final.py ── 0.3 秒刷新 + 完成後停止刷新 + 可重整重啟 | |
| import gradio as gr | |
| import requests, json, re, sys, time | |
| from threading import Thread | |
| URL = "http://localhost:8000/v1/chat/completions" | |
| HEADERS = {"Content-Type": "application/json"} | |
| def sanitize(text: str): | |
| return re.sub(r"[\ud800-\udfff]", "", text) | |
| # ====================== | |
| # 全域狀態(每次重整會重設) | |
| # ====================== | |
| history_openai = [] | |
| current_chatbot = [] | |
| assistant_buffer = "" | |
| is_streaming = False | |
| # ====================== | |
| # Streaming 主執行緒 | |
| # ====================== | |
| def stream_to_buffer(user_input: str): | |
| global assistant_buffer, is_streaming, history_openai | |
| user_input = sanitize(user_input) | |
| history_openai.append({"role": "user", "content": user_input}) | |
| payload = {"messages": history_openai, "stream": True, "temperature": 0.7} | |
| assistant_buffer = "" | |
| is_streaming = True | |
| try: | |
| with requests.post(URL, headers=HEADERS, json=payload, stream=True, timeout=60) as r: | |
| r.raise_for_status() | |
| byte_buf = b"" | |
| for chunk in r.iter_content(chunk_size=1024): | |
| if not chunk: | |
| break | |
| byte_buf += chunk | |
| while b"\n" in byte_buf: | |
| line_bytes, byte_buf = byte_buf.split(b"\n", 1) | |
| line = line_bytes.decode("utf-8", errors="replace").strip() | |
| if not line.startswith("data: "): | |
| continue | |
| data = line[6:] | |
| if data == "[DONE]": | |
| is_streaming = False | |
| break | |
| try: | |
| tok = json.loads(data)["choices"][0]["delta"].get("content") | |
| except json.JSONDecodeError: | |
| byte_buf = line_bytes + b"\n" + byte_buf | |
| continue | |
| if tok: | |
| assistant_buffer += tok | |
| # 結束後更新歷史 | |
| history_openai.append({"role": "assistant", "content": sanitize(assistant_buffer)}) | |
| is_streaming = False | |
| except Exception as e: | |
| assistant_buffer = f"请求失败: {e}" | |
| is_streaming = False | |
| # ====================== | |
| # 使用者送出訊息 | |
| # ====================== | |
| def user_submit(user_msg, chatbot): | |
| global current_chatbot, assistant_buffer, is_streaming | |
| current_chatbot = chatbot + [[user_msg, ""]] | |
| assistant_buffer = "" | |
| is_streaming = True | |
| Thread(target=stream_to_buffer, args=(user_msg,), daemon=True).start() | |
| return "", current_chatbot | |
| # ====================== | |
| # Timer 定時刷新 | |
| # ====================== | |
| def flush_buffer(): | |
| """每 0.3 秒刷新 buffer,若已完成就不再更新""" | |
| global current_chatbot, assistant_buffer, is_streaming | |
| if not current_chatbot: | |
| return current_chatbot | |
| # 更新目前的內容 | |
| current_chatbot[-1][1] = assistant_buffer | |
| # 若結束則停止 timer 更新 | |
| if not is_streaming: | |
| time.sleep(0.1) # 確保最後一次更新 | |
| return current_chatbot | |
| # ====================== | |
| # Gradio 介面 | |
| # ====================== | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## Chat8000 Lab3 - 每 0.3 秒刷新 Buffer(完成自動停止)") | |
| chatbot = gr.Chatbot() | |
| msg = gr.Textbox(show_label=False, placeholder="輸入訊息後按 Enter") | |
| msg.submit(user_submit, [msg, chatbot], [msg, chatbot], queue=False) | |
| timer = gr.Timer(value=0.3, active=True) | |
| timer.tick(flush_buffer, outputs=chatbot) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) |