Files

189 lines
4.9 KiB
Python
Raw Permalink Normal View History

2026-02-05 16:25:52 +08:00
"""
意图编制 API 路由
"""
from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from pydantic import BaseModel
from datetime import datetime
from pathlib import Path
from app.database import get_db
from app.models.intent import Intent, AICheckRecord
from planner.planning_agent.input_pipeline import parse_intent_file
import tempfile
router = APIRouter(prefix="/intent", tags=["意图编制"])
# ============ Pydantic Schemas ============
class IntentCreate(BaseModel):
"""创建意图请求"""
title: str
content: Optional[str] = None
status: str = "draft"
class IntentUpdate(BaseModel):
"""更新意图请求"""
title: Optional[str] = None
content: Optional[str] = None
status: Optional[str] = None
class IntentResponse(BaseModel):
"""意图响应"""
id: int
title: str
content: Optional[str]
status: str
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True
class IntentListResponse(BaseModel):
"""意图列表响应"""
total: int
items: List[IntentResponse]
# ============ API Endpoints ============
@router.post("", response_model=IntentResponse, status_code=status.HTTP_201_CREATED)
async def create_intent(
intent_data: IntentCreate,
db: AsyncSession = Depends(get_db)
):
"""创建新意图"""
intent = Intent(
title=intent_data.title,
content=intent_data.content,
status=intent_data.status
)
db.add(intent)
await db.commit()
await db.refresh(intent)
return intent
@router.get("", response_model=IntentListResponse)
async def list_intents(
skip: int = 0,
limit: int = 20,
status_filter: Optional[str] = None,
db: AsyncSession = Depends(get_db)
):
"""获取意图列表"""
query = select(Intent)
if status_filter:
query = query.where(Intent.status == status_filter)
query = query.order_by(Intent.updated_at.desc())
# 获取总数
count_query = select(Intent)
if status_filter:
count_query = count_query.where(Intent.status == status_filter)
result = await db.execute(count_query)
total = len(result.scalars().all())
# 获取分页数据
query = query.offset(skip).limit(limit)
result = await db.execute(query)
items = result.scalars().all()
return IntentListResponse(total=total, items=items)
@router.get("/{intent_id}", response_model=IntentResponse)
async def get_intent(
intent_id: int,
db: AsyncSession = Depends(get_db)
):
"""获取单个意图"""
result = await db.execute(select(Intent).where(Intent.id == intent_id))
intent = result.scalar_one_or_none()
if not intent:
raise HTTPException(status_code=404, detail="意图不存在")
return intent
@router.put("/{intent_id}", response_model=IntentResponse)
async def update_intent(
intent_id: int,
intent_data: IntentUpdate,
db: AsyncSession = Depends(get_db)
):
"""更新意图"""
result = await db.execute(select(Intent).where(Intent.id == intent_id))
intent = result.scalar_one_or_none()
if not intent:
raise HTTPException(status_code=404, detail="意图不存在")
if intent_data.title is not None:
intent.title = intent_data.title
if intent_data.content is not None:
intent.content = intent_data.content
if intent_data.status is not None:
intent.status = intent_data.status
intent.updated_at = datetime.utcnow()
await db.commit()
await db.refresh(intent)
return intent
@router.delete("/{intent_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_intent(
intent_id: int,
db: AsyncSession = Depends(get_db)
):
"""删除意图"""
result = await db.execute(select(Intent).where(Intent.id == intent_id))
intent = result.scalar_one_or_none()
if not intent:
raise HTTPException(status_code=404, detail="意图不存在")
await db.delete(intent)
await db.commit()
return None
@router.post("/parse-file")
async def parse_intent_file_endpoint(file: UploadFile = File(...)):
"""解析意图编制导入文件pdf/图片走 MinerU文本直接读取"""
if not file.filename:
raise HTTPException(status_code=400, detail="未提供文件")
suffix = Path(file.filename).suffix.lower()
with tempfile.TemporaryDirectory() as tmp_dir:
tmp_path = Path(tmp_dir) / file.filename
content = await file.read()
tmp_path.write_bytes(content)
try:
result = parse_intent_file(str(tmp_path))
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
return {
"filename": file.filename,
"suffix": suffix,
"title": result.get("title", ""),
"content": result.get("content", ""),
"raw_result": result.get("raw_result"),
}