feat: add video OCR/ASR, DOCX/PDF export, input block and risk config updates

- Video pipeline: video file OCR via VLM plus audio track ASR, integrated
  into job_handlers with progress emit per phase. New media_utils.py for
  audio extraction from video files.
- Document export: richExport.js replaces inline docx builder; DOCX and PDF
  export buttons are now enabled in MilkdownEditor. File size limit raised to
  100 MB.
- Input block: new InputBlockCrepe.vue component with inputBlockPlugin.ts
  and inputBlock.js for custom user-input nodes in the editor.
- Risk config: added Vite dev server ports (5173) to CORS allowlist and
  increased OCR max input from 10 MB to 100 MB.
- TTS/ASR refactor: simplified tts_asr.py model loading and warmup logic.
- Test coverage: updated tests for llm, main endpoints, pro completions and
  web search modules.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
“ydy0615”
2026-06-18 16:32:31 +08:00
parent 4813196b0a
commit 356108e792
34 changed files with 1457 additions and 563 deletions
+20 -8
View File
@@ -551,31 +551,43 @@ async def stream_ollama_events(
)
async def call_vlm_ocr(image_bytes: bytes, language: str = 'auto') -> str:
"""OCR via VLM using OpenAI-compatible vision API (image_url content part)."""
async def call_vlm_ocr(
media_bytes: bytes,
language: str = 'auto',
*,
mime_type: str = 'image/png',
media_type: str = 'image',
) -> str:
"""OCR via VLM using OpenAI-compatible multimodal API."""
start = time.perf_counter()
start_dt = datetime.now()
logger.info(
'[VLM][ocr] request model=%s base_url=%s image_bytes=%d language=%s',
VLM_MODEL, LLM_BASE_URL, len(image_bytes), language,
'[VLM][ocr] request model=%s base_url=%s media_type=%s media_bytes=%d language=%s mime=%s',
VLM_MODEL, LLM_BASE_URL, media_type, len(media_bytes), language, mime_type,
)
image_b64 = base64.b64encode(image_bytes).decode('ascii')
media_b64 = base64.b64encode(media_bytes).decode('ascii')
content_part_type = 'video_url' if media_type == 'video' else 'image_url'
url_key = 'video_url' if media_type == 'video' else 'image_url'
payload = {
'model': VLM_MODEL,
'messages': [{
'role': 'user',
'content': [
{'type': 'text', 'text': get_vlm_ocr_prompt()},
{'type': 'text', 'text': f"{get_vlm_ocr_prompt()}\n\nTarget language hint: {language or 'auto'}"},
{
'type': 'image_url',
'image_url': {'url': f'data:image/png;base64,{image_b64}'},
'type': content_part_type,
url_key: {'url': f'data:{mime_type or "application/octet-stream"};base64,{media_b64}'},
},
],
}],
'stream': False,
'options': {
'temperature': 0,
'think': False,
},
}
http_timeout = httpx.Timeout(connect=10.0, read=None, write=30.0, pool=30.0)