Skip to content

Latest commit

 

History

History
 
 

README.md

FileX for AWorld

FileX is AWorld's document and media ingestion runtime. It turns local files, public URLs, or restricted object-store references into Markdown and structured artifacts that an agent can inspect without copying a large source file through the model context.

The repository ships two deployment shapes:

  • AWorld all-in-one image: aworld-cli, the FileX skill, and the FileX CLI.
  • FileX GPU service: an asynchronous HTTP service with a bounded queue and a persistent PaddleOCR-VL worker for scanned documents.

Supported inputs include PDF, Markdown/text, Word, PowerPoint, Excel/CSV, images, audio, video, HTTP(S) files, and YouTube transcript sources. PDF output uses Document IR v2; video output can include timestamped keyframes, OCR evidence, and a storyboard. Video evidence is not yet a full semantic video understanding model.

Quick start

Local development

FileX requires Python 3.12, uv, FFmpeg, LibreOffice, Poppler, and Noto CJK fonts. From this directory:

cd aworld-tools/filex
uv sync --dev
uv run filex --help
uv run filex parse /path/to/report.pdf
uv run pytest tests/document_parse_service

FileX writes under ~/workspace by default. Use FILEX_WORKSPACE_ROOT to select another workspace. Inputs must remain inside that workspace when using --workspace-path.

The PaddleOCR provider enables chart recognition by default in both CLI and service use, so detected charts are sent to the configured VLM for their data instead of appearing only as cropped images. Set FILEX_PADDLE_OCR_USE_CHART_RECOGNITION=false to disable it, or pass {"paddle_ocr_use_chart_recognition": false} in the request's env_content. An explicit request setting takes precedence over the environment.

FileX uses PaddleX's native Chart Recognition: task token and does not enforce a chart output contract by default. This compatibility mode applies to native and external gateway VLMs: FileX accepts the first completed document even when a chart response is narrative, so a slow chart request is not followed by a silent replay of the complete document or a failure after useful output was produced.

Models known to handle a detailed chart-to-table instruction can opt in with FILEX_PADDLE_OCR_CHART_PROMPT_MODE=structured. Deployments that also require an enforced chart contract can independently set FILEX_PADDLE_OCR_CHART_OUTPUT_CONTRACT=strict. Strict mode requires every detected chart block to contain a multi-column Markdown or HTML table with an independent numeric cell and otherwise raises PaddleOcrChartContractError. It validates one pass by default. Set FILEX_PADDLE_OCR_CHART_CONTRACT_RETRIES to a positive number only when replaying the complete document is acceptable. Each explicit contract retry asks the VLM to read the chart again with a correction prompt; it is not a local reformatting pass. Prompt selection and contract enforcement are independent settings, so either can be enabled without the other.

Transient VLM transport failures retry the complete document at most once by default. Set FILEX_PADDLE_OCR_VLM_MAX_RETRIES=0 to disable that replay, or set an explicit higher value only when the caller's time budget can accommodate multiple full parsing attempts. The effective transport and chart retry limits are included in the provider's model_info diagnostics.

AWorld all-in-one container

Build from the AWorld repository root:

docker build --platform linux/amd64 \
  -f aworld-tools/filex/Dockerfile -t aworld-filex:local .
mkdir -p workspace
cp /path/to/report.pdf workspace/report.pdf
docker run --rm \
  --platform linux/amd64 \
  -v "$PWD/workspace:/root/workspace" \
  aworld-filex:local \
  filex parse /root/workspace/report.pdf

The default container command is aworld-cli. The image also exposes FileX through the bundled skill:

docker run --rm -it \
  --platform linux/amd64 \
  --env-file .env.aworld-filex \
  -v "$PWD/workspace:/root/workspace" \
  aworld-filex:local \
  aworld-cli run --agent Aworld --skill filex \
  --task "Parse /root/workspace/report.pdf and summarize it"

From the AWorld repository root, create the runtime environment file and keep real model credentials outside the repository:

cp aworld-tools/filex/config/aworld.env.example .env.aworld-filex
chmod 600 .env.aworld-filex

File and URL parsing

The CLI accepts a workspace path or an HTTP(S) URL:

filex inspect /root/workspace/report.pdf
filex parse /root/workspace/report.pdf
filex parse "https://example.com/report.pdf" --file-type pdf
filex status --batch-resume-id <resume-id>

For large PDFs, select pages and enable resumable batches:

filex parse /root/workspace/report.pdf \
  --pages 1,3-20 \
  --page-batch-size 3 \
  --batch-resume-id report-2026-01

For a synchronous local parse, the FileX CLI can atomically produce a self-verifying artifact bundle without an agent-specific exporter:

filex parse /root/workspace/report.pdf \
  --no-cache \
  --layout-format parse-output \
  --artifacts-dir /logs/artifacts

