genkit_ops 0.1.3 copy "genkit_ops: ^0.1.3" to clipboard
genkit_ops: ^0.1.3 copied to clipboard

Caching, terminal diagnostics, redaction, and operational middleware for Genkit Dart generate calls.

example/main.dart

// Customer support cache example.
//
// Scenario:
// A support product receives many repeated questions:
// - "How do I reset my password?"
// - "What is your refund policy?"
// - "How can I cancel my subscription?"
//
// Without caching, each repeated question may create another paid model call.
// With genkit_ops, repeated model requests can be returned from memory while
// the terminal still shows cache hit/miss, latency, finish reason, and token
// usage reported by the provider.
//
// Before running this example in a real app:
// 1. Add a Genkit model provider package, such as Google AI or Vertex AI.
// 2. Register that provider plugin in the Genkit plugins list below.
// 3. Configure a default model or pass a model to _ai.generate().

import 'package:genkit/genkit.dart';
import 'package:genkit_ops/genkit_ops.dart';

/// A simplified support ticket from an ecommerce application.
final class SupportTicket {
  /// Creates a support ticket.
  const SupportTicket({
    required this.id,
    required this.tenantId,
    required this.customerQuestion,
    required this.customerPlan,
    required this.locale,
  });

  /// Internal ticket id used by the application.
  final String id;

  /// Tenant, workspace, or merchant id.
  final String tenantId;

  /// Customer's original question.
  final String customerQuestion;

  /// Customer's plan or segment, used in the prompt.
  final String customerPlan;

  /// Locale used both in the prompt and cache key.
  final String locale;
}

/// Version of the policy prompt used by support answers.
///
/// Bump this value whenever refund, delivery, cancellation, or security policy
/// text changes. Changing it invalidates old cache keys without clearing the
/// whole store.
const _supportPolicyVersion = 'support-policy-2026-01';

/// Memory cache for support replies.
///
/// In production, this interface can be backed by Redis, a database, Hive, Isar,
/// or another store by implementing `CacheStore<ModelResponse>`.
final _supportCache = InMemoryCacheStore<ModelResponse>(
  defaultTtl: const Duration(minutes: 30),
  maxEntries: 1000,
);

/// Terminal logger for local development.
///
/// The default info level prints metadata such as cache status, latency, finish
/// reason, and token usage. It does not print raw prompt/output payloads.
final _supportLogger = GenkitOpsLogger(
  level: GenkitOpsLogLevel.info,
  sink: (message) {
    // Replace this with package:logging, Sentry breadcrumbs, or your internal
    // logger if you do not want to print directly in production.
    print(message);
  },
);

final _ai = Genkit(
  plugins: [
    // Register your model provider plugin here.
    //
    // Example shape:
    // googleAI(),
    //
    // Then either configure a default model on Genkit or pass `model:` to
    // _ai.generate().
    GenkitOpsPlugin(cacheStore: _supportCache, logger: _supportLogger),
  ],
);

/// Generates a support reply with cache and terminal diagnostics.
Future<String> answerSupportTicket(SupportTicket ticket) async {
  final response = await _ai.generate(
    prompt: _buildSupportPrompt(ticket),
    context: {
      // Only selected context keys affect the cache key. See contextKeys below.
      'tenantId': ticket.tenantId,
      'locale': ticket.locale,
    },
    use: genkitOps(
      policy: CachePolicy(
        // Namespace prevents one tenant's cache from being reused by another.
        namespace: 'support-replies-${ticket.tenantId}',

        // Deterministic invalidation for policy/prompt changes.
        keyVersion: _supportPolicyVersion,

        // Repeated answers are useful for a short support window, but should
        // expire so policy updates and fresh context can take effect.
        ttl: const Duration(minutes: 30),

        // Only these context values are included in the cache identity.
        contextKeys: const ['tenantId', 'locale'],
      ),
      logger: _supportLogger,
    ),
  );

  return response.text;
}

String _buildSupportPrompt(SupportTicket ticket) {
  return '''
You are a concise support assistant for an ecommerce application.

Rules:
- Answer in the customer's locale.
- Give clear next steps.
- Do not invent refund, cancellation, or security policy details.
- If policy details are missing, ask the customer to contact support.
- Keep the answer under 120 words.

Customer metadata:
- Plan: ${ticket.customerPlan}
- Locale: ${ticket.locale}

Customer question:
${ticket.customerQuestion}
''';
}

Future<void> main() async {
  final firstTicket = SupportTicket(
    id: 'ticket-1001',
    tenantId: 'merchant-acme',
    customerQuestion: 'How do I reset my password?',
    customerPlan: 'Pro',
    locale: 'en-US',
  );

  final repeatedTicket = SupportTicket(
    id: 'ticket-1002',
    tenantId: 'merchant-acme',
    customerQuestion: 'How do I reset my password?',
    customerPlan: 'Pro',
    locale: 'en-US',
  );

  // Expected behavior after a model provider is configured:
  // 1. The first call is a cache miss and reaches the model.
  // 2. The second call has the same prompt/config/context and returns from
  //    cache while the logger prints a cache-hit event.
  final firstAnswer = await answerSupportTicket(firstTicket);
  final secondAnswer = await answerSupportTicket(repeatedTicket);

  print('First answer:\n$firstAnswer\n');
  print('Second answer:\n$secondAnswer\n');
}
1
likes
160
points
93
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Caching, terminal diagnostics, redaction, and operational middleware for Genkit Dart generate calls.

Repository (GitHub)
View/report issues

Topics

#genkit #ai #cache #logging #middleware

License

MIT (license)

Dependencies

genkit

More

Packages that depend on genkit_ops