baodan/api/insurance/chat/routes.py

181 lines
6.3 KiB
Python
Raw Normal View History

"""智能问答路由A2
POST /chat/message 发送消息SSE 流式
GET /chat/sessions 会话列表
POST /chat/sessions 创建会话
DELETE /chat/sessions/{id} 删除会话
GET /chat/sessions/{id}/messages 消息记录
POST /chat/messages/{id}/feedback 提交反馈
POST /chat/suggest 推荐追问
2026-07-12 14:17:18 +08:00
GET /chat/app-opening 获取应用开场配置
"""
import json
from flask import Blueprint, request, jsonify, Response, current_app
from insurance.chat.service import ChatService
from insurance.middleware.auth_middleware import jwt_required
chat_bp = Blueprint("chat", __name__)
chat_service = ChatService()
@chat_bp.route("/message", methods=["POST"])
@jwt_required
def send_message():
"""发送消息SSE 流式返回 AI 回答。"""
data = request.get_json()
2026-07-12 14:17:18 +08:00
if not data:
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
message = data.get("message", "")
session_id = data.get("session_id", "")
filters = data.get("filters", {})
api_token = data.get("api_token", "")
if not message:
return jsonify({"code": 1001, "message": "请输入问题内容", "data": None}), 400
user_id = request.user_id
# 在请求上下文内提前读取配置和捕获 app 对象(生成器运行时上下文已销毁)
default_api_key = current_app.config.get("BAODAN_CHAT_API_KEY", "")
base_url = current_app.config.get("BAODAN_API_URL", "http://localhost:5001")
flask_app = current_app._get_current_object()
def generate():
# 在整个生成器执行期间保持应用上下文
with flask_app.app_context():
try:
for event in chat_service.send_message_stream(
user_id=user_id,
message=message,
session_id=session_id,
filters=filters,
api_token=api_token or default_api_key,
base_url=base_url,
):
yield f"data: {event}\n\n"
except GeneratorExit:
# 客户端断开连接,静默退出
pass
except Exception as e:
import logging
logging.exception(f"SSE 生成器异常: {e}")
yield f"data: {json.dumps({'type': 'error', 'data': {'message': '服务器内部错误'}})}\n\n"
response = Response(generate(), content_type="text/event-stream")
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["X-Accel-Buffering"] = "no"
response.headers["Connection"] = "keep-alive"
return response
@chat_bp.route("/sessions", methods=["GET"])
@jwt_required
def get_sessions():
"""获取当前用户的会话列表。"""
2026-07-12 14:17:18 +08:00
page = max(1, request.args.get("page", 1, type=int))
page_size = min(100, max(1, request.args.get("page_size", 20, type=int)))
user_id = request.user_id
result = chat_service.get_sessions(user_id, page, page_size)
return jsonify(result)
@chat_bp.route("/sessions", methods=["POST"])
@jwt_required
def create_session():
"""创建新会话。"""
user_id = request.user_id
result = chat_service.create_session(user_id)
return jsonify(result)
@chat_bp.route("/sessions/<session_id>", methods=["DELETE"])
@jwt_required
def delete_session(session_id):
"""软删除会话。"""
user_id = request.user_id
result = chat_service.delete_session(user_id, session_id)
return jsonify(result)
@chat_bp.route("/sessions/<session_id>/messages", methods=["GET"])
@jwt_required
def get_messages(session_id):
"""获取会话消息记录。"""
user_id = request.user_id
result = chat_service.get_messages(user_id, session_id)
return jsonify(result)
@chat_bp.route("/messages/<message_id>/feedback", methods=["POST"])
@jwt_required
def submit_feedback(message_id):
"""提交回答评分或纠错。"""
data = request.get_json()
2026-07-12 14:17:18 +08:00
if not data:
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
rating = data.get("rating", "")
2026-07-12 14:17:18 +08:00
correction = data.get("correction", "")
user_id = request.user_id
if rating not in ("helpful", "not_helpful"):
return jsonify({"code": 1001, "message": "评分值无效", "data": None}), 400
2026-07-12 14:17:18 +08:00
result = chat_service.submit_feedback(user_id, message_id, rating, correction)
return jsonify(result)
@chat_bp.route("/suggest", methods=["POST"])
@jwt_required
def suggest():
"""基于当前回答生成推荐追问。"""
data = request.get_json()
2026-07-12 14:17:18 +08:00
if not data:
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
message = data.get("message", "")
if not message:
return jsonify({"code": 1001, "message": "请输入回答内容", "data": None}), 400
result = chat_service.get_suggestions(message)
return jsonify(result)
2026-07-12 14:17:18 +08:00
@chat_bp.route("/app-opening", methods=["GET"])
@jwt_required
def get_app_opening():
"""获取 Dify 应用的开场配置(开场白 + 推荐问题)。"""
api_token = request.args.get("api_token", "")
result = chat_service.get_app_opening(api_token)
return jsonify(result)
@chat_bp.route("/sessions/<session_id>/rename", methods=["PUT"])
@jwt_required
def rename_session(session_id):
"""重命名会话。"""
data = request.get_json()
2026-07-12 14:17:18 +08:00
if not data:
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
name = data.get("name", "")
if not name:
return jsonify({"code": 1001, "message": "请输入会话名称", "data": None}), 400
user_id = request.user_id
result = chat_service.rename_session(user_id, session_id, name)
return jsonify(result)
@chat_bp.route("/sessions/<session_id>/auto-name", methods=["POST"])
@jwt_required
def auto_name_session(session_id):
"""根据首条消息自动命名会话。"""
data = request.get_json()
2026-07-12 14:17:18 +08:00
if not data:
return jsonify({"code": 1001, "message": "请求体不能为空", "data": None}), 400
first_message = data.get("message", "")
if not first_message:
return jsonify({"code": 1001, "message": "请输入消息内容", "data": None}), 400
user_id = request.user_id
result = chat_service.auto_name_session(user_id, session_id, first_message)
return jsonify(result)