返回目录
文件与数据 插件

orchestral

orchestral-media/orchestral

TypeScript library for building multimedia-generation agents: text-to-image, video, speech and audio pipelines with capability-based model routing, automatic cross-model fallback, and BYOK direct provider calls (no gateway). 27 built-in patterns, provider-SDK-free core.

Stars
1
Forks
0
Issues
0
更新
今天

PROJECT TOPICS

项目标签

INSTALL REFERENCE

安装参考

未验证
dsh plugin --profile web add github:orchestral-media/orchestral

该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。

PROJECT README

README

Orchestral

License: Apache-2.0

A TypeScript orchestration layer for media generation — text-to-image, image-to-video, text-to-speech, speech recognition — built for local-first, BYOK apps: capability routing, opt-in semantic fallback, and an asset-handle protocol.

You describe what a step needs (text-to-image, image-to-video, automatic-speech-recognition, …), not which model to call. Orchestral routes that capability to a model you supplied, retries inside the router, knows the semantically equivalent paths a capability without a model could degrade through (reporting them on failure by default; redirecting automatically is opt-in), and passes generated media between steps as opaque handles the host resolves. It ships no provider SDK and no API keys — calling a model is a ~15-line adapter you write, over whichever SDK you already use. Everything runs in your process; there is no hosted control plane.

How it relates to the AI SDK / LangChain

