| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- import json
- import os
- from fastapi import APIRouter, UploadFile, File, Form, HTTPException
- from fastapi.responses import StreamingResponse
- import utils.util
- from api.handler_registry import HANDLER_REGISTRY
- from api.schema import ChatRequest
- from config.settings import JSON_CACHE_DIR, REPORT_OUTPUT_DIR, SERVER_HOST, PDF_SAVE_DIR
- from service.stream_service import format_sse_event, stream_calculation_sync, detect_intent, stream_review_sync
- from service.history_manager import fetch_all_sessions, fetch_session_detail, remove_session_file
- from service.pdf_parse_service import parse_pdf, get_latest_file
- router = APIRouter()
- @router.post("/api/vent/review/pdf")
- async def api_review(
- file: UploadFile = File(),
- session_id: str | None = Form(default=None),
- message : str | None = Form(default=None)
- ):
- if not file.filename.endswith(".pdf"):
- raise HTTPException(status_code=400, detail="仅支持PDF")
- return StreamingResponse(
- stream_review_sync(file,message,session_id),
- media_type="text/event-stream",
- headers={
- "Cache-Control": "no-cache",
- "Connection": "keep-alive",
- "X-Accel-Buffering": "no"
- }
- )
- @router.post("/api/vent/chat")
- async def vent_chat(req: ChatRequest):
- return StreamingResponse(
- stream_calculation_sync(req.message, req.session_id),
- media_type="text/event-stream",
- headers={
- "Cache-Control": "no-cache",
- "Connection": "keep-alive"
- }
- )
- @router.get("/health")
- async def health():
- return {"status": "ok", "agent": "create_agent(LangGraph)"}
- @router.get("/api/history/session_list")
- async def list_sessions():
- return {"code":200,"data":fetch_all_sessions()}
- @router.get("/api/history/detail/{session_id}")
- async def get_session_history(session_id:str):
- data = fetch_session_detail(session_id)
- return {"code":200,"data":data}
- @router.delete("/api/history/delete/{session_id}")
- async def remove_session(session_id: str):
- success = remove_session_file(session_id)
- if not success:
- raise HTTPException(
- status_code=404,
- detail=f"会话 {session_id} 不存在或删除失败"
- )
- return {"code": 200, "message": "会话删除成功", "data": None}
- @router.get("/api/latest-json", summary="")
- async def get_latest_json():
- """
- 获取指定文件夹中修改时间最新的JSON文件并返回内容
- """
- hash_id = utils.util.get_user_setting("last_upload_file")
- latest_file_path = f"{JSON_CACHE_DIR}/{hash_id}.json"
- try:
- with open(latest_file_path, "r", encoding="utf-8") as f:
- data = json.load(f)
- except json.JSONDecodeError:
- raise HTTPException(status_code=500, detail="JSON文件格式错误")
- except Exception as e:
- raise HTTPException(status_code=500, detail=f"读取文件失败: {str(e)}")
- return {"code": 200, "message": "一切ok", "data": data}
- @router.get("/api/latest-pdf", summary="")
- async def get_latest_pdf():
- hash_id = utils.util.get_user_setting("last_upload_file")
- pdf_filename = f"{hash_id}.pdf"
- url = f"{SERVER_HOST}/static/save_pdf/{pdf_filename}"
- return {"code": 200, "message": "一切ok", "data": url}
- @router.post("/api/vent/unified")
- async def unified_vent_api(
- # 表单参数
- message: str = Form(...),
- session_id: str | None = Form(default=None),
- # 文件参数(可选)
- file: UploadFile | None = File(default=None)
- ):
- """
- 配风管理统一入口:意图识别 + 自动分发业务
- 支持:纯文本对话 / PDF文件+文本审查
- """
- # 1. 基础参数校验
- if not message.strip():
- raise HTTPException(status_code=400, detail="指令内容不能为空")
- # 2. 意图识别
- has_file = bool(file)
- intent_type = await detect_intent(session_id,message,has_file)
- # 3. 未知意图:使用stream_calculation_sync进行流式处理
- if intent_type not in HANDLER_REGISTRY:
- headers = {"Cache-Control": "no-cache", "Connection": "keep-alive"}
- return StreamingResponse(
- stream_calculation_sync(message, session_id),
- media_type="text/event-stream",
- headers=headers
- )
- # 4. 从注册表获取对应处理器
- handler = HANDLER_REGISTRY[intent_type]
- # 5. 执行当前业务的专属参数校验
- handler.validate(file)
- # 6. 生成流式响应(分两种场景调用)
- if handler.need_file:
- # 带文件:审查场景
- stream_iter = handler.stream_func(file,message, session_id)
- headers = {"Cache-Control": "no-cache", "Connection": "keep-alive", "X-Accel-Buffering": "no"}
- else:
- # 无文件:计算场景
- stream_iter = handler.stream_func(message, session_id)
- headers = {"Cache-Control": "no-cache", "Connection": "keep-alive"}
- return StreamingResponse(stream_iter, media_type="text/event-stream", headers=headers)
|