The CLI writes document.md, public layout.json, original document-ir.json, and a commit-marker result.json. The receipt uses filex.artifact-bundle/v1; its filex_provenance uses filex.provenance/v1 with exporter: filex-cli and hashes the source, Document IR, Markdown, layout, and unmodified FileX response. result.json is invalidated before provider execution and written last, so a failed retry cannot leave an earlier attempt looking successful. Use document-ir instead of parse-output when the native FileX IR should be layout.json.

Keep CLI parsing synchronous. When invoking it through AWorld's terminal run_code tool, supply an explicit timeout, such as 900 seconds or 1800 for larger documents, within the remaining task budget. Chart recognition can legitimately take more than 120 seconds. Wait for the foreground command rather than starting duplicate parses or manually restarting a slow parser.

The standalone CLI's --sync-mode async schedules a coroutine in the CLI's own event loop; it does not create a worker that survives CLI exit. It is unsuitable for producing durable task artifacts, and the CLI requires synchronous local parsing for --artifacts-dir. filex status only reads saved PDF batch checkpoints; it does not supervise a background job. Use the separately deployed HTTP service below when asynchronous job submission is needed.

YouTube sources use a transcript-first policy. Discovery does not download media; audio fallback requires explicit permission and a rights basis:

filex inspect "https://www.youtube.com/watch?v=VIDEO_ID"
filex parse "https://www.youtube.com/watch?v=VIDEO_ID" \
  --mode transcript --language en
filex parse "https://www.youtube.com/watch?v=VIDEO_ID" \
  --mode transcript --allow-media-download --rights-basis user-owned

FileX does not use browser cookies or bypass access controls.

Asynchronous HTTP service

Run the service from the all-in-one image:

docker run --rm \
  --platform linux/amd64 \
  -p 18080:18080 \
  -e FILEX_SERVICE_HOST=0.0.0.0 \
  -e FILEX_SERVICE_CONCURRENCY=1 \
  -e FILEX_SERVICE_MAX_PENDING_JOBS=8 \
  -v "$PWD/workspace:/root/workspace" \
  aworld-filex:local filex-server

Submit a file without authentication when no service token is configured:

curl -sS -X POST http://127.0.0.1:18080/v1/parse \
  -F 'file=@report.pdf' \
  -F 'provider=liteparse'

Submit a public URL so FileX downloads the source directly:

curl -sS -X POST http://127.0.0.1:18080/v1/parse \
  -F 'source_url=https://example.com/report.pdf' \
  -F 'provider=liteparse'

For a private object store, set FILEX_SERVICE_SOURCE_URL_HOSTS to a comma-separated allowlist and submit a short-lived pre-signed URL together with its expected size and SHA-256. FileX validates redirects, destination addresses, size, and digest. Public URL mode rejects private and loopback destinations.

Poll GET /v1/jobs/{job_id}, cancel with DELETE /v1/jobs/{job_id}, and download successful artifacts through the URLs returned by the job response. GET /healthz reports queue and worker state.

GPU service image

The GPU overlay expects a revision-pinned Faster Whisper model directory at .ci-models/faster-whisper-base. From the FileX directory, prepare it and build the overlay:

./bin/download-whisper-model.sh .ci-models/faster-whisper-base
docker build --platform linux/amd64 \
  -f Dockerfile.gpu-service -t filex-gpu:local .
docker run --rm --gpus all \
  --platform linux/amd64 \
  --shm-size=8g \
  -p 18080:18080 \
  -e FILEX_SERVICE_HOST=0.0.0.0 \
  -e FILEX_SERVICE_PADDLE_WARMUP=true \
  -e FILEX_SERVICE_PADDLE_IDLE_SECONDS=0 \
  -v filex-paddlex-cache:/root/.paddlex \
  -v "$PWD/workspace:/root/workspace" \
  filex-gpu:local

The default GPU overlay is pinned to a published Linux AMD64 AWorld base image. To test the overlay against a local base, pass --build-arg BASE_IMAGE=aworld-filex:local and make that image available to the builder.

PaddleOCR-VL model weights are downloaded during the first warmup unless they already exist in the image or /root/.paddlex cache. The first start therefore needs model-registry network access. Persist the cache volume as shown above, or pre-warm and capture the cache during an image build for an offline runtime. After the service becomes ready, submit scanned PDFs with:

curl -sS -X POST http://127.0.0.1:18080/v1/parse \
  -F 'file=@scanned-report.pdf' \
  -F 'provider=paddle_ocr'

FILEX_SERVICE_PADDLE_IDLE_SECONDS=0 keeps the OCR worker resident. A positive value unloads it only after that many idle seconds; active or queued work does not trigger idle shutdown. The no-progress watchdog restarts a stalled worker.

Hardware profiles

Profile Suitable workload Requirements
CPU development Text, Office, tables, text-layer PDFs, light audio/video 4+ CPU cores, 16 GiB RAM recommended
GPU OCR service Scanned PDFs and sustained PaddleOCR-VL traffic NVIDIA GPU with 16 GiB+ VRAM recommended, 32 GiB RAM, 8 GiB shared memory
Validated service host Long-running OCR service validation NVIDIA RTX 5090 32 GiB; about 8.5 GiB resident VRAM was observed after warmup, not measured as peak or minimum

