| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- from __future__ import annotations
- from fastapi import APIRouter, File, Form, HTTPException, UploadFile
- from finrep_algo_agent.api.deps import RagServiceDep, SettingsDep
- from finrep_algo_agent.rag.ingestion import extract_text_from_upload
- from finrep_algo_agent.schemas.rag import (
- RagDeleteResponse,
- RagDocumentIn,
- RagFileProcessResult,
- RagIngestFilesResponse,
- RagIngestRequest,
- RagIngestResponse,
- RagRetrieveRequest,
- RagRetrieveResponse,
- )
- router = APIRouter()
- @router.post("/ingest-files", response_model=RagIngestFilesResponse)
- async def rag_ingest_files(
- settings: SettingsDep,
- rag: RagServiceDep,
- task_id: str = Form(..., description="报告任务 ID,材料向量按 task 隔离"),
- replace: bool = Form(True),
- files: list[UploadFile] = File(..., description="业务上传材料,服务端解析文本后自动分块入库"),
- ) -> RagIngestFilesResponse:
- """文件直达 Python 时走本接口:解析 → 向量化 → 写入本任务 RAG 索引(无需 Java 先抽正文)。"""
- if not (settings.embedding_api_key or settings.llm_api_key):
- raise HTTPException(
- status_code=400,
- detail="RAG 入库需配置 FINREP_EMBEDDING_API_KEY 或 FINREP_LLM_API_KEY",
- )
- if not files:
- raise HTTPException(status_code=422, detail="files 不能为空")
- file_results: list[RagFileProcessResult] = []
- documents: list[RagDocumentIn] = []
- for uf in files:
- raw = await uf.read()
- ex = extract_text_from_upload(filename=uf.filename or "upload.bin", data=raw)
- fr = RagFileProcessResult(
- filename=ex.source_label,
- doc_id=ex.doc_id,
- characters=len(ex.text),
- skipped=not bool(ex.text),
- warning=ex.warning,
- )
- file_results.append(fr)
- if ex.text:
- documents.append(
- RagDocumentIn(
- doc_id=ex.doc_id,
- title="",
- text=ex.text,
- source_label=ex.source_label,
- )
- )
- if not documents:
- raise HTTPException(
- status_code=422,
- detail="所有文件均未解析出有效文本,未写入索引",
- )
- try:
- ing = await rag.ingest(task_id, documents, replace=replace)
- except ValueError as e:
- raise HTTPException(status_code=422, detail=str(e)) from e
- except Exception as e:
- raise HTTPException(status_code=502, detail=f"向量化服务异常: {e}") from e
- return RagIngestFilesResponse(
- task_id=ing.task_id,
- document_count=ing.document_count,
- chunk_count=ing.chunk_count,
- files=file_results,
- )
- @router.post("/ingest", response_model=RagIngestResponse)
- async def rag_ingest(
- body: RagIngestRequest,
- settings: SettingsDep,
- rag: RagServiceDep,
- ) -> RagIngestResponse:
- if not (settings.embedding_api_key or settings.llm_api_key):
- raise HTTPException(
- status_code=400,
- detail="RAG 入库需配置 FINREP_EMBEDDING_API_KEY 或 FINREP_LLM_API_KEY",
- )
- try:
- return await rag.ingest(
- body.task_id,
- body.documents,
- replace=body.replace,
- )
- except ValueError as e:
- raise HTTPException(status_code=422, detail=str(e)) from e
- except Exception as e:
- raise HTTPException(status_code=502, detail=f"向量化服务异常: {e}") from e
- @router.post("/retrieve", response_model=RagRetrieveResponse)
- async def rag_retrieve(
- body: RagRetrieveRequest,
- settings: SettingsDep,
- rag: RagServiceDep,
- ) -> RagRetrieveResponse:
- if not (settings.embedding_api_key or settings.llm_api_key):
- raise HTTPException(
- status_code=400,
- detail="RAG 检索需配置 FINREP_EMBEDDING_API_KEY 或 FINREP_LLM_API_KEY",
- )
- try:
- return await rag.retrieve(
- body.task_id,
- body.query,
- top_k=body.top_k,
- min_score=body.min_score,
- )
- except Exception as e:
- raise HTTPException(status_code=502, detail=f"检索服务异常: {e}") from e
- @router.delete("/{task_id}", response_model=RagDeleteResponse)
- async def rag_delete_index(task_id: str, rag: RagServiceDep) -> RagDeleteResponse:
- deleted = rag.delete_index(task_id)
- return RagDeleteResponse(task_id=task_id, deleted=deleted)
|