import { BotpressClientLike, Cognitive, CognitiveRequest, CognitiveResponse, Model, Models } from "@botpress/cognitive"; //#region src/utils.d.ts type GenerationMetadata = { model: string; cost: { input: number; output: number; }; latency: number; tokens: { input: number; output: number; }; }; //#endregion //#region src/adapters/adapter.d.ts type SaveExampleProps = { key: string; taskType: string; taskId: string; instructions: string; input: TInput; output: TOutput; explanation?: string; metadata: GenerationMetadata; status?: 'pending' | 'approved'; }; type GetExamplesProps = { taskType: string; taskId: string; input: TInput; }; declare abstract class Adapter { abstract getExamples(props: GetExamplesProps): Promise>; abstract saveExample(props: SaveExampleProps): Promise; } //#endregion //#region src/tokenizer.d.ts type TruncateMode = 'head' | 'tail' | 'middle'; type CountOptions = { approximate?: boolean; }; type TextTokenizer = { count(text: string, options?: CountOptions): number; truncate(text: string, maxTokens: number, mode?: TruncateMode): string; split(text: string): string[]; }; //#endregion //#region src/zai.d.ts /** * A memoizer that caches the result of async operations by a unique key. * * When used with the Botpress ADK workflow `step` function, this enables * Zai operations to resume where they left off if a workflow is interrupted. * */ type Memoizer = { run: (id: string, fn: () => Promise) => Promise; }; /** * Arbitrary key-value metadata attached to every cognitive call made by a Zai instance. * * Forwarded on the request `meta` and recorded on usage events server-side, enabling * usage breakdowns by custom dimensions (e.g. conversation). * * @example * ```typescript * const convZai = zai.with({ metadata: { conversationId: message.conversationId } }) * await convZai.check(text, 'Is this a refund request?') * ``` */ type ZaiMetadata = Record; /** * Active learning configuration for improving AI operations over time. * * When enabled, Zai stores successful operation results in a table and uses them as examples * for future operations, improving accuracy and consistency. * * @example * ```typescript * const activeLearning = { * enable: true, * tableName: 'MyAppLearningTable', * taskId: 'sentiment-analysis' * } * ``` */ type ActiveLearning = { /** Whether to enable active learning for this Zai instance */ enable: boolean; /** Name of the Botpress table to store learning examples (must end with 'Table') */ tableName: string; /** Unique identifier for this learning task */ taskId: string; }; /** * Configuration options for creating a Zai instance. * * @example * ```typescript * import { Client } from '@botpress/client' * import { Zai } from '@botpress/zai' * * const client = new Client({ token: 'your-token' }) * const config: ZaiConfig = { * client, * modelId: 'best', // Use the best available model * userId: 'user-123', * namespace: 'my-app', * activeLearning: { * enable: true, * tableName: 'MyLearningTable', * taskId: 'extraction' * } * } * const zai = new Zai(config) * ``` */ type ZaiConfig = { /** Botpress client or Cognitive client instance */ client: BotpressClientLike | Cognitive; /** Optional user ID for tracking and attribution */ userId?: string; /** * Model to use: 'best' (default), 'fast', or specific model like 'openai:gpt-4'. * An array can be provided to specify ordered fallback models if the primary * model is unavailable. Server-side fallback is honored on the cognitive-v2 * path; the legacy integration path uses the first entry only. */ modelId?: Models | Models[]; /** Active learning configuration to improve operations over time */ activeLearning?: ActiveLearning; /** Namespace for organizing tasks (default: 'zai') */ namespace?: string; /** * Memoizer (or factory returning one) for caching cognitive call results. * * When provided, all LLM calls are wrapped in the memoizer, allowing results * to be cached and replayed. This is useful for resuming workflow runs where * Zai operations have already completed their cognitive calls. * * If a factory function is provided, it is called once per Zai operation invocation. */ memoize?: Memoizer | (() => Memoizer); /** * Arbitrary key-value metadata attached to every cognitive call, recorded on usage * events server-side. Use `zai.with({ metadata })` to scope it, e.g. per conversation. */ metadata?: ZaiMetadata; }; /** * Zai - A type-safe LLM utility library for production-ready AI operations. * * Zai provides high-level abstractions for common AI tasks with built-in features like: * - Active learning (learns from successful operations) * - Automatic chunking for large inputs * - Retry logic with error recovery * - Usage tracking (tokens, cost, latency) * - Type-safe schema validation with Zod * * @example Basic usage * ```typescript * import { Client } from '@botpress/client' * import { Zai } from '@botpress/zai' * import { z } from '@bpinternal/zui' * * const client = new Client({ token: process.env.BOTPRESS_TOKEN }) * const zai = new Zai({ client }) * * // Extract structured data * const schema = z.object({ * name: z.string(), * age: z.number() * }) * const person = await zai.extract('John is 30 years old', schema) * // Output: { name: 'John', age: 30 } * * // Check conditions * const isPositive = await zai.check('I love this product!', 'Is the sentiment positive?') * // Output: true * * // Summarize text * const summary = await zai.summarize(longDocument, { length: 100 }) * ``` * * @example With active learning * ```typescript * const zai = new Zai({ * client, * activeLearning: { * enable: true, * tableName: 'SentimentTable', * taskId: 'product-reviews' * } * }) * * // Enable learning for specific task * const result = await zai.learn('sentiment').check(review, 'Is this positive?') * // Future calls will use approved examples for better accuracy * ``` * * @example Chaining configuration * ```typescript * // Use fast model for quick operations * const fastZai = zai.with({ modelId: 'fast' }) * await fastZai.check(text, 'Is this spam?') * * // Use specific model * const gpt4Zai = zai.with({ modelId: 'openai:gpt-4' }) * await gpt4Zai.extract(document, complexSchema) * ``` */ declare class Zai { protected static tokenizer: TextTokenizer; protected client: Cognitive; private _originalConfig; private _userId; protected Model: Models | Models[]; protected ModelDetails: Model; protected namespace: string; protected adapter: Adapter; protected activeLearning: ActiveLearning; protected _memoize?: Memoizer | (() => Memoizer); protected metadata?: ZaiMetadata; /** * Creates a new Zai instance with the specified configuration. * * @param config - Configuration object containing client, model, and learning settings * * @example * ```typescript * import { Client } from '@botpress/client' * import { Zai } from '@botpress/zai' * * const client = new Client({ token: 'your-token' }) * const zai = new Zai({ * client, * modelId: 'best', * namespace: 'my-app', * userId: 'user-123' * }) * ``` * * @throws {Error} If the configuration is invalid (e.g., invalid modelId format) */ constructor(config: ZaiConfig); /** @internal */ protected callModel(props: Parameters[0]): ReturnType; /** @internal */ protected _resolveMemoizer(): Memoizer | undefined; protected getTokenizer(): Promise; protected fetchModelDetails(): Promise; protected get taskId(): string; /** * Creates a new Zai instance with merged configuration options. * * This method allows you to create variations of your Zai instance with different * settings without modifying the original. Useful for switching models, namespaces, * or other configuration on a per-operation basis. * * @param options - Partial configuration to override the current settings * @returns A new Zai instance with the merged configuration * * @example Switch to a faster model * ```typescript * const zai = new Zai({ client }) * * // Use fast model for simple operations * const fastZai = zai.with({ modelId: 'fast' }) * await fastZai.check(text, 'Is this spam?') * * // Use best model for complex operations * const bestZai = zai.with({ modelId: 'best' }) * await bestZai.extract(document, complexSchema) * ``` * * @example Change namespace * ```typescript * const customerZai = zai.with({ namespace: 'customer-support' }) * const salesZai = zai.with({ namespace: 'sales' }) * ``` * * @example Use specific model * ```typescript * const gpt4 = zai.with({ modelId: 'openai:gpt-4' }) * const claude = zai.with({ modelId: 'anthropic:claude-3-5-sonnet-20241022' }) * ``` */ with(options: Partial): Zai; /** * Creates a new Zai instance with active learning enabled for a specific task. * * Active learning stores successful operation results and uses them as examples for * future operations, improving accuracy and consistency over time. Each task ID * maintains its own set of learned examples. * * @param taskId - Unique identifier for the learning task (alphanumeric, hyphens, underscores, slashes) * @returns A new Zai instance with active learning enabled for the specified task * * @example Sentiment analysis with learning * ```typescript * const zai = new Zai({ * client, * activeLearning: { * enable: false, * tableName: 'AppLearningTable', * taskId: 'default' * } * }) * * // Enable learning for sentiment analysis * const sentimentZai = zai.learn('sentiment-analysis') * const result = await sentimentZai.check(review, 'Is this review positive?') * * // Each successful call is stored and used to improve future calls * ``` * * @example Different tasks for different purposes * ```typescript * // Extract user info with learning * const userExtractor = zai.learn('user-extraction') * await userExtractor.extract(text, userSchema) * * // Extract product info with separate learning * const productExtractor = zai.learn('product-extraction') * await productExtractor.extract(text, productSchema) * * // Each task learns independently * ``` * * @example Combining with other configuration * ```typescript * // Use fast model + learning * const fastLearner = zai.with({ modelId: 'fast' }).learn('quick-checks') * await fastLearner.check(email, 'Is this spam?') * ``` * * @see {@link ZaiConfig.activeLearning} for configuration options */ learn(taskId: string): Zai; } //#endregion //#region src/context.d.ts /** Per-request accounting in the shape zai has always tracked it. */ type Meta = { cached: boolean; model: { integration: string; model: string; }; latency: number; cost: { input: number; output: number; }; tokens: { input: number; output: number; }; }; type GenerateContentProps = Omit & { maxRetries?: number; transform?: (text: string | undefined, response: CognitiveResponse) => T; }; type ZaiContextProps = { client: Cognitive; taskType: string; taskId: string; modelId: string | string[]; adapter?: Adapter; source?: CognitiveRequest['meta']; memoizer?: Memoizer; metadata?: ZaiMetadata; }; /** * Usage statistics tracking tokens, cost, and request metrics for an operation. * * This type is returned via Response events and the `.result()` method, providing * real-time visibility into: * - Token consumption (input/output/total) * - Cost in USD (input/output/total) * - Request statistics (count, errors, cache hits, progress percentage) * * @example * ```typescript * const { usage } = await zai.extract(text, schema).result() * * console.log(usage.tokens.total) // 1250 * console.log(usage.cost.total) // 0.0075 (USD) * console.log(usage.requests.cached) // 0 * ``` */ type Usage = { /** Request statistics */ requests: { /** Total number of requests initiated */ requests: number; /** Number of requests that failed with errors */ errors: number; /** Number of successful responses received */ responses: number; /** Number of responses served from cache (no tokens used) */ cached: number; /** Operation progress as a decimal (0.0 to 1.0) */ percentage: number; }; /** Cost statistics in USD */ cost: { /** Cost for input tokens */ input: number; /** Cost for output tokens */ output: number; /** Total cost (input + output) */ total: number; }; /** Token usage statistics */ tokens: { /** Input tokens consumed */ input: number; /** Output tokens generated */ output: number; /** Total tokens (input + output) */ total: number; }; }; type ContextEvents = { update: Usage; }; declare class ZaiContext { private _startedAt; private _inputCost; private _outputCost; private _inputTokens; private _outputTokens; private _totalCachedResponses; private _totalRequests; private _totalErrors; private _totalResponses; taskId: string; taskType: string; modelId: CognitiveRequest['model']; adapter?: Adapter; source?: CognitiveRequest['meta']; metadata?: ZaiMetadata; private _eventEmitter; private _memoizer; controller: AbortController; private _client; private static _noopMemoizer; constructor(props: ZaiContextProps); /** The primary model id as a plain string (first entry when fallbacks are configured). */ get modelName(): string; getModel(): Promise; on(type: K, listener: (event: ContextEvents[K]) => void): this; clear(): void; generateContent(props: GenerateContentProps): Promise<{ meta: Meta; output: CognitiveResponse; text: string | undefined; extracted: Out; }>; private _generateContentInner; get elapsedTime(): number; get usage(): Usage; } //#endregion //#region src/response.d.ts /** * Event types emitted during operation execution. * * @property progress - Emitted periodically with usage statistics (tokens, cost, requests) * @property complete - Emitted when operation completes successfully with the result * @property error - Emitted when operation fails with the error */ type ResponseEvents = { /** Emitted during execution with updated usage statistics */ progress: Usage; /** Emitted when the operation completes with the full result */ complete: TComplete; /** Emitted when the operation fails with an error */ error: unknown; }; /** * Promise-like wrapper for Zai operations with observability and control. * * Response provides a dual-value system: * - **Simplified value**: When awaited directly, returns a simplified result (e.g., boolean for `check()`) * - **Full result**: Via `.result()` method, returns `{ output, usage, elapsed }` * * All Zai operations return a Response instance, allowing you to: * - Track progress and usage in real-time * - Abort operations * - Bind to external abort signals * - Get detailed cost and performance metrics * * @template T - The full output type * @template S - The simplified output type (defaults to T) * * @example Basic usage (simplified) * ```typescript * // Simplified result (boolean) * const isPositive = await zai.check(review, 'Is this positive?') * console.log(isPositive) // true or false * ``` * * @example Full result with usage * ```typescript * const response = zai.check(review, 'Is this positive?') * const { output, usage, elapsed } = await response.result() * * console.log(output.value) // true/false * console.log(output.explanation) // "The review expresses satisfaction..." * console.log(usage.tokens.total) // 150 * console.log(usage.cost.total) // 0.002 * console.log(elapsed) // 1234 (ms) * ``` * * @example Progress tracking * ```typescript * const response = zai.summarize(longDocument, { length: 500 }) * * response.on('progress', (usage) => { * console.log(`Progress: ${usage.requests.percentage * 100}%`) * console.log(`Tokens: ${usage.tokens.total}`) * console.log(`Cost: $${usage.cost.total}`) * }) * * const summary = await response * ``` * * @example Aborting operations * ```typescript * const response = zai.extract(hugeDocument, schema) * * // Abort after 5 seconds * setTimeout(() => response.abort('Timeout'), 5000) * * try { * const result = await response * } catch (error) { * console.log('Operation aborted:', error) * } * ``` * * @example External abort signal * ```typescript * const controller = new AbortController() * const response = zai.answer(documents, question).bindSignal(controller.signal) * * // User clicks cancel button * cancelButton.onclick = () => controller.abort() * * const answer = await response * ``` * * @example Error handling * ```typescript * const response = zai.extract(text, schema) * * response.on('error', (error) => { * console.error('Operation failed:', error) * }) * * try { * const result = await response * } catch (error) { * // Handle error * } * ``` */ declare class Response implements PromiseLike { private _promise; private _eventEmitter; private _context; private _elasped; private _simplify; static reject(context: ZaiContext, err: Error): Response; constructor(context: ZaiContext, promise: Promise, simplify: (value: T) => S); /** * Subscribes to events emitted during operation execution. * * @param type - Event type: 'progress', 'complete', or 'error' * @param listener - Callback function to handle the event * @returns This Response instance for chaining * * @example Track progress * ```typescript * response.on('progress', (usage) => { * console.log(`${usage.requests.percentage * 100}% complete`) * console.log(`Cost: $${usage.cost.total}`) * }) * ``` * * @example Handle completion * ```typescript * response.on('complete', (result) => { * console.log('Operation completed:', result) * }) * ``` * * @example Handle errors * ```typescript * response.on('error', (error) => { * console.error('Operation failed:', error) * }) * ``` */ on>(type: K, listener: (event: ResponseEvents[K]) => void): this; /** * Unsubscribes from events. * * @param type - Event type to unsubscribe from * @param listener - The exact listener function to remove * @returns This Response instance for chaining * * @example * ```typescript * const progressHandler = (usage) => console.log(usage.tokens.total) * response.on('progress', progressHandler) * // Later... * response.off('progress', progressHandler) * ``` */ off>(type: K, listener: (event: ResponseEvents[K]) => void): this; /** * Subscribes to an event for a single emission. * * The listener is automatically removed after being called once. * * @param type - Event type: 'progress', 'complete', or 'error' * @param listener - Callback function to handle the event once * @returns This Response instance for chaining * * @example * ```typescript * response.once('complete', (result) => { * console.log('Finished:', result) * }) * ``` */ once>(type: K, listener: (event: ResponseEvents[K]) => void): this; /** * Binds an external AbortSignal to this operation. * * When the signal is aborted, the operation will be cancelled automatically. * Useful for integrating with UI cancel buttons or request timeouts. * * @param signal - AbortSignal to bind * @returns This Response instance for chaining * * @example With AbortController * ```typescript * const controller = new AbortController() * const response = zai.extract(data, schema).bindSignal(controller.signal) * * // Cancel from elsewhere * cancelButton.onclick = () => controller.abort() * ``` * * @example With timeout * ```typescript * const controller = new AbortController() * setTimeout(() => controller.abort('Timeout'), 10000) * * const response = zai.answer(docs, question).bindSignal(controller.signal) * ``` */ bindSignal(signal: AbortSignal): this; /** * Aborts the operation in progress. * * The operation will be cancelled and throw an abort error. * Any partial results will not be returned. * * @param reason - Optional reason for aborting (string or Error) * * @example * ```typescript * const response = zai.extract(largeDocument, schema) * * // Abort after 5 seconds * setTimeout(() => response.abort('Operation timeout'), 5000) * * try { * await response * } catch (error) { * console.log('Aborted:', error) * } * ``` */ abort(reason?: string | Error): void; /** * Promise interface - allows awaiting the Response. * * When awaited, returns the simplified value (S). * Use `.result()` for full output with usage statistics. * * @param onfulfilled - Success handler * @param onrejected - Error handler * @returns Promise resolving to simplified value * * @example * ```typescript * // Simplified value * const isPositive = await zai.check(review, 'Is positive?') * console.log(isPositive) // true * ``` */ then(onfulfilled?: ((value: S) => TResult1 | PromiseLike) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike) | null): PromiseLike; /** * Promise interface - handles errors. * * @param onrejected - Error handler * @returns Promise resolving to simplified value or error result */ catch(onrejected?: ((reason: unknown) => TResult | PromiseLike) | null): PromiseLike; /** * Gets the full result with detailed usage statistics and timing. * * Unlike awaiting the Response directly (which returns simplified value), * this method provides: * - `output`: Full operation result (not simplified) * - `usage`: Detailed token usage, cost, and request statistics * - `elapsed`: Operation duration in milliseconds * * @returns Promise resolving to full result object * * @example * ```typescript * const { output, usage, elapsed } = await zai.check(text, condition).result() * * console.log(output.value) // true/false * console.log(output.explanation) // "The text expresses..." * console.log(usage.tokens.total) // 245 * console.log(usage.cost.total) // 0.0012 * console.log(elapsed) // 1523 (ms) * ``` * * @example Usage statistics breakdown * ```typescript * const { usage } = await response.result() * * console.log('Requests:', usage.requests.requests) * console.log('Cached:', usage.requests.cached) * console.log('Input tokens:', usage.tokens.input) * console.log('Output tokens:', usage.tokens.output) * console.log('Input cost:', usage.cost.input) * console.log('Output cost:', usage.cost.output) * console.log('Total cost:', usage.cost.total) * ``` */ result(): Promise<{ output: T; usage: Usage; elapsed: number; }>; } //#endregion //#region src/operations/text.d.ts type Options$11 = { /** The maximum number of tokens to generate */ length?: number; }; declare module '@botpress/zai' { interface Zai { /** * Generates text content based on a natural language prompt. * * This operation creates original text content using LLMs with optional length constraints. * Perfect for generating descriptions, emails, articles, creative content, and more. * * @param prompt - Natural language description of what text to generate * @param options - Optional configuration for text length * @returns Response promise resolving to the generated text * * @example Product description * ```typescript * const description = await zai.text( * 'Write a compelling product description for eco-friendly bamboo toothbrushes' * ) * ``` * * @example With length constraint * ```typescript * const tagline = await zai.text( * 'Create a catchy tagline for a fitness app', * { length: 10 } // ~10 tokens (7-8 words) * ) * ``` * * @example Email generation * ```typescript * const email = await zai.text(` * Write a professional email to a customer explaining * that their order will be delayed by 2 days due to weather. * Apologize and offer a 10% discount on their next purchase. * `, { length: 150 }) * ``` * * @example Blog post * ```typescript * const blogPost = await zai.text(` * Write an informative blog post about the benefits of meditation * for software developers. Include practical tips and scientific research. * `, { length: 500 }) * ``` * * @example Social media content * ```typescript * const tweet = await zai.text( * 'Write an engaging tweet announcing our new AI-powered chatbot feature', * { length: 30 } // Twitter-friendly length * ) * ``` */ text(prompt: string, options?: Options$11): Response; } } //#endregion //#region src/operations/rewrite.d.ts type Example$3 = { input: string; output: string; instructions?: string; }; type Options$10 = { /** Examples to guide the rewriting */ examples?: Array; /** The maximum number of tokens to generate */ length?: number; }; declare module '@botpress/zai' { interface Zai { /** * Rewrites text according to specific instructions while preserving the core meaning. * * This operation transforms text based on natural language instructions. Perfect for * tone adjustment, format conversion, translation, simplification, and style changes. * * @param original - The text to rewrite * @param prompt - Instructions describing how to transform the text * @param options - Configuration for examples and length constraints * @returns Response promise resolving to the rewritten text * * @example Change tone * ```typescript * const original = "Your request has been denied due to insufficient funds." * const friendly = await zai.rewrite( * original, * 'Make this sound more friendly and empathetic' * ) * // Result: "We appreciate your interest, but unfortunately we're unable to proceed..." * ``` * * @example Simplify technical content * ```typescript * const technical = "The API implements RESTful architecture with OAuth 2.0 authentication..." * const simple = await zai.rewrite( * technical, * 'Explain this in simple terms for non-technical users' * ) * ``` * * @example Professional email conversion * ```typescript * const casual = "Hey, can you send me that report? Thanks!" * const professional = await zai.rewrite( * casual, * 'Rewrite this as a formal business email' * ) * // Result: "Dear colleague, I would appreciate it if you could share the report..." * ``` * * @example Format conversion * ```typescript * const paragraph = "First do this. Then do that. Finally do this other thing." * const bullets = await zai.rewrite( * paragraph, * 'Convert this to a bulleted list' * ) * // Result: * // - First do this * // - Then do that * // - Finally do this other thing * ``` * * @example With examples for consistent style * ```typescript * const result = await zai.rewrite( * original, * 'Rewrite in our brand voice', * { * examples: [ * { * input: 'We offer many products.', * output: 'Discover our curated collection of innovative solutions.' * }, * { * input: 'Contact us for help.', * output: "We're here to support your success. Let's connect!" * } * ], * length: 200 // Limit output length * } * ) * ``` * * @example Translation-like transformation * ```typescript * const code = "if (user.isActive && user.hasPermission) { allowAccess() }" * const pseudocode = await zai.rewrite( * code, * 'Convert this code to natural language pseudocode' * ) * // Result: "If the user is active AND has permission, then allow access" * ``` */ rewrite(original: string, prompt: string, options?: Options$10): Response; } } //#endregion //#region src/operations/summarize.d.ts type Options$9 = { /** What should the text be summarized to? */ prompt?: string; /** How to format the example text */ format?: string; /** The length of the summary in tokens */ length?: number; /** How many times longer (than final length) are the intermediate summaries generated */ intermediateFactor?: number; /** The maximum number of iterations to perform */ maxIterations?: number; /** Sliding window options */ sliding?: { window: number; overlap: number; }; }; declare module '@botpress/zai' { interface Zai { /** * Summarizes text of any length to a target length using intelligent chunking strategies. * * This operation can handle documents from a few paragraphs to entire books. It uses * two strategies based on document size: * - **Sliding window**: For moderate documents, processes overlapping chunks iteratively * - **Merge sort**: For very large documents, recursively summarizes and merges * * @param original - The text to summarize * @param options - Configuration for length, focus, format, and chunking strategy * @returns Response promise resolving to the summary text * * @example Basic summarization * ```typescript * const article = "Long article text here..." * const summary = await zai.summarize(article, { * length: 100 // Target 100 tokens (~75 words) * }) * ``` * * @example Custom focus and format * ```typescript * const meetingNotes = "... detailed meeting transcript ..." * const summary = await zai.summarize(meetingNotes, { * length: 200, * prompt: 'Key decisions, action items, and next steps', * format: 'Bullet points with clear sections for Decisions, Actions, and Next Steps' * }) * ``` * * @example Summarizing very large documents * ```typescript * const book = await readFile('large-book.txt', 'utf-8') // 100k+ tokens * const summary = await zai.summarize(book, { * length: 500, * intermediateFactor: 4, // Intermediate summaries can be 4x target length * prompt: 'Main themes, key events, and character development' * }) * // Automatically uses merge-sort strategy for efficiency * ``` * * @example Technical documentation summary * ```typescript * const docs = "... API documentation ..." * const summary = await zai.summarize(docs, { * length: 300, * prompt: 'Core API endpoints, authentication methods, and rate limits', * format: 'Structured markdown with code examples where relevant' * }) * ``` * * @example Adjusting chunking strategy * ```typescript * const summary = await zai.summarize(document, { * length: 150, * sliding: { * window: 30000, // Process 30k tokens at a time * overlap: 500 // 500 token overlap between windows * } * }) * ``` * * @example Progress tracking for long documents * ```typescript * const response = zai.summarize(veryLongDocument, { length: 400 }) * * response.on('progress', (usage) => { * console.log(`Progress: ${Math.round(usage.requests.percentage * 100)}%`) * console.log(`Tokens used: ${usage.tokens.total}`) * }) * * const summary = await response * ``` */ summarize(original: string, options?: Options$9): Response; } } //#endregion //#region src/operations/check.d.ts type Example$2 = { input: unknown; check: boolean; reason?: string; condition?: string; }; type Options$8 = { /** Examples to check the condition against */ examples?: Array; }; declare module '@botpress/zai' { interface Zai { /** * Checks whether a condition is true for the given input, with an explanation. * * This operation evaluates natural language conditions against your input data, * returning both a boolean result and a detailed explanation. Perfect for * content moderation, sentiment analysis, quality checks, and business rule validation. * * @param input - The data to evaluate (text, object, or any value) * @param condition - Natural language description of the condition to check * @param options - Optional examples to guide the evaluation * @returns Response with { value: boolean, explanation: string }, simplified to boolean when awaited * * @example Basic sentiment check * ```typescript * const review = "This product exceeded my expectations!" * const isPositive = await zai.check(review, 'Is the sentiment positive?') * // Result: true * * // Get full details * const { value, explanation } = await zai.check(review, 'Is the sentiment positive?').result() * // value: true * // explanation: "The review expresses satisfaction and exceeded expectations..." * ``` * * @example Content moderation * ```typescript * const comment = "Great article! Very informative." * const isSpam = await zai.check(comment, 'Is this spam or promotional content?') * // Result: false * * const hasProfanity = await zai.check(comment, 'Does this contain profanity or offensive language?') * // Result: false * ``` * * @example Business rules validation * ```typescript * const invoice = { * total: 1500, * items: ['laptop', 'mouse'], * customer: 'Enterprise Corp' * } * * const needsApproval = await zai.check( * invoice, * 'Does this invoice require manager approval? (over $1000 or enterprise customer)' * ) * // Result: true * ``` * * @example With examples for consistency * ```typescript * const result = await zai.check(text, 'Is this a technical question?', { * examples: [ * { * input: 'How do I deploy to production?', * check: true, * reason: 'Question about deployment process' * }, * { * input: 'What time is the meeting?', * check: false, * reason: 'Not a technical question' * } * ] * }) * ``` * * @example Quality assurance * ```typescript * const code = "function add(a, b) { return a + b }" * const hasDocumentation = await zai.check(code, 'Is this code properly documented?') * const hasTests = await zai.check(code, 'Does this include unit tests?') * const followsConventions = await zai.check(code, 'Does this follow naming conventions?') * ``` */ check(input: unknown, condition: string, options?: Options$8): Response<{ /** Whether the condition is true or not */ value: boolean; /** The explanation of the decision */ explanation: string; }, boolean>; } } //#endregion //#region src/operations/filter.d.ts type Example$1 = { input: unknown; filter: boolean; reason?: string; }; type Options$7 = { /** The maximum number of tokens per item */ tokensPerItem?: number; /** Examples to filter the condition against */ examples?: Array; }; declare module '@botpress/zai' { interface Zai { /** * Filters array elements based on a natural language condition. * * This operation evaluates each element against a condition using LLMs, * returning only elements that match. Handles large arrays automatically * by processing in parallel chunks. * * @param input - Array of elements to filter * @param condition - Natural language description of what to keep * @param options - Configuration for token limits per item and examples * @returns Response promise resolving to filtered array * * @example Filter positive reviews * ```typescript * const reviews = [ * "Great product, love it!", * "Terrible quality, broke immediately", * "Amazing! Exceeded expectations", * "Worst purchase ever" * ] * * const positive = await zai.filter(reviews, 'Keep only positive reviews') * // Result: ["Great product, love it!", "Amazing! Exceeded expectations"] * ``` * * @example Filter technical questions * ```typescript * const questions = [ * "How do I deploy to production?", * "What time is lunch?", * "Why is the API returning 500 errors?", * "Can you book the conference room?" * ] * * const technical = await zai.filter( * questions, * 'Keep only technical or engineering questions' * ) * // Result: ["How do I deploy to production?", "Why is the API returning 500 errors?"] * ``` * * @example Filter with object array * ```typescript * const products = [ * { name: 'Laptop', category: 'Electronics', inStock: true }, * { name: 'Desk', category: 'Furniture', inStock: false }, * { name: 'Mouse', category: 'Electronics', inStock: true }, * { name: 'Chair', category: 'Furniture', inStock: true } * ] * * const available = await zai.filter( * products, * 'Keep only products that are in stock' * ) * // Returns products where inStock === true * ``` * * @example Complex filtering logic * ```typescript * const emails = [...] // Array of email objects * * const urgent = await zai.filter( * emails, * 'Keep emails that are urgent, from the CEO, or mention "critical bug"' * ) * ``` * * @example With examples for consistency * ```typescript * const filtered = await zai.filter(items, 'Keep valid entries', { * examples: [ * { * input: { status: 'active', verified: true }, * filter: true, * reason: 'Active and verified' * }, * { * input: { status: 'pending', verified: false }, * filter: false, * reason: 'Not yet verified' * } * ], * tokensPerItem: 100 // Limit tokens per item for performance * }) * ``` */ filter(input: Array, condition: string, options?: Options$7): Response>; } } //#endregion //#region src/operations/extract.d.ts type Options$6 = { /** Instructions to guide the user on how to extract the data */ instructions?: string; /** The maximum number of tokens per chunk */ chunkLength?: number; /** Whether to strictly follow the schema or not */ strict?: boolean; }; type __Z$1 = { __type__: 'ZuiType'; _output: T; }; type OfType$1 = __Z$1> = T extends __Z$1 ? T : never; declare module '@botpress/zai' { interface Zai { /** * Extracts structured data from unstructured text using a Zod schema. * * This operation uses LLMs to intelligently parse text and extract information * according to your schema. It handles large inputs automatically by chunking * and supports both objects and arrays. * * @param input - The text or data to extract information from * @param schema - Zod schema defining the structure to extract * @param options - Optional configuration for extraction behavior * @returns A Response promise that resolves to data matching your schema * * @example Extract a single object * ```typescript * import { z } from '@bpinternal/zui' * * const personSchema = z.object({ * name: z.string(), * age: z.number(), * email: z.string().email() * }) * * const text = "Contact John Doe (35) at john@example.com" * const person = await zai.extract(text, personSchema) * // Result: { name: 'John Doe', age: 35, email: 'john@example.com' } * ``` * * @example Extract an array of items * ```typescript * const productSchema = z.array(z.object({ * name: z.string(), * price: z.number() * })) * * const text = "We have Apple ($1.50), Banana ($0.80), and Orange ($1.20)" * const products = await zai.extract(text, productSchema) * // Result: [ * // { name: 'Apple', price: 1.50 }, * // { name: 'Banana', price: 0.80 }, * // { name: 'Orange', price: 1.20 } * // ] * ``` * * @example With custom instructions * ```typescript * const result = await zai.extract(document, schema, { * instructions: 'Only extract confirmed information, skip uncertain data', * chunkLength: 10000, // Smaller chunks for better accuracy * strict: true // Enforce strict schema validation * }) * ``` * * @example Track usage and cost * ```typescript * const response = zai.extract(text, schema) * * // Monitor progress * response.on('progress', (usage) => { * console.log(`Tokens used: ${usage.tokens.total}`) * console.log(`Cost so far: $${usage.cost.total}`) * }) * * // Get full results * const { output, usage, elapsed } = await response.result() * console.log(`Extraction took ${elapsed}ms and cost $${usage.cost.total}`) * ``` */ extract>(input: unknown, schema: S, options?: Options$6): Response; } } //#endregion //#region src/operations/label.d.ts type Label = keyof typeof LABELS; declare const LABELS: { readonly ABSOLUTELY_NOT: 'ABSOLUTELY_NOT'; readonly PROBABLY_NOT: 'PROBABLY_NOT'; readonly AMBIGUOUS: 'AMBIGUOUS'; readonly PROBABLY_YES: 'PROBABLY_YES'; readonly ABSOLUTELY_YES: 'ABSOLUTELY_YES'; }; type Example = { input: unknown; labels: Partial>; }; type Options$5 = { /** Examples to help the user make a decision */ examples?: Array>; /** Instructions to guide the user on how to extract the data */ instructions?: string; /** The maximum number of tokens per chunk */ chunkLength?: number; }; type Labels = Record; declare module '@botpress/zai' { interface Zai { /** * Tags input with multiple labels, each with explanation, value, and confidence level. * * This operation evaluates input against multiple categories simultaneously, providing * nuanced confidence levels (ABSOLUTELY_YES, PROBABLY_YES, AMBIGUOUS, PROBABLY_NOT, ABSOLUTELY_NOT). * Perfect for content classification, intent detection, and multi-criteria evaluation. * * @param input - The data to label (text, object, or any value) * @param labels - Object mapping label keys to their descriptions * @param options - Configuration for examples, instructions, and chunking * @returns Response with detailed results per label (explanation, value, confidence), simplified to booleans * * @example Content moderation * ```typescript * const comment = "This is a great article! Click here for cheap products!" * * const result = await zai.label(comment, { * spam: 'Is this spam or promotional content?', * helpful: 'Is this comment helpful and constructive?', * profanity: 'Does this contain profanity or offensive language?' * }).result() * * // result.output: * // { * // spam: { value: true, confidence: 0.5, explanation: 'Contains promotional link...' }, * // helpful: { value: true, confidence: 1, explanation: 'Positive feedback...' }, * // profanity: { value: false, confidence: 1, explanation: 'No offensive language' } * // } * * // Simplified (when awaited directly): * const simple = await zai.label(comment, { spam: 'Is this spam?' }) * // simple: { spam: true } * ``` * * @example Intent classification * ```typescript * const message = "I can't log in to my account" * * const intents = await zai.label(message, { * technical_issue: 'Is this a technical problem?', * urgent: 'Does this require immediate attention?', * needs_human: 'Should this be escalated to a human agent?', * billing_related: 'Is this about billing or payments?' * }) * // Returns boolean for each intent * ``` * * @example Sentiment analysis with nuance * ```typescript * const review = "The product is okay, but shipping was slow" * * const { output } = await zai.label(review, { * positive: 'Is the overall sentiment positive?', * negative: 'Is the overall sentiment negative?', * mixed: 'Does this express mixed feelings?' * }).result() * * // Check confidence levels * if (output.mixed.confidence > 0.5) { * console.log('Mixed sentiment detected:', output.mixed.explanation) * } * ``` * * @example Product categorization * ```typescript * const product = { * name: 'Wireless Headphones', * description: 'Noise-canceling Bluetooth headphones for music lovers', * price: 199 * } * * const categories = await zai.label(product, { * electronics: 'Is this an electronic device?', * audio: 'Is this audio equipment?', * premium: 'Is this a premium/luxury product?', * portable: 'Is this portable/mobile?' * }) * // Returns: { electronics: true, audio: true, premium: true, portable: true } * ``` * * @example With examples for consistency * ```typescript * const result = await zai.label(email, { * urgent: 'Requires immediate response', * complaint: 'Customer is dissatisfied' * }, { * examples: [ * { * input: 'ASAP! System is down!', * labels: { * urgent: { label: 'ABSOLUTELY_YES', explanation: 'Critical issue' }, * complaint: { label: 'PROBABLY_YES', explanation: 'Implicit complaint' } * } * } * ], * instructions: 'Consider tone, urgency keywords, and context' * }) * ``` * * @example Understanding confidence levels * ```typescript * const { output } = await zai.label(text, labels).result() * * // Confidence values: * // ABSOLUTELY_YES: confidence = 1.0, value = true * // PROBABLY_YES: confidence = 0.5, value = true * // AMBIGUOUS: confidence = 0, value = false * // PROBABLY_NOT: confidence = 0.5, value = false * // ABSOLUTELY_NOT: confidence = 1.0, value = false * * Object.entries(output).forEach(([key, result]) => { * if (result.value && result.confidence === 1) { * console.log(`Definitely ${key}:`, result.explanation) * } else if (result.value && result.confidence === 0.5) { * console.log(`Probably ${key}:`, result.explanation) * } * }) * ``` */ label(input: unknown, labels: Labels, options?: Options$5): Response<{ [K in T]: { explanation: string; value: boolean; confidence: number; }; }, { [K in T]: boolean; }>; } } //#endregion //#region src/operations/group.d.ts type Group = { id: string; label: string; elements: T[]; }; type InitialGroup = { id: string; label: string; elements?: unknown[]; }; type Options$4 = { instructions?: string; tokensPerElement?: number; chunkLength?: number; initialGroups?: Array; maxGroups?: number; minElements?: number; /** Allow the model to create groups beyond `initialGroups` (default true). Set false to classify into a fixed list. */ newGroups?: boolean; /** Example elements shown under each group in the prompt (default 3), taken from `initialGroups[].elements`. */ examplesPerGroup?: number; /** Maximum elements per model call (default 30). Smaller chunks are more accurate; larger ones use fewer calls. */ elementsPerChunk?: number; /** Maximum model calls in flight (default 20). */ concurrency?: number; }; declare module '@botpress/zai' { interface Zai { /** * Groups array items into categories based on semantic similarity or criteria. * * This operation intelligently categorizes items by analyzing their content and * creating meaningful groups. It can discover natural groupings automatically or * use predefined categories. Perfect for clustering, classification, and organization. * * @param input - Array of items to group * @param options - Configuration for grouping behavior, instructions, and initial categories * @param options.maxGroups - Maximum number of groups allowed (minimum 2). When set, groups are merged at the end until within limit. * @param options.minElements - Minimum elements per group (minimum 1). Groups below this threshold have their elements redistributed via AI. * @param options.newGroups - Set false to only use `initialGroups` (classification into a fixed list); the model must pick one of them. * @param options.examplesPerGroup - How many `initialGroups[].elements` to show under each group as examples (default 3). * @param options.elementsPerChunk - Maximum elements per model call (default 30). * @param options.concurrency - Maximum model calls in flight (default 20). * @returns Response with groups array (simplified to Record) * * @example Automatic grouping * ```typescript * const messages = [ * "I can't log in to my account", * "How do I reset my password?", * "When will my order arrive?", * "The app keeps crashing", * "I haven't received my package", * "Error 500 on checkout" * ] * * const groups = await zai.group(messages, { * instructions: 'Group by type of customer issue' * }) * // Result (simplified): * // { * // "Login Issues": ["I can't log in...", "How do I reset..."], * // "Shipping Questions": ["When will my order...", "I haven't received..."], * // "Technical Errors": ["The app keeps crashing", "Error 500..."] * // } * * // Full result: * const { output } = await zai.group(messages, { instructions: '...' }).result() * // output: [ * // { id: 'login_issues', label: 'Login Issues', elements: [...] }, * // { id: 'shipping', label: 'Shipping Questions', elements: [...] }, * // { id: 'errors', label: 'Technical Errors', elements: [...] } * // ] * ``` * * @example With predefined categories * ```typescript * const articles = [ * "How to build a React app", * "Python machine learning tutorial", * "Understanding Docker containers", * "Vue.js best practices", * "Deep learning with TensorFlow" * ] * * const groups = await zai.group(articles, { * instructions: 'Categorize by technology', * initialGroups: [ * { id: 'frontend', label: 'Frontend Development' }, * { id: 'backend', label: 'Backend Development' }, * { id: 'ml', label: 'Machine Learning' }, * { id: 'devops', label: 'DevOps & Infrastructure' } * ] * }) * // Groups articles into predefined categories * ``` * * @example Grouping products * ```typescript * const products = [ * { name: 'Laptop', price: 999, category: 'Electronics' }, * { name: 'Desk', price: 299, category: 'Furniture' }, * { name: 'Mouse', price: 29, category: 'Electronics' }, * { name: 'Chair', price: 199, category: 'Furniture' } * ] * * const grouped = await zai.group(products, { * instructions: 'Group by price range: budget (< $100), mid-range ($100-$500), premium (> $500)' * }) * // Result: * // { * // "Budget": [Mouse], * // "Mid-range": [Chair, Desk], * // "Premium": [Laptop] * // } * ``` * * @example Content categorization * ```typescript * const emails = [ * { subject: 'Meeting tomorrow', body: '...', from: 'boss@company.com' }, * { subject: 'Invoice #1234', body: '...', from: 'billing@vendor.com' }, * { subject: 'Weekly report', body: '...', from: 'team@company.com' }, * { subject: 'Payment received', body: '...', from: 'accounting@company.com' } * ] * * const categorized = await zai.group(emails, { * instructions: 'Categorize by email type: work communication, financial, reports', * tokensPerElement: 300 // Allow more context per email * }) * ``` * * @example Customer feedback grouping * ```typescript * const feedback = [ * "Love the new UI!", * "App is too slow", * "Great customer service", * "Confusing navigation", * "Fast shipping!", * "Hard to find features" * ] * * const grouped = await zai.group(feedback, { * instructions: 'Group by aspect: UI/UX, Performance, Customer Service, Shipping' * }) * ``` * * @example Topic clustering for research * ```typescript * const papers = [ * { title: 'Transformer Networks for NLP', abstract: '...' }, * { title: 'CNN Image Classification', abstract: '...' }, * { title: 'BERT Language Understanding', abstract: '...' }, * { title: 'Object Detection with YOLO', abstract: '...' } * ] * * const clusters = await zai.group(papers, { * instructions: 'Group by research area', * chunkLength: 10000 // Allow more tokens for detailed abstracts * }) * // Result: Groups papers by topic (NLP, Computer Vision, etc.) * ``` * * @example With initial seed groups * ```typescript * const tasks = [ * "Fix login bug", * "Update documentation", * "Add dark mode", * "Optimize database queries" * ] * * const grouped = await zai.group(tasks, { * instructions: 'Categorize development tasks', * initialGroups: [ * { id: 'bugs', label: 'Bug Fixes', elements: [] }, * { id: 'features', label: 'New Features', elements: [] }, * { id: 'docs', label: 'Documentation', elements: [] }, * { id: 'performance', label: 'Performance', elements: [] } * ] * }) * ``` */ /** * @example Limiting number of groups * ```typescript * const items = ['apple', 'banana', 'carrot', 'chicken', 'rice', 'bread', 'salmon', 'milk'] * * const groups = await zai.group(items, { * instructions: 'Group by food type', * maxGroups: 3 // At most 3 groups — smallest groups get merged if exceeded * }) * // Guarantees no more than 3 groups in the result * ``` */ group(input: Array, options?: Options$4): Response>, Record>; } } //#endregion //#region src/operations/rate.d.ts type RatingInstructions = string | Record; type Options$3 = { /** The maximum number of tokens per item */ tokensPerItem?: number; /** The maximum number of items to rate per chunk */ maxItemsPerChunk?: number; }; type RatingResult = T extends string ? { [key: string]: number; total: number; } : T extends Record ? { [K in keyof T]: number; } & { total: number; } : never; type SimplifiedRatingResult = T extends string ? number : RatingResult; declare module '@botpress/zai' { interface Zai { /** * Rates array items on a 1-5 scale based on single or multiple criteria. * * This operation evaluates each item and assigns numeric ratings (1-5) where: * - 1 = Very Bad, 2 = Bad, 3 = Average, 4 = Good, 5 = Very Good * * Supports both simple single-criterion rating (string instructions) and * multi-criteria rating (object with criterion → description mapping). * * @param input - Array of items to rate * @param instructions - Single criterion (string) or multiple criteria (object) * @param options - Configuration for chunking and tokens per item * @returns Response with ratings array (simplified to numbers for single criterion) * * @example Single criterion rating * ```typescript * const reviews = [ * "Amazing product! Best purchase ever!", * "It's okay, nothing special", * "Terrible quality, broke immediately" * ] * * const ratings = await zai.rate(reviews, 'Rate the sentiment') * // Result: [5, 3, 1] (simplified to numbers) * * // Get full details * const { output } = await zai.rate(reviews, 'Rate the sentiment').result() * // output[0]: { sentiment: 5, total: 5 } * ``` * * @example Multi-criteria rating * ```typescript * const essays = [ * "... student essay text ...", * "... another essay ...", * ] * * const ratings = await zai.rate(essays, { * grammar: 'Rate the grammar and spelling', * clarity: 'Rate how clear and well-organized the writing is', * argumentation: 'Rate the strength of arguments and evidence' * }) * * // Result: [ * // { grammar: 4, clarity: 5, argumentation: 3, total: 12 }, * // { grammar: 3, clarity: 4, argumentation: 4, total: 11 } * // ] * ``` * * @example Rating customer support conversations * ```typescript * const conversations = [ * { agent: 'John', messages: [...], duration: 300 }, * { agent: 'Jane', messages: [...], duration: 180 } * ] * * const ratings = await zai.rate(conversations, { * professionalism: 'How professional was the agent?', * helpfulness: 'How helpful was the agent in solving the issue?', * efficiency: 'How efficiently was the conversation handled?' * }) * * // Calculate average scores * const avgProfessionalism = ratings.reduce((sum, r) => sum + r.professionalism, 0) / ratings.length * ``` * * @example Rating code quality * ```typescript * const codeSamples = [ * "function foo() { return x + y }", * "const calculateTotal = (items) => items.reduce((sum, item) => sum + item.price, 0)", * ] * * const quality = await zai.rate(codeSamples, { * readability: 'How readable and clear is the code?', * best_practices: 'Does it follow coding best practices?', * documentation: 'Is the code well-documented?' * }) * ``` * * @example Product review rating * ```typescript * const products = [ * { name: 'Laptop', reviews: [...], avgStars: 4.2 }, * { name: 'Mouse', reviews: [...], avgStars: 3.8 } * ] * * const ratings = await zai.rate( * products, * 'Rate overall product quality based on reviews and rating', * { * tokensPerItem: 500, // Allow more tokens for detailed reviews * maxItemsPerChunk: 20 // Process 20 products per chunk * } * ) * ``` * * @example Finding highest-rated items * ```typescript * const ratings = await zai.rate(items, { * quality: 'Product quality', * value: 'Value for money', * design: 'Design and aesthetics' * }) * * // Sort by total score * const sorted = items * .map((item, idx) => ({ item, rating: ratings[idx] })) * .sort((a, b) => b.rating.total - a.rating.total) * * console.log('Top rated:', sorted[0].item) * console.log('Score breakdown:', sorted[0].rating) * ``` */ rate(input: Array, instructions: I, options?: Options$3): Response>, Array>>; } } //#endregion //#region src/operations/sort.d.ts type Options$2 = { /** The maximum number of tokens per item */ tokensPerItem?: number; }; declare module '@botpress/zai' { interface Zai { /** * Sorts array items based on natural language sorting criteria. * * This operation intelligently orders items according to your instructions, understanding * complex sorting logic like priority, quality, chronology, or any custom criteria. * Perfect for ranking, organizing, and prioritizing lists based on subjective or * multi-faceted criteria. * * @param input - Array of items to sort * @param instructions - Natural language description of how to sort (e.g., "by priority", "newest first") * @param options - Configuration for tokens per item * @returns Response resolving to the sorted array * * @example Sort by price * ```typescript * const products = [ * { name: 'Laptop', price: 999 }, * { name: 'Mouse', price: 29 }, * { name: 'Keyboard', price: 79 } * ] * * const sorted = await zai.sort(products, 'from least expensive to most expensive') * // Result: [Mouse ($29), Keyboard ($79), Laptop ($999)] * ``` * * @example Sort by priority/urgency * ```typescript * const tasks = [ * "Update documentation", * "Fix critical security bug", * "Add new feature", * "System is down - all users affected" * ] * * const prioritized = await zai.sort(tasks, 'by urgency and impact, most urgent first') * // Result: ["System is down...", "Fix critical security bug", "Add new feature", "Update documentation"] * ``` * * @example Sort by quality/rating * ```typescript * const reviews = [ * "Product is okay", * "Absolutely amazing! Best purchase ever!", * "Terrible, broke immediately", * "Good quality for the price" * ] * * const sorted = await zai.sort(reviews, 'by sentiment, most positive first') * // Result: [amazing review, good review, okay review, terrible review] * ``` * * @example Sort by complexity * ```typescript * const problems = [ * "Fix typo in README", * "Redesign entire authentication system", * "Update a dependency version", * "Implement new microservice architecture" * ] * * const sorted = await zai.sort(problems, 'by complexity, simplest first') * ``` * * @example Sort by relevance to query * ```typescript * const documents = [ * "Article about cats", * "Article about dogs and their training", * "Article about dog breeds", * "Article about fish" * ] * * const sorted = await zai.sort( * documents, * 'by relevance to "dog training", most relevant first' * ) * // Result: [dogs and training, dog breeds, cats, fish] * ``` * * @example Sort candidates by fit * ```typescript * const candidates = [ * { name: 'Alice', experience: 5, skills: ['React', 'Node'] }, * { name: 'Bob', experience: 10, skills: ['Python', 'ML'] }, * { name: 'Charlie', experience: 3, skills: ['React', 'TypeScript'] } * ] * * const sorted = await zai.sort( * candidates, * 'by fit for a senior React developer position, best fit first' * ) * ``` * * @example Sort chronologically * ```typescript * const events = [ * "Started the project last month", * "Will launch next week", * "Met with client yesterday", * "Planning meeting tomorrow" * ] * * const chronological = await zai.sort(events, 'in chronological order') * // Understands relative time expressions * ``` * * @example With token limit per item * ```typescript * const sorted = await zai.sort( * longDocuments, * 'by relevance to climate change research', * { tokensPerItem: 500 } // Allow 500 tokens per document * ) * ``` */ sort(input: Array, instructions: string, options?: Options$2): Response, Array>; } } //#endregion //#region src/operations/answer.d.ts /** * Citation referencing a specific line or range of lines in support documents */ type Citation = { /** The character offset where this citation appears in the answer */ offset: number; /** The support document item(s) used at this offset */ item: T; /** The line contents joined together as a snippet */ snippet: string; }; /** * A single answer with citations */ type AnswerWithCitations = { /** The answer text */ answer: string; /** Citations mapping answer text to support documents */ citations: Citation[]; }; /** * Response type when a clear answer can be provided */ type AnswerResponse = { type: 'answer'; } & AnswerWithCitations; /** * Response type when the question is ambiguous and multiple interpretations exist */ type AmbiguousResponse = { type: 'ambiguous'; /** What is the ambiguity? What concepts clash or are unclear? */ ambiguity: string; /** A follow-up question to clear out the ambiguity */ follow_up: string; /** Possible answers for different interpretations (2-3 answers) */ answers: AnswerWithCitations[]; }; /** * Response type when the question is out of topic */ type OutOfTopicResponse = { type: 'out_of_topic'; /** Why is this question considered out of topic? */ reason: string; }; /** * Response type when the question is invalid or malformed */ type InvalidQuestionResponse = { type: 'invalid_question'; /** What makes this an invalid question? */ reason: string; }; /** * Response type when there is insufficient knowledge to answer */ type MissingKnowledgeResponse = { type: 'missing_knowledge'; /** What knowledge is missing to generate a high-quality answer? */ reason: string; }; /** * All possible response types from zai.answer */ type AnswerResult = AnswerResponse | AmbiguousResponse | OutOfTopicResponse | InvalidQuestionResponse | MissingKnowledgeResponse; /** * Example for few-shot learning */ type AnswerExample = { /** Support documents for this example */ documents: T[]; /** The question asked */ question: string; /** The expected answer result */ result: AnswerResult; }; type Options$1 = { /** Examples to help guide answer generation */ examples?: AnswerExample[]; /** Additional instructions for answer generation */ instructions?: string; /** Maximum number of tokens per document chunk */ chunkLength?: number; /** * Maximum number of refinement iterations when merging chunked results * @default 3 */ maxRefinementPasses?: number; }; declare module '@botpress/zai' { interface Zai { /** * Answers questions from documents with citations and intelligent handling of edge cases. * * This operation provides a production-ready question-answering system that: * - Cites sources with precise line references * - Handles ambiguous questions with multiple interpretations * - Detects out-of-topic or invalid questions * - Identifies missing knowledge * - Automatically chunks and processes large document sets * * @param documents - Array of documents to search (strings, objects, or any type) * @param question - The question to answer * @param options - Configuration for chunking, examples, and instructions * @returns Response with answer + citations, or error states (ambiguous, out_of_topic, invalid, missing_knowledge) * * @example Basic usage with string documents * ```typescript * const documents = [ * 'Botpress was founded in 2016.', * 'The company is based in Quebec, Canada.', * 'Botpress provides an AI agent platform.' * ] * * const result = await zai.answer(documents, 'When was Botpress founded?') * if (result.type === 'answer') { * console.log(result.answer) // "Botpress was founded in 2016." * console.log(result.citations) // [{ offset: 30, item: documents[0], snippet: '...' }] * } * ``` * * @example With object documents * ```typescript * const products = [ * { id: 1, name: 'Pro Plan', price: 99, features: ['AI', 'Analytics'] }, * { id: 2, name: 'Enterprise', price: 499, features: ['AI', 'Support', 'SLA'] } * ] * * const result = await zai.answer(products, 'What features does the Pro Plan include?') * // Returns answer with citations pointing to the product objects * ``` * * @example Handling different response types * ```typescript * const result = await zai.answer(documents, question) * * switch (result.type) { * case 'answer': * console.log('Answer:', result.answer) * console.log('Sources:', result.citations) * break * * case 'ambiguous': * console.log('Question is ambiguous:', result.ambiguity) * console.log('Clarifying question:', result.follow_up) * console.log('Possible answers:', result.answers) * break * * case 'out_of_topic': * console.log('Question unrelated:', result.reason) * break * * case 'invalid_question': * console.log('Invalid question:', result.reason) * break * * case 'missing_knowledge': * console.log('Insufficient info:', result.reason) * break * } * ``` * * @example With custom instructions * ```typescript * const result = await zai.answer(documents, 'What is the pricing?', { * instructions: 'Provide detailed pricing breakdown including all tiers', * chunkLength: 8000 // Process in smaller chunks for accuracy * }) * ``` * * @example Large document sets (auto-chunking) * ```typescript * // Handles thousands of documents automatically * const manyDocs = await loadDocuments() // 1000+ documents * const result = await zai.answer(manyDocs, 'What is the refund policy?') * // Automatically chunks, processes in parallel, and merges results * ``` * * @example Tracking citations * ```typescript * const result = await zai.answer(documents, question) * if (result.type === 'answer') { * result.citations.forEach(citation => { * console.log(`At position ${citation.offset}:`) * console.log(` Cited: "${citation.snippet}"`) * console.log(` From document:`, citation.item) * }) * } * ``` */ answer(documents: T[], question: string, options?: Options$1): Response, AnswerResult>; } } //#endregion //#region src/operations/patch.d.ts /** * Represents a file to be patched */ type File = { /** The file path (e.g., 'src/components/Button.tsx') */ path: string; /** The file name (e.g., 'Button.tsx') */ name: string; /** The file content */ content: string; /** The patch operations that were applied (only present in output) */ patch?: string; }; type __Z = { __type__: 'ZuiType'; _output: T; }; type OfType = __Z> = T extends __Z ? T : never; type Options = { /** * Maximum tokens per chunk when processing large files or many files. * If a single file exceeds this limit, it will be split into chunks. * If all files together exceed this limit, they will be processed in batches. * If not specified, all files must fit in a single prompt. */ maxTokensPerChunk?: number; /** * Optional Zui schema to validate JSON files against after patching. * Only applies to files detected as JSON (by .json extension). * If the patched JSON doesn't match the schema, the LLM is re-prompted to fix it. */ schema?: OfType; }; declare module '@botpress/zai' { interface Zai { /** * Patches files based on natural language instructions using the micropatch protocol. * * This operation takes an array of files and instructions, then returns the modified files. * It uses a token-efficient line-based patching protocol (micropatch) that allows precise * modifications without regenerating entire files. * * @param files - Array of files to patch, each with path, name, and content * @param instructions - Natural language instructions describing what changes to make * @param options - Optional configuration for patch generation * @returns Response promise resolving to array of patched files * * @example Simple text replacement * ```typescript * const files = [{ * path: 'src/hello.ts', * name: 'hello.ts', * content: 'console.log("Hello World")' * }] * * const patched = await zai.patch( * files, * 'change the message to say "Hi World"' * ) * // patched[0].content contains: console.log("Hi World") * // patched[0].patch contains: ◼︎=1|console.log("Hi World") * ``` * * @example Adding documentation * ```typescript * const files = [{ * path: 'src/utils.ts', * name: 'utils.ts', * content: 'export function add(a: number, b: number) {\n return a + b\n}' * }] * * const patched = await zai.patch( * files, * 'add JSDoc comments to all exported functions' * ) * ``` * * @example Patching multiple files * ```typescript * const files = [ * { path: 'package.json', name: 'package.json', content: '...' }, * { path: 'config.json', name: 'config.json', content: '...' } * ] * * const patched = await zai.patch( * files, * 'update version to 2.0.0 in all config files' * ) * ``` * * @example Refactoring code * ```typescript * const files = [{ * path: 'src/api.ts', * name: 'api.ts', * content: 'function fetchUser() { ... }' * }] * * const patched = await zai.patch( * files, * 'convert fetchUser to an async function and add error handling' * ) * ``` * * @example Removing code * ```typescript * const files = [{ * path: 'src/legacy.ts', * name: 'legacy.ts', * content: 'const debug = true\nconsole.log("Debug mode")\nfunction main() {...}' * }] * * const patched = await zai.patch( * files, * 'remove all debug-related code' * ) * ``` * * @example Inspecting applied patches * ```typescript * const patched = await zai.patch(files, 'add error handling') * * // Check what patches were applied * for (const file of patched) { * if (file.patch) { * console.log(`Patches for ${file.path}:`) * console.log(file.patch) * } * } * ``` */ patch(files: Array, instructions: string, options?: Options): Response>; } } //#endregion export { type Memoizer, Zai, type ZaiConfig };