aigc_prompt_composer 0.1.0-dev.4 copy "aigc_prompt_composer: ^0.1.0-dev.4" to clipboard
aigc_prompt_composer: ^0.1.0-dev.4 copied to clipboard

A provider-neutral, extensible prompt composition toolkit for pure Dart applications.

aigc_prompt_composer #

aigc_prompt_composer is a provider-neutral, pure Dart toolkit for building deterministic prompts from reusable, localized fragments. It works in Flutter, server, and command-line Dart applications without depending on Flutter.

The package deliberately focuses on composition. It contains no model clients, networking, persistence, user interface, analytics, billing, or vendor SDKs.

Features #

  • User-defined section identifiers instead of a closed section enum.
  • Stable section and fragment ordering with explicit tie-breakers.
  • Fragment deduplication by identifier or resolved content.
  • {{variable}} substitution with fragment, recipe, and operation precedence.
  • Required and optional sections, single-fragment constraints, and conflicts.
  • Locale selection with parent-locale and configured fallback chains.
  • Immutable models with JSON serialization round trips.
  • Plain-text and structured JSON renderers.
  • Custom validator and renderer extension points.
  • Strict composition with typed, recoverable validation exceptions.
  • Ordered batch composition with complete strict-failure results.

Installation #

Add the package to pubspec.yaml:

dependencies:
  aigc_prompt_composer: ^0.1.0-dev.4

Then run:

dart pub get

Quick start #

import 'package:aigc_prompt_composer/aigc_prompt_composer.dart';

void main() {
  final schema = PromptSchema(
    id: 'image.v1',
    version: '1',
    defaultLocale: 'en',
    sections: <PromptSectionDefinition>[
      PromptSectionDefinition(
        id: 'subject',
        order: 10,
        required: true,
        localizedHeaders: const <String, String>{'en': 'Subject'},
      ),
      PromptSectionDefinition(
        id: 'lighting',
        order: 20,
        localizedHeaders: const <String, String>{'en': 'Lighting'},
      ),
    ],
  );

  final recipe = PromptRecipe(
    schemaId: schema.id,
    variables: const <String, Object?>{'material': 'frosted glass'},
    fragments: <PromptFragment>[
      PromptFragment.text(
        id: 'main-subject',
        sectionId: 'subject',
        content: 'A {{material}} sculpture on a stone plinth',
      ),
      PromptFragment.text(
        id: 'soft-light',
        sectionId: 'lighting',
        content: 'Soft window light with gentle shadows',
      ),
    ],
  );

  final result = PromptComposer().compose(schema: schema, recipe: recipe);
  final text = const PlainTextPromptRenderer().render(result);

  print(text);
}

The resulting text is deterministic:

Subject:
A frosted glass sculpture on a stone plinth

Lighting:
Soft window light with gentle shadows

Ordering and deduplication #

Sections are sorted by PromptSectionDefinition.order, then by section id. Fragments are sorted by their section, PromptFragment.order, fragment id, and finally original position. This produces stable output even when collections arrive in a different order.

PromptCompositionOptions.deduplication accepts:

  • FragmentDeduplication.none
  • FragmentDeduplication.byId
  • FragmentDeduplication.byResolvedContent

Resolved-content deduplication is scoped to a section.

Variables #

Fragments use {{name}} placeholders. Values are merged in this order, with later layers taking precedence:

  1. PromptFragment.variables
  2. PromptRecipe.variables
  3. PromptCompositionOptions.variables

Missing variables produce an error issue. The placeholder is preserved by default; use MissingVariableBehavior.emptyString to remove it from output.

Locales and fallback #

The requested locale is selected from composition options, the recipe, then the schema default. Locale tags are compared case-insensitively, _ and - are treated equally, and parent tags are tried from most to least specific.

For example, zh-Hant-HK tries zh-Hant-HK, zh-Hant, then zh. Operation fallbacks are tried next, followed by schema fallbacks and the schema default. If nothing matches, the lexicographically first available locale is selected so the result remains deterministic. A fallback emits an informational issue.

Validation #

