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.
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_serviceFileX 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.
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.pdfThe 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-filexThe 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-01For 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/artifactsThe 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-ownedFileX does not use browser cookies or bypass access controls.
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-serverSubmit 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.
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:localThe 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.
| 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.
| 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.
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_MODELFILEX_LOCAL_MEDIA_DEVICEFILEX_LOCAL_MEDIA_COMPUTE_TYPEFILEX_CONFIG_PATHFILEX_WORKSPACE_ROOT
- 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.
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.
- 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_HOSTSnarrow; 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.