Different layers, and Orchestral expects you to keep using the others:

  • A provider SDK (the Vercel AI SDK, an official vendor SDK) owns one model call — auth, request shape, streaming, transport retries. Your Orchestral call adapter is usually a dozen lines over one of these; the examples here use the AI SDK's generateImage.
  • An agent framework (LangChain / LangGraph, the AI SDK's own tool loop) owns the generic tool loop — planning, memory, a graph of steps. Orchestral's agent patterns delegate the loop to whichever one you inject.
  • Orchestral owns what neither covers for media: routing a capability rather than a model id, declaring semantically equivalent fallback paths for when no model serves that capability, and threading generated assets between steps as handles instead of raw ids.

Quickstart

Not on npm yet — 0.1.0 publishes shortly. Until then, clone this repo and run the examples.

npm install @orchestral/core @orchestral/runtime @orchestral/patterns zod

Two optional packages sit on top: @orchestral/discovery (the BM25 search behind a find_pattern tool) and @orchestral/agent (the two agent patterns). Neither pulls in a provider SDK.

zod v4 (>=4.3 <5) is a peer dependency: pattern input/output schemas are zod schemas on the public API, so your app and Orchestral must share one zod instance.

Two runnable hosts live in this repo:

pnpm install
pnpm --filter atomic-hello-world start   # needs OPENAI_API_KEY
pnpm --filter atomic-hello-world test    # no key: same wiring, mock model

Minimal example

Registry, model bridge, router, runtime, one dispatch — the whole surface:

import {
  PatternRegistry,
  InMemoryJobStore,
  createDefaultCapabilityRouter,
  type DispatchContext,
  type DispatchResult,
  type ModelCapability,
} from '@orchestral/core'
import { InlineRuntime } from '@orchestral/runtime'
import { createTextToImagePattern } from '@orchestral/patterns'
import { generateImage } from 'ai'
import { openai } from '@ai-sdk/openai'

const registry = new PatternRegistry()
registry.add(createTextToImagePattern())

// The seam you write: your provider SDK behind a ModelCapability envelope.
const model: ModelCapability = {
  capabilities: ['text-to-image'],
  provider: 'openai',
  modelId: 'gpt-image-1',
  inputs: ['text'],
  outputs: ['image'],
  tags: [],
  source: 'user',
  async call<I, O>(input: I, ctx: DispatchContext): Promise<DispatchResult<O>> {
    const startedAt = Date.now()
    const { images } = await generateImage({
      model: openai.image('gpt-image-1'),
      prompt: (input as { prompt: string }).prompt,
      abortSignal: ctx.signal,
    })
    const assets = images.map((img, i) => ({
      assetId: `img-${i}`,
      modality: 'image' as const,
      url: `data:${img.mediaType ?? 'image/png'};base64,${img.base64}`,
    }))
    const output = {
      modality: 'image' as const,
      assets,
      cost: 0,
      latencyMs: Date.now() - startedAt,
      model: 'openai:gpt-image-1',
      provider: 'openai',
    }
    return { output: output as O }
  },
}

const runtime = new InlineRuntime({
  store: new InMemoryJobStore(),
  registry,
  router: createDefaultCapabilityRouter({
    getModels: (cap) => (cap === 'text-to-image' ? [model] : []),
  }),
})

const job = await runtime.submitJob({
  patternId: 'text-to-image',
  input: { prompt: 'a watercolour fox in a misty forest' },
})
console.log(job.status, job.output) // 'done'  { modality: 'image', assets: [...] }

The annotated version of the same wiring is in packages/orchestral-core/README.md.

What's in the box

@orchestral/patterns ships 25 patterns: 10 atomic ones (one per capability — text-to-image, image-to-video, text-to-speech, automatic-speech-recognition, …) and 15 meta pipelines with their prompts inlined (storyboarding, script planning, idea-to-video, best-of-N image selection, …). The 2 agent patterns (an orchestrator and a long-form-video director) live in the optional @orchestral/agent package.

The full table — kind, input slots, outputs, and the host operations each pattern expects you to supply — is generated from the built package: pattern catalog.

The three seams

A host adopts Orchestral by satisfying three injection points. Two are implementations you swap; the third is the call adapter:

Seam What it decides What ships
JobStore where job rows live InMemoryJobStore for dev/test; bring a durable one (e.g. SQLite-backed) for production
CapabilityRouter which model answers a capability createDefaultCapabilityRouter; you inject getModels and an optional enablement gate
ModelCapability.call the actual provider invocation nothing — this is the ~15-line adapter you write over your own SDK

Agent patterns add a fourth seam, AgentRunImpl, which drives the inner LLM tool-loop. It is @alpha, and it ships nothing for the same reason ModelCapability.call does not: picking an agent framework is the host's call. examples/agent-hello-world wires one over the AI SDK's tool loop in ~150 lines — copy it and swap in whatever loop you already run.

Packages

Package What it is
@orchestral/core The vocabulary and contracts: Pattern / ModelCapability / Alternative, Job / JobStore / Runtime, the default capability router, and the pattern registry. No execution engine, no provider SDK.
@orchestral/patterns The first-party pattern catalog: one atomic pattern per capability, plus meta pipelines (storyboarding, script planning, idea-to-video, best-of-N selection, …) with their prompts inlined.
@orchestral/runtime InlineRuntime, the in-process reference implementation of core's Runtime: submits jobs, dispatches through the router, handles retries, opt-in cross-pattern fallback and idempotency. No durable queue — the host owns each job's lifetime.
@orchestral/discovery Optional. The LLM discovery layer: the BM25 PatternSearchIndex and the find_pattern tool handler. Core keeps the input contract; this package owns the searching.
@orchestral/agent Optional. The two agent patterns (an orchestrator and a long-form-video director). Declarations only — the tool loop that runs them is the AgentRunImpl you inject.
@orchestral/dsh-plugin Experimental. A deepseek-harness plugin exposing registered patterns as dsh agent tools. A leaf package on its own version line — dsh is a dev preview, so breakage stops at the bridge.

All packages are Apache-2.0. The @orchestral/* packages are released together on one version line; @orchestral/dsh-plugin versions independently.

Honest limitations

This is 0.x. Each package README states its own edges rather than hiding them:

  • Agent resume is lossy. The transcript stores a step projection, not raw provider messages: tool_use pairing and reasoning blocks are gone on resume — runtime § Resume fidelity.
  • No durable queue. InlineRuntime runs a job in the caller's tick, and abandonOrphanedJobs() marks jobs a dead process left behind as stale; ctx.askUser parks in memory only — runtime § Runtime semantics worth knowing.
  • Deliverable metas need a multimedia backend you supply. Six MetaCommonDeps operations (ffmpeg-shaped: concat, subtitles, background audio, …) are specified but not implemented here — patterns § Deliverable metas.
  • One shipped fallback, and taking it is opt-in. image-to-image → caption → re-render is the only Alternative in the first-party catalog, and InlineRuntime defaults to failing with the applicable paths listed rather than redirecting through them (alternatives: 'auto' turns redirects on) — runtime § Alternative fallback is opt-in, core § Semantic fallback.

Versioning

0.x: minor versions may contain breaking changes, patch versions never do. The @orchestral/* packages share one version line and are published together — pin the exact set you tested against. @orchestral/dsh-plugin versions independently against its dev-preview host. The 1.0 line will follow semver strictly.

Repository layout

packages/orchestral-core/        @orchestral/core
packages/orchestral-discovery/   @orchestral/discovery
packages/orchestral-patterns/    @orchestral/patterns
packages/orchestral-runtime/     @orchestral/runtime
packages/orchestral-agent/       @orchestral/agent
packages/orchestral-dsh-plugin/  @orchestral/dsh-plugin (independent version line)
examples/                        runnable hosts, ~50 lines each
scripts/smoke-dist.mjs           executes the built dist bundles end to end

Development

pnpm install
pnpm build        # tsdown bundle + tsc declarations + api-extractor rollup
pnpm test         # vitest, all packages and examples
pnpm typecheck
pnpm api:check    # public .d.ts surface vs the committed etc/*.api.md report
pnpm smoke:dist   # build, then run the published dist bundles end to end
pnpm docs:catalog # regenerate the pattern catalog table from the built dist

pnpm api:check failing means the public API changed. Review the diff, run pnpm api:update, and commit the updated report alongside the change.

License

Apache-2.0 — see LICENSE and NOTICE.

@orchestral/patterns contains prompt text derived from a third-party MIT project; the affected constants and the upstream license text are listed in packages/orchestral-patterns/CREDITS.md.

Contributing and security

See CONTRIBUTING.md. For vulnerabilities, please use the private channel in SECURITY.md rather than a public issue.

CLASSIFICATION EVIDENCE

分类依据

项目类型插件
功能分类文件与数据
规则置信度

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: image-generation、model-routing、multimodal、text-to-image、text-to-video、video-generation。