ComposedPrompt.issues contains machine-readable diagnostics. Built-in checks cover schema identity and version, duplicate identifiers, unknown sections, required sections, section multiplicity, missing localized content, unresolved variables, and section or fragment conflicts.

Composition returns the best available output alongside diagnostics. Check ComposedPrompt.isValid or ComposedPrompt.hasErrors before sending output to another system.

Compare built-in codes with PromptIssueCodes constants. The complete catalog and severity contract are documented in Validation.

Use issuesWhere() or hasIssue() for exact, composable diagnostic queries:

final missingSubject = result.hasIssue(
  code: PromptIssueCodes.requiredSectionMissing,
  sectionId: 'subject',
);
final warnings = result.issuesWhere(
  severity: PromptIssueSeverity.warning,
);

Add application rules by implementing PromptValidator:

final class MaximumLengthValidator implements PromptValidator {
  MaximumLengthValidator(this.maximumLength);

  final int maximumLength;

  @override
  Iterable<PromptValidationIssue> validate(PromptValidationContext context) {
    final length = context.sections
        .expand((section) => section.fragments)
        .fold<int>(0, (sum, fragment) => sum + fragment.content.length);
    if (length <= maximumLength) return const <PromptValidationIssue>[];
    return <PromptValidationIssue>[
      PromptValidationIssue(
        code: 'maximum_length_exceeded',
        message: 'Resolved content is longer than allowed.',
        severity: PromptIssueSeverity.error,
        details: <String, Object?>{'maximumLength': maximumLength},
      ),
    ];
  }
}

Pass validators to PromptComposer(validators: [...]).

Strict composition #

Use composeOrThrow() when invalid output must never reach a renderer or downstream system:

try {
  final prompt = PromptComposer().composeOrThrow(
    schema: schema,
    recipe: recipe,
  );
  print(const PlainTextPromptRenderer().render(prompt));
} on PromptCompositionException catch (error) {
  for (final issue in error.errors) {
    print('${issue.code}: ${issue.message}');
  }
}

Only error-severity diagnostics throw. Warnings and informational diagnostics remain available through warningIssues and infoIssues. The exception keeps the complete partial prompt, allowing callers to log or inspect the exact composition result without recomputing it.

Batch composition #

Use composeAll() when multiple recipes share a schema and operation options. Results are immutable and preserve recipe iteration order:

final prompts = PromptComposer().composeAll(
  schema: schema,
  recipes: recipes,
  options: PromptCompositionOptions(locale: 'en'),
);

composeAllOrThrow() composes the complete batch before throwing. A PromptBatchCompositionException exposes every result through prompts, the zero-based invalidIndexes, and the flattened error diagnostics through errors. This allows callers to retain successful results and retry only the invalid inputs.

Rendering #

Use PlainTextPromptRenderer for display-ready text. Use StructuredJsonPromptRenderer when another component needs typed section, fragment, locale, metadata, and diagnostic data.

Implement PromptRenderer<T> to render any application-specific output type.

Serialization #

All configuration and result models provide toJson() and fromJson(). Values are JSON-compatible maps rather than encoded strings, so callers remain in control of storage and transport.

Top-level payloads include formatVersion. See Serialization for version and compatibility rules.

Examples #

  • Image prompt composition
  • Video prompt composition

Design references:

  • Architecture
  • Locale selection
  • Serialization
  • Validation

Development #

dart pub get
dart format --set-exit-if-changed .
dart analyze --fatal-infos
dart test
dart doc
dart pub publish --dry-run

Additional quality checks:

dart test --coverage=coverage
dart run coverage:format_coverage --lcov --in=coverage --out=coverage/lcov.info --report-on=lib
dart run tool/check_coverage.dart coverage/lcov.info 90
dart run tool/consumer_smoke_test.dart
dart run benchmark/composition_benchmark.dart

License #

BSD 3-Clause. See LICENSE.

1
likes
0
points
297
downloads

Publisher

unverified uploader

Weekly Downloads

A provider-neutral, extensible prompt composition toolkit for pure Dart applications.

Repository (GitHub)
View/report issues

Topics

#aigc #prompts #composition #localization #validation

License

unknown (license)

More

Packages that depend on aigc_prompt_composer