feat: OCR 并发识别控制,支持多用户同时上传
- config.py: 新增 OCR_CONCURRENCY 参数(默认1,范围1-10) - images.py: 用 asyncio.Semaphore 控制 OCR 并发,4个上传端点统一受控 - settings API: 新增 ocr_concurrency 字段读写 - 前端设置页: 新增 OCR 并发数量输入框 - .env / .env.example: 新增 OCR_CONCURRENCY 配置项 - Semaphore 动态重建:修改配置后立即生效,无需重启
This commit is contained in:
@@ -30,6 +30,19 @@ from app.services.llm_service import LLMService
|
||||
logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
# OCR 并发控制信号量(动态读取配置)
|
||||
_ocr_semaphore: asyncio.Semaphore | None = None
|
||||
|
||||
|
||||
def _get_ocr_semaphore() -> asyncio.Semaphore:
|
||||
"""获取/重建 OCR 并发信号量"""
|
||||
global _ocr_semaphore
|
||||
from app.config import settings
|
||||
concurrency = settings.OCR_CONCURRENCY
|
||||
if _ocr_semaphore is None or _ocr_semaphore._value != concurrency:
|
||||
_ocr_semaphore = asyncio.Semaphore(concurrency)
|
||||
return _ocr_semaphore
|
||||
|
||||
ALLOWED_EXTENSIONS = {".png", ".jpg", ".jpeg", ".bmp", ".webp"}
|
||||
|
||||
# 全局 BM25 索引实例(在 main.py 中初始化)
|
||||
@@ -126,7 +139,8 @@ async def recognize_image(image_id: int, db: AsyncSession = Depends(get_db)):
|
||||
await db.flush()
|
||||
|
||||
try:
|
||||
ocr_result = await OCRService.recognize(image_record.file_path)
|
||||
async with _get_ocr_semaphore():
|
||||
ocr_result = await OCRService.recognize(image_record.file_path)
|
||||
_save_ocr_result(image_record, ocr_result, db)
|
||||
await db.flush()
|
||||
await db.refresh(image_record)
|
||||
@@ -171,7 +185,8 @@ async def batch_recognize(files: List[UploadFile], db: AsyncSession = Depends(ge
|
||||
db.add(image_record)
|
||||
await db.flush()
|
||||
try:
|
||||
ocr_result = await OCRService.recognize(str(dest_path))
|
||||
async with _get_ocr_semaphore():
|
||||
ocr_result = await OCRService.recognize(str(dest_path))
|
||||
# OCR 内容去重
|
||||
existing_id = await _check_ocr_duplicate(ocr_result.text, db)
|
||||
if existing_id is not None:
|
||||
@@ -239,7 +254,8 @@ async def import_from_paths(data: PathImportRequest, db: AsyncSession = Depends(
|
||||
db.add(image_record)
|
||||
await db.flush()
|
||||
try:
|
||||
ocr_result = await OCRService.recognize(file_path)
|
||||
async with _get_ocr_semaphore():
|
||||
ocr_result = await OCRService.recognize(file_path)
|
||||
# OCR 内容去重
|
||||
existing_id = await _check_ocr_duplicate(ocr_result.text, db)
|
||||
if existing_id is not None:
|
||||
@@ -279,7 +295,8 @@ async def recognize_direct(file: UploadFile, db: AsyncSession = Depends(get_db))
|
||||
db.add(image_record)
|
||||
await db.flush()
|
||||
try:
|
||||
ocr_result = await OCRService.recognize(str(dest_path))
|
||||
async with _get_ocr_semaphore():
|
||||
ocr_result = await OCRService.recognize(str(dest_path))
|
||||
# OCR 内容去重
|
||||
existing_id = await _check_ocr_duplicate(ocr_result.text, db)
|
||||
if existing_id is not None:
|
||||
|
||||
Reference in New Issue
Block a user