AI 生成: 基于 Flask 的 AI 免费对话应用,后端集成豆包(Doubao)和 DeepSeek,通过 SSE 实时推送消息,前端提供简洁的聊天界面。
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
AI Free Chat - Flask 主应用
|
||||
提供聊天页面和 SSE 流式接口
|
||||
"""
|
||||
import os
|
||||
import json
|
||||
from flask import Flask, render_template, request, Response, stream_with_context
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from services.doubao import DoubaoService
|
||||
from services.deepseek import DeepSeekService
|
||||
|
||||
# 加载环境变量
|
||||
load_dotenv()
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
# 初始化服务
|
||||
services = {
|
||||
"doubao": DoubaoService(),
|
||||
"deepseek": DeepSeekService(),
|
||||
}
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
"""渲染聊天页面"""
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.route("/api/chat", methods=["POST"])
|
||||
def chat():
|
||||
"""
|
||||
SSE 流式聊天接口
|
||||
请求体: { provider: 'doubao'|'deepseek', messages: [{role, content}] }
|
||||
响应: text/event-stream
|
||||
"""
|
||||
data = request.get_json(silent=True) or {}
|
||||
provider = data.get("provider", "deepseek")
|
||||
messages = data.get("messages", [])
|
||||
|
||||
if provider not in services:
|
||||
return Response(
|
||||
f"data: {json.dumps({'error': '未知的 provider'})}\n\n",
|
||||
mimetype="text/event-stream",
|
||||
)
|
||||
|
||||
if not messages:
|
||||
return Response(
|
||||
f"data: {json.dumps({'error': 'messages 不能为空'})}\n\n",
|
||||
mimetype="text/event-stream",
|
||||
)
|
||||
|
||||
service = services[provider]
|
||||
|
||||
def generate():
|
||||
"""生成 SSE 事件流"""
|
||||
try:
|
||||
for chunk in service.stream_chat(messages):
|
||||
payload = json.dumps({"content": chunk}, ensure_ascii=False)
|
||||
yield f"data: {payload}\n\n"
|
||||
yield "data: [DONE]\n\n"
|
||||
except Exception as e: # noqa: BLE001
|
||||
err = json.dumps({"error": str(e)}, ensure_ascii=False)
|
||||
yield f"data: {err}\n\n"
|
||||
|
||||
headers = {
|
||||
"Cache-Control": "no-cache",
|
||||
"X-Accel-Buffering": "no",
|
||||
"Connection": "keep-alive",
|
||||
}
|
||||
return Response(
|
||||
stream_with_context(generate()),
|
||||
mimetype="text/event-stream",
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
port = int(os.getenv("PORT", "5000"))
|
||||
app.run(host="0.0.0.0", port=port, debug=True, threaded=True)
|
||||
Reference in New Issue
Block a user