The GPU image installs PaddlePaddle GPU 3.3.0 from the CUDA 12.9 package index by default. The host needs a compatible NVIDIA driver and NVIDIA Container Toolkit. Reserve additional disk space for container layers, model weights, and job artifacts; tens of GiB is a practical starting point. CPU-only scanned-PDF OCR is not recommended as a production throughput profile.

Configuration

Service environment

Variable Default Purpose
FILEX_SERVICE_HOST 127.0.0.1 Listen address
FILEX_SERVICE_PORT 18080 Listen port
FILEX_SERVICE_CONCURRENCY 1 Maximum simultaneous parses
FILEX_SERVICE_MAX_PENDING_JOBS 8 Queue bound; excess requests receive backpressure
FILEX_SERVICE_MAX_UPLOAD_BYTES 1073741824 Upload and remote-source size limit
FILEX_SERVICE_PARSE_TIMEOUT_SECONDS 1800 Per-job deadline
FILEX_SERVICE_SOURCE_URL_TIMEOUT_SECONDS 900 Remote-source download deadline
FILEX_SERVICE_SOURCE_URL_HOSTS empty Allowed private object-store hosts
FILEX_SERVICE_API_TOKEN empty Optional bearer token
FILEX_SERVICE_API_TOKEN_FILE empty Optional bearer-token file
FILEX_SERVICE_TENANT_ID empty Optional required value for the X-Tenant-ID header
FILEX_SERVICE_PADDLE_WARMUP false Warm the OCR worker on service startup
FILEX_SERVICE_PADDLE_IDLE_SECONDS 0 Idle unload delay; 0 keeps the model resident
FILEX_SERVICE_PADDLE_NO_PROGRESS_SECONDS 300 Stalled-worker watchdog
FILEX_SERVICE_LOG_LEVEL INFO Service log level

Set FILEX_SERVICE_CONCURRENCY=1 for one-GPU PaddleOCR-VL deployments. The queue is deliberately bounded so callers receive backpressure instead of unbounded memory and disk growth.

Parser and model configuration

config/filex.yaml contains credential-free provider defaults. Replace it by mounting a YAML file and setting FILEX_CONFIG_PATH. The CLI can load provider credentials with --env-content-file using a copy of config/filex-env.example.json; the HTTP endpoint does not accept arbitrary provider credentials per request. Configure service-side providers at startup. Do not put secrets in the image, YAML, command history, or Git.

Useful model variables are:

  • FILEX_LOCAL_MEDIA_MODEL
  • FILEX_LOCAL_MEDIA_DEVICE
  • FILEX_LOCAL_MEDIA_COMPUTE_TYPE
  • FILEX_CONFIG_PATH
  • FILEX_WORKSPACE_ROOT

Operational model

  • HTTP jobs are persisted under the workspace and survive client disconnects.
  • FileX uses one persistent Paddle worker, three-page OCR batches, checkpoints, and per-batch progress so long PDFs can resume without recomputing completed pages.
  • The service downloads pre-signed URLs directly, avoiding an extra large-file copy through an agent runtime.
  • Queue status, parse status, artifacts, and errors remain separate in the job contract; a completed transport request does not imply a successful parse.
  • Authentication is optional at the FileX boundary. Use a bearer token or put the service behind an authenticated gateway for untrusted networks.

Evaluation

The latest validated component baseline on the pinned ParseBench 2,553-case suite is 52.07% five-dimension equal-weight overall. Strongest performance is content faithfulness (82.88%); the main remaining gap is visual grounding (5.30%).

Dimension Cases FileX score Official PaddleOCR-VL-1.6 reference
Tables 503 67.64% 67.77%
Charts 568 56.14% 54.24%
Content faithfulness 506 82.88% 82.71%
Semantic formatting 476 48.40% 54.64%
Visual grounding / layout 500 5.30% 77.80%
Equal-weight overall 2,553 52.07% 67.43%

Nineteen formatting cases returned not_scored and are excluded rather than counted as zero. The table combines the newest trusted campaign for each dimension, so it is a component baseline rather than a claim that every row was produced by one immutable release. See the ParseBench evaluation report for pinned revisions, methodology, limitations, and the optimization roadmap.

Security and production checklist

  • Keep provider keys and service tokens outside Git and container layers.
  • Mount the workspace on persistent storage and apply a retention policy to job sources and artifacts.
  • Do not expose the unauthenticated service directly to an untrusted network.
  • Keep FILEX_SERVICE_SOURCE_URL_HOSTS narrow; prefer short-lived, read-only pre-signed URLs with expected size and SHA-256.
  • Start with concurrency 1 per GPU and scale with multiple replicas only after measuring VRAM and queue latency.
  • Monitor /healthz, queue depth, no-progress restarts, disk usage, and model warmup latency.

The GitHub workflow .github/workflows/filex-image.yml validates pull requests and publishes the Linux AMD64 all-in-one image on eligible branches and tags.