π Planning: llm-ports v0.1.0-alpha.31 β Local runtime + orchestration (transformers.js + Tesseract + pipelines) #67
baabakk
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Status: Planning discussion. Target ship window 2026-09-15 to 2026-09-29 (four to six weeks after alpha.30). Substantially larger release than alpha.28-30; own theme.
Theme: Local runtime + orchestration. Three items that together open up a new class of
@llm-portsconsumer: apps running local models (transformers.js, Tesseract) alongside cloud models, unified behind one Registry with one telemetry/session/retry pipeline.Prior release: alpha.30 (planned 2026-09-02; persistent backends + caching; see planning discussion filed alongside).
What ships in alpha.31
Three items forming a single coherent theme.
Item 1 β
@llm-ports/adapter-transformers-nodeConsumer: Dramma (1a).
Current gap.
@xenova/transformersis the JavaScript port of Hugging Face's transformers library. It runs a broad catalog of small-to-medium models (SmolVLM, SmolDocling, TrOCR, DistilBERT, T5, and many more) locally on Node without a Python subprocess. No@llm-portsadapter wraps it today. Consumers that want to run local models alongside cloud models build their own subprocess: HTTP server + response contract + transport plumbing (Dramma'slocal-ocr-serveris 315 LoC of exactly this shape).Fix shape. New package
@llm-ports/adapter-transformers-node. ImplementsLLMPort(generateText+generateStructured+streamText). Wraps@xenova/transformers'pipeline()API. Handles:Xenova/smolvlm-256m,Xenova/smoldocling-256m, etc.pricing: 'free'(per alpha.28 Item 12).Task type routing. Consumers wire the transformers adapter into
LLM_PROVIDER_*env like any cloud adapter:LLM_PROVIDER_LOCAL_VLM=transformers-node|Xenova/smolvlm-256m|req:1000/hour. Task routes point at it:LLM_TASK_ROUTE_OCR=cloud-vision,local-vlmand the fallback chain works uniformly.Estimated: ~1000 LoC (adapter + tests + docs + conformance suite compliance).
Item 2 β
@llm-ports/adapter-tesseractjsConsumer: Dramma (1b).
Current gap.
tesseract.jsruns Tesseract OCR (open-source, mature, high accuracy on scanned text) in Node. No@llm-portsadapter wraps it. Dramma runs it inside the same subprocess as transformers-node.Fix shape. New package
@llm-ports/adapter-tesseractjs. ImplementsLLMPort:generateTextreturns the recognized text;generateStructuredthrowsUnsupportedOperationError(Tesseract has no structured-output contract). Wrapstesseract.js worker.recognize. Handles:uncaughtExceptionhandler pattern (tesseract.js occasionally raises uncaught errors from its WASM boundary; consumers currently install their own handlers).eng,fra,deu, etc. viaLLM_TASK_ROUTE_TESSERACT_ENG=tesseract-eng.pricing: 'free'.Estimated: ~600 LoC (smaller than transformers-node because OCR-only).
Item 3 β Pipeline primitive:
port.pipeline([...])Consumers: Dramma (4). Also relevant for SalesCoach's coaching + summary chain patterns and BEPA's multi-step triage-then-draft flows.
Current gap. Multi-step call chains where each step depends on the previous one's output, and the consumer wants automatic aggregation of cost, usage, latencyMs, providerAlias, retry events across steps, are hand-rolled at every call site. Dramma's
runRefine(dramma-ocr.ts:659-694) is called from three places (cloud, local, self-hosted) with identical aggregation code.Fix shape. New port method
pipeline(steps: PipelineStep[], options?: PipelineOptions)returns a rolled-upPipelineResult.Semantics.
inputbuilder.PipelineResult.stepsup to the failure.aggregation: "sum-cost-and-usage"aggregates by summation;"last-only"returns the last step's usage + cost (rare);"custom"accepts a reducer function.refs.pipeline_idif they set one onPipelineOptions.refs.budgetScopeapplies pipeline-total, not per-step (per Item 4 in alpha.28).Estimated: ~400 LoC (design + implementation + tests + docs).
Open design questions
Five questions consumers should signal on before implementation begins:
adapter-transformers-nodestreaming. Some transformers models support token-by-token streaming; others don't. ShipstreamTextasfalsefor all transformers models (simpler; consistent) OR route on a per-model basis (correct; requires per-model wiring)? Recommendation: per-model wiring behind acapabilitiesfield in the model registry within the adapter.adapter-tesseractjslanguages. Register one adapter per language (tesseract-eng,tesseract-fra) OR one adapter that takes the language on the call viaproviderExtras.lang? Recommendation: one adapter with per-call language; consistent with how vision-model adapters take image size / detail knobs.PipelineOptions.signalcompose with per-attempt timeouts on individual steps (alpha.28 Item 1) and per-call timeouts (alpha.28 Item 7)? Recommendation: step-level signals compose with pipeline signal (the shorter trigger wins); per-attempt timeout applies to individual step attempts within the pipeline.input, OR is that the consumer's responsibility via theinput: (prev) => LLMMessage[]closure? Recommendation: explicit via closure; matches TypeScript ergonomics and avoids surprise coupling.Consumer credit
Other consumers benefit indirectly: BEPA's future local-triage workflows, SalesCoach's coaching-cue latency work, and any ADW flow that would benefit from a small-fast-local first stage before falling to a large-remote model.
Cross-references
Post design-question answers below by 2026-09-01 for baseline scope. This is a longer window than alpha.28-30's because the pipeline design surface benefits from consumer feedback.
